tensorcircuit-nightly 1.0.2.dev20250108__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.

Files changed (76) hide show
  1. tensorcircuit/__init__.py +18 -2
  2. tensorcircuit/about.py +46 -0
  3. tensorcircuit/abstractcircuit.py +4 -0
  4. tensorcircuit/analogcircuit.py +413 -0
  5. tensorcircuit/applications/layers.py +1 -1
  6. tensorcircuit/applications/van.py +1 -1
  7. tensorcircuit/backends/abstract_backend.py +320 -7
  8. tensorcircuit/backends/cupy_backend.py +3 -1
  9. tensorcircuit/backends/jax_backend.py +102 -4
  10. tensorcircuit/backends/jax_ops.py +110 -1
  11. tensorcircuit/backends/numpy_backend.py +49 -3
  12. tensorcircuit/backends/pytorch_backend.py +92 -3
  13. tensorcircuit/backends/tensorflow_backend.py +102 -3
  14. tensorcircuit/basecircuit.py +157 -98
  15. tensorcircuit/circuit.py +115 -57
  16. tensorcircuit/cloud/local.py +1 -1
  17. tensorcircuit/cloud/quafu_provider.py +1 -1
  18. tensorcircuit/cloud/tencent.py +1 -1
  19. tensorcircuit/compiler/simple_compiler.py +2 -2
  20. tensorcircuit/cons.py +142 -21
  21. tensorcircuit/densitymatrix.py +43 -14
  22. tensorcircuit/experimental.py +387 -129
  23. tensorcircuit/fgs.py +282 -81
  24. tensorcircuit/gates.py +66 -22
  25. tensorcircuit/interfaces/__init__.py +1 -3
  26. tensorcircuit/interfaces/jax.py +189 -0
  27. tensorcircuit/keras.py +3 -3
  28. tensorcircuit/mpscircuit.py +154 -65
  29. tensorcircuit/quantum.py +868 -152
  30. tensorcircuit/quditcircuit.py +733 -0
  31. tensorcircuit/quditgates.py +618 -0
  32. tensorcircuit/results/counts.py +147 -20
  33. tensorcircuit/results/readout_mitigation.py +4 -1
  34. tensorcircuit/shadows.py +1 -1
  35. tensorcircuit/simplify.py +3 -1
  36. tensorcircuit/stabilizercircuit.py +479 -0
  37. tensorcircuit/templates/__init__.py +2 -0
  38. tensorcircuit/templates/blocks.py +2 -2
  39. tensorcircuit/templates/hamiltonians.py +174 -0
  40. tensorcircuit/templates/lattice.py +1789 -0
  41. tensorcircuit/timeevol.py +896 -0
  42. tensorcircuit/translation.py +10 -3
  43. tensorcircuit/utils.py +7 -0
  44. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/METADATA +73 -23
  45. tensorcircuit_nightly-1.4.0.dev20251103.dist-info/RECORD +96 -0
  46. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/WHEEL +1 -1
  47. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info}/top_level.txt +0 -1
  48. tensorcircuit_nightly-1.0.2.dev20250108.dist-info/RECORD +0 -115
  49. tests/__init__.py +0 -0
  50. tests/conftest.py +0 -67
  51. tests/test_backends.py +0 -1031
  52. tests/test_calibrating.py +0 -149
  53. tests/test_channels.py +0 -365
  54. tests/test_circuit.py +0 -1699
  55. tests/test_cloud.py +0 -219
  56. tests/test_compiler.py +0 -147
  57. tests/test_dmcircuit.py +0 -555
  58. tests/test_ensemble.py +0 -72
  59. tests/test_fgs.py +0 -310
  60. tests/test_gates.py +0 -156
  61. tests/test_interfaces.py +0 -429
  62. tests/test_keras.py +0 -160
  63. tests/test_miscs.py +0 -277
  64. tests/test_mpscircuit.py +0 -341
  65. tests/test_noisemodel.py +0 -156
  66. tests/test_qaoa.py +0 -86
  67. tests/test_qem.py +0 -152
  68. tests/test_quantum.py +0 -526
  69. tests/test_quantum_attr.py +0 -42
  70. tests/test_results.py +0 -347
  71. tests/test_shadows.py +0 -160
  72. tests/test_simplify.py +0 -46
  73. tests/test_templates.py +0 -218
  74. tests/test_torchnn.py +0 -99
  75. tests/test_van.py +0 -102
  76. {tensorcircuit_nightly-1.0.2.dev20250108.dist-info → tensorcircuit_nightly-1.4.0.dev20251103.dist-info/licenses}/LICENSE +0 -0
@@ -17,7 +17,7 @@ from .channels import kraus_to_super_gate
17
17
  from .circuit import Circuit
18
18
  from .cons import backend, contractor, dtypestr
19
19
  from .basecircuit import BaseCircuit
20
- from .quantum import QuOperator
20
+ from .quantum import QuOperator, _infer_num_sites
21
21
 
22
22
  Gate = gates.Gate
23
23
  Tensor = Any
@@ -35,9 +35,11 @@ class DMCircuit(BaseCircuit):
35
35
  dminputs: Optional[Tensor] = None,
36
36
  mpo_dminputs: Optional[QuOperator] = None,
37
37
  split: Optional[Dict[str, Any]] = None,
38
+ dim: Optional[int] = None,
38
39
  ) -> None:
39
40
  """
40
41
  The density matrix simulator based on tensornetwork engine.
42
+ Do not use this class with d!=2 directly
41
43
 
42
44
  :param nqubits: Number of qubits
43
45
  :type nqubits: int
@@ -55,6 +57,7 @@ class DMCircuit(BaseCircuit):
55
57
  ``max_singular_values`` and ``max_truncation_err``.
56
58
  :type split: Optional[Dict[str, Any]]
57
59
  """
60
+ self._d = 2 if dim is None else dim
58
61
  if not empty:
59
62
  if (
60
63
  (inputs is None)
@@ -73,9 +76,9 @@ class DMCircuit(BaseCircuit):
73
76
  inputs = backend.cast(inputs, dtype=dtypestr)
74
77
  inputs = backend.reshape(inputs, [-1])
75
78
  N = inputs.shape[0]
76
- n = int(np.log(N) / np.log(2))
79
+ n = _infer_num_sites(N, self._d)
77
80
  assert n == nqubits
78
- inputs = backend.reshape(inputs, [2 for _ in range(n)])
81
+ inputs = backend.reshape(inputs, [self._d for _ in range(n)])
79
82
  inputs_gate = Gate(inputs)
80
83
  self._nodes = [inputs_gate]
81
84
  self.coloring_nodes(self._nodes)
@@ -94,7 +97,9 @@ class DMCircuit(BaseCircuit):
94
97
  elif dminputs is not None:
95
98
  dminputs = backend.convert_to_tensor(dminputs)
96
99
  dminputs = backend.cast(dminputs, dtype=dtypestr)
97
- dminputs = backend.reshape(dminputs, [2 for _ in range(2 * nqubits)])
100
+ dminputs = backend.reshape(
101
+ dminputs, [self._d for _ in range(2 * nqubits)]
102
+ )
98
103
  dminputs_gate = Gate(dminputs)
99
104
  nodes = [dminputs_gate]
100
105
  self._front = [dminputs_gate.get_edge(i) for i in range(2 * nqubits)]
@@ -173,14 +178,39 @@ class DMCircuit(BaseCircuit):
173
178
  self._nodes = [t]
174
179
 
175
180
  @staticmethod
176
- def check_kraus(kraus: Sequence[Gate]) -> bool: # TODO(@refraction-ray)
181
+ def check_kraus(kraus: Sequence[Gate]) -> bool:
182
+ r"""
183
+ Check if Kraus operators satisfy the completeness relation:
184
+ :math:`\sum_i K_i^\dagger K_i = I`
185
+
186
+ :param kraus: Sequence of Kraus operators
187
+ :type kraus: Sequence[Gate]
188
+ :return: True if completeness relation is satisfied within tolerance
189
+ :rtype: bool
190
+ :raises ValueError: If completeness relation is not satisfied
191
+ """
192
+ # Convert all operators to tensors and get their shape
193
+ k_tensors = [k.tensor if isinstance(k, tn.Node) else k for k in kraus]
194
+ shape = k_tensors[0].shape
195
+ dim = shape[0] # Assuming square matrices
196
+
197
+ # Sum K_i K_i^†
198
+ sum_kk = backend.zeros([dim, dim], dtype=k_tensors[0].dtype)
199
+ for k in k_tensors:
200
+ kdag = backend.conj(backend.transpose(k))
201
+ sum_kk = sum_kk + backend.matmul(kdag, k)
202
+
203
+ # Check if sum equals identity within tolerance
204
+ identity = backend.eye(dim, dtype=sum_kk.dtype)
205
+ if not np.allclose(sum_kk, identity, atol=1e-5):
206
+ raise ValueError("Kraus operators do not satisfy completeness relation")
207
+
177
208
  return True
178
209
 
179
210
  def apply_general_kraus(
180
211
  self, kraus: Sequence[Gate], index: Sequence[Tuple[int, ...]], **kws: Any
181
212
  ) -> None:
182
213
  # note the API difference for index arg between DM and DM2
183
- self.check_kraus(kraus)
184
214
  assert len(kraus) == len(index) or len(index) == 1
185
215
  if len(index) == 1:
186
216
  index = [index[0] for _ in range(len(kraus))]
@@ -192,7 +222,7 @@ class DMCircuit(BaseCircuit):
192
222
  dd = dmc.densitymatrix()
193
223
  circuits.append(dd)
194
224
  tensor = reduce(add, circuits)
195
- tensor = backend.reshape(tensor, [2 for _ in range(2 * self._nqubits)])
225
+ tensor = backend.reshaped(tensor, d=self._d)
196
226
  self._nodes = [Gate(tensor)]
197
227
  dangling = [e for e in self._nodes[0]]
198
228
  self._front = dangling
@@ -202,7 +232,7 @@ class DMCircuit(BaseCircuit):
202
232
 
203
233
  @staticmethod
204
234
  def apply_general_kraus_delayed(
205
- krausf: Callable[..., Sequence[Gate]]
235
+ krausf: Callable[..., Sequence[Gate]],
206
236
  ) -> Callable[..., None]:
207
237
  def apply(self: "DMCircuit", *index: int, **vars: float) -> None:
208
238
  for key in ["status", "name"]:
@@ -230,7 +260,7 @@ class DMCircuit(BaseCircuit):
230
260
  t = contractor(nodes, output_edge_order=d_edges)
231
261
  else:
232
262
  t = nodes[0]
233
- dm = backend.reshape(t.tensor, shape=[2**self._nqubits, 2**self._nqubits])
263
+ dm = backend.reshapem(t.tensor)
234
264
  if check:
235
265
  self.check_density_matrix(dm)
236
266
  return dm
@@ -249,7 +279,7 @@ class DMCircuit(BaseCircuit):
249
279
  dm = self.densitymatrix()
250
280
  e, v = backend.eigh(dm)
251
281
  np.testing.assert_allclose(
252
- e[:-1], backend.zeros([2**self._nqubits - 1]), atol=1e-5
282
+ e[:-1], backend.zeros([self._d**self._nqubits - 1]), atol=1e-5
253
283
  )
254
284
  return v[:, -1]
255
285
 
@@ -272,7 +302,7 @@ class DMCircuit(BaseCircuit):
272
302
  reuse: bool = True,
273
303
  noise_conf: Optional[Any] = None,
274
304
  status: Optional[Tensor] = None,
275
- **kws: Any
305
+ **kws: Any,
276
306
  ) -> tn.Node.tensor:
277
307
  """
278
308
  Compute the expectation of corresponding operators.
@@ -341,7 +371,6 @@ class DMCircuit2(DMCircuit):
341
371
  )
342
372
  for k in kraus
343
373
  ]
344
- self.check_kraus(kraus)
345
374
  if not isinstance(
346
375
  index[0], int
347
376
  ): # try best to be compatible with DMCircuit interface
@@ -351,7 +380,7 @@ class DMCircuit2(DMCircuit):
351
380
  # index = [index[0] for _ in range(len(kraus))]
352
381
  super_op = kraus_to_super_gate(kraus)
353
382
  nlegs = 4 * len(index)
354
- super_op = backend.reshape(super_op, [2 for _ in range(nlegs)])
383
+ super_op = backend.reshape(super_op, [self._d for _ in range(nlegs)])
355
384
  super_op = Gate(super_op)
356
385
  o2i = int(nlegs / 2)
357
386
  r2l = int(nlegs / 4)
@@ -367,7 +396,7 @@ class DMCircuit2(DMCircuit):
367
396
 
368
397
  @staticmethod
369
398
  def apply_general_kraus_delayed(
370
- krausf: Callable[..., Sequence[Gate]]
399
+ krausf: Callable[..., Sequence[Gate]],
371
400
  ) -> Callable[..., None]:
372
401
  def apply(self: "DMCircuit2", *index: int, **vars: float) -> None:
373
402
  for key in ["status", "name"]: