tensorcircuit-nightly 1.3.0.dev20250728__py3-none-any.whl → 1.4.0.dev20251103__py3-none-any.whl
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.
Potentially problematic release.
This version of tensorcircuit-nightly might be problematic. Click here for more details.
- tensorcircuit/__init__.py +5 -1
- tensorcircuit/abstractcircuit.py +4 -0
- tensorcircuit/analogcircuit.py +413 -0
- tensorcircuit/applications/layers.py +1 -1
- tensorcircuit/applications/van.py +1 -1
- tensorcircuit/backends/abstract_backend.py +312 -5
- tensorcircuit/backends/cupy_backend.py +3 -1
- tensorcircuit/backends/jax_backend.py +92 -3
- tensorcircuit/backends/jax_ops.py +108 -0
- tensorcircuit/backends/numpy_backend.py +49 -3
- tensorcircuit/backends/pytorch_backend.py +92 -3
- tensorcircuit/backends/tensorflow_backend.py +102 -3
- tensorcircuit/basecircuit.py +123 -82
- tensorcircuit/circuit.py +67 -57
- tensorcircuit/cloud/local.py +1 -1
- tensorcircuit/cloud/quafu_provider.py +1 -1
- tensorcircuit/cloud/tencent.py +1 -1
- tensorcircuit/compiler/simple_compiler.py +2 -2
- tensorcircuit/cons.py +1 -0
- tensorcircuit/densitymatrix.py +16 -11
- tensorcircuit/experimental.py +7 -152
- tensorcircuit/fgs.py +5 -6
- tensorcircuit/gates.py +66 -22
- tensorcircuit/keras.py +3 -3
- tensorcircuit/mpscircuit.py +109 -61
- tensorcircuit/quantum.py +697 -133
- tensorcircuit/quditcircuit.py +733 -0
- tensorcircuit/quditgates.py +618 -0
- tensorcircuit/results/counts.py +45 -31
- tensorcircuit/shadows.py +1 -1
- tensorcircuit/simplify.py +3 -1
- tensorcircuit/stabilizercircuit.py +4 -2
- tensorcircuit/templates/blocks.py +2 -2
- tensorcircuit/templates/hamiltonians.py +29 -8
- tensorcircuit/templates/lattice.py +676 -335
- tensorcircuit/timeevol.py +896 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/METADATA +50 -25
- tensorcircuit_nightly-1.4.0.dev20251103.dist-info/RECORD +96 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/top_level.txt +0 -1
- tensorcircuit_nightly-1.3.0.dev20250728.dist-info/RECORD +0 -122
- tests/__init__.py +0 -0
- tests/conftest.py +0 -67
- tests/test_backends.py +0 -1035
- tests/test_calibrating.py +0 -149
- tests/test_channels.py +0 -409
- tests/test_circuit.py +0 -1713
- tests/test_cloud.py +0 -219
- tests/test_compiler.py +0 -147
- tests/test_dmcircuit.py +0 -555
- tests/test_ensemble.py +0 -72
- tests/test_fgs.py +0 -318
- tests/test_gates.py +0 -156
- tests/test_hamiltonians.py +0 -159
- tests/test_interfaces.py +0 -557
- tests/test_keras.py +0 -160
- tests/test_lattice.py +0 -1666
- tests/test_miscs.py +0 -334
- tests/test_mpscircuit.py +0 -341
- tests/test_noisemodel.py +0 -156
- tests/test_qaoa.py +0 -86
- tests/test_qem.py +0 -152
- tests/test_quantum.py +0 -549
- tests/test_quantum_attr.py +0 -42
- tests/test_results.py +0 -379
- tests/test_shadows.py +0 -160
- tests/test_simplify.py +0 -46
- tests/test_stabilizer.py +0 -226
- tests/test_templates.py +0 -218
- tests/test_torchnn.py +0 -99
- tests/test_van.py +0 -102
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/WHEEL +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250728.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/licenses/LICENSE +0 -0
tensorcircuit/results/counts.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import Any, Dict, Optional, Sequence
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
|
|
9
|
+
from ..quantum import _decode_basis_label
|
|
9
10
|
|
|
10
11
|
Tensor = Any
|
|
11
12
|
ct = Dict[str, int]
|
|
@@ -89,14 +90,24 @@ def marginal_count(count: ct, keep_list: Sequence[int]) -> ct:
|
|
|
89
90
|
return reverse_count(ncount)
|
|
90
91
|
|
|
91
92
|
|
|
92
|
-
def count2vec(
|
|
93
|
+
def count2vec(
|
|
94
|
+
count: ct, normalization: bool = True, dim: Optional[int] = None
|
|
95
|
+
) -> Tensor:
|
|
93
96
|
"""
|
|
94
|
-
Convert
|
|
97
|
+
Convert a dictionary of counts (with string keys) to a probability/count vector.
|
|
98
|
+
|
|
99
|
+
Support:
|
|
100
|
+
- base-d string (d <= 36), characters taken from 0-9A-Z (case-insensitive)
|
|
101
|
+
For example:
|
|
102
|
+
qubit: '0101'
|
|
103
|
+
qudit: '012' or '09A' (A represents 10, which means [0, 9, 10])
|
|
95
104
|
|
|
96
105
|
:param count: A dictionary mapping bit strings to counts
|
|
97
106
|
:type count: ct
|
|
98
107
|
:param normalization: Whether to normalize the counts to probabilities, defaults to True
|
|
99
108
|
:type normalization: bool, optional
|
|
109
|
+
:param dim: Dimensionality of the vector, defaults to 2
|
|
110
|
+
:type dim: int, optional
|
|
100
111
|
:return: Probability vector as numpy array
|
|
101
112
|
:rtype: Tensor
|
|
102
113
|
|
|
@@ -105,44 +116,47 @@ def count2vec(count: ct, normalization: bool = True) -> Tensor:
|
|
|
105
116
|
>>> count2vec({"00": 2, "10": 3, "11": 5})
|
|
106
117
|
array([0.2, 0. , 0.3, 0.5])
|
|
107
118
|
"""
|
|
108
|
-
nqubit = len(list(count.keys())[0])
|
|
109
|
-
probability = [0] * 2**nqubit
|
|
110
|
-
shots = sum([v for k, v in count.items()])
|
|
111
|
-
for k, v in count.items():
|
|
112
|
-
if normalization is True:
|
|
113
|
-
v /= shots # type: ignore
|
|
114
|
-
probability[int(k, 2)] = v
|
|
115
|
-
return np.array(probability)
|
|
116
119
|
|
|
120
|
+
if not count:
|
|
121
|
+
return np.array([], dtype=float)
|
|
117
122
|
|
|
118
|
-
|
|
119
|
-
"""
|
|
120
|
-
Convert probability vector to count dictionary.
|
|
123
|
+
dim = 2 if dim is None else dim
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
n = len(next(iter(count)).upper())
|
|
126
|
+
prob = np.zeros(dim**n, dtype=float)
|
|
127
|
+
shots = float(sum(count.values())) if normalization else 1.0
|
|
128
|
+
if shots == 0:
|
|
129
|
+
return prob
|
|
130
|
+
|
|
131
|
+
powers = [dim**p for p in range(n)][::-1]
|
|
132
|
+
for k, v in count.items():
|
|
133
|
+
digits = _decode_basis_label(k, n, dim)
|
|
134
|
+
idx = sum(dig * p for dig, p in zip(digits, powers))
|
|
135
|
+
prob[idx] = (v / shots) if normalization else v
|
|
136
|
+
|
|
137
|
+
return prob
|
|
128
138
|
|
|
129
|
-
:Example:
|
|
130
139
|
|
|
131
|
-
|
|
132
|
-
{'00': 0.2, '01': 0.3, '10': 0.1, '11': 0.4}
|
|
140
|
+
def vec2count(vec: Tensor, prune: bool = False, dim: Optional[int] = None) -> ct:
|
|
133
141
|
"""
|
|
134
|
-
|
|
142
|
+
Map a count/probability vector of length D to a dictionary with base-d string keys (0-9A-Z).
|
|
143
|
+
Only generate string keys when d <= 36; if d is inferred to be > 36, raise a NotImplementedError.
|
|
135
144
|
|
|
145
|
+
:param vec: A one-dimensional vector of length D = d**n
|
|
146
|
+
:param prune: Whether to prune near-zero elements (threshold 1e-8)
|
|
147
|
+
:param dim: Dimensionality of the vector, defaults to 2
|
|
148
|
+
:return: {base-d string key: value}, key length n
|
|
149
|
+
"""
|
|
150
|
+
from ..quantum import count_vector2dict, _infer_num_sites
|
|
151
|
+
|
|
152
|
+
dim = 2 if dim is None else dim
|
|
136
153
|
if isinstance(vec, list):
|
|
137
154
|
vec = np.array(vec)
|
|
138
|
-
n = int(
|
|
139
|
-
c = count_vector2dict(vec, n, key="bin")
|
|
140
|
-
if prune
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if np.abs(v) < 1e-8:
|
|
144
|
-
del nc[k]
|
|
145
|
-
return nc
|
|
155
|
+
n = _infer_num_sites(int(vec.shape[0]), dim)
|
|
156
|
+
c: ct = count_vector2dict(vec, n, key="bin", dim=dim) # type: ignore
|
|
157
|
+
if prune:
|
|
158
|
+
c = {k: v for k, v in c.items() if np.abs(v) >= 1e-8}
|
|
159
|
+
|
|
146
160
|
return c
|
|
147
161
|
|
|
148
162
|
|
tensorcircuit/shadows.py
CHANGED
|
@@ -334,7 +334,7 @@ def entropy_shadow(
|
|
|
334
334
|
|
|
335
335
|
def renyi_entropy_2(snapshots: Tensor, sub: Optional[Sequence[int]] = None) -> Tensor:
|
|
336
336
|
r"""To calculate the second order Renyi entropy of a subsystem from snapshot, please refer to
|
|
337
|
-
Brydges, T. et al. Science 364, 260
|
|
337
|
+
Brydges, T. et al. Science 364, 260-263 (2019). This function is not jitable.
|
|
338
338
|
|
|
339
339
|
:param snapshots: shape = (ns, repeat, nq)
|
|
340
340
|
:type: Tensor
|
tensorcircuit/simplify.py
CHANGED
|
@@ -121,7 +121,9 @@ def _split_two_qubit_gate(
|
|
|
121
121
|
if fixed_choice == 2: # swap one
|
|
122
122
|
return n3, n4, True # swap
|
|
123
123
|
s2 = n3.tensor.shape[-1]
|
|
124
|
-
if (s1 >=
|
|
124
|
+
if (s1 >= n[0].dimension * n[2].dimension) and (
|
|
125
|
+
s2 >= n[1].dimension * n[3].dimension
|
|
126
|
+
):
|
|
125
127
|
# jax jit unspport split_node with trun_err anyway
|
|
126
128
|
# tf function doesn't work either, though I believe it may work on tf side
|
|
127
129
|
# CANNOT DONE(@refraction-ray): tf.function version with trun_err set
|
|
@@ -96,10 +96,12 @@ class StabilizerCircuit(AbstractCircuit):
|
|
|
96
96
|
|
|
97
97
|
if name.lower() in self.gate_map:
|
|
98
98
|
# self._stim_circuit.append(gate_map[name.lower()], list(index))
|
|
99
|
-
|
|
99
|
+
gn = self.gate_map[name.lower()]
|
|
100
|
+
instruction = f"{gn} {' '.join(map(str, index))}"
|
|
100
101
|
self._stim_circuit.append_from_stim_program_text(instruction)
|
|
101
102
|
# append is much slower
|
|
102
|
-
self.current_sim.do(stim.Circuit(instruction))
|
|
103
|
+
# self.current_sim.do(stim.Circuit(instruction))
|
|
104
|
+
getattr(self.current_sim, gn.lower())(*index)
|
|
103
105
|
else:
|
|
104
106
|
raise ValueError(f"Gate {name} is not supported in stabilizer simulation")
|
|
105
107
|
|
|
@@ -91,7 +91,7 @@ def QAOA_block(
|
|
|
91
91
|
e2,
|
|
92
92
|
unitary=G._zz_matrix,
|
|
93
93
|
theta=paramzz * g[e1][e2].get("weight", 1.0),
|
|
94
|
-
**kws
|
|
94
|
+
**kws,
|
|
95
95
|
)
|
|
96
96
|
else:
|
|
97
97
|
i = 0
|
|
@@ -157,7 +157,7 @@ def qft(
|
|
|
157
157
|
*index: int,
|
|
158
158
|
do_swaps: bool = True,
|
|
159
159
|
inverse: bool = False,
|
|
160
|
-
insert_barriers: bool = False
|
|
160
|
+
insert_barriers: bool = False,
|
|
161
161
|
) -> Circuit:
|
|
162
162
|
"""
|
|
163
163
|
This function applies quantum fourier transformation (QFT) to the selected circuit lines
|
|
@@ -17,13 +17,14 @@ def _create_empty_sparse_matrix(shape: Tuple[int, int]) -> Any:
|
|
|
17
17
|
def heisenberg_hamiltonian(
|
|
18
18
|
lattice: AbstractLattice,
|
|
19
19
|
j_coupling: Union[float, List[float], Tuple[float, ...]] = 1.0,
|
|
20
|
+
interaction_scope: str = "neighbors",
|
|
20
21
|
) -> Any:
|
|
21
|
-
"""
|
|
22
|
+
r"""
|
|
22
23
|
Generates the sparse matrix of the Heisenberg Hamiltonian for a given lattice.
|
|
23
24
|
|
|
24
25
|
The Heisenberg Hamiltonian is defined as:
|
|
25
|
-
H = J
|
|
26
|
-
where the sum is over
|
|
26
|
+
:math:`H = J\sum_{i,j} (X_i X_j + Y_i Y_j + Z_i Z_j)`
|
|
27
|
+
where the sum is over a specified set of interacting pairs {i,j}.
|
|
27
28
|
|
|
28
29
|
:param lattice: An instance of a class derived from AbstractLattice,
|
|
29
30
|
which provides the geometric information of the system.
|
|
@@ -32,11 +33,23 @@ def heisenberg_hamiltonian(
|
|
|
32
33
|
isotropic model (Jx=Jy=Jz) or a list/tuple of 3 floats for an
|
|
33
34
|
anisotropic model (Jx, Jy, Jz). Defaults to 1.0.
|
|
34
35
|
:type j_coupling: Union[float, List[float], Tuple[float, ...]], optional
|
|
36
|
+
:param interaction_scope: Defines the range of interactions.
|
|
37
|
+
- "neighbors": Includes only nearest-neighbor pairs (default).
|
|
38
|
+
- "all": Includes all unique pairs of sites.
|
|
39
|
+
:type interaction_scope: str, optional
|
|
35
40
|
:return: The Hamiltonian as a backend-agnostic sparse matrix.
|
|
36
41
|
:rtype: Any
|
|
37
42
|
"""
|
|
38
43
|
num_sites = lattice.num_sites
|
|
39
|
-
|
|
44
|
+
if interaction_scope == "neighbors":
|
|
45
|
+
neighbor_pairs = lattice.get_neighbor_pairs(k=1, unique=True)
|
|
46
|
+
elif interaction_scope == "all":
|
|
47
|
+
neighbor_pairs = lattice.get_all_pairs()
|
|
48
|
+
else:
|
|
49
|
+
raise ValueError(
|
|
50
|
+
f"Invalid interaction_scope: '{interaction_scope}'. "
|
|
51
|
+
"Must be 'neighbors' or 'all'."
|
|
52
|
+
)
|
|
40
53
|
|
|
41
54
|
if isinstance(j_coupling, (float, int)):
|
|
42
55
|
js = [float(j_coupling)] * 3
|
|
@@ -73,13 +86,21 @@ def heisenberg_hamiltonian(
|
|
|
73
86
|
def rydberg_hamiltonian(
|
|
74
87
|
lattice: AbstractLattice, omega: float, delta: float, c6: float
|
|
75
88
|
) -> Any:
|
|
76
|
-
"""
|
|
89
|
+
r"""
|
|
77
90
|
Generates the sparse matrix of the Rydberg atom array Hamiltonian.
|
|
78
91
|
|
|
79
92
|
The Hamiltonian is defined as:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
93
|
+
.. math::
|
|
94
|
+
|
|
95
|
+
H = \sum_i \frac{\Omega}{2} X_i
|
|
96
|
+
- \sum_i \frac{\delta}{2} \bigl(1 - Z_i \bigr)
|
|
97
|
+
+ \sum_{i<j} \frac{V_{ij}}{4} \bigl(1 - Z_i \bigr)\bigl(1 - Z_j \bigr)
|
|
98
|
+
|
|
99
|
+
= \sum_i \frac{\Omega}{2} X_i
|
|
100
|
+
+ \sum_i \frac{\delta}{2} Z_i
|
|
101
|
+
+ \sum_{i<j} \frac{V_{ij}}{4}\,\bigl(Z_i Z_j - Z_i - Z_j \bigr)
|
|
102
|
+
|
|
103
|
+
where :math:`V_{ij} = C6 / |r_i - r_j|^6`.
|
|
83
104
|
|
|
84
105
|
Note: Constant energy offset terms (proportional to the identity operator)
|
|
85
106
|
are ignored in this implementation.
|