ket-lang 0.10.2.dev2__tar.gz → 0.10.2.dev3__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 (117) hide show
  1. {ket_lang-0.10.2.dev2/src/ket_lang.egg-info → ket_lang-0.10.2.dev3}/PKG-INFO +1 -1
  2. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/__init__.py +1 -1
  3. ket_lang-0.10.2.dev2/src/ket/base.py → ket_lang-0.10.2.dev3/src/ket/base/__init__.py +17 -360
  4. ket_lang-0.10.2.dev3/src/ket/base/qasm.py +101 -0
  5. ket_lang-0.10.2.dev3/src/ket/base/quant.py +331 -0
  6. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qint.py +11 -28
  7. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/__init__.py +80 -3
  8. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3/src/ket_lang.egg-info}/PKG-INFO +1 -1
  9. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/SOURCES.txt +3 -1
  10. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/LICENSE +0 -0
  11. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/MANIFEST.in +0 -0
  12. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/README.md +0 -0
  13. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/pyproject.toml +0 -0
  14. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/setup.cfg +0 -0
  15. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/setup.py +0 -0
  16. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/amazon.py +0 -0
  17. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/__init__.py +0 -0
  18. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/kbw.py +0 -0
  19. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libket/__init__.py +0 -0
  20. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libket/execution.py +0 -0
  21. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/__init__.py +0 -0
  22. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.git +0 -0
  23. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.gitignore +0 -0
  24. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.gitlab-ci.yml +0 -0
  25. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.pre-commit-config.yaml +0 -0
  26. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/CHANGELOG.md +0 -0
  27. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/Cargo.toml +0 -0
  28. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/LICENSE +0 -0
  29. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/LICENSES/Apache-2.0.txt +0 -0
  30. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/README.md +0 -0
  31. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/REUSE.toml +0 -0
  32. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/build.rs +0 -0
  33. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/cbindgen.toml +0 -0
  34. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_batch.rs +0 -0
  35. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_live.rs +0 -0
  36. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_live_dv2.rs +0 -0
  37. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/kbw.h +0 -0
  38. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/bitwise.rs +0 -0
  39. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/block.rs +0 -0
  40. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/c_api.rs +0 -0
  41. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/convert.rs +0 -0
  42. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense.rs +0 -0
  43. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_gpu/kernel.rs +0 -0
  44. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_gpu/mod.rs +0 -0
  45. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_v2.rs +0 -0
  46. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/lib.rs +0 -0
  47. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/quantum_execution.rs +0 -0
  48. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/sparse.rs +0 -0
  49. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/sparse_v2.rs +0 -0
  50. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.git +0 -0
  51. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.gitignore +0 -0
  52. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.gitlab-ci.yml +0 -0
  53. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.pre-commit-config.yaml +0 -0
  54. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/CHANGELOG.md +0 -0
  55. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/Cargo.toml +0 -0
  56. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/LICENSE +0 -0
  57. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/LICENSES/Apache-2.0.txt +0 -0
  58. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/README.md +0 -0
  59. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/REUSE.toml +0 -0
  60. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/build.rs +0 -0
  61. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/cbindgen.toml +0 -0
  62. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/examples/grover.rs +0 -0
  63. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/examples/qft.rs +0 -0
  64. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/libket.h +0 -0
  65. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/block.rs +0 -0
  66. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/execute.rs +0 -0
  67. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/mod.rs +0 -0
  68. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/process.rs +0 -0
  69. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/mod.rs +0 -0
  70. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/network.rs +0 -0
  71. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/su2.rs +0 -0
  72. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/u2.rs +0 -0
  73. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/util.rs +0 -0
  74. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/c2to4x.rs +0 -0
  75. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/mod.rs +0 -0
  76. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/single_aux.rs +0 -0
  77. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/v_chain.rs +0 -0
  78. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/error.rs +0 -0
  79. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/execution.rs +0 -0
  80. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/block.rs +0 -0
  81. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/gate.rs +0 -0
  82. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/hamiltonian.rs +0 -0
  83. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/mod.rs +0 -0
  84. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/lib.rs +0 -0
  85. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/allocation.rs +0 -0
  86. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/dynamic_look_ahead.rs +0 -0
  87. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/graph.rs +0 -0
  88. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/mod.rs +0 -0
  89. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/matrix.rs +0 -0
  90. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/classical_shadow.rs +0 -0
  91. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/mod.rs +0 -0
  92. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/qwc.rs +0 -0
  93. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/ast.rs +0 -0
  94. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/executor.rs +0 -0
  95. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/gates.rs +0 -0
  96. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/mod.rs +0 -0
  97. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/openqasm.lalrpop +0 -0
  98. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/tests.rs +0 -0
  99. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/wrapper.py +0 -0
  100. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/expv.py +0 -0
  101. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/fermion.py +0 -0
  102. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/gates.py +0 -0
  103. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/ibm.py +0 -0
  104. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/measurement.py +0 -0
  105. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/mps.py +0 -0
  106. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/npsim.py +0 -0
  107. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/operations.py +0 -0
  108. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/quantumstate.py +0 -0
  109. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/gates.py +0 -0
  110. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/ham.py +0 -0
  111. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/oracle.py +0 -0
  112. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/prepare.py +0 -0
  113. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/dependency_links.txt +0 -0
  114. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/not-zip-safe +0 -0
  115. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/requires.txt +0 -0
  116. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/top_level.txt +0 -0
  117. {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/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.2.dev2
3
+ Version: 0.10.2.dev3
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.2.dev2"
86
+ __version__ = "0.10.2.dev3"
87
87
 
88
88
  __all__ = (
89
89
  all_base
@@ -18,23 +18,21 @@ from __future__ import annotations
18
18
 
19
19
  from collections import defaultdict
20
20
  from contextlib import contextmanager
21
- from ctypes import c_void_p, c_size_t
22
- from functools import partial
23
- from os import PathLike
21
+ from ctypes import c_void_p
24
22
  import json
25
- from typing import Literal, Optional, Any
26
- import weakref
23
+ from typing import Literal, Optional
27
24
 
28
- from .clib.libket import (
25
+ from ..clib.libket import (
29
26
  Block,
30
27
  HasProcess,
31
28
  Process as LibketProcess,
32
29
  API as libket,
33
30
  )
34
31
 
35
- from .clib.libket.execution import LiveExecution, BatchExecution
36
-
37
- from .clib.kbw import get_simulator
32
+ from ..clib.libket.execution import LiveExecution, BatchExecution
33
+ from ..clib.kbw import get_simulator
34
+ from .qasm import qasm
35
+ from .quant import Quant
38
36
 
39
37
  __all__ = ["Process", "Quant", "Parameter", "qasm"]
40
38
 
@@ -242,7 +240,7 @@ class Process(LibketProcess): # pylint: disable=too-many-instance-attributes
242
240
  qubits_index = [self._alloc() for _ in range(num_qubits)]
243
241
  return Quant(qubits=qubits_index, process=self)
244
242
 
245
- def alloc_aux(self, num_qubits: int = 1) -> Quant:
243
+ def alloc_aux(self, num_qubits: int = 1, depends_on: list | None = None) -> Quant:
246
244
  """Allocate auxiliary qubits managed by the process for uncomputation.
247
245
 
248
246
  Auxiliary (ancilla) qubits are temporary qubits used in intermediate
@@ -267,11 +265,15 @@ class Process(LibketProcess): # pylint: disable=too-many-instance-attributes
267
265
  Args:
268
266
  num_qubits: The number of auxiliary qubits to allocate.
269
267
  Defaults to 1.
268
+ depends_on: A list of objects (such as other :class:`~ket.Quant` instances)
269
+ that the allocated auxiliary register depends on. This prevents early
270
+ uncomputation; for example, if ``b`` depends on ``a``, ``a`` cannot be
271
+ uncomputed before ``b``. Defaults to ``None``.
270
272
 
271
273
  Returns:
272
274
  A :class:`~ket.base.Quant` object containing
273
275
  the auxiliary qubits. It supports use as a context manager: on exit
274
- the qubits are returned to the qubit pool.
276
+ the qubits are returned to the pool.
275
277
 
276
278
  Raises:
277
279
  ValueError: If ``num_qubits`` is less than 1.
@@ -279,6 +281,9 @@ class Process(LibketProcess): # pylint: disable=too-many-instance-attributes
279
281
  if num_qubits < 1:
280
282
  raise ValueError("Cannot allocate less than 1 qubit")
281
283
 
284
+ if depends_on is not None:
285
+ depends_on = [q for q in depends_on if isinstance(q, Quant)]
286
+
282
287
  aux_index = [self._alloc() for _ in range(num_qubits)]
283
288
 
284
289
  self._aux.update(aux_index)
@@ -287,6 +292,7 @@ class Process(LibketProcess): # pylint: disable=too-many-instance-attributes
287
292
  qubits=aux_index,
288
293
  process=self,
289
294
  undo=lambda: self._free_aux(aux_index),
295
+ source=depends_on,
290
296
  )
291
297
 
292
298
  def _free_aux(self, qubits: list[int]):
@@ -488,268 +494,6 @@ class Process(LibketProcess): # pylint: disable=too-many-instance-attributes
488
494
  self.append_block(block)
489
495
 
490
496
 
491
- class Quant(HasProcess):
492
- """List of qubits.
493
-
494
- This class represents a list of qubit indices within a quantum process. Direct instantiation
495
- of this class is not recommended. Instead, it should be created by calling the
496
- :meth:`~ket.base.Process.alloc` method.
497
-
498
- A :class:`~ket.base.Quant` serves as a fundamental quantum object where quantum operations
499
- should be applied.
500
-
501
- Example:
502
-
503
- .. code-block:: python
504
-
505
- from ket import *
506
- # Create a quantum process
507
- p = Process()
508
- # Allocate 2 qubits
509
- q1 = p.alloc(2)
510
- # Apply a Hadamard gates on the first qubit of `q1`
511
- H(q1[0])
512
- # Allocate more 2 qubits
513
- q2 = p.alloc(2)
514
- # Concatenate two Quant objects
515
- result_quant = q1 + q2
516
- print(result_quant)
517
- # <Ket 'Quant' [0, 1, 2, 3] pid=0x...>
518
- # Use the fist qubit to control the application of
519
- # a Pauli X gate on the other qubits
520
- ctrl(result_quant[0], X)(result_quant[1:])
521
- # Select qubits at specific indexes
522
- selected_quant = result_quant.at([0, 1])
523
- print(selected_quant)
524
- # <Ket 'Quant' [0, 1] pid=0x...>
525
-
526
- Supported operations:
527
-
528
- - Addition (``+``): Concatenates two :class:`~ket.base.Quant` objects.
529
- The processes must be the same.
530
- - Indexing (``[index]``): Returns a new :class:`~ket.base.Quant` object with selected qubits
531
- based on the provided index.
532
- - Iteration (``for q in qubits``): Allows iterating over qubits in a :class:`~ket.base.Quant`
533
- object.
534
- - Reversal (``reversed(qubits)``): Returns a new :class:`~ket.base.Quant` object with reversed
535
- qubits.
536
- - Length (``len(qubits)``): Returns the number of qubits in the :class:`~ket.base.Quant` object.
537
-
538
- """
539
-
540
- def __init__(self, *, qubits: list[int], process: Process, undo=None, source=None):
541
- super().__init__(ket_process=process)
542
-
543
- self.qubits = qubits
544
- self._finalizer = weakref.finalize(self, undo) if undo is not None else None
545
- self.source = source
546
-
547
- def __add__(self, other: Quant) -> Quant:
548
- """Concatenate two :class:`~ket.base.Quant` objects into a single register.
549
-
550
- Creates a new :class:`~ket.base.Quant` whose qubit list is the ordered
551
- concatenation of ``self`` followed by ``other``. Both objects must belong
552
- to the same :class:`~ket.base.Process` and must not share any qubit indices.
553
-
554
- Example:
555
- .. code-block:: python
556
-
557
- from ket import Process
558
- p = Process()
559
- q1 = p.alloc(2)
560
- q2 = p.alloc(2)
561
- combined = q1 + q2
562
- print(len(combined))
563
- # 4
564
-
565
- Args:
566
- other: The qubit register to append.
567
-
568
- Returns:
569
- A new register containing all qubits from
570
- ``self`` followed by all qubits from ``other``.
571
-
572
- Raises:
573
- ValueError: If ``other`` belongs to a different process, or if the
574
- two registers share any qubit indices.
575
- """
576
- if not isinstance(other, Quant):
577
- return NotImplemented
578
- if self.ket_process is not other.ket_process:
579
- raise ValueError("Cannot concatenate qubits from different processes")
580
- if any(qubit in other.qubits for qubit in self.qubits):
581
- raise ValueError("Cannot concatenate qubits with overlapping indices")
582
- return Quant(
583
- qubits=self.qubits + other.qubits,
584
- process=self.ket_process,
585
- source=[self, other],
586
- )
587
-
588
- def at(self, index: list[int]) -> Quant:
589
- """Return a subset of qubits at specified indices.
590
-
591
- Create a new :class:`~ket.base.Quant` object with qubit references at the positions defined
592
- by the provided ``index`` list.
593
-
594
- Example:
595
-
596
- .. code-block:: python
597
-
598
- from ket import *
599
- # Create a quantum process
600
- p = Process()
601
- # Allocate 5 qubits
602
- q = p.alloc(5)
603
- # Select qubits at odd indices (1, 3)
604
- odd_qubits = q.at([1, 3])
605
-
606
- Args:
607
- index: List of indices specifying the positions of qubits to be included in the
608
- new :class:`~ket.base.Quant`.
609
-
610
- Returns:
611
- A new :class:`~ket.base.Quant` object containing the selected qubits.
612
- """
613
-
614
- return Quant(
615
- qubits=[self.qubits[i] for i in index],
616
- process=self.ket_process,
617
- source=self,
618
- )
619
-
620
- def __reversed__(self):
621
- return Quant(
622
- qubits=list(reversed(self.qubits)),
623
- process=self.ket_process,
624
- source=self,
625
- )
626
-
627
- def __getitem__(self, key):
628
- qubits = self.qubits.__getitem__(key)
629
- return Quant(
630
- qubits=qubits if isinstance(qubits, list) else [qubits],
631
- process=self.ket_process,
632
- source=self,
633
- )
634
-
635
- def __len__(self):
636
- return len(self.qubits)
637
-
638
- def __eq__(self, other: Any):
639
- if not isinstance(other, int):
640
- return NotImplemented
641
-
642
- from .operations import ( # pylint: disable=import-outside-toplevel,cyclic-import
643
- undo,
644
- _flip_to_control,
645
- )
646
-
647
- return undo(_flip_to_control(other), self)
648
-
649
- def __enter__(self):
650
- return self
651
-
652
- def __exit__(self, exc_type, exc_value, traceback):
653
- if self._finalizer is not None and self._finalizer.alive:
654
- self._finalizer()
655
-
656
- def as_int(self, number: int = 0):
657
- """Interpret and initialize this quantum register as a quantum integer.
658
-
659
- Wraps the register as a :class:`~ket.qint.Qint`, enabling quantum
660
- arithmetic operations (addition, subtraction, comparison, etc.) on the
661
- underlying qubits. The register is initialized to the given classical
662
- integer value using :func:`~ket.gates.X` gates.
663
-
664
- The :class:`~ket.qint.Qint` uses a two's-complement signed representation
665
- internally.
666
-
667
- Example:
668
- .. code-block:: python
669
-
670
- from ket import Process, measure
671
- p = Process()
672
- q = p.alloc(5)
673
- qi = q.as_int(5) # register initialized to |5⟩
674
- qi += 3 # in-place addition: |5⟩ → |8⟩
675
- print(measure(qi).value)
676
- # 8
677
-
678
- Args:
679
- number: The initial classical integer value to encode into the
680
- quantum register. Defaults to ``0``.
681
-
682
- Returns:
683
- A quantum integer wrapping this register,
684
- initialized to ``number``.
685
- """
686
- from .qint import Qint # pylint: disable=import-outside-toplevel,cyclic-import
687
-
688
- return Qint(self, number)
689
-
690
- def as_real(self, exp: int, number: float = 0.0):
691
- r"""Interpret and initialize this quantum register as a fixed-point quantum real number.
692
-
693
- Wraps the register as a :class:`~ket.qint.Qreal`, enabling quantum
694
- arithmetic operations on floating-point values encoded in a fixed-point
695
- binary representation.
696
-
697
- The real number is stored internally as an integer scaled by
698
- :math:`2^{\texttt{exp}}`:
699
-
700
- - A **positive** ``exp`` increases fractional precision (smaller representable
701
- step size of :math:`2^{-\texttt{exp}}`).
702
- - A **negative** ``exp`` increases the representable magnitude at the cost of
703
- precision.
704
-
705
- Example:
706
- .. code-block:: python
707
-
708
- from ket import Process, measure
709
- p = Process()
710
- q = p.alloc(8) # 8 qubits for fixed-point
711
- qr = q.as_real(4, 1.5) # precision: 1/16, initialized to 1.5
712
- qr += 0.25 # in-place addition
713
- print(measure(qr).value)
714
- # 1.75
715
-
716
- Args:
717
- exp: The exponent defining the fixed-point scale. The stored
718
- integer ``n`` represents the real value ``n / 2**exp``.
719
- number: The initial classical float value to encode into the
720
- quantum register. Defaults to ``0.0``.
721
-
722
- Returns:
723
- A quantum real number wrapping this register,
724
- initialized to ``number``.
725
- """
726
- from .qint import Qreal # pylint: disable=import-outside-toplevel,cyclic-import
727
-
728
- return Qreal(self, exp, number)
729
-
730
- def dump_format(self):
731
- """Return the state-formatting callable used by :func:`~ket.operations.dump`.
732
-
733
- Provides a function that converts a raw integer basis-state index into a
734
- zero-padded binary string of the correct width for this register. This is
735
- used internally by :class:`~ket.quantumstate.QuantumState` to display
736
- multi-register states with per-register labels.
737
-
738
- Returns:
739
- A function that accepts an integer basis-state
740
- value and returns its binary string representation (zero-padded to
741
- ``len(self)`` bits).
742
- """
743
-
744
- def dump_format(size, state):
745
- return f"{state:0{size}b}"
746
-
747
- return partial(dump_format, len(self))
748
-
749
- def __repr__(self):
750
- return f"<Ket 'Quant' {self.qubits} pid={hex(id(self.ket_process))}>"
751
-
752
-
753
497
  class Parameter(HasProcess):
754
498
  """A differentiable scalar parameter for variational quantum circuits.
755
499
 
@@ -878,90 +622,3 @@ class Parameter(HasProcess):
878
622
  self._gradient = grads[self._index]
879
623
  libket["ket_string_delete"](result_ptr)
880
624
  return self._gradient
881
-
882
-
883
- def qasm(
884
- qubits: Quant,
885
- source: str | None = None,
886
- path: PathLike | None = None,
887
- ) -> Quant:
888
- """Apply an OpenQASM 2.0 circuit to a qubit register.
889
-
890
- Parses the supplied OpenQASM 2.0 program and appends the resulting gate
891
- sequence to the current quantum process. The qubit register ``qubits``
892
- is mapped, in order, to the first ``qreg`` declared inside the QASM
893
- program. Exactly one of ``source`` or ``path`` must be provided.
894
-
895
- Example:
896
-
897
- .. code-block:: python
898
-
899
- from ket import *
900
-
901
- p = Process()
902
- q = p.alloc(2)
903
-
904
- bell_qasm = \"\"\"
905
- OPENQASM 2.0;
906
- include "qelib1.inc";
907
- qreg q[2];
908
- h q[0];
909
- cx q[0],q[1];
910
- \"\"\"
911
-
912
- qasm(q, source=bell_qasm)
913
- print(dump(q).show())
914
-
915
- A file path can be used instead:
916
-
917
- .. code-block:: python
918
-
919
- qasm(q, path="bell.qasm")
920
-
921
- Args:
922
- qubits: The qubit register to apply the circuit to. Its length must
923
- match the size of the first ``qreg`` declared in the QASM program.
924
- source: A string containing the OpenQASM 2.0 source code.
925
- Mutually exclusive with ``path``.
926
- path: Path to a ``.qasm`` file containing the OpenQASM 2.0 source
927
- code. Mutually exclusive with ``source``.
928
-
929
- Returns:
930
- The input ``qubits`` register, unchanged, so that the call can be
931
- chained with other gate functions.
932
-
933
- Raises:
934
- TypeError: If ``qubits`` is not a :class:`~ket.base.Quant` instance.
935
- ValueError: If neither or both of ``source`` and ``path`` are given.
936
- FileNotFoundError: If ``path`` is provided but the file does not exist.
937
- OSError: If the file at ``path`` cannot be opened or read.
938
- """
939
- if not isinstance(qubits, Quant):
940
- raise TypeError(
941
- f"'qubits' must be a Quant instance, got {type(qubits).__name__!r}"
942
- )
943
-
944
- if source is None and path is None:
945
- raise ValueError(
946
- "one of 'source' or 'path' must be provided, but neither was given"
947
- )
948
-
949
- if source is not None and path is not None:
950
- raise ValueError(
951
- "only one of 'source' or 'path' may be provided, but both were given"
952
- )
953
-
954
- if source is not None:
955
- encoded = source.encode("utf-8")
956
- else:
957
- with open(path, "rb") as file:
958
- encoded = file.read()
959
-
960
- process = qubits.ket_process
961
- qubit_array = (c_size_t * len(qubits))(*qubits.qubits)
962
- block = Block(
963
- process,
964
- libket["ket_parse_openqasm"](qubit_array, len(qubits), encoded),
965
- )
966
- process.append_block(block)
967
- return qubits
@@ -0,0 +1,101 @@
1
+ # SPDX-FileCopyrightText: 2026 Evandro Chagas Ribeiro da Rosa <evandro@quantuloop.com>
2
+ #
3
+ # SPDX-License-Identifier: Apache-2.0
4
+
5
+ """OpenQASM 2.0 integration for Ket.
6
+
7
+ This module provides the :func:`~ket.base.qasm.qasm` function, which allows
8
+ applying OpenQASM 2.0 circuits directly to quantum registers in a Ket process.
9
+ """
10
+
11
+ from ctypes import c_size_t
12
+ from os import PathLike
13
+ from .quant import Quant
14
+ from ..clib.libket import Block, API as libket
15
+
16
+
17
+ def qasm(
18
+ qubits: Quant,
19
+ source: str | None = None,
20
+ path: PathLike | None = None,
21
+ ) -> Quant:
22
+ """Apply an OpenQASM 2.0 circuit to a qubit register.
23
+
24
+ Parses the supplied OpenQASM 2.0 program and appends the resulting gate
25
+ sequence to the current quantum process. The qubit register ``qubits``
26
+ is mapped, in order, to the first ``qreg`` declared inside the QASM
27
+ program. Exactly one of ``source`` or ``path`` must be provided.
28
+
29
+ Example:
30
+
31
+ .. code-block:: python
32
+
33
+ from ket import *
34
+
35
+ p = Process()
36
+ q = p.alloc(2)
37
+
38
+ bell_qasm = \"\"\"
39
+ OPENQASM 2.0;
40
+ include "qelib1.inc";
41
+ qreg q[2];
42
+ h q[0];
43
+ cx q[0],q[1];
44
+ \"\"\"
45
+
46
+ qasm(q, source=bell_qasm)
47
+ print(dump(q).show())
48
+
49
+ A file path can be used instead:
50
+
51
+ .. code-block:: python
52
+
53
+ qasm(q, path="bell.qasm")
54
+
55
+ Args:
56
+ qubits: The qubit register to apply the circuit to. Its length must
57
+ match the size of the first ``qreg`` declared in the QASM program.
58
+ source: A string containing the OpenQASM 2.0 source code.
59
+ Mutually exclusive with ``path``.
60
+ path: Path to a ``.qasm`` file containing the OpenQASM 2.0 source
61
+ code. Mutually exclusive with ``source``.
62
+
63
+ Returns:
64
+ The input ``qubits`` register, unchanged, so that the call can be
65
+ chained with other gate functions.
66
+
67
+ Raises:
68
+ TypeError: If ``qubits`` is not a :class:`~ket.base.Quant` instance.
69
+ ValueError: If neither or both of ``source`` and ``path`` are given.
70
+ FileNotFoundError: If ``path`` is provided but the file does not exist.
71
+ OSError: If the file at ``path`` cannot be opened or read.
72
+ """
73
+ if not isinstance(qubits, Quant):
74
+ raise TypeError(
75
+ f"'qubits' must be a Quant instance, got {type(qubits).__name__!r}"
76
+ )
77
+
78
+ if source is None and path is None:
79
+ raise ValueError(
80
+ "one of 'source' or 'path' must be provided, but neither was given"
81
+ )
82
+
83
+ if source is not None and path is not None:
84
+ raise ValueError(
85
+ "only one of 'source' or 'path' may be provided, but both were given"
86
+ )
87
+
88
+ if source is not None:
89
+ encoded = source.encode("utf-8")
90
+ else:
91
+ with open(path, "rb") as file:
92
+ encoded = file.read()
93
+
94
+ process = qubits.ket_process
95
+ qubit_array = (c_size_t * len(qubits))(*qubits.qubits)
96
+ block = Block(
97
+ process,
98
+ libket["ket_parse_openqasm"](qubit_array, len(qubits), encoded),
99
+ )
100
+ process.append_block(block)
101
+ return qubits