tensorcircuit-nightly 1.3.0.dev20250812__tar.gz → 1.3.0.dev20250814__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.
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/CHANGELOG.md +8 -0
- {tensorcircuit_nightly-1.3.0.dev20250812/tensorcircuit_nightly.egg-info → tensorcircuit_nightly-1.3.0.dev20250814}/PKG-INFO +2 -1
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/README.md +1 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/__init__.py +1 -1
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/abstract_backend.py +15 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/jax_backend.py +3 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/numpy_backend.py +3 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/tensorflow_backend.py +6 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/basecircuit.py +16 -11
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/mpscircuit.py +22 -4
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/quantum.py +414 -19
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814/tensorcircuit_nightly.egg-info}/PKG-INFO +2 -1
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/HISTORY.md +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/LICENSE +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/MANIFEST.in +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/README_cn.md +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/pyproject.toml +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/setup.cfg +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/setup.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/about.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/abstractcircuit.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/ai/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/ai/ensemble.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/dqas.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/finance/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/finance/portfolio.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/graphdata.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/layers.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/optimization.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/physics/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/physics/baseline.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/physics/fss.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/utils.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/vags.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/van.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/applications/vqes.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/asciiart.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/backend_factory.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/cupy_backend.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/jax_ops.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/pytorch_backend.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/pytorch_ops.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/backends/tf_ops.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/channels.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/circuit.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/abstraction.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/apis.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/config.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/local.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/quafu_provider.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/tencent.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/utils.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cloud/wrapper.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/compiler/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/compiler/composed_compiler.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/compiler/qiskit_compiler.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/compiler/simple_compiler.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/cons.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/densitymatrix.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/experimental.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/fgs.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/gates.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/jax.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/numpy.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/scipy.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/tensorflow.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/tensortrans.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/interfaces/torch.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/keras.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/mps_base.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/noisemodel.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/counts.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/qem/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/qem/benchmark_circuits.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/qem/qem_methods.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/results/readout_mitigation.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/shadows.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/simplify.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/stabilizercircuit.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/__init__.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/ansatz.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/blocks.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/chems.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/conversions.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/dataset.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/graphs.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/hamiltonians.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/lattice.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/templates/measurements.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/timeevol.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/torchnn.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/translation.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/utils.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit/vis.py +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit_nightly.egg-info/SOURCES.txt +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit_nightly.egg-info/dependency_links.txt +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit_nightly.egg-info/requires.txt +0 -0
- {tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/tensorcircuit_nightly.egg-info/top_level.txt +0 -0
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/CHANGELOG.md
RENAMED
|
@@ -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.
|
|
3
|
+
Version: 1.3.0.dev20250814
|
|
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>
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/README.md
RENAMED
|
@@ -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>
|
|
@@ -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
|
-
|
|
602
|
-
def perfect_sampling(key: Any) -> Any:
|
|
603
|
-
backend.set_random_state(key)
|
|
604
|
-
return self.perfect_sampling()
|
|
607
|
+
else:
|
|
605
608
|
|
|
606
|
-
|
|
609
|
+
@backend.jit
|
|
610
|
+
def perfect_sampling(key: Any) -> Any:
|
|
611
|
+
backend.set_random_state(key)
|
|
612
|
+
return self.perfect_sampling()
|
|
607
613
|
|
|
608
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1158
|
+
Extract and sort tensors from QuOperator for conversion to other tensor network formats.
|
|
1157
1159
|
|
|
1158
|
-
:param
|
|
1159
|
-
:type
|
|
1160
|
-
:return:
|
|
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
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
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.
|
|
3
|
+
Version: 1.3.0.dev20250814
|
|
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>
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/HISTORY.md
RENAMED
|
File without changes
|
|
File without changes
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/MANIFEST.in
RENAMED
|
File without changes
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/README_cn.md
RENAMED
|
File without changes
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/pyproject.toml
RENAMED
|
File without changes
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/setup.cfg
RENAMED
|
File without changes
|
{tensorcircuit_nightly-1.3.0.dev20250812 → tensorcircuit_nightly-1.3.0.dev20250814}/setup.py
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
|
|
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
|
|
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
|
|
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
|
|
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
|