-
Notifications
You must be signed in to change notification settings - Fork 19
Fix cotengra bug for empty contraction paths with tests #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -545,3 +545,24 @@ | |
| qir = c.to_qir() | ||
| c2 = tc.Circuit.from_qir(qir, circuit_params={"nqubits": n}) | ||
| np.testing.assert_allclose(c.state(), c2.state(), atol=1e-5) | ||
|
|
||
| @pytest.mark.parametrize("contractor_setup", [("cotengra", {"use_primitives": True})], indirect=True) | ||
| def test_algebraic_contraction_edge_cases(contractor_setup, backend_setup): | ||
| from tensorcircuit.cons import _algebraic_base_contraction | ||
| import opt_einsum | ||
|
Comment on lines
+551
to
+552
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is generally preferred to place imports at the top of the file to adhere to PEP 8 guidelines and improve readability, unless there is a specific reason for a local import (e.g., avoiding circular dependencies). Since References
|
||
|
|
||
| # 0 nodes case | ||
| res0 = _algebraic_base_contraction([], opt_einsum.paths.greedy) | ||
| np.testing.assert_allclose(tc.backend.numpy(res0.tensor), 1.0) | ||
|
|
||
| # 1 node case | ||
| a = tn.Node(tc.backend.convert_to_tensor(np.array([1.0, 2.0]))) | ||
| res1 = _algebraic_base_contraction([a], opt_einsum.paths.greedy) | ||
| np.testing.assert_allclose(tc.backend.numpy(res1.tensor), np.array([1.0, 2.0])) | ||
|
|
||
| # 1 node with self-loop (trace) | ||
| # _extract_topology handles traces by mapping them to symbols | ||
| b = tn.Node(tc.backend.convert_to_tensor(np.eye(2))) | ||
| b[0] ^ b[1] | ||
|
Check warning on line 566 in tests/test_hyperedge.py
|
||
|
|
||
| res1_trace = _algebraic_base_contraction([b], opt_einsum.paths.greedy) | ||
| np.testing.assert_allclose(tc.backend.numpy(res1_trace.tensor), 2.0) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The check
len(raw_tensors) == 0correctly handles the case wherenodesis empty, but it also catches cases wherenodescontains onlyCopyNodes (hyperedges). In the latter case, if there are dangling edges, returning a scalarones([])will cause a crash at line 632 because the tensor rank (0) will not match the number of dangling edges. It is safer to explicitly check ifnodesis empty for the scalar 1.0 result, or handle theCopyNode-only case specifically.