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.
- {ket_lang-0.10.2.dev2/src/ket_lang.egg-info → ket_lang-0.10.2.dev3}/PKG-INFO +1 -1
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/__init__.py +1 -1
- ket_lang-0.10.2.dev2/src/ket/base.py → ket_lang-0.10.2.dev3/src/ket/base/__init__.py +17 -360
- ket_lang-0.10.2.dev3/src/ket/base/qasm.py +101 -0
- ket_lang-0.10.2.dev3/src/ket/base/quant.py +331 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qint.py +11 -28
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/__init__.py +80 -3
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3/src/ket_lang.egg-info}/PKG-INFO +1 -1
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/SOURCES.txt +3 -1
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/LICENSE +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/MANIFEST.in +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/README.md +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/pyproject.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/setup.cfg +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/setup.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/amazon.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/__init__.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/kbw.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libket/__init__.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libket/execution.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/__init__.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.git +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.gitignore +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.gitlab-ci.yml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/.pre-commit-config.yaml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/CHANGELOG.md +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/Cargo.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/LICENSE +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/LICENSES/Apache-2.0.txt +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/README.md +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/REUSE.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/build.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/cbindgen.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_batch.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_live.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/examples/grover_live_dv2.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/kbw.h +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/bitwise.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/block.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/c_api.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/convert.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_gpu/kernel.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_gpu/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/dense_v2.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/lib.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/quantum_execution.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/sparse.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/kbw/src/sparse_v2.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.git +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.gitignore +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.gitlab-ci.yml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/.pre-commit-config.yaml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/CHANGELOG.md +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/Cargo.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/LICENSE +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/LICENSES/Apache-2.0.txt +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/README.md +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/REUSE.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/build.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/cbindgen.toml +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/examples/grover.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/examples/qft.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/libket.h +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/block.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/execute.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/c_api/process.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/network.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/su2.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/u2.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/util.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/c2to4x.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/decompose/x/mod.rs +0 -0
- {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
- {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
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/error.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/execution.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/block.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/gate.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/hamiltonian.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/ir/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/lib.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/allocation.rs +0 -0
- {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
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/graph.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/mapping/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/matrix.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/classical_shadow.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/process/qwc.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/ast.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/executor.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/gates.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/mod.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/qasm/openqasm.lalrpop +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/libs/libket/src/tests.rs +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/clib/wrapper.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/expv.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/fermion.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/gates.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/ibm.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/measurement.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/mps.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/npsim.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/operations.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/quantumstate.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/gates.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/ham.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/oracle.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket/qulib/prepare.py +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/dependency_links.txt +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/not-zip-safe +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/requires.txt +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/src/ket_lang.egg-info/top_level.txt +0 -0
- {ket_lang-0.10.2.dev2 → ket_lang-0.10.2.dev3}/tests/test_fermion.py +0 -0
|
@@ -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
|
|
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
|
|
26
|
-
import weakref
|
|
23
|
+
from typing import Literal, Optional
|
|
27
24
|
|
|
28
|
-
from
|
|
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
|
|
36
|
-
|
|
37
|
-
from .
|
|
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
|
|
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
|