ket-lang 0.10.4.2.dev1__tar.gz → 0.10.4.3.dev0__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.4.2.dev1/src/ket_lang.egg-info → ket_lang-0.10.4.3.dev0}/PKG-INFO +1 -1
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/__init__.py +1 -1
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/expv.py +258 -25
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/gates.py +44 -4
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/operations.py +17 -2
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qulib/__init__.py +4 -2
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0/src/ket_lang.egg-info}/PKG-INFO +1 -1
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/LICENSE +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/MANIFEST.in +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/README.md +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/pyproject.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/setup.cfg +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/setup.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/amazon.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/base/__init__.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/base/qasm.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/base/quant.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/__init__.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/kbw.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libket/__init__.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libket/execution.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/__init__.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/.git +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/.gitignore +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/.gitlab-ci.yml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/.pre-commit-config.yaml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/CHANGELOG.md +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/Cargo.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/LICENSE +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/LICENSES/Apache-2.0.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/README.md +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/REUSE.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/build.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/cbindgen.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_batch.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_live.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_live_dv2.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/kbw.h +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/bitwise.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/block.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/c_api.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/convert.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense_gpu/kernel.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense_gpu/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense_v2.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/lib.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/quantum_execution.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/sparse.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/sparse_v2.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/.git +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/.gitignore +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/.gitlab-ci.yml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/.pre-commit-config.yaml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/CHANGELOG.md +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/Cargo.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/LICENSE +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/LICENSES/Apache-2.0.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/README.md +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/REUSE.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/build.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/cbindgen.toml +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/examples/grover.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/examples/qft.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/libket.h +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/block.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/execute.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/process.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/network.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/su2.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/u2.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/util.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/c2to4x.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/single_aux.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/v_chain.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/error.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/execution.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/block.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/gate.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/hamiltonian.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/macros.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/lib.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/allocation.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/dynamic_look_ahead.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/graph.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/matrix.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/process/classical_shadow.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/process/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/process/qwc.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/ast.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/executor.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/gates.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/mod.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/openqasm.lalrpop +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/tests.rs +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/wrapper.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/fermion.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/gateset.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/ibm.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/measurement.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/mps.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/npsim.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qint.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/quantumstate.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qulib/gates.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qulib/ham.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qulib/oracle.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/qulib/prepare.py +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/SOURCES.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/dependency_links.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/not-zip-safe +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/requires.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/top_level.txt +0 -0
- {ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/tests/test_fermion.py +0 -0
|
@@ -22,7 +22,25 @@ Example:
|
|
|
22
22
|
# Heisenberg XX + YY + ZZ Hamiltonian
|
|
23
23
|
h = X(q[0])*X(q[1]) + Y(q[0])*Y(q[1]) + Z(q[0])*Z(q[1])
|
|
24
24
|
ev = exp_value(h)
|
|
25
|
-
print(ev.get()) #
|
|
25
|
+
print(ev.get()) # 1.0 for the Bell state |Φ+⟩
|
|
26
|
+
|
|
27
|
+
Hamiltonians can also be built without a process. ``with obs(n) as q:``
|
|
28
|
+
yields ``n`` placeholder qubits (:class:`~ket.expv.ObsQubits`). The result is
|
|
29
|
+
an *unbound* Hamiltonian that you bind to real qubits later, either with
|
|
30
|
+
:meth:`~ket.expv.Hamiltonian.bind` (or the call shorthand ``h(qubits)``) or by
|
|
31
|
+
passing the qubits to :func:`~ket.operations.exp_value` or
|
|
32
|
+
:func:`~ket.gates.evolve`:
|
|
33
|
+
|
|
34
|
+
.. code-block:: python
|
|
35
|
+
|
|
36
|
+
from ket import *
|
|
37
|
+
with obs(2) as q:
|
|
38
|
+
h = X(q[0])*X(q[1]) + Y(q[0])*Y(q[1]) + Z(q[0])*Z(q[1])
|
|
39
|
+
|
|
40
|
+
p = Process()
|
|
41
|
+
r = p.alloc(2)
|
|
42
|
+
CNOT(H(r[0]), r[1])
|
|
43
|
+
print(exp_value(h, r).get()) # same as exp_value(h(r))
|
|
26
44
|
"""
|
|
27
45
|
|
|
28
46
|
from __future__ import annotations
|
|
@@ -34,6 +52,7 @@ from __future__ import annotations
|
|
|
34
52
|
|
|
35
53
|
# pylint: disable=duplicate-code,protected-access
|
|
36
54
|
import json
|
|
55
|
+
import operator
|
|
37
56
|
from numbers import Number
|
|
38
57
|
from itertools import product
|
|
39
58
|
from functools import reduce
|
|
@@ -44,6 +63,7 @@ from .base import Parameter, Process, Quant
|
|
|
44
63
|
from .clib.libket import HasProcess
|
|
45
64
|
|
|
46
65
|
__all__ = [
|
|
66
|
+
"ObsQubits",
|
|
47
67
|
"Pauli",
|
|
48
68
|
"Hamiltonian",
|
|
49
69
|
"commutator",
|
|
@@ -51,6 +71,95 @@ __all__ = [
|
|
|
51
71
|
]
|
|
52
72
|
|
|
53
73
|
|
|
74
|
+
class ObsQubits:
|
|
75
|
+
"""Placeholder qubits for building Hamiltonians without a process.
|
|
76
|
+
|
|
77
|
+
Placeholder qubits are numbered ``0`` to ``n - 1``. A Hamiltonian built on
|
|
78
|
+
them is *unbound*: it supports all the usual algebra, but it must be bound
|
|
79
|
+
to qubits from a :class:`~ket.base.Process` before computing an
|
|
80
|
+
expectation value or evolving a state. Binding maps placeholder ``i`` to
|
|
81
|
+
the ``i``-th qubit of the given register.
|
|
82
|
+
|
|
83
|
+
.. note::
|
|
84
|
+
You usually get these from ``with obs(n) as q:`` rather than by
|
|
85
|
+
instantiating this class directly.
|
|
86
|
+
|
|
87
|
+
Example:
|
|
88
|
+
|
|
89
|
+
.. code-block:: python
|
|
90
|
+
|
|
91
|
+
from ket import *
|
|
92
|
+
with obs(3) as q:
|
|
93
|
+
h = sum(Z(q[i]) * Z(q[i + 1]) for i in range(2))
|
|
94
|
+
|
|
95
|
+
p = Process()
|
|
96
|
+
r = p.alloc(3)
|
|
97
|
+
ev = exp_value(h, r)
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
num_qubits: Number of placeholder qubits.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def __init__(self, num_qubits: int = 0, *, _qubits: list[int] | None = None):
|
|
104
|
+
self.qubits = list(range(num_qubits)) if _qubits is None else _qubits
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def ket_process(self) -> None:
|
|
108
|
+
"""Always ``None``: placeholder qubits do not belong to a process."""
|
|
109
|
+
return None
|
|
110
|
+
|
|
111
|
+
def __getitem__(self, key) -> ObsQubits:
|
|
112
|
+
qubits = self.qubits.__getitem__(key)
|
|
113
|
+
return ObsQubits(_qubits=qubits if isinstance(qubits, list) else [qubits])
|
|
114
|
+
|
|
115
|
+
def __iter__(self):
|
|
116
|
+
for qubit in self.qubits:
|
|
117
|
+
yield ObsQubits(_qubits=[qubit])
|
|
118
|
+
|
|
119
|
+
def __reversed__(self) -> ObsQubits:
|
|
120
|
+
return ObsQubits(_qubits=list(reversed(self.qubits)))
|
|
121
|
+
|
|
122
|
+
def __len__(self) -> int:
|
|
123
|
+
return len(self.qubits)
|
|
124
|
+
|
|
125
|
+
def __add__(self, other: ObsQubits) -> ObsQubits:
|
|
126
|
+
if not isinstance(other, ObsQubits):
|
|
127
|
+
return NotImplemented
|
|
128
|
+
if any(qubit in other.qubits for qubit in self.qubits):
|
|
129
|
+
raise ValueError("Cannot concatenate qubits with overlapping indices")
|
|
130
|
+
return ObsQubits(_qubits=self.qubits + other.qubits)
|
|
131
|
+
|
|
132
|
+
def at(self, index: list[int]) -> ObsQubits:
|
|
133
|
+
"""Return the placeholder qubits at the given positions."""
|
|
134
|
+
return ObsQubits(_qubits=[self.qubits[i] for i in index])
|
|
135
|
+
|
|
136
|
+
def __repr__(self) -> str:
|
|
137
|
+
return f"<Ket 'ObsQubits' {self.qubits}>"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def _check_same_process(lhs: HasProcess, rhs: HasProcess):
|
|
141
|
+
if lhs.ket_process is rhs.ket_process:
|
|
142
|
+
return
|
|
143
|
+
if lhs.ket_process is None or rhs.ket_process is None:
|
|
144
|
+
raise ValueError(
|
|
145
|
+
"Cannot combine bound and unbound operators; "
|
|
146
|
+
"bind the unbound one to qubits first"
|
|
147
|
+
)
|
|
148
|
+
raise ValueError("different Ket processes")
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _as_quant(qubits) -> Quant:
|
|
152
|
+
if not isinstance(qubits, Quant):
|
|
153
|
+
qubits = reduce(operator.add, qubits)
|
|
154
|
+
if not isinstance(qubits, Quant):
|
|
155
|
+
raise TypeError("Can only bind to qubits allocated from a Process")
|
|
156
|
+
return qubits
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _pid(process) -> str:
|
|
160
|
+
return "unbound" if process is None else f"pid={hex(id(process))}"
|
|
161
|
+
|
|
162
|
+
|
|
54
163
|
class Pauli(HasProcess):
|
|
55
164
|
"""Pauli operator for Hamiltonian creation.
|
|
56
165
|
|
|
@@ -66,7 +175,9 @@ class Pauli(HasProcess):
|
|
|
66
175
|
|
|
67
176
|
Args:
|
|
68
177
|
pauli: Pauli operator type.
|
|
69
|
-
qubits: Qubits to apply the Pauli operator to.
|
|
178
|
+
qubits: Qubits to apply the Pauli operator to. Either qubits from a
|
|
179
|
+
:class:`~ket.base.Process` or placeholder :class:`~ket.expv.ObsQubits`;
|
|
180
|
+
the latter creates an unbound operator (see :meth:`bind`).
|
|
70
181
|
process: *For internal usage*. Quantum process, default is the process of the given qubits.
|
|
71
182
|
pauli_list: *For internal usage*. List of Pauli operators.
|
|
72
183
|
qubits_list: *For internal usage*. List of Qubit.
|
|
@@ -77,24 +188,23 @@ class Pauli(HasProcess):
|
|
|
77
188
|
def __init__( # pylint: disable=too-many-arguments
|
|
78
189
|
self,
|
|
79
190
|
pauli: Literal["X", "Y", "Z", "I"] | None,
|
|
80
|
-
qubits: Quant | None,
|
|
191
|
+
qubits: Quant | ObsQubits | None,
|
|
81
192
|
*,
|
|
82
193
|
_process: Process | None = None,
|
|
83
194
|
_map: dict[int, str] | None = None,
|
|
84
195
|
_coef: float | complex | None = None,
|
|
85
196
|
):
|
|
86
|
-
if qubits is not None and not isinstance(qubits, Quant):
|
|
87
|
-
qubits = reduce(
|
|
197
|
+
if qubits is not None and not isinstance(qubits, (Quant, ObsQubits)):
|
|
198
|
+
qubits = reduce(operator.add, qubits)
|
|
88
199
|
|
|
89
200
|
if pauli is not None and qubits is not None:
|
|
90
201
|
super().__init__(ket_process=qubits.ket_process)
|
|
91
202
|
self.map = {q: pauli for q in qubits.qubits}
|
|
92
203
|
self.coef = 1.0
|
|
93
204
|
else:
|
|
94
|
-
assert
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
205
|
+
assert (
|
|
206
|
+
_map is not None and _coef is not None
|
|
207
|
+
), "If pauli and qubits are not provided, map and coef must be provided."
|
|
98
208
|
super().__init__(ket_process=_process)
|
|
99
209
|
self.map = _map
|
|
100
210
|
self.coef = _coef
|
|
@@ -118,8 +228,7 @@ class Pauli(HasProcess):
|
|
|
118
228
|
if isinstance(other, Hamiltonian):
|
|
119
229
|
return other.__mul__(self)
|
|
120
230
|
|
|
121
|
-
|
|
122
|
-
raise ValueError("different Ket processes")
|
|
231
|
+
_check_same_process(self, other)
|
|
123
232
|
|
|
124
233
|
if not set(self.map.keys()).isdisjoint(other.map.keys()):
|
|
125
234
|
raise ValueError("Pauli operators act on the same qubits")
|
|
@@ -138,8 +247,7 @@ class Pauli(HasProcess):
|
|
|
138
247
|
if isinstance(rhs, Hamiltonian):
|
|
139
248
|
return Hamiltonian([self], self.ket_process) @ rhs
|
|
140
249
|
|
|
141
|
-
|
|
142
|
-
raise ValueError("different Ket processes")
|
|
250
|
+
_check_same_process(self, rhs)
|
|
143
251
|
|
|
144
252
|
qubits = {*self.map.keys(), *rhs.map.keys()}
|
|
145
253
|
result_map = {}
|
|
@@ -195,8 +303,7 @@ class Pauli(HasProcess):
|
|
|
195
303
|
if isinstance(other, Number):
|
|
196
304
|
other = Pauli(None, None, _process=self.ket_process, _map={}, _coef=other)
|
|
197
305
|
|
|
198
|
-
|
|
199
|
-
raise ValueError("different Ket processes")
|
|
306
|
+
_check_same_process(self, other)
|
|
200
307
|
|
|
201
308
|
if isinstance(other, Hamiltonian):
|
|
202
309
|
result = Hamiltonian([self], process=self.ket_process) + other
|
|
@@ -217,8 +324,57 @@ class Pauli(HasProcess):
|
|
|
217
324
|
def __truediv__(self, other: float) -> Pauli:
|
|
218
325
|
return self.__mul__(1.0 / other)
|
|
219
326
|
|
|
327
|
+
@property
|
|
328
|
+
def is_bound(self) -> bool:
|
|
329
|
+
"""``True`` if the operator acts on qubits from a process."""
|
|
330
|
+
return self.ket_process is not None
|
|
331
|
+
|
|
332
|
+
@property
|
|
333
|
+
def num_qubits(self) -> int:
|
|
334
|
+
"""Number of qubits needed to bind the operator.
|
|
335
|
+
|
|
336
|
+
For an unbound operator this is the highest placeholder index plus
|
|
337
|
+
one. For a bound operator it is the number of qubits it acts on.
|
|
338
|
+
"""
|
|
339
|
+
if self.is_bound:
|
|
340
|
+
return len(self.map)
|
|
341
|
+
return max(self.map, default=-1) + 1
|
|
342
|
+
|
|
343
|
+
def bind(self, qubits: Quant) -> Pauli:
|
|
344
|
+
"""Bind an unbound operator to qubits from a process.
|
|
345
|
+
|
|
346
|
+
Placeholder qubit ``i`` becomes ``qubits[i]``. Calling the operator,
|
|
347
|
+
``pauli(qubits)``, is a shorthand for this method.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
qubits: Qubits allocated from a :class:`~ket.base.Process`. Must
|
|
351
|
+
have at least :attr:`num_qubits` qubits.
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
A new operator bound to the process of ``qubits``.
|
|
355
|
+
|
|
356
|
+
Raises:
|
|
357
|
+
ValueError: If the operator is already bound or ``qubits`` is too short.
|
|
358
|
+
"""
|
|
359
|
+
if self.is_bound:
|
|
360
|
+
raise ValueError("Operator is already bound to a process")
|
|
361
|
+
qubits = _as_quant(qubits)
|
|
362
|
+
if len(qubits) < self.num_qubits:
|
|
363
|
+
raise ValueError(
|
|
364
|
+
f"Operator needs {self.num_qubits} qubits, but got {len(qubits)}"
|
|
365
|
+
)
|
|
366
|
+
return Pauli(
|
|
367
|
+
None,
|
|
368
|
+
None,
|
|
369
|
+
_process=qubits.ket_process,
|
|
370
|
+
_map={qubits.qubits[i]: p for i, p in self.map.items()},
|
|
371
|
+
_coef=self.coef,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
__call__ = bind
|
|
375
|
+
|
|
220
376
|
@staticmethod
|
|
221
|
-
def x(qubits: Quant) -> Pauli:
|
|
377
|
+
def x(qubits: Quant | ObsQubits) -> Pauli:
|
|
222
378
|
"""Pauli X operator.
|
|
223
379
|
|
|
224
380
|
Args:
|
|
@@ -227,7 +383,7 @@ class Pauli(HasProcess):
|
|
|
227
383
|
return Pauli("X", qubits)
|
|
228
384
|
|
|
229
385
|
@staticmethod
|
|
230
|
-
def y(qubits: Quant) -> Pauli:
|
|
386
|
+
def y(qubits: Quant | ObsQubits) -> Pauli:
|
|
231
387
|
"""Pauli Y operator.
|
|
232
388
|
|
|
233
389
|
Args:
|
|
@@ -236,7 +392,7 @@ class Pauli(HasProcess):
|
|
|
236
392
|
return Pauli("Y", qubits)
|
|
237
393
|
|
|
238
394
|
@staticmethod
|
|
239
|
-
def z(qubits: Quant) -> Pauli:
|
|
395
|
+
def z(qubits: Quant | ObsQubits) -> Pauli:
|
|
240
396
|
"""Pauli Z operator.
|
|
241
397
|
|
|
242
398
|
Args:
|
|
@@ -245,7 +401,7 @@ class Pauli(HasProcess):
|
|
|
245
401
|
return Pauli("Z", qubits)
|
|
246
402
|
|
|
247
403
|
@staticmethod
|
|
248
|
-
def i(qubits: Quant) -> Pauli:
|
|
404
|
+
def i(qubits: Quant | ObsQubits) -> Pauli:
|
|
249
405
|
"""Pauli I operator.
|
|
250
406
|
|
|
251
407
|
Args:
|
|
@@ -263,7 +419,7 @@ class Pauli(HasProcess):
|
|
|
263
419
|
return f"{self.coef}" + ("*" + self._str_no_coef() if len(self.map) > 0 else "")
|
|
264
420
|
|
|
265
421
|
def __repr__(self) -> str:
|
|
266
|
-
return f"<Ket 'Pauli' {str(self)},
|
|
422
|
+
return f"<Ket 'Pauli' {str(self)}, {_pid(self.ket_process)}>"
|
|
267
423
|
|
|
268
424
|
def _repr_latex_no_math_(self) -> str: # pylint: disable=too-many-branches
|
|
269
425
|
coef = self.coef
|
|
@@ -352,6 +508,20 @@ class Hamiltonian(HasProcess):
|
|
|
352
508
|
xx = sum(-h * X(q[i]) for i in range(3))
|
|
353
509
|
H = zz + xx
|
|
354
510
|
|
|
511
|
+
To build a Hamiltonian before allocating qubits, use ``with obs(n) as q:``.
|
|
512
|
+
The result is *unbound*; bind it with :meth:`bind`, the call shorthand
|
|
513
|
+
``H(qubits)``, or by passing the qubits to
|
|
514
|
+
:func:`~ket.operations.exp_value` or :func:`~ket.gates.evolve`:
|
|
515
|
+
|
|
516
|
+
.. code-block:: python
|
|
517
|
+
|
|
518
|
+
with obs(3) as q:
|
|
519
|
+
H = sum(-Z(q[i]) * Z(q[i+1]) for i in range(2))
|
|
520
|
+
|
|
521
|
+
p = Process()
|
|
522
|
+
r = p.alloc(3)
|
|
523
|
+
exp_value(H, r) # same as exp_value(H(r))
|
|
524
|
+
|
|
355
525
|
Supported arithmetic operators:
|
|
356
526
|
|
|
357
527
|
- **Addition** (``+``): Combine two Hamiltonians or add a scalar constant.
|
|
@@ -376,8 +546,7 @@ class Hamiltonian(HasProcess):
|
|
|
376
546
|
if isinstance(other, Pauli):
|
|
377
547
|
other = Hamiltonian([other], self.ket_process)
|
|
378
548
|
|
|
379
|
-
|
|
380
|
-
raise ValueError("different Ket processes")
|
|
549
|
+
_check_same_process(self, other)
|
|
381
550
|
|
|
382
551
|
result = Hamiltonian(self.terms + other.terms, self.ket_process)
|
|
383
552
|
result._filter()
|
|
@@ -390,13 +559,20 @@ class Hamiltonian(HasProcess):
|
|
|
390
559
|
__radd__ = __add__
|
|
391
560
|
|
|
392
561
|
def _filter(self):
|
|
562
|
+
# Merge like terms into copies, so the operands' terms are never modified.
|
|
393
563
|
new_terms = {}
|
|
394
564
|
for term in self.terms:
|
|
395
565
|
str_term = term._str_no_coef()
|
|
396
566
|
if all(c not in str_term for c in "XYZ"):
|
|
397
567
|
str_term = ""
|
|
398
568
|
if str_term not in new_terms:
|
|
399
|
-
new_terms[str_term] =
|
|
569
|
+
new_terms[str_term] = Pauli(
|
|
570
|
+
None,
|
|
571
|
+
None,
|
|
572
|
+
_process=term.ket_process,
|
|
573
|
+
_map=dict(term.map),
|
|
574
|
+
_coef=term.coef,
|
|
575
|
+
)
|
|
400
576
|
else:
|
|
401
577
|
new_terms[str_term].coef += term.coef
|
|
402
578
|
|
|
@@ -406,6 +582,8 @@ class Hamiltonian(HasProcess):
|
|
|
406
582
|
if isinstance(other, Pauli):
|
|
407
583
|
other = Hamiltonian([other], self.ket_process)
|
|
408
584
|
|
|
585
|
+
_check_same_process(self, other)
|
|
586
|
+
|
|
409
587
|
result = Hamiltonian(
|
|
410
588
|
[a @ b for a, b in product(self.terms, other.terms)],
|
|
411
589
|
self.ket_process,
|
|
@@ -427,6 +605,7 @@ class Hamiltonian(HasProcess):
|
|
|
427
605
|
)
|
|
428
606
|
|
|
429
607
|
if isinstance(other, Hamiltonian):
|
|
608
|
+
_check_same_process(self, other)
|
|
430
609
|
return Hamiltonian(
|
|
431
610
|
[p * q for p, q in product(self.terms, other.terms)],
|
|
432
611
|
process=self.ket_process,
|
|
@@ -461,10 +640,57 @@ class Hamiltonian(HasProcess):
|
|
|
461
640
|
def __len__(self) -> int:
|
|
462
641
|
return len(self.terms)
|
|
463
642
|
|
|
643
|
+
@property
|
|
644
|
+
def is_bound(self) -> bool:
|
|
645
|
+
"""``True`` if the Hamiltonian acts on qubits from a process."""
|
|
646
|
+
return self.ket_process is not None
|
|
647
|
+
|
|
648
|
+
@property
|
|
649
|
+
def num_qubits(self) -> int:
|
|
650
|
+
"""Number of qubits needed to bind the Hamiltonian.
|
|
651
|
+
|
|
652
|
+
For an unbound Hamiltonian this is the highest placeholder index plus
|
|
653
|
+
one. For a bound Hamiltonian it is the number of qubits it acts on.
|
|
654
|
+
"""
|
|
655
|
+
if self.is_bound:
|
|
656
|
+
return len({q for term in self.terms for q in term.map})
|
|
657
|
+
return max((term.num_qubits for term in self.terms), default=0)
|
|
658
|
+
|
|
659
|
+
def bind(self, qubits: Quant) -> Hamiltonian:
|
|
660
|
+
"""Bind an unbound Hamiltonian to qubits from a process.
|
|
661
|
+
|
|
662
|
+
Placeholder qubit ``i`` becomes ``qubits[i]``. Calling the Hamiltonian,
|
|
663
|
+
``h(qubits)``, is a shorthand for this method, so an unbound
|
|
664
|
+
Hamiltonian can be passed anywhere a ``Callable[[Quant], Hamiltonian]``
|
|
665
|
+
is expected.
|
|
666
|
+
|
|
667
|
+
Args:
|
|
668
|
+
qubits: Qubits allocated from a :class:`~ket.base.Process`. Must
|
|
669
|
+
have at least :attr:`num_qubits` qubits.
|
|
670
|
+
|
|
671
|
+
Returns:
|
|
672
|
+
A new Hamiltonian bound to the process of ``qubits``.
|
|
673
|
+
|
|
674
|
+
Raises:
|
|
675
|
+
ValueError: If the Hamiltonian is already bound or ``qubits`` is too short.
|
|
676
|
+
"""
|
|
677
|
+
if self.is_bound:
|
|
678
|
+
raise ValueError("Hamiltonian is already bound to a process")
|
|
679
|
+
qubits = _as_quant(qubits)
|
|
680
|
+
if len(qubits) < self.num_qubits:
|
|
681
|
+
raise ValueError(
|
|
682
|
+
f"Hamiltonian needs {self.num_qubits} qubits, but got {len(qubits)}"
|
|
683
|
+
)
|
|
684
|
+
return Hamiltonian(
|
|
685
|
+
[term.bind(qubits) for term in self.terms], qubits.ket_process
|
|
686
|
+
)
|
|
687
|
+
|
|
688
|
+
__call__ = bind
|
|
689
|
+
|
|
464
690
|
def __repr__(self) -> str:
|
|
465
691
|
return (
|
|
466
692
|
f"<Ket 'Hamiltonian' {' + '.join(str(p) for p in self.terms)}, "
|
|
467
|
-
f"
|
|
693
|
+
f"{_pid(self.ket_process)}>"
|
|
468
694
|
)
|
|
469
695
|
|
|
470
696
|
def _repr_latex_(self) -> str:
|
|
@@ -535,7 +761,14 @@ class ExpValue(HasProcess):
|
|
|
535
761
|
|
|
536
762
|
pauli_map = {"X": "PauliX", "Y": "PauliY", "Z": "PauliZ"}
|
|
537
763
|
|
|
538
|
-
def __init__(self, hamiltonian: Hamiltonian | Pauli):
|
|
764
|
+
def __init__(self, hamiltonian: Hamiltonian | Pauli, qubits: Quant | None = None):
|
|
765
|
+
if qubits is not None:
|
|
766
|
+
hamiltonian = hamiltonian.bind(qubits)
|
|
767
|
+
elif not hamiltonian.is_bound:
|
|
768
|
+
raise ValueError(
|
|
769
|
+
"Cannot compute the expectation value of an unbound Hamiltonian; "
|
|
770
|
+
"pass the qubits to exp_value or bind it first"
|
|
771
|
+
)
|
|
539
772
|
super().__init__(ket_process=hamiltonian.ket_process)
|
|
540
773
|
if isinstance(hamiltonian, Pauli):
|
|
541
774
|
hamiltonian = Hamiltonian([hamiltonian], process=hamiltonian.ket_process)
|
|
@@ -67,7 +67,7 @@ from ket.clib.libket import search_process, API as libket, Block
|
|
|
67
67
|
from .base import Process, Quant, Parameter
|
|
68
68
|
from .operations import ctrl, cat, kron, around
|
|
69
69
|
|
|
70
|
-
from .expv import Pauli, Hamiltonian
|
|
70
|
+
from .expv import Pauli, Hamiltonian, ObsQubits
|
|
71
71
|
|
|
72
72
|
__all__ = [
|
|
73
73
|
"I",
|
|
@@ -115,7 +115,7 @@ _build_obs = contextvars.ContextVar("build_obs", default=False)
|
|
|
115
115
|
|
|
116
116
|
|
|
117
117
|
@contextmanager
|
|
118
|
-
def obs():
|
|
118
|
+
def obs(num_qubits: int | None = None):
|
|
119
119
|
r"""Context manager for constructing quantum observables in symbolic form.
|
|
120
120
|
|
|
121
121
|
Inside a ``with obs():`` block, the Pauli gate functions
|
|
@@ -144,10 +144,34 @@ def obs():
|
|
|
144
144
|
h_c = -0.5 * sum(1 - Z(i) * Z(j) for i, j in edges)
|
|
145
145
|
|
|
146
146
|
ev = exp_value(h_c)
|
|
147
|
+
|
|
148
|
+
Pass ``num_qubits`` to build an observable before allocating any qubits.
|
|
149
|
+
The block then yields that many placeholder qubits
|
|
150
|
+
(:class:`~ket.expv.ObsQubits`) and the result is an *unbound*
|
|
151
|
+
Hamiltonian. Bind it to real qubits with
|
|
152
|
+
:meth:`~ket.expv.Hamiltonian.bind`, the call shorthand ``h_c(qubits)``,
|
|
153
|
+
or by passing the qubits to :func:`~ket.operations.exp_value` or
|
|
154
|
+
:func:`~ket.gates.evolve`:
|
|
155
|
+
|
|
156
|
+
.. code-block:: python
|
|
157
|
+
|
|
158
|
+
from ket import *
|
|
159
|
+
|
|
160
|
+
with obs(4) as q:
|
|
161
|
+
edges = [(q[0], q[1]), (q[1], q[2]), (q[2], q[3])]
|
|
162
|
+
h_c = -0.5 * sum(1 - Z(i) * Z(j) for i, j in edges)
|
|
163
|
+
|
|
164
|
+
p = Process()
|
|
165
|
+
r = p.alloc(4)
|
|
166
|
+
ev = exp_value(h_c, r) # same as exp_value(h_c(r))
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
num_qubits: Number of placeholder qubits to yield. If ``None``, the
|
|
170
|
+
block yields ``None`` and observables are built on process qubits.
|
|
147
171
|
"""
|
|
148
172
|
token = _build_obs.set(True)
|
|
149
173
|
try:
|
|
150
|
-
yield
|
|
174
|
+
yield None if num_qubits is None else ObsQubits(num_qubits)
|
|
151
175
|
finally:
|
|
152
176
|
_build_obs.reset(token)
|
|
153
177
|
|
|
@@ -863,7 +887,7 @@ def _rzg(angle, qubits):
|
|
|
863
887
|
_RGATE = {"X": RX, "Y": RY, "Z": RZ}
|
|
864
888
|
|
|
865
889
|
|
|
866
|
-
def evolve(hamiltonian: Hamiltonian):
|
|
890
|
+
def evolve(hamiltonian: Hamiltonian | Pauli, qubits: Quant | None = None):
|
|
867
891
|
r"""Time evolution :math:`e^{-iHt}` for a Hamiltonian.
|
|
868
892
|
|
|
869
893
|
For each Pauli term :math:`c_k P_k` in the Hamiltonian, applies the
|
|
@@ -890,12 +914,28 @@ def evolve(hamiltonian: Hamiltonian):
|
|
|
890
914
|
|
|
891
915
|
evolve(H_ising) # one Trotter step with t encoded in the coefficients
|
|
892
916
|
|
|
917
|
+
with obs(2) as v:
|
|
918
|
+
H_free = -1.0 * Z(v[0]) * Z(v[1]) - 0.5 * X(v[0])
|
|
919
|
+
|
|
920
|
+
evolve(H_free, q) # unbound Hamiltonian, same as evolve(H_free(q))
|
|
921
|
+
|
|
893
922
|
Args:
|
|
894
923
|
hamiltonian: The Hamiltonian to
|
|
895
924
|
simulate. The coefficient of each term serves as the rotation
|
|
896
925
|
angle.
|
|
926
|
+
qubits: Qubits to bind an unbound Hamiltonian to: placeholder ``i``
|
|
927
|
+
becomes ``qubits[i]``. Required for an unbound Hamiltonian and not
|
|
928
|
+
allowed for a bound one.
|
|
897
929
|
"""
|
|
898
930
|
|
|
931
|
+
if qubits is not None:
|
|
932
|
+
hamiltonian = hamiltonian.bind(qubits)
|
|
933
|
+
elif not hamiltonian.is_bound:
|
|
934
|
+
raise ValueError(
|
|
935
|
+
"Cannot evolve an unbound Hamiltonian; "
|
|
936
|
+
"pass the qubits to evolve or bind it first"
|
|
937
|
+
)
|
|
938
|
+
|
|
899
939
|
process = hamiltonian.ket_process
|
|
900
940
|
if isinstance(hamiltonian, Pauli):
|
|
901
941
|
hamiltonian = Hamiltonian([hamiltonian], process)
|
|
@@ -754,7 +754,9 @@ def sample(qubits: Quant, shots: int = 2048) -> Samples:
|
|
|
754
754
|
return Samples(qubits, int(shots), postprocessing)
|
|
755
755
|
|
|
756
756
|
|
|
757
|
-
def exp_value(
|
|
757
|
+
def exp_value(
|
|
758
|
+
hamiltonian: Hamiltonian | Pauli, qubits: Quant | None = None
|
|
759
|
+
) -> ExpValue:
|
|
758
760
|
"""Calculate the expectation value of a Hamiltonian for the current quantum state.
|
|
759
761
|
|
|
760
762
|
Registers an expectation-value computation for the given Hamiltonian or
|
|
@@ -778,16 +780,29 @@ def exp_value(hamiltonian: Hamiltonian | Pauli) -> ExpValue:
|
|
|
778
780
|
ev = exp_value(h)
|
|
779
781
|
print(ev.get()) # ⟨Bell|XX|Bell⟩ = 1.0
|
|
780
782
|
|
|
783
|
+
An unbound Hamiltonian, built with ``with obs(n) as q:``, needs the
|
|
784
|
+
qubits to evaluate it on:
|
|
785
|
+
|
|
786
|
+
.. code-block:: python
|
|
787
|
+
|
|
788
|
+
with obs(2) as q:
|
|
789
|
+
h = X(q[0]) * X(q[1])
|
|
790
|
+
ev = exp_value(h, r) # same as exp_value(h(r))
|
|
791
|
+
|
|
781
792
|
Args:
|
|
782
793
|
hamiltonian:
|
|
783
794
|
The observable to evaluate.
|
|
795
|
+
qubits:
|
|
796
|
+
Qubits to bind an unbound observable to: placeholder ``i``
|
|
797
|
+
becomes ``qubits[i]``. Required for an unbound observable and not
|
|
798
|
+
allowed for a bound one.
|
|
784
799
|
|
|
785
800
|
Returns:
|
|
786
801
|
A handle to the expectation value result.
|
|
787
802
|
Access :attr:`~ket.expv.ExpValue.value` or call ``.get()`` to retrieve
|
|
788
803
|
the result as a ``float``.
|
|
789
804
|
"""
|
|
790
|
-
return ExpValue(hamiltonian)
|
|
805
|
+
return ExpValue(hamiltonian, qubits)
|
|
791
806
|
|
|
792
807
|
|
|
793
808
|
def using_aux(unsafe: bool = False, **names):
|
|
@@ -35,7 +35,7 @@ from ..clib.libket.execution import LiveExecution, BatchExecution
|
|
|
35
35
|
from ..base import Process, Quant
|
|
36
36
|
from ..operations import dump, exp_value, measure
|
|
37
37
|
from ..gates import H, CNOT, X, Z, obs
|
|
38
|
-
from ..expv import Hamiltonian
|
|
38
|
+
from ..expv import Hamiltonian, Pauli
|
|
39
39
|
from . import gates, prepare, oracle, ham
|
|
40
40
|
|
|
41
41
|
try:
|
|
@@ -510,7 +510,7 @@ def pauli_string(
|
|
|
510
510
|
|
|
511
511
|
Args:
|
|
512
512
|
hamiltonian: A callable that takes a collection of qubits
|
|
513
|
-
(``Quant``) and returns a ``Hamiltonian`` object.
|
|
513
|
+
(``Quant``) and returns a ``Hamiltonian`` or ``Pauli`` object.
|
|
514
514
|
num_qubits: The total number of qubits the Hamiltonian acts on.
|
|
515
515
|
reversed_qubits: If True, the order of the allocated qubits is reversed
|
|
516
516
|
before being passed to the `hamiltonian` function. Defaults to False.
|
|
@@ -526,6 +526,8 @@ def pauli_string(
|
|
|
526
526
|
if reversed_qubits:
|
|
527
527
|
qubits = reversed(qubits)
|
|
528
528
|
h = hamiltonian(qubits)
|
|
529
|
+
if isinstance(h, Pauli):
|
|
530
|
+
h = Hamiltonian([h], h.ket_process)
|
|
529
531
|
|
|
530
532
|
coef = []
|
|
531
533
|
pauli_str = []
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/.pre-commit-config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/LICENSES/Apache-2.0.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_batch.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_live.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/examples/grover_live_dv2.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense_gpu/kernel.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/dense_gpu/mod.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/kbw/src/quantum_execution.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/.pre-commit-config.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/LICENSES/Apache-2.0.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/examples/grover.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/block.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/execute.rs
RENAMED
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/c_api/process.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/mod.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/network.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/su2.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/u2.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/util.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/c2to4x.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/decompose/x/mod.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/ir/hamiltonian.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/allocation.rs
RENAMED
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/graph.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/mapping/mod.rs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/process/mod.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/process/qwc.rs
RENAMED
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/executor.rs
RENAMED
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/gates.rs
RENAMED
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket/clib/libs/libket/src/qasm/openqasm.lalrpop
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ket_lang-0.10.4.2.dev1 → ket_lang-0.10.4.3.dev0}/src/ket_lang.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|