tensorcircuit-nightly 1.3.0.dev20250811__tar.gz → 1.3.0.dev20250813__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.

Potentially problematic release.


This version of tensorcircuit-nightly might be problematic. Click here for more details.

Files changed (103) hide show
  1. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/CHANGELOG.md +8 -0
  2. {tensorcircuit_nightly-1.3.0.dev20250811/tensorcircuit_nightly.egg-info → tensorcircuit_nightly-1.3.0.dev20250813}/PKG-INFO +2 -1
  3. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/README.md +1 -0
  4. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/__init__.py +1 -1
  5. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/abstract_backend.py +15 -0
  6. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/jax_backend.py +3 -0
  7. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/numpy_backend.py +3 -0
  8. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/tensorflow_backend.py +6 -0
  9. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/basecircuit.py +16 -11
  10. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/mpscircuit.py +22 -4
  11. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/quantum.py +414 -19
  12. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813/tensorcircuit_nightly.egg-info}/PKG-INFO +2 -1
  13. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/HISTORY.md +0 -0
  14. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/LICENSE +0 -0
  15. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/MANIFEST.in +0 -0
  16. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/README_cn.md +0 -0
  17. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/pyproject.toml +0 -0
  18. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/setup.cfg +0 -0
  19. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/setup.py +0 -0
  20. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/about.py +0 -0
  21. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/abstractcircuit.py +0 -0
  22. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/__init__.py +0 -0
  23. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/ai/__init__.py +0 -0
  24. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/ai/ensemble.py +0 -0
  25. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/dqas.py +0 -0
  26. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/finance/__init__.py +0 -0
  27. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/finance/portfolio.py +0 -0
  28. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/graphdata.py +0 -0
  29. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/layers.py +0 -0
  30. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/optimization.py +0 -0
  31. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/physics/__init__.py +0 -0
  32. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/physics/baseline.py +0 -0
  33. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/physics/fss.py +0 -0
  34. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/utils.py +0 -0
  35. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/vags.py +0 -0
  36. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/van.py +0 -0
  37. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/applications/vqes.py +0 -0
  38. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/asciiart.py +0 -0
  39. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/__init__.py +0 -0
  40. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/backend_factory.py +0 -0
  41. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/cupy_backend.py +0 -0
  42. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/jax_ops.py +0 -0
  43. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/pytorch_backend.py +0 -0
  44. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/pytorch_ops.py +0 -0
  45. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/backends/tf_ops.py +0 -0
  46. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/channels.py +0 -0
  47. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/circuit.py +0 -0
  48. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/__init__.py +0 -0
  49. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/abstraction.py +0 -0
  50. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/apis.py +0 -0
  51. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/config.py +0 -0
  52. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/local.py +0 -0
  53. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/quafu_provider.py +0 -0
  54. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/tencent.py +0 -0
  55. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/utils.py +0 -0
  56. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cloud/wrapper.py +0 -0
  57. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/compiler/__init__.py +0 -0
  58. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/compiler/composed_compiler.py +0 -0
  59. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/compiler/qiskit_compiler.py +0 -0
  60. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/compiler/simple_compiler.py +0 -0
  61. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/cons.py +0 -0
  62. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/densitymatrix.py +0 -0
  63. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/experimental.py +0 -0
  64. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/fgs.py +0 -0
  65. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/gates.py +0 -0
  66. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/__init__.py +0 -0
  67. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/jax.py +0 -0
  68. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/numpy.py +0 -0
  69. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/scipy.py +0 -0
  70. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/tensorflow.py +0 -0
  71. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/tensortrans.py +0 -0
  72. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/interfaces/torch.py +0 -0
  73. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/keras.py +0 -0
  74. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/mps_base.py +0 -0
  75. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/noisemodel.py +0 -0
  76. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/__init__.py +0 -0
  77. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/counts.py +0 -0
  78. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/qem/__init__.py +0 -0
  79. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/qem/benchmark_circuits.py +0 -0
  80. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/qem/qem_methods.py +0 -0
  81. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/results/readout_mitigation.py +0 -0
  82. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/shadows.py +0 -0
  83. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/simplify.py +0 -0
  84. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/stabilizercircuit.py +0 -0
  85. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/__init__.py +0 -0
  86. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/ansatz.py +0 -0
  87. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/blocks.py +0 -0
  88. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/chems.py +0 -0
  89. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/conversions.py +0 -0
  90. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/dataset.py +0 -0
  91. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/graphs.py +0 -0
  92. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/hamiltonians.py +0 -0
  93. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/lattice.py +0 -0
  94. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/templates/measurements.py +0 -0
  95. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/timeevol.py +0 -0
  96. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/torchnn.py +0 -0
  97. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/translation.py +0 -0
  98. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/utils.py +0 -0
  99. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit/vis.py +0 -0
  100. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit_nightly.egg-info/SOURCES.txt +0 -0
  101. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit_nightly.egg-info/dependency_links.txt +0 -0
  102. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit_nightly.egg-info/requires.txt +0 -0
  103. {tensorcircuit_nightly-1.3.0.dev20250811 → tensorcircuit_nightly-1.3.0.dev20250813}/tensorcircuit_nightly.egg-info/top_level.txt +0 -0
@@ -20,6 +20,10 @@
20
20
 
21
21
  - Introducing pyproject.toml finally
22
22
 
23
+ - Add `argsort` method for backends
24
+
25
+ - Add transformation method between tensornetwork, quimb, tenpy and QuOperator in tc-ng including `qop2tenpy`, `qop2quimb`, `qop2tn`, `tenpy2qop`, support both MPS and MPO formats.
26
+
23
27
  ### Fixed
24
28
 
25
29
  - Fixed `one_hot` in numpy backend.
@@ -28,6 +32,10 @@
28
32
 
29
33
  - Fix potential np.matrix return from `PaulistringSum2Dense`.
30
34
 
35
+ - `MPSCircuit` now will first try to transform `QuVector` input to tensors directly instead of evaluating it to dense wavefunction first.
36
+
37
+ - Fix to use `status` for `circuit.sample` when `allow_state=True`.
38
+
31
39
  ### Changed
32
40
 
33
41
  - The order of arguments of `tc.timeevol.ed_evol` are changed for consistent interface with other evolution methods.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensorcircuit-nightly
3
- Version: 1.3.0.dev20250811
3
+ Version: 1.3.0.dev20250813
4
4
  Summary: High performance unified quantum computing framework for the NISQ era
5
5
  Author-email: TensorCircuit Authors <znfesnpbh@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -342,6 +342,7 @@ TensorCircuit-NG is open source, released under the Apache License, Version 2.0.
342
342
  </tr>
343
343
  <tr>
344
344
  <td align="center" valign="top" width="16.66%"><a href="https://github.com/Stellogic"><img src="https://avatars.githubusercontent.com/u/186928579?v=4?s=100" width="100px;" alt="Stellogic"/><br /><sub><b>Stellogic</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Code">💻</a> <a href="#example-Stellogic" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Tests">⚠️</a></td>
345
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Charlespkuer"><img src="https://avatars.githubusercontent.com/u/112697147?v=4?s=100" width="100px;" alt="Huang"/><br /><sub><b>Huang</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Code">💻</a> <a href="#example-Charlespkuer" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Tests">⚠️</a></td>
345
346
  </tr>
346
347
  </tbody>
347
348
  </table>
@@ -307,6 +307,7 @@ TensorCircuit-NG is open source, released under the Apache License, Version 2.0.
307
307
  </tr>
308
308
  <tr>
309
309
  <td align="center" valign="top" width="16.66%"><a href="https://github.com/Stellogic"><img src="https://avatars.githubusercontent.com/u/186928579?v=4?s=100" width="100px;" alt="Stellogic"/><br /><sub><b>Stellogic</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Code">💻</a> <a href="#example-Stellogic" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Tests">⚠️</a></td>
310
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Charlespkuer"><img src="https://avatars.githubusercontent.com/u/112697147?v=4?s=100" width="100px;" alt="Huang"/><br /><sub><b>Huang</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Code">💻</a> <a href="#example-Charlespkuer" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Tests">⚠️</a></td>
310
311
  </tr>
311
312
  </tbody>
312
313
  </table>
@@ -1,4 +1,4 @@
1
- __version__ = "1.3.0.dev20250811"
1
+ __version__ = "1.3.0.dev20250813"
2
2
  __author__ = "TensorCircuit Authors"
3
3
  __creator__ = "refraction-ray"
4
4
 
@@ -581,6 +581,21 @@ class ExtendedBackend:
581
581
  "Backend '{}' has not implemented `argmin`.".format(self.name)
582
582
  )
583
583
 
584
+ def argsort(self: Any, a: Tensor, axis: int = -1) -> Tensor:
585
+ """
586
+ return the indices that would sort an array.
587
+
588
+ :param a: the tensor to be sorted
589
+ :type a: Tensor
590
+ :param axis: the sorted axis, defaults to -1
591
+ :type axis: int
592
+ :return: the sorted indices
593
+ :rtype: Tensor
594
+ """
595
+ raise NotImplementedError(
596
+ "Backend '{}' has not implemented `argsort`.".format(self.name)
597
+ )
598
+
584
599
  def unique_with_counts(self: Any, a: Tensor, **kws: Any) -> Tuple[Tensor, Tensor]:
585
600
  """
586
601
  Find the unique elements and their corresponding counts of the given tensor ``a``.
@@ -387,6 +387,9 @@ class JaxBackend(jax_backend.JaxBackend, ExtendedBackend): # type: ignore
387
387
  def argmin(self, a: Tensor, axis: int = 0) -> Tensor:
388
388
  return jnp.argmin(a, axis=axis)
389
389
 
390
+ def argsort(self, a: Tensor, axis: int = -1) -> Tensor:
391
+ return jnp.argsort(a, axis=axis)
392
+
390
393
  def unique_with_counts( # type: ignore
391
394
  self, a: Tensor, *, size: Optional[int] = None, fill_value: Optional[int] = None
392
395
  ) -> Tuple[Tensor, Tensor]:
@@ -251,6 +251,9 @@ class NumpyBackend(numpy_backend.NumPyBackend, ExtendedBackend): # type: ignore
251
251
  def searchsorted(self, a: Tensor, v: Tensor, side: str = "left") -> Tensor:
252
252
  return np.searchsorted(a, v, side=side) # type: ignore
253
253
 
254
+ def argsort(self, a: Tensor, axis: int = -1) -> Tensor:
255
+ return np.argsort(a, axis=axis)
256
+
254
257
  def set_random_state(
255
258
  self, seed: Optional[int] = None, get_only: bool = False
256
259
  ) -> Any:
@@ -530,6 +530,12 @@ class TensorFlowBackend(tensorflow_backend.TensorFlowBackend, ExtendedBackend):
530
530
  def argmin(self, a: Tensor, axis: int = 0) -> Tensor:
531
531
  return tf.math.argmin(a, axis=axis)
532
532
 
533
+ def argsort(self, a: Tensor, axis: int = -1) -> Tensor:
534
+ return tf.argsort(a, axis=axis)
535
+
536
+ def shape_tuple(self, a: Tensor) -> Tuple[int, ...]:
537
+ return tuple(a.shape)
538
+
533
539
  def unique_with_counts(self, a: Tensor, **kws: Any) -> Tuple[Tensor, Tensor]:
534
540
  r = tf.unique_with_counts(a)
535
541
  order = tf.argsort(r.y)
@@ -576,7 +576,8 @@ class BaseCircuit(AbstractCircuit):
576
576
  :param random_generator: random generator, defaults to None
577
577
  :type random_generator: Optional[Any], optional
578
578
  :param status: external randomness given by tensor uniformly from [0, 1],
579
- if set, can overwrite random_generator
579
+ if set, can overwrite random_generator, shape [batch] for `allow_state=True`
580
+ and shape [batch, nqubits] for `allow_state=False` using perfect sampling implementation
580
581
  :type status: Optional[Tensor]
581
582
  :param jittable: when converting to count, whether keep the full size. if false, may be conflict
582
583
  external jit, if true, may fail for large scale system with actual limited count results
@@ -597,20 +598,24 @@ class BaseCircuit(AbstractCircuit):
597
598
  return r
598
599
  r = [r] # type: ignore
599
600
  else:
601
+ r = [] # type: ignore
602
+ if status is not None:
603
+ assert backend.shape_tuple(status)[0] == batch
604
+ for seed in status:
605
+ r.append(self.perfect_sampling(seed)) # type: ignore
600
606
 
601
- @backend.jit
602
- def perfect_sampling(key: Any) -> Any:
603
- backend.set_random_state(key)
604
- return self.perfect_sampling()
607
+ else:
605
608
 
606
- # TODO(@refraction-ray): status is not used here
609
+ @backend.jit
610
+ def perfect_sampling(key: Any) -> Any:
611
+ backend.set_random_state(key)
612
+ return self.perfect_sampling()
607
613
 
608
- r = [] # type: ignore
614
+ subkey = random_generator
615
+ for _ in range(batch):
616
+ key, subkey = backend.random_split(subkey)
617
+ r.append(perfect_sampling(key)) # type: ignore
609
618
 
610
- subkey = random_generator
611
- for _ in range(batch):
612
- key, subkey = backend.random_split(subkey)
613
- r.append(perfect_sampling(key)) # type: ignore
614
619
  if format is None:
615
620
  return r
616
621
  r = backend.stack([ri[0] for ri in r]) # type: ignore
@@ -4,21 +4,24 @@ Quantum circuit: MPS state simulator
4
4
 
5
5
  # pylint: disable=invalid-name
6
6
 
7
- from functools import reduce
7
+ from functools import reduce, partial
8
8
  from typing import Any, List, Optional, Sequence, Tuple, Dict, Union
9
9
  from copy import copy
10
+ import logging
10
11
 
11
12
  import numpy as np
12
13
  import tensornetwork as tn
13
- from tensorcircuit.quantum import QuOperator, QuVector
14
14
 
15
15
  from . import gates
16
16
  from .cons import backend, npdtype, contractor, rdtypestr, dtypestr
17
+ from .quantum import QuOperator, QuVector, extract_tensors_from_qop
17
18
  from .mps_base import FiniteMPS
18
19
  from .abstractcircuit import AbstractCircuit
20
+ from .utils import arg_alias
19
21
 
20
22
  Gate = gates.Gate
21
23
  Tensor = Any
24
+ logger = logging.getLogger(__name__)
22
25
 
23
26
 
24
27
  def split_tensor(
@@ -77,6 +80,10 @@ class MPSCircuit(AbstractCircuit):
77
80
 
78
81
  is_mps = True
79
82
 
83
+ @partial(
84
+ arg_alias,
85
+ alias_dict={"wavefunction": ["inputs"]},
86
+ )
80
87
  def __init__(
81
88
  self,
82
89
  nqubits: int,
@@ -118,8 +125,19 @@ class MPSCircuit(AbstractCircuit):
118
125
  ), "tensors and wavefunction cannot be used at input simutaneously"
119
126
  # TODO(@SUSYUSTC): find better way to address QuVector
120
127
  if isinstance(wavefunction, QuVector):
121
- wavefunction = wavefunction.eval()
122
- tensors = self.wavefunction_to_tensors(wavefunction, split=self.split)
128
+ try:
129
+ nodes, is_mps, _ = extract_tensors_from_qop(wavefunction)
130
+ if not is_mps:
131
+ raise ValueError("wavefunction is not a valid MPS")
132
+ tensors = [node.tensor for node in nodes]
133
+ except ValueError as e:
134
+ logger.warning(repr(e))
135
+ wavefunction = wavefunction.eval()
136
+ tensors = self.wavefunction_to_tensors(
137
+ wavefunction, split=self.split
138
+ )
139
+ else: # full wavefunction
140
+ tensors = self.wavefunction_to_tensors(wavefunction, split=self.split)
123
141
  assert len(tensors) == nqubits
124
142
  self._mps = FiniteMPS(tensors, canonicalize=False)
125
143
  self._mps.center_position = 0
@@ -23,6 +23,7 @@ from typing import (
23
23
  )
24
24
 
25
25
  import numpy as np
26
+ import tensornetwork as tn
26
27
  from tensornetwork.network_components import AbstractNode, CopyNode, Edge, Node, connect
27
28
  from tensornetwork.network_operations import (
28
29
  copy,
@@ -1151,33 +1152,281 @@ def generate_local_hamiltonian(
1151
1152
  return hop
1152
1153
 
1153
1154
 
1154
- def tn2qop(tn_mpo: Any) -> QuOperator:
1155
+ # TODO(@Charlespkuer): Add more conversion functions for other packages
1156
+ def extract_tensors_from_qop(qop: QuOperator) -> Tuple[List[Node], bool, int]:
1155
1157
  """
1156
- Convert MPO in TensorNetwork package to QuOperator.
1158
+ Extract and sort tensors from QuOperator for conversion to other tensor network formats.
1157
1159
 
1158
- :param tn_mpo: MPO in the form of TensorNetwork package
1159
- :type tn_mpo: ``tn.matrixproductstates.mpo.*``
1160
- :return: MPO in the form of QuOperator
1160
+ :param qop: Input QuOperator to extract tensors from
1161
+ :type qop: QuOperator
1162
+ :return: Tuple containing (sorted_nodes, is_mps, nwires) where:
1163
+ - sorted_nodes: List of Node objects sorted in linear chain order
1164
+ - is_mps: Boolean flag indicating if the structure is MPS (True) or MPO (False)
1165
+ - nwires: Integer number of physical edges/qubits in the system
1166
+ :rtype: Tuple[List[Node], bool, int]
1167
+ """
1168
+ is_mps = len(qop.in_edges) == 0
1169
+ nwires = len(qop.out_edges)
1170
+ if not is_mps and len(qop.in_edges) != nwires:
1171
+ raise ValueError(
1172
+ "MPO must have the same number of input and output edges. "
1173
+ f"Got {len(qop.in_edges)} and {nwires}."
1174
+ )
1175
+
1176
+ # Collect all nodes from edges
1177
+ nodes_for_sorting = qop.nodes
1178
+ if len(nodes_for_sorting) != nwires:
1179
+ raise ValueError(f"Number of nodes does not match number of wires.")
1180
+
1181
+ # Find endpoint nodes
1182
+ endpoint_nodes = set()
1183
+ physical_edges = set(qop.out_edges) if is_mps else set(qop.in_edges + qop.out_edges)
1184
+ if is_mps:
1185
+ rank_2_nodes = {node for node in nodes_for_sorting if len(node.edges) == 2}
1186
+ if len(rank_2_nodes) == 2:
1187
+ endpoint_nodes = rank_2_nodes
1188
+
1189
+ if not endpoint_nodes:
1190
+ endpoint_nodes = {edge.node1 for edge in qop.ignore_edges if edge.node1}
1191
+
1192
+ if not endpoint_nodes and len(nodes_for_sorting) > 1:
1193
+ virtual_bond_counts = {}
1194
+ virtual_bond_dim_sums = {}
1195
+
1196
+ for node in nodes_for_sorting:
1197
+ virtual_bonds = 0
1198
+ virtual_dim_sum = 0
1199
+
1200
+ for edge in node.edges:
1201
+ if edge not in physical_edges and not edge.is_dangling():
1202
+ virtual_bonds += 1
1203
+ virtual_dim_sum += edge.dimension
1204
+
1205
+ virtual_bond_counts[node] = virtual_bonds
1206
+ virtual_bond_dim_sums[node] = virtual_dim_sum
1207
+
1208
+ min_dim_sum = min(virtual_bond_dim_sums.values())
1209
+ min_dim_nodes = {
1210
+ node
1211
+ for node, dim_sum in virtual_bond_dim_sums.items()
1212
+ if dim_sum == min_dim_sum
1213
+ }
1214
+
1215
+ if len(min_dim_nodes) == 2:
1216
+ endpoint_nodes = min_dim_nodes
1217
+
1218
+ if not endpoint_nodes:
1219
+ if len(nodes_for_sorting) == 1:
1220
+ raise ValueError("Cannot determine chain structure: only one node found.")
1221
+ elif len(nodes_for_sorting) >= 2:
1222
+ raise ValueError(f"Cannot identify endpoint nodes for your nodes.")
1223
+
1224
+ # Sort nodes along the chain
1225
+ sorted_nodes: list[Node] = []
1226
+ if endpoint_nodes and len(endpoint_nodes) >= 1:
1227
+ current = next(iter(endpoint_nodes))
1228
+ while current and len(sorted_nodes) < nwires:
1229
+ sorted_nodes.append(current)
1230
+ current = next(
1231
+ (
1232
+ e.node2 if e.node1 is current else e.node1
1233
+ for e in current.edges
1234
+ if not e.is_dangling()
1235
+ and e not in physical_edges
1236
+ and (e.node2 if e.node1 is current else e.node1) not in sorted_nodes
1237
+ ),
1238
+ None,
1239
+ )
1240
+
1241
+ if not sorted_nodes:
1242
+ raise ValueError("No valid chain structure found in the QuOperator. ")
1243
+ if len(sorted_nodes) > 0 and len(qop.ignore_edges) > 0:
1244
+ if sorted_nodes[0] is not qop.ignore_edges[0].node1:
1245
+ sorted_nodes = sorted_nodes[::-1]
1246
+
1247
+ return sorted_nodes, is_mps, nwires
1248
+
1249
+
1250
+ def tenpy2qop(tenpy_obj: Any) -> QuOperator:
1251
+ """
1252
+ Converts a TeNPy MPO or MPS to a TensorCircuit QuOperator.
1253
+ This definitive version correctly handles axis ordering and boundary
1254
+ conditions to be compatible with `eval_matrix`.
1255
+
1256
+ :param tenpy_obj: A MPO or MPS object from the TeNPy package.
1257
+ :type tenpy_obj: Union[tenpy.networks.mpo.MPO, tenpy.networks.mps.MPS]
1258
+ :return: The corresponding state or operator as a QuOperator.
1161
1259
  :rtype: QuOperator
1162
1260
  """
1163
- tn_mpo = tn_mpo.tensors
1164
- nwires = len(tn_mpo)
1165
- mpo = []
1166
- for i in range(nwires):
1167
- mpo.append(Node(tn_mpo[i], name=f"mpo_{i}"))
1261
+ # MPO objects have _W attribute containing tensor list (documented in tenpy.networks.mpo.MPO)
1262
+ # MPS objects have _B attribute containing tensor list (documented in tenpy.networks.mps.MPS)
1263
+ # These are internal attributes that store the actual tensor data for each site
1264
+ # Reference: https://tenpy.readthedocs.io/en/latest/reference/tenpy.networks.mpo.html
1265
+ # https://tenpy.readthedocs.io/en/latest/reference/tenpy.networks.mps.html
1266
+ is_mpo = hasattr(tenpy_obj, "_W")
1267
+ tenpy_tensors = tenpy_obj._W if is_mpo else tenpy_obj._B
1268
+ nwires = len(tenpy_tensors)
1269
+ if nwires == 0:
1270
+ return quantum_constructor([], [], [])
1271
+
1272
+ nodes = []
1273
+ if is_mpo:
1274
+ original_tensors_obj = tenpy_tensors
1275
+
1276
+ for i, W_obj in enumerate(original_tensors_obj):
1277
+ arr = W_obj.to_ndarray()
1278
+ labels = W_obj.get_leg_labels()
1279
+ wL_idx = labels.index("wL")
1280
+ p_idx = labels.index("p")
1281
+ p_star_idx = labels.index("p*")
1282
+ wR_idx = labels.index("wR")
1283
+
1284
+ arr_reordered = arr.transpose((wL_idx, p_idx, p_star_idx, wR_idx))
1285
+ if nwires == 1:
1286
+ arr_reordered = arr_reordered[[0], :, :, :]
1287
+ arr_reordered = arr_reordered[:, :, :, [-1]]
1288
+ else:
1289
+ if i == 0:
1290
+ arr_reordered = arr_reordered[[0], :, :, :]
1291
+ elif i == nwires - 1:
1292
+ arr_reordered = arr_reordered[:, :, :, [-1]]
1293
+
1294
+ node = Node(
1295
+ arr_reordered, name=f"mpo_{i}", axis_names=["wL", "p", "p*", "wR"]
1296
+ )
1297
+ nodes.append(node)
1298
+
1299
+ if nwires > 1:
1300
+ for i in range(nwires - 1):
1301
+ nodes[i][3] ^ nodes[i + 1][0]
1302
+
1303
+ out_edges = [n[2] for n in nodes]
1304
+ in_edges = [n[1] for n in nodes]
1305
+ ignore_edges = [nodes[0][0], nodes[-1][3]]
1306
+ else: # MPS
1307
+ for i in range(nwires):
1308
+ B_obj = tenpy_obj.get_B(i)
1309
+ arr = B_obj.to_ndarray()
1310
+ labels = B_obj.get_leg_labels()
1311
+ vL_idx = labels.index("vL")
1312
+ p_idx = labels.index("p")
1313
+ vR_idx = labels.index("vR")
1314
+ arr_reordered = arr.transpose((vL_idx, p_idx, vR_idx))
1315
+ node = Node(arr_reordered, name=f"mps_{i}", axis_names=["vL", "p", "vR"])
1316
+ nodes.append(node)
1317
+
1318
+ if nwires > 1:
1319
+ for i in range(nwires - 1):
1320
+ nodes[i][2] ^ nodes[i + 1][0]
1321
+
1322
+ out_edges = [n[1] for n in nodes]
1323
+ in_edges = []
1324
+ ignore_edges = [nodes[0][0], nodes[-1][2]]
1325
+
1326
+ qop = quantum_constructor(out_edges, in_edges, [], ignore_edges)
1168
1327
 
1169
- for i in range(nwires - 1):
1170
- connect(mpo[i][1], mpo[i + 1][0])
1171
- # TODO(@refraction-ray): whether in and out edge is in the correct order require further check
1172
- qop = quantum_constructor(
1173
- [mpo[i][-1] for i in range(nwires)], # out_edges
1174
- [mpo[i][-2] for i in range(nwires)], # in_edges
1175
- [],
1176
- [mpo[0][0], mpo[-1][1]], # ignore_edges
1177
- )
1178
1328
  return qop
1179
1329
 
1180
1330
 
1331
+ def qop2tenpy(qop: QuOperator) -> Any:
1332
+ """
1333
+ Convert TensorCircuit QuOperator to MPO or MPS from TeNPy.
1334
+
1335
+ Requirements: QuOperator must represent valid MPS/MPO structure:
1336
+ - Linear chain topology with open boundaries only
1337
+ - MPS: no input edges, consistent virtual bonds, rank-3 or 4(with empty input edges) tensors
1338
+ - MPO: equal input/output edges, rank-4 tensors
1339
+ - Cyclic boundary conditions NOT supported
1340
+
1341
+ :param qop: The corresponding state/operator as a QuOperator.
1342
+ :type qop: QuOperator
1343
+ :return: MPO or MPS object from the TeNPy package.
1344
+ :rtype: Union[tenpy.networks.mpo.MPO, tenpy.networks.mps.MPS]
1345
+ """
1346
+ try:
1347
+ from tenpy.networks import MPO, MPS, Site
1348
+ from tenpy.linalg import np_conserved as npc
1349
+ from tenpy.linalg import LegCharge
1350
+ except ImportError:
1351
+ raise ImportError("Please install TeNPy package to use this function.")
1352
+
1353
+ sorted_nodes, is_mps, nwires = extract_tensors_from_qop(qop)
1354
+
1355
+ physical_dim = qop.out_edges[0].dimension if is_mps else qop.in_edges[0].dimension
1356
+ sites = [Site(LegCharge.from_trivial(physical_dim), "q") for _ in range(nwires)]
1357
+
1358
+ # MPS Conversion
1359
+ if is_mps:
1360
+ tensors = []
1361
+ for i, node in enumerate(sorted_nodes):
1362
+ tensor = np.asarray(node.tensor)
1363
+ if tensor.ndim == 3:
1364
+ if i == 0:
1365
+ if tensor.shape[0] > 1:
1366
+ tensor = tensor[0:1, :, :]
1367
+ elif i == len(sorted_nodes) - 1:
1368
+ if tensor.shape[2] > 1:
1369
+ tensor = tensor[:, :, 0:1]
1370
+ tensors.append(
1371
+ npc.Array.from_ndarray(
1372
+ tensor,
1373
+ legcharges=[LegCharge.from_trivial(s) for s in tensor.shape],
1374
+ labels=["vL", "p", "vR"],
1375
+ )
1376
+ )
1377
+
1378
+ SVs = (
1379
+ [np.ones([1])]
1380
+ + [np.ones(tensors[i].get_leg("vR").ind_len) for i in range(nwires - 1)]
1381
+ + [np.ones([1])]
1382
+ )
1383
+ return MPS(sites, tensors, SVs, bc="finite")
1384
+
1385
+ # MPO Conversion
1386
+ raw_tensors = [np.asarray(node.tensor) for node in sorted_nodes]
1387
+
1388
+ if nwires == 1:
1389
+ chi = 1
1390
+ IdL = IdR = 0
1391
+ reconstructed_tensors = raw_tensors
1392
+ else:
1393
+ chi = max(
1394
+ raw_tensors[0].shape[3] if raw_tensors[0].ndim > 3 else 1,
1395
+ raw_tensors[-1].shape[0] if raw_tensors[-1].ndim > 3 else 1,
1396
+ )
1397
+ IdL = 0
1398
+ IdR = chi - 1 if chi > 1 else 0
1399
+
1400
+ reconstructed_tensors = []
1401
+ for i, tensor in enumerate(raw_tensors):
1402
+ if i == 0 and tensor.shape[0] < chi:
1403
+ new_shape = (chi,) + tensor.shape[1:]
1404
+ padded_tensor = np.zeros(new_shape, dtype=tensor.dtype)
1405
+ padded_tensor[IdL, ...] = tensor[0, ...]
1406
+ reconstructed_tensors.append(padded_tensor)
1407
+ elif i == nwires - 1 and len(tensor.shape) > 3 and tensor.shape[3] < chi:
1408
+ new_shape = tensor.shape[:3] + (chi,)
1409
+ padded_tensor = np.zeros(new_shape, dtype=tensor.dtype)
1410
+ padded_tensor[..., IdR] = tensor[..., 0]
1411
+ reconstructed_tensors.append(padded_tensor)
1412
+ else:
1413
+ reconstructed_tensors.append(tensor)
1414
+
1415
+ tenpy_Ws = []
1416
+ for tensor in reconstructed_tensors:
1417
+ labels = ["wL", "wR", "p", "p*"]
1418
+ tensor = np.transpose(tensor, (0, 3, 1, 2))
1419
+ tenpy_Ws.append(
1420
+ npc.Array.from_ndarray(
1421
+ tensor,
1422
+ legcharges=[LegCharge.from_trivial(s) for s in tensor.shape],
1423
+ labels=labels,
1424
+ )
1425
+ )
1426
+
1427
+ return MPO(sites, tenpy_Ws, bc="finite", IdL=IdL, IdR=IdR)
1428
+
1429
+
1181
1430
  def quimb2qop(qb_mpo: Any) -> QuOperator:
1182
1431
  """
1183
1432
  Convert MPO in Quimb package to QuOperator.
@@ -1219,6 +1468,152 @@ def quimb2qop(qb_mpo: Any) -> QuOperator:
1219
1468
  return qop
1220
1469
 
1221
1470
 
1471
+ def qop2quimb(qop: QuOperator) -> Any:
1472
+ """
1473
+ Convert QuOperator to MPO or MPS in Quimb package.
1474
+
1475
+ Requirements: QuOperator must represent valid MPS/MPO structure:
1476
+ - Linear chain topology with open boundaries only
1477
+ - MPS: no input edges, consistent virtual bonds between adjacent tensors
1478
+ - MPO: equal input/output edges, rank-4 tensors
1479
+ - Edge connectivity: each internal node connected to exactly 2 neighbors
1480
+ - Cyclic boundary conditions NOT supported
1481
+
1482
+ :param qop: MPO in the form of QuOperator
1483
+ :type qop: QuOperator
1484
+ :return: MPO in the form of Quimb package
1485
+ :rtype: quimb.tensor.tensor_gen.MatrixProductOperator
1486
+ """
1487
+ try:
1488
+ import quimb.tensor as qtn
1489
+ except ImportError:
1490
+ raise ImportError("Please install Quimb package to use this function.")
1491
+
1492
+ sorted_nodes, is_mps, _ = extract_tensors_from_qop(qop)
1493
+
1494
+ quimb_tensors = []
1495
+ node_map = {node: i for i, node in enumerate(sorted_nodes)}
1496
+
1497
+ for i, node in enumerate(sorted_nodes):
1498
+ tensor_data = node.tensor
1499
+ inds: List[str] = []
1500
+
1501
+ for axis, edge in enumerate(node.edges):
1502
+ if edge in qop.out_edges:
1503
+ site_index = qop.out_edges.index(edge)
1504
+ inds.append(f"k{site_index}")
1505
+ elif edge in qop.in_edges and not is_mps:
1506
+ site_index = qop.in_edges.index(edge)
1507
+ inds.append(f"b{site_index}")
1508
+ elif edge in qop.ignore_edges:
1509
+ if i == 0:
1510
+ inds.append("_left_dangling")
1511
+ elif i == len(sorted_nodes) - 1:
1512
+ inds.append("_right_dangling")
1513
+ else:
1514
+ inds.append(f"_ignore_{i}_{axis}")
1515
+ else:
1516
+ neighbor = edge.node1 if edge.node2 is node else edge.node2
1517
+ if neighbor in node_map:
1518
+ j = node_map[neighbor]
1519
+ left, right = min(i, j), max(i, j)
1520
+ inds.append(f"v{left}_{right}")
1521
+ else:
1522
+ inds.append(f"_unconnected_{i}_{axis}")
1523
+
1524
+ quimb_tensors.append(qtn.Tensor(tensor_data, inds=inds, tags=f"I{i}"))
1525
+
1526
+ tn = qtn.TensorNetwork(quimb_tensors)
1527
+
1528
+ if is_mps:
1529
+ return tn.as_network(qtn.MatrixProductState)
1530
+ else:
1531
+ return tn.as_network(qtn.MatrixProductOperator)
1532
+
1533
+
1534
+ def tn2qop(tn_obj: Any) -> QuOperator:
1535
+ """
1536
+ Convert MPO in TensorNetwork package to QuOperator.
1537
+
1538
+ :param tn_mpo: MPO in the form of TensorNetwork package
1539
+ :type tn_mpo: ``tn.matrixproductstates.mpo.*``
1540
+ :return: MPO in the form of QuOperator
1541
+ :rtype: QuOperator
1542
+ """
1543
+ tn_tensors = tn_obj.tensors
1544
+ nwires = len(tn_tensors)
1545
+
1546
+ if nwires == 0:
1547
+ return quantum_constructor([], [], [])
1548
+
1549
+ is_mps = all(len(t.shape) <= 3 for t in tn_tensors)
1550
+
1551
+ nodes = []
1552
+ for i in range(nwires):
1553
+ nodes.append(Node(tn_tensors[i], name=f"tensor_{i}"))
1554
+
1555
+ if is_mps:
1556
+ for i in range(nwires - 1):
1557
+ connect(nodes[i][-1], nodes[i + 1][0])
1558
+
1559
+ out_edges = []
1560
+ for i, node in enumerate(nodes):
1561
+ if len(node.edges) == 2:
1562
+ physical_edge = next(e for e in node.edges if e.is_dangling())
1563
+ out_edges.append(physical_edge)
1564
+ else:
1565
+ out_edges.append(node[1])
1566
+
1567
+ in_edges = []
1568
+
1569
+ ignore_edges = []
1570
+ left_dangling = next(
1571
+ (e for e in nodes[0].edges if e.is_dangling() and e not in out_edges), None
1572
+ )
1573
+ right_dangling = next(
1574
+ (e for e in nodes[-1].edges if e.is_dangling() and e not in out_edges), None
1575
+ )
1576
+
1577
+ if left_dangling:
1578
+ ignore_edges.append(left_dangling)
1579
+ if right_dangling:
1580
+ ignore_edges.append(right_dangling)
1581
+
1582
+ else:
1583
+ for i in range(nwires - 1):
1584
+ connect(nodes[i][1], nodes[i + 1][0])
1585
+
1586
+ out_edges = [nodes[i][-1] for i in range(nwires)]
1587
+ in_edges = [nodes[i][-2] for i in range(nwires)]
1588
+ ignore_edges = [nodes[0][0], nodes[-1][1]]
1589
+
1590
+ qop = quantum_constructor(
1591
+ out_edges,
1592
+ in_edges,
1593
+ [],
1594
+ ignore_edges,
1595
+ )
1596
+ return qop
1597
+
1598
+
1599
+ def qop2tn(qop: QuOperator) -> Any:
1600
+ """
1601
+ Convert QuOperator back to MPO or MPS in TensorNetwork package.
1602
+
1603
+ :param qop: MPO or MPS in the form of QuOperator, param in docstring
1604
+ :return: MPO or MPS in the form of TensorNetwork
1605
+ :rtype: Union[tn.matrixproductstates.MPO, tn.matrixproductstates.MPS]
1606
+ """
1607
+ sorted_nodes, is_mps, _ = extract_tensors_from_qop(qop)
1608
+
1609
+ tensors = [node.tensor for node in sorted_nodes]
1610
+
1611
+ if is_mps:
1612
+ return tn.FiniteMPS(tensors, canonicalize=False)
1613
+ else:
1614
+ return tn.matrixproductstates.mpo.FiniteMPO(tensors)
1615
+
1616
+
1222
1617
  # TODO(@refraction-ray): Z2 analogy or more general analogies for the following u1 functions
1223
1618
 
1224
1619
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tensorcircuit-nightly
3
- Version: 1.3.0.dev20250811
3
+ Version: 1.3.0.dev20250813
4
4
  Summary: High performance unified quantum computing framework for the NISQ era
5
5
  Author-email: TensorCircuit Authors <znfesnpbh@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -342,6 +342,7 @@ TensorCircuit-NG is open source, released under the Apache License, Version 2.0.
342
342
  </tr>
343
343
  <tr>
344
344
  <td align="center" valign="top" width="16.66%"><a href="https://github.com/Stellogic"><img src="https://avatars.githubusercontent.com/u/186928579?v=4?s=100" width="100px;" alt="Stellogic"/><br /><sub><b>Stellogic</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Code">💻</a> <a href="#example-Stellogic" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Stellogic" title="Tests">⚠️</a></td>
345
+ <td align="center" valign="top" width="16.66%"><a href="https://github.com/Charlespkuer"><img src="https://avatars.githubusercontent.com/u/112697147?v=4?s=100" width="100px;" alt="Huang"/><br /><sub><b>Huang</b></sub></a><br /><a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Code">💻</a> <a href="#example-Charlespkuer" title="Examples">💡</a> <a href="https://github.com/tensorcircuit/tensorcircuit-ng/commits?author=Charlespkuer" title="Tests">⚠️</a></td>
345
346
  </tr>
346
347
  </tbody>
347
348
  </table>