ket-lang 0.10.4.dev1__tar.gz → 0.10.4.1.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. {ket_lang-0.10.4.dev1/src/ket_lang.egg-info → ket_lang-0.10.4.1.dev1}/PKG-INFO +1 -1
  2. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/__init__.py +1 -1
  3. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libket/execution.py +16 -10
  4. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/process/mod.rs +13 -0
  5. ket_lang-0.10.4.1.dev1/src/ket/gateset.py +176 -0
  6. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/mps.py +0 -6
  7. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qulib/__init__.py +207 -105
  8. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1/src/ket_lang.egg-info}/PKG-INFO +1 -1
  9. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket_lang.egg-info/SOURCES.txt +1 -0
  10. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/LICENSE +0 -0
  11. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/MANIFEST.in +0 -0
  12. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/README.md +0 -0
  13. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/pyproject.toml +0 -0
  14. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/setup.cfg +0 -0
  15. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/setup.py +0 -0
  16. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/amazon.py +0 -0
  17. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/base/__init__.py +0 -0
  18. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/base/qasm.py +0 -0
  19. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/base/quant.py +0 -0
  20. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/__init__.py +0 -0
  21. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/kbw.py +0 -0
  22. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libket/__init__.py +0 -0
  23. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/__init__.py +0 -0
  24. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/.git +0 -0
  25. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/.gitignore +0 -0
  26. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/.gitlab-ci.yml +0 -0
  27. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/.pre-commit-config.yaml +0 -0
  28. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/CHANGELOG.md +0 -0
  29. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/Cargo.toml +0 -0
  30. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/LICENSE +0 -0
  31. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/LICENSES/Apache-2.0.txt +0 -0
  32. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/README.md +0 -0
  33. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/REUSE.toml +0 -0
  34. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/build.rs +0 -0
  35. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/cbindgen.toml +0 -0
  36. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/examples/grover_batch.rs +0 -0
  37. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/examples/grover_live.rs +0 -0
  38. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/examples/grover_live_dv2.rs +0 -0
  39. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/kbw.h +0 -0
  40. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/bitwise.rs +0 -0
  41. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/block.rs +0 -0
  42. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/c_api.rs +0 -0
  43. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/convert.rs +0 -0
  44. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/dense.rs +0 -0
  45. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/dense_gpu/kernel.rs +0 -0
  46. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/dense_gpu/mod.rs +0 -0
  47. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/dense_v2.rs +0 -0
  48. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/lib.rs +0 -0
  49. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/quantum_execution.rs +0 -0
  50. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/sparse.rs +0 -0
  51. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/kbw/src/sparse_v2.rs +0 -0
  52. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/.git +0 -0
  53. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/.gitignore +0 -0
  54. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/.gitlab-ci.yml +0 -0
  55. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/.pre-commit-config.yaml +0 -0
  56. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/CHANGELOG.md +0 -0
  57. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/Cargo.toml +0 -0
  58. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/LICENSE +0 -0
  59. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/LICENSES/Apache-2.0.txt +0 -0
  60. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/README.md +0 -0
  61. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/REUSE.toml +0 -0
  62. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/build.rs +0 -0
  63. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/cbindgen.toml +0 -0
  64. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/examples/grover.rs +0 -0
  65. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/examples/qft.rs +0 -0
  66. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/libket.h +0 -0
  67. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/c_api/block.rs +0 -0
  68. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/c_api/execute.rs +0 -0
  69. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/c_api/mod.rs +0 -0
  70. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/c_api/process.rs +0 -0
  71. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/mod.rs +0 -0
  72. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/network.rs +0 -0
  73. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/su2.rs +0 -0
  74. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/u2.rs +0 -0
  75. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/util.rs +0 -0
  76. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/x/c2to4x.rs +0 -0
  77. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/x/mod.rs +0 -0
  78. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/x/single_aux.rs +0 -0
  79. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/decompose/x/v_chain.rs +0 -0
  80. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/error.rs +0 -0
  81. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/execution.rs +0 -0
  82. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/ir/block.rs +0 -0
  83. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/ir/gate.rs +0 -0
  84. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/ir/hamiltonian.rs +0 -0
  85. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/ir/macros.rs +0 -0
  86. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/ir/mod.rs +0 -0
  87. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/lib.rs +0 -0
  88. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/mapping/allocation.rs +0 -0
  89. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/mapping/dynamic_look_ahead.rs +0 -0
  90. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/mapping/graph.rs +0 -0
  91. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/mapping/mod.rs +0 -0
  92. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/matrix.rs +0 -0
  93. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/process/classical_shadow.rs +0 -0
  94. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/process/qwc.rs +0 -0
  95. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/qasm/ast.rs +0 -0
  96. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/qasm/executor.rs +0 -0
  97. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/qasm/gates.rs +0 -0
  98. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/qasm/mod.rs +0 -0
  99. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/qasm/openqasm.lalrpop +0 -0
  100. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/libs/libket/src/tests.rs +0 -0
  101. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/clib/wrapper.py +0 -0
  102. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/expv.py +0 -0
  103. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/fermion.py +0 -0
  104. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/gates.py +0 -0
  105. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/ibm.py +0 -0
  106. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/measurement.py +0 -0
  107. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/npsim.py +0 -0
  108. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/operations.py +0 -0
  109. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qint.py +0 -0
  110. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/quantumstate.py +0 -0
  111. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qulib/gates.py +0 -0
  112. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qulib/ham.py +0 -0
  113. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qulib/oracle.py +0 -0
  114. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket/qulib/prepare.py +0 -0
  115. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket_lang.egg-info/dependency_links.txt +0 -0
  116. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket_lang.egg-info/not-zip-safe +0 -0
  117. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket_lang.egg-info/requires.txt +0 -0
  118. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/src/ket_lang.egg-info/top_level.txt +0 -0
  119. {ket_lang-0.10.4.dev1 → ket_lang-0.10.4.1.dev1}/tests/test_fermion.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ket-lang
3
- Version: 0.10.4.dev1
3
+ Version: 0.10.4.1.dev1
4
4
  Summary: Ket quantum programming language interpreter and library
5
5
  Home-page: https://quantumket.org
6
6
  Author: Evandro Chagas Ribeiro da Rosa
@@ -83,7 +83,7 @@ from .fermion import *
83
83
  from .fermion import __all__ as all_fermion
84
84
  from . import qulib
85
85
 
86
- __version__ = "0.10.4.dev1"
86
+ __version__ = "0.10.4.1.dev1"
87
87
 
88
88
  __all__ = (
89
89
  all_base
@@ -15,6 +15,7 @@ from ctypes import (
15
15
  POINTER,
16
16
  c_uint64,
17
17
  c_double,
18
+ pointer,
18
19
  )
19
20
  import json
20
21
  from abc import ABC, abstractmethod
@@ -426,6 +427,13 @@ class NativeGateSet(ABC):
426
427
  """
427
428
 
428
429
  def __init__(self):
430
+ # Accumulate every JSON result buffer in a list so that raw C pointers
431
+ # returned by the callbacks remain valid for the lifetime of this object.
432
+ # Using a single overwritten instance variable causes a use-after-free
433
+ # segfault because the old bytes object is GC'd while Rust still holds
434
+ # a pointer into it.
435
+ self._result_buffers: list[bytes] = []
436
+
429
437
  @CFUNCTYPE(
430
438
  c_int32,
431
439
  c_char_p, # gate_json
@@ -439,12 +447,11 @@ class NativeGateSet(ABC):
439
447
  for row in flat
440
448
  ]
441
449
  result = self.translate(matrix, target)
442
- self._translate_result = json.dumps(result).encode("utf-8")
443
- native_gate_json[0] = self._translate_result
450
+ buf = json.dumps(result).encode("utf-8")
451
+ self._result_buffers.append(buf)
452
+ native_gate_json[0] = buf
444
453
  return 0
445
454
 
446
- self._translate_result = None
447
-
448
455
  @CFUNCTYPE(
449
456
  c_int32,
450
457
  c_size_t, # control
@@ -453,12 +460,11 @@ class NativeGateSet(ABC):
453
460
  )
454
461
  def cnot(control, target, native_gate_json):
455
462
  result = self.cnot(control, target)
456
- self._cnot_result = json.dumps(result).encode("utf-8")
457
- native_gate_json[0] = self._cnot_result
463
+ buf = json.dumps(result).encode("utf-8")
464
+ self._result_buffers.append(buf)
465
+ native_gate_json[0] = buf
458
466
  return 0
459
467
 
460
- self._cnot_result = None
461
-
462
468
  # Keep references alive for the duration of the object's lifetime.
463
469
  self._cb_translate = translate
464
470
  self._cb_cnot = cnot
@@ -526,7 +532,7 @@ def make_live_configuration(
526
532
  """
527
533
 
528
534
  if native_gate_set is not None:
529
- native_gate_set_ptr = native_gate_set.c_struct
535
+ native_gate_set_ptr = pointer(native_gate_set.c_struct)
530
536
  else:
531
537
  native_gate_set_ptr = None
532
538
 
@@ -582,7 +588,7 @@ def make_batch_configuration( # pylint: disable=too-many-arguments,too-many-pos
582
588
  exp_value_strategy_json = json.dumps("Native").encode("utf-8")
583
589
 
584
590
  if native_gate_set is not None:
585
- native_gate_set_ptr = native_gate_set.c_struct
591
+ native_gate_set_ptr = pointer(native_gate_set.c_struct)
586
592
  else:
587
593
  native_gate_set_ptr = None
588
594
 
@@ -715,7 +715,20 @@ impl Process {
715
715
  }
716
716
  }
717
717
  }
718
+ } else if gate.control.len() == 1 && matches!(gate.gate, QuantumGate::PauliX) {
719
+ let control = *gate.control.iter().next().unwrap();
720
+ let target = gate.target;
721
+ flush_sq!(control);
722
+ flush_sq!(target);
723
+ physical_circuit.append(&mut native_gate_set.cnot(control, target)?);
718
724
  } else {
725
+ if !gate.control.is_empty() {
726
+ println!(
727
+ "PANIC! gate: {:?}, control len: {}",
728
+ gate.gate,
729
+ gate.control.len()
730
+ );
731
+ }
719
732
  assert!(
720
733
  gate.control.is_empty(),
721
734
  "controlled gates should be decomposed at this pont"
@@ -0,0 +1,176 @@
1
+ """Native gate set decompositions for Ket."""
2
+
3
+ # SPDX-FileCopyrightText: 2026 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
4
+ # SPDX-FileCopyrightText: 2026 Ruan Luiz Molgero Lopes <ruan.molgero@grad.ufsc.br>
5
+ #
6
+ # SPDX-License-Identifier: Apache-2.0
7
+
8
+
9
+ import cmath
10
+ import math
11
+ from .clib.libket.execution import NativeGateSet
12
+
13
+
14
+ def _extract_u3(matrix):
15
+ """
16
+ Extracts U3 angles (theta, phi, lambda) from a 2x2 unitary matrix.
17
+ Ignores global phase.
18
+ """
19
+ u00, u01 = matrix[0]
20
+ u10, u11 = matrix[1]
21
+
22
+ if abs(u00) > 1e-10:
23
+ phase_g = cmath.phase(u00)
24
+ u00 *= cmath.exp(-1j * phase_g)
25
+ u01 *= cmath.exp(-1j * phase_g)
26
+ u10 *= cmath.exp(-1j * phase_g)
27
+ u11 *= cmath.exp(-1j * phase_g)
28
+
29
+ val = max(-1.0, min(1.0, u00.real))
30
+ theta = 2 * math.acos(val)
31
+
32
+ phi = cmath.phase(u10) if abs(u10) > 1e-10 else 0.0
33
+ lam = cmath.phase(-u01) if abs(u01) > 1e-10 else cmath.phase(u11) - phi
34
+ else:
35
+ theta = math.pi
36
+ phase_g = cmath.phase(u10)
37
+ u10 *= cmath.exp(-1j * phase_g)
38
+ u01 *= cmath.exp(-1j * phase_g)
39
+ phi = 0.0
40
+ lam = cmath.phase(-u01) if abs(u01) > 1e-10 else 0.0
41
+
42
+ return theta, phi, lam
43
+
44
+
45
+ class RzSXCZ(NativeGateSet):
46
+ """Gate set using CZ for CNOT decomposition."""
47
+
48
+ def translate(self, matrix: list[list[complex]], target: int) -> list:
49
+ theta, phi, lam = _extract_u3(matrix)
50
+ return [
51
+ ["rz", [lam], [target]],
52
+ ["sxdg", [], [target]],
53
+ ["rz", [-theta], [target]],
54
+ ["sx", [], [target]],
55
+ ["rz", [phi], [target]],
56
+ ]
57
+
58
+ def cnot(self, control: int, target: int) -> list:
59
+ return [
60
+ ["rz", [math.pi / 2], [target]],
61
+ ["sx", [], [target]],
62
+ ["rz", [math.pi / 2], [target]],
63
+ ["cz", [], [control, target]],
64
+ ["rz", [math.pi / 2], [target]],
65
+ ["sx", [], [target]],
66
+ ["rz", [math.pi / 2], [target]],
67
+ ]
68
+
69
+
70
+ class RzSXXRzz(NativeGateSet):
71
+ """Gate set using Rzz for CNOT decomposition."""
72
+
73
+ def translate(self, matrix: list[list[complex]], target: int) -> list:
74
+ theta, phi, lam = _extract_u3(matrix)
75
+ return [
76
+ ["rz", [lam], [target]],
77
+ ["sxdg", [], [target]],
78
+ ["rz", [-theta], [target]],
79
+ ["sx", [], [target]],
80
+ ["rz", [phi], [target]],
81
+ ]
82
+
83
+ def cnot(self, control: int, target: int) -> list:
84
+ return [
85
+ ["rz", [math.pi / 2], [target]],
86
+ ["sx", [], [target]],
87
+ ["rz", [math.pi / 2], [target]],
88
+ ["rzz", [math.pi / 2], [control, target]],
89
+ ["rz", [math.pi / 2], [target]],
90
+ ["sx", [], [target]],
91
+ ["rz", [math.pi / 2], [target]],
92
+ ["sx", [], [target]],
93
+ ["x", [], [target]],
94
+ ["rz", [-math.pi / 2], [control]],
95
+ ]
96
+
97
+
98
+ class RzSXECR(NativeGateSet):
99
+ """Gate set using ECR for CNOT decomposition."""
100
+
101
+ def translate(self, matrix: list[list[complex]], target: int) -> list:
102
+ theta, phi, lam = _extract_u3(matrix)
103
+ return [
104
+ ["rz", [lam], [target]],
105
+ ["sxdg", [], [target]],
106
+ ["rz", [-theta], [target]],
107
+ ["sx", [], [target]],
108
+ ["rz", [phi], [target]],
109
+ ]
110
+
111
+ def cnot(self, control: int, target: int) -> list:
112
+ return [
113
+ ["rz", [-math.pi / 2], [control]],
114
+ ["rz", [-math.pi], [target]],
115
+ ["sx", [], [target]],
116
+ ["rz", [-math.pi], [target]],
117
+ ["ecr", [], [control, target]],
118
+ ["sx", [], [control]],
119
+ ["sx", [], [control]],
120
+ ]
121
+
122
+
123
+ class RzRxISWAP(NativeGateSet):
124
+ """Gate set using iSWAP for CNOT decomposition."""
125
+
126
+ def translate(self, matrix: list[list[complex]], target: int) -> list:
127
+ theta, phi, lam = _extract_u3(matrix)
128
+ return [
129
+ ["rz", [lam], [target]],
130
+ ["rx", [math.pi / 2], [target]],
131
+ ["rz", [theta], [target]],
132
+ ["rx", [-math.pi / 2], [target]],
133
+ ["rz", [phi], [target]],
134
+ ]
135
+
136
+ def cnot(self, control: int, target: int) -> list:
137
+ return [
138
+ ["rz", [-math.pi / 2], [control]],
139
+ ["rz", [math.pi / 2], [target]],
140
+ ["iswap", [], [control, target]],
141
+ ["rx", [math.pi / 2], [control]],
142
+ ["iswap", [], [control, target]],
143
+ ["rx", [-math.pi / 2], [target]],
144
+ ["rz", [math.pi / 2], [target]],
145
+ ["rx", [math.pi / 2], [target]],
146
+ ["rz", [math.pi / 2], [target]],
147
+ ]
148
+
149
+
150
+ class RzGPiGPi2MS(NativeGateSet):
151
+ """Gate set using MS and GPi for CNOT decomposition."""
152
+
153
+ def translate(self, matrix: list[list[complex]], target: int) -> list:
154
+ theta, phi, lam = _extract_u3(matrix)
155
+ return [
156
+ ["rz", [lam], [target]],
157
+ ["gpi2", [0.0], [target]],
158
+ ["rz", [theta], [target]],
159
+ ["gpi2", [math.pi], [target]],
160
+ ["rz", [phi], [target]],
161
+ ]
162
+
163
+ def cnot(self, control: int, target: int) -> list:
164
+ return [
165
+ ["h", [], [target]],
166
+ ["gpi", [0.0], [control]],
167
+ ["h", [], [control]],
168
+ ["h", [], [target]],
169
+ ["ms", [], [control, target]],
170
+ ["h", [], [control]],
171
+ ["gpi", [0.0], [control]],
172
+ ["rz", [math.pi / 2], [control]],
173
+ ["h", [], [target]],
174
+ ["rz", [math.pi / 2], [target]],
175
+ ["h", [], [target]],
176
+ ]
@@ -153,8 +153,6 @@ class MPS(BatchExecution, LiveExecution):
153
153
 
154
154
  Args:
155
155
  num_qubits: Total number of qubits to simulate.
156
- backend: Target hardware for execution, either ``"cpu"`` or ``"gpu"``.
157
- Defaults to ``"cpu"``.
158
156
  max_bond: Maximum bond dimension for SVD truncations during the simulation.
159
157
  If specified, it restricts entanglement and keeps the MPS strictly 1D, enabling
160
158
  the simulation of large numbers of qubits. However, this dynamically changes tensor
@@ -168,7 +166,6 @@ class MPS(BatchExecution, LiveExecution):
168
166
  def __init__(
169
167
  self,
170
168
  num_qubits: int,
171
- backend: Literal["cpu", "gpu"] = "cpu",
172
169
  max_bond: int = None,
173
170
  double_precision: bool = False,
174
171
  execution: Optional[Literal["live", "batch"]] = None,
@@ -179,10 +176,7 @@ class MPS(BatchExecution, LiveExecution):
179
176
  self._live_psi = None
180
177
  self.num_qubits = num_qubits
181
178
  self.max_bond = max_bond
182
- if backend not in ["cpu", "gpu"]:
183
- raise ValueError("backend must be 'cpu' or 'gpu'")
184
179
  jax.config.update("jax_enable_x64", double_precision)
185
- jax.config.update("jax_platform_name", backend)
186
180
 
187
181
  self.last_grad = None
188
182
 
@@ -29,7 +29,7 @@ except ImportError:
29
29
  _MULTIPROCESS_AVAILABLE = False
30
30
 
31
31
 
32
- from ..clib.libket.execution import LiveExecution
32
+ from ..clib.libket.execution import LiveExecution, BatchExecution
33
33
  from ..base import Process, Quant
34
34
  from ..operations import dump, exp_value, measure
35
35
  from ..gates import H, CNOT, X, Z, obs
@@ -52,6 +52,7 @@ except ImportError:
52
52
  try:
53
53
  from qiskit import QuantumCircuit, QuantumRegister
54
54
  from qiskit.circuit import library, Gate
55
+ from qiskit.circuit.gate import Gate as QiskitGate
55
56
 
56
57
  QISKIT_AVAILABLE = True
57
58
  except ImportError:
@@ -162,131 +163,228 @@ DRAW_STYLE = {
162
163
  }
163
164
 
164
165
 
165
- class _IBMDeviceForDraw(LiveExecution):
166
+ class _IBMDeviceForDraw(BatchExecution):
166
167
  """IBMDevice use for qulib.draw"""
167
168
 
168
169
  def __init__(
170
+ # pylint: disable=too-many-arguments, too-many-positional-arguments
169
171
  self,
170
172
  num_qubits: list[int],
171
173
  names: list[str],
172
174
  decompose: bool = False,
173
175
  keep_order: bool = True,
176
+ coupling_graph: list[tuple[int, int]] | None = None,
177
+ native_gate_set=None,
174
178
  ):
175
179
  super().__init__()
176
- qubits = [QuantumRegister(n, l) for n, l in zip(num_qubits, names)]
180
+ if coupling_graph is not None:
181
+ qubits = [QuantumRegister(sum(num_qubits), "q")]
182
+ else:
183
+ qubits = [QuantumRegister(n, l) for n, l in zip(num_qubits, names)]
177
184
  self.circuit = QuantumCircuit(*qubits)
178
185
  self.num_qubits = sum(num_qubits)
179
186
  self.decompose = decompose
180
187
  self.keep_order = keep_order
188
+ self.coupling_graph = coupling_graph
189
+ self.native_gate_set = native_gate_set
181
190
  self.last_gate = None
182
191
 
183
- def pauli_x(self, target, control):
184
- if self.keep_order and self.last_gate != "X":
185
- self.circuit.barrier()
186
- gate = library.XGate()
187
- if len(control) >= 1:
188
- gate = gate.control(len(control))
189
- self.circuit.append(gate, control + [target])
190
- self.last_gate = "X"
191
-
192
- def pauli_y(self, target, control):
193
- if self.keep_order and self.last_gate != "Y":
194
- self.circuit.barrier()
195
- gate = library.YGate()
196
- if len(control) >= 1:
197
- gate = gate.control(len(control))
198
- self.circuit.append(gate, control + [target])
199
- self.last_gate = "Y"
200
-
201
- def pauli_z(self, target, control):
202
- if self.keep_order and self.last_gate != "Z":
203
- self.circuit.barrier()
204
- gate = library.ZGate()
205
- if len(control) >= 1:
206
- gate = gate.control(len(control))
207
- self.circuit.append(gate, control + [target])
208
- self.last_gate = "Z"
209
-
210
- def hadamard(self, target, control):
211
- if self.keep_order and self.last_gate != "H":
212
- self.circuit.barrier()
213
- gate = library.HGate()
214
- if len(control) >= 1:
215
- gate = gate.control(len(control))
216
- self.circuit.append(gate, control + [target])
217
- self.last_gate = "H"
218
-
219
- def rotation_x(self, target, control, angle):
220
- if self.keep_order and self.last_gate != "RX":
221
- self.circuit.barrier()
222
- gate = library.RXGate(angle)
223
- if len(control) >= 1:
224
- gate = gate.control(len(control))
225
- self.circuit.append(gate, control + [target])
226
- self.last_gate = "RX"
227
-
228
- def rotation_y(self, target, control, angle):
229
- if self.keep_order and self.last_gate != "RY":
230
- self.circuit.barrier()
231
- gate = library.RYGate(angle)
232
- if len(control) >= 1:
233
- gate = gate.control(len(control))
234
- self.circuit.append(gate, control + [target])
235
- self.last_gate = "RY"
236
-
237
- def rotation_z(self, target, control, angle):
238
- if self.keep_order and self.last_gate != "RZ":
239
- self.circuit.barrier()
240
- gate = library.RZGate(angle)
241
- if len(control) >= 1:
242
- gate = gate.control(len(control))
243
- self.circuit.append(gate, control + [target])
244
- self.last_gate = "RZ"
245
-
246
- def phase(self, target, control, angle):
247
- if self.keep_order and self.last_gate != "P":
248
- self.circuit.barrier()
249
- gate = library.PhaseGate(angle)
250
- if len(control) >= 1:
251
- gate = gate.control(len(control))
252
- self.circuit.append(gate, control + [target])
253
- self.last_gate = "P"
254
-
255
- def measure(self, qubits: list[int]) -> int:
256
- mea = Gate(name="measure", num_qubits=len(qubits), params=[])
257
- if self.keep_order and self.last_gate != "M":
258
- self.circuit.barrier()
259
- self.circuit.append(mea, qubits)
260
- self.last_gate = "M"
261
- return 0
262
-
263
- def exp_value(self, _):
264
- """Compute the expectation value of the given Hamiltonian."""
265
- return 0
266
-
267
- def sample(self, qubits: list[int], shots: int):
268
- sample = Gate(name=f"sample({shots=})", num_qubits=len(qubits), params=[])
192
+ def _add_gate(self, gate_name, target, control, value):
193
+ # pylint: disable=too-many-branches, too-many-statements
194
+ if gate_name == "PauliX":
195
+ if self.keep_order and self.last_gate != "X":
196
+ self.circuit.barrier()
197
+ gate = library.XGate()
198
+ if len(control) >= 1:
199
+ gate = gate.control(len(control))
200
+ self.circuit.append(gate, control + [target])
201
+ self.last_gate = "X"
202
+ elif gate_name == "PauliY":
203
+ if self.keep_order and self.last_gate != "Y":
204
+ self.circuit.barrier()
205
+ gate = library.YGate()
206
+ if len(control) >= 1:
207
+ gate = gate.control(len(control))
208
+ self.circuit.append(gate, control + [target])
209
+ self.last_gate = "Y"
210
+ elif gate_name == "PauliZ":
211
+ if self.keep_order and self.last_gate != "Z":
212
+ self.circuit.barrier()
213
+ gate = library.ZGate()
214
+ if len(control) >= 1:
215
+ gate = gate.control(len(control))
216
+ self.circuit.append(gate, control + [target])
217
+ self.last_gate = "Z"
218
+ elif gate_name == "Hadamard":
219
+ if self.keep_order and self.last_gate != "H":
220
+ self.circuit.barrier()
221
+ gate = library.HGate()
222
+ if len(control) >= 1:
223
+ gate = gate.control(len(control))
224
+ self.circuit.append(gate, control + [target])
225
+ self.last_gate = "H"
226
+ elif gate_name == "RotationX":
227
+ if self.keep_order and self.last_gate != "RX":
228
+ self.circuit.barrier()
229
+ gate = library.RXGate(value)
230
+ if len(control) >= 1:
231
+ gate = gate.control(len(control))
232
+ self.circuit.append(gate, control + [target])
233
+ self.last_gate = "RX"
234
+ elif gate_name == "RotationY":
235
+ if self.keep_order and self.last_gate != "RY":
236
+ self.circuit.barrier()
237
+ gate = library.RYGate(value)
238
+ if len(control) >= 1:
239
+ gate = gate.control(len(control))
240
+ self.circuit.append(gate, control + [target])
241
+ self.last_gate = "RY"
242
+ elif gate_name == "RotationZ":
243
+ if self.keep_order and self.last_gate != "RZ":
244
+ self.circuit.barrier()
245
+ gate = library.RZGate(value)
246
+ if len(control) >= 1:
247
+ gate = gate.control(len(control))
248
+ self.circuit.append(gate, control + [target])
249
+ self.last_gate = "RZ"
250
+ elif gate_name == "Phase":
251
+ if self.keep_order and self.last_gate != "P":
252
+ self.circuit.barrier()
253
+ gate = library.PhaseGate(value)
254
+ if len(control) >= 1:
255
+ gate = gate.control(len(control))
256
+ self.circuit.append(gate, control + [target])
257
+ self.last_gate = "P"
258
+
259
+ def _build_circuit(self, gate_list):
260
+ # pylint: disable=too-many-branches, too-many-statements, too-many-nested-blocks
261
+ # pylint: disable=too-many-branches, too-many-statements
262
+ for g in gate_list:
263
+ if g.get("decomposed"):
264
+ for dec_g in g["decomposed"]:
265
+ if "U" in dec_g:
266
+ u_info = dec_g["U"]
267
+ gate_info = u_info[0]
268
+ target = u_info[1]
269
+ control = []
270
+ if isinstance(gate_info, str):
271
+ gate_name = gate_info
272
+ value = 0.0
273
+ else:
274
+ gate_name = list(gate_info.keys())[0]
275
+ val_info = gate_info[gate_name]
276
+ if isinstance(val_info, dict) and "Ref" in val_info:
277
+ value = val_info["Ref"]["value"]
278
+ else:
279
+ value = val_info.get("Value", 0.0)
280
+ self._add_gate(gate_name, target, control, value)
281
+ elif "CNOT" in dec_g:
282
+ cnot_info = dec_g["CNOT"]
283
+ target = cnot_info[1]
284
+ control = [cnot_info[0]]
285
+ self._add_gate("PauliX", target, control, 0.0)
286
+ else:
287
+ gate_info = g["gate"]
288
+ target = g.get("target", 0)
289
+ control = sorted(g.get("control", []))
290
+
291
+ if isinstance(gate_info, str):
292
+ gate_name = gate_info
293
+ value = 0.0
294
+ else:
295
+ gate_name = list(gate_info.keys())[0]
296
+ val_info = gate_info[gate_name]
297
+ if isinstance(val_info, dict) and "Ref" in val_info:
298
+ value = val_info["Ref"]["value"]
299
+ else:
300
+ value = val_info.get("Value", 0.0)
301
+
302
+ self._add_gate(gate_name, target, control, value)
303
+
304
+ # pylint: disable=too-many-branches, too-many-statements
305
+
306
+ def exp_value_native(
307
+ self, gate_list, hamiltonians
308
+ ): # pylint: disable=arguments-renamed, redefined-outer-name
309
+ for g in gate_list:
310
+ gate_name = g[0]
311
+ params = g[1]
312
+ qubits = g[2]
313
+
314
+ if gate_name.lower() in ("x", "paulix"):
315
+ gate = library.XGate()
316
+ elif gate_name.lower() in ("y", "pauliy"):
317
+ gate = library.YGate()
318
+ elif gate_name.lower() in ("z", "pauliz"):
319
+ gate = library.ZGate()
320
+ elif gate_name.lower() in ("h", "hadamard"):
321
+ gate = library.HGate()
322
+ elif gate_name.lower() in ("rx", "rotationx"):
323
+ gate = library.RXGate(params[0])
324
+ elif gate_name.lower() in ("ry", "rotationy"):
325
+ gate = library.RYGate(params[0])
326
+ elif gate_name.lower() in ("rz", "rotationz"):
327
+ gate = library.RZGate(params[0])
328
+ elif gate_name.lower() in ("p", "phase"):
329
+ gate = library.PhaseGate(params[0])
330
+ elif gate_name.lower() == "sx":
331
+ gate = library.SXGate()
332
+ elif gate_name.lower() == "sxdg":
333
+ gate = library.SXdgGate()
334
+ elif gate_name.lower() == "cz":
335
+ gate = library.CZGate()
336
+ elif gate_name.lower() == "rzz":
337
+ gate = library.RZZGate(params[0])
338
+ elif gate_name.lower() == "ecr":
339
+ gate = library.ECRGate()
340
+ elif gate_name.lower() == "iswap":
341
+ gate = library.iSwapGate()
342
+ elif gate_name.lower() == "ms":
343
+
344
+ gate = (
345
+ library.XXMinusYYGate(params[0])
346
+ if len(params) > 0
347
+ else QiskitGate("MS", 2, [])
348
+ )
349
+ elif gate_name.lower() == "cnot":
350
+ gate = library.CXGate()
351
+ else:
352
+ gate = QiskitGate(gate_name, len(qubits), params)
353
+
354
+ if self.keep_order and self.last_gate != gate_name:
355
+ self.circuit.barrier()
356
+ self.circuit.append(gate, qubits)
357
+ self.last_gate = gate_name
358
+
359
+ return [0.0] * len(hamiltonians)
360
+
361
+ def exp_value(
362
+ self, gate_list, hamiltonian_list
363
+ ): # pylint: disable=arguments-renamed, redefined-outer-name
364
+ self._build_circuit(gate_list)
365
+ return [0.0] * len(hamiltonian_list)
366
+
367
+ def sample(
368
+ self, gate_list, qubits_to_sample, shots: int
369
+ ): # pylint: disable=arguments-renamed, redefined-outer-name
370
+ self._build_circuit(gate_list)
371
+ sample = Gate(
372
+ name=f"sample({shots=})", num_qubits=len(qubits_to_sample), params=[]
373
+ )
269
374
  if self.keep_order and self.last_gate != "M":
270
375
  self.circuit.barrier()
271
- self.circuit.append(sample, qubits)
376
+ self.circuit.append(sample, qubits_to_sample)
272
377
  self.last_gate = "M"
273
378
  return ([[0]], [0])
274
379
 
275
- def dump(self, qubits: list[int]) -> dict:
276
- dump_gate = Gate(name="dump", num_qubits=len(qubits), params=[])
277
- if self.keep_order and self.last_gate != "M":
278
- self.circuit.barrier()
279
- self.circuit.append(dump_gate, qubits)
280
- self.last_gate = "M"
281
- return {
282
- "basis_states": [[0]],
283
- "amplitudes_real": [0.0],
284
- "amplitudes_imag": [0.0],
285
- }
286
-
287
380
  def connect(self):
288
381
  """Configure process"""
289
- return super().configure(self.num_qubits, self.decompose)
382
+ return super().configure(
383
+ self.num_qubits,
384
+ decompose=self.decompose,
385
+ coupling_graph=self.coupling_graph,
386
+ native_gate_set=self.native_gate_set,
387
+ )
290
388
 
291
389
 
292
390
  def draw( # pylint: disable=too-many-arguments, too-many-locals, too-many-branches
@@ -297,6 +395,8 @@ def draw( # pylint: disable=too-many-arguments, too-many-locals, too-many-branc
297
395
  qubits: int | list[int] | None = None,
298
396
  qpu_size: int | None = None,
299
397
  decompose: bool = False,
398
+ coupling_graph: list[tuple[int, int]] | None = None,
399
+ native_gate_set=None,
300
400
  title: str | None = None,
301
401
  keep_order: bool = True,
302
402
  **kwargs,
@@ -371,14 +471,16 @@ def draw( # pylint: disable=too-many-arguments, too-many-locals, too-many-branc
371
471
  num_qubits.append(qpu_size - total)
372
472
  names.append("AUX")
373
473
 
374
- device = _IBMDeviceForDraw(num_qubits, names, decompose, keep_order)
474
+ device = _IBMDeviceForDraw(
475
+ num_qubits, names, decompose, keep_order, coupling_graph, native_gate_set
476
+ )
375
477
 
376
478
  p = Process(device)
377
479
  q = [p.alloc(n) for n in (num_qubits if qpu_size is None else num_qubits[:-1])]
378
480
  gate(*args, *q)
379
481
 
380
482
  with obs():
381
- exp_value(Z(q[0]))
483
+ exp_value(Z(q[0])).get()
382
484
 
383
485
  if "output" not in kwargs and _IN_NOTEBOOK:
384
486
  kwargs["output"] = "mpl"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ket-lang
3
- Version: 0.10.4.dev1
3
+ Version: 0.10.4.1.dev1
4
4
  Summary: Ket quantum programming language interpreter and library
5
5
  Home-page: https://quantumket.org
6
6
  Author: Evandro Chagas Ribeiro da Rosa
@@ -9,6 +9,7 @@ src/ket/amazon.py
9
9
  src/ket/expv.py
10
10
  src/ket/fermion.py
11
11
  src/ket/gates.py
12
+ src/ket/gateset.py
12
13
  src/ket/ibm.py
13
14
  src/ket/measurement.py
14
15
  src/ket/mps.py
File without changes