Skip to content

Commit 2cf3eef

Browse files
committed
Changes on tenpy_sz_convention.py
1 parent 89e289a commit 2cf3eef

File tree

2 files changed

+71
-25
lines changed

2 files changed

+71
-25
lines changed

examples/dmrg_tenpy_integration.py renamed to examples/tenpy_sz_convention.py

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
"""
2-
Demonstration of TeNPy-DMRG and TensorCircuit integration
3-
1. Compute ground state (MPS) of 1D Transverse Field Ising model using TeNPy
4-
2. Convert MPS to TensorCircuit's QuOperator
5-
3. Initialize MPSCircuit with converted state and verify results
2+
Demonstrates the different internal basis conventions between
3+
TeNPy's TFIChain and XXZChain models and showcases a robust
4+
method for handling these inconsistencies when converting to TensorCircuit.
5+
6+
1. TFIChain: Shows a direct conversion works perfectly.
7+
2. XXZChain:
8+
a. Runs DMRG to obtain a non-trivial ground state.
9+
b. Shows that direct conversion leads to incorrect expectation values for correlation functions.
10+
c. Demonstrates that applying a layer of X-gates in TensorCircuit
11+
3. Tensor Dissection: Provides definitive proof of the differing internal basis conventions between the two models.
612
"""
713

814
import numpy as np
@@ -14,7 +20,6 @@
1420
import tensorcircuit as tc
1521

1622
print("Scenario 1: Antiferromagnetic State (TFIChain)")
17-
1823
L = 10
1924
afm_model_params = {"L": L, "bc_MPS": "finite", "J": 1.0, "g": 0.0, "conserve": None}
2025
afm_M = TFIChain(afm_model_params)
@@ -33,7 +38,6 @@
3338
for i in range(L)
3439
]
3540
)
36-
3741
print("\nAntiferromagnetic state site-by-site magnetization comparison:")
3842
print("TeNPy:", np.round(mag_z_afm_tenpy, 8))
3943
print("TC: ", np.round(mag_z_afm_tc, 8))
@@ -42,21 +46,17 @@
4246
"\n[SUCCESS] TFI-based Antiferromagnetic state matches perfectly with the pure converter."
4347
)
4448

45-
# --- Scenario 2: XXZChain Model ---
46-
print("Scenario 2: XXZChain Model")
4749

50+
print("Scenario 2: XXZChain Model")
4851
xxz_model_params = {"L": L, "bc_MPS": "finite", "Jxx": 1.0, "Jz": 0.5, "hz": 0.1}
4952
xxz_M = XXZChain(xxz_model_params)
50-
rng = np.random.default_rng(42)
51-
random_state = rng.choice(["up", "down"], size=L).tolist()
52-
print(f"Testing with a random product state: {random_state}")
53-
53+
example_state = ["up", "down", "up", "up", "down", "down", "up", "down", "down", "up"]
54+
print(f"Testing with a random product state: {example_state}")
5455
psi_rand_xxz = MPS.from_product_state(
55-
xxz_M.lat.mps_sites(), random_state, bc=xxz_M.lat.bc_MPS
56+
xxz_M.lat.mps_sites(), example_state, bc=xxz_M.lat.bc_MPS
5657
)
5758
tc_rand_xxz_state = tc.quantum.tenpy2qop(psi_rand_xxz)
5859
circuit_rand_xxz = tc.MPSCircuit(L, wavefunction=tc_rand_xxz_state)
59-
6060
mag_z_rand_xxz_tenpy = psi_rand_xxz.expectation_value("Sz")
6161
mag_z_rand_xxz_tc = np.array(
6262
[
@@ -67,11 +67,9 @@
6767
for i in range(L)
6868
]
6969
)
70-
7170
print("\nXXZ-based random state site-by-site magnetization comparison:")
7271
print("TeNPy:", np.round(mag_z_rand_xxz_tenpy, 8))
7372
print("TC: ", np.round(mag_z_rand_xxz_tc, 8))
74-
7573
try:
7674
np.testing.assert_allclose(mag_z_rand_xxz_tenpy, mag_z_rand_xxz_tc, atol=1e-5)
7775
except AssertionError as e:
@@ -85,12 +83,10 @@
8583
"[SUCCESS] Test passes after applying the sign correction for the XXZChain model."
8684
)
8785

88-
# --- Scenario 3: Tensor Dissection for Both Models ---
89-
print("Scenario 3: Tensor Dissection for Both Models")
9086

87+
print("Scenario 3: Tensor Dissection for Both Models")
9188
simple_L = 2
9289
simple_labels = ["up", "down"]
93-
9490
print("\nDissecting TFIChain-based Tensors")
9591
sites_tfi = afm_M.lat.mps_sites()[:simple_L]
9692
psi_simple_tfi = MPS.from_product_state(sites_tfi, simple_labels, bc="finite")
@@ -99,7 +95,6 @@
9995
print(
10096
f"For '{label}', TFIChain internal tensor has non-zero at physical index {np.where(B_tensor[0,:,0] != 0)[0][0]}"
10197
)
102-
10398
print("\nDissecting XXZChain-based Tensors")
10499
sites_xxz = xxz_M.lat.mps_sites()[:simple_L]
105100
psi_simple_xxz = MPS.from_product_state(sites_xxz, simple_labels, bc="finite")
@@ -108,9 +103,7 @@
108103
print(
109104
f"For '{label}', XXZChain internal tensor has non-zero at physical index {np.where(B_tensor[0,:,0] != 0)[0][0]}"
110105
)
111-
112-
113-
print("\nFinal Conclusion")
106+
print("\n Conclusion")
114107
print("The dissection above shows the root cause of the different behaviors:")
115108
print(
116109
" - TFIChain's 'up' maps to index 0, 'down' to index 1. This matches TC's standard."
@@ -124,4 +117,47 @@
124117
)
125118
print("or to create model-specific converters.")
126119

120+
121+
print("--- Scenario 3: Correcting XXZChain DMRG state with X-gates ---")
122+
123+
L = 10
124+
xxz_model_params = {"L": L, "bc_MPS": "finite", "Jxx": 1.0, "Jz": 1.0, "conserve": None}
125+
xxz_M = XXZChain(xxz_model_params)
126+
psi0_xxz = MPS.from_product_state(
127+
xxz_M.lat.mps_sites(), ["up", "down"] * (L // 2), bc=xxz_M.lat.bc_MPS
128+
)
129+
dmrg_params = {"max_sweeps": 10, "trunc_params": {"chi_max": 64}}
130+
eng = dmrg.TwoSiteDMRGEngine(psi0_xxz, xxz_M, dmrg_params)
131+
E, psi_gs_xxz = eng.run()
132+
print(f"XXZ DMRG finished. Ground state energy: {E:.10f}")
133+
134+
state_raw_quvector = tc.quantum.tenpy2qop(psi_gs_xxz)
135+
136+
i, j = L // 2 - 1, L // 2
137+
corr_tenpy = psi_gs_xxz.correlation_function("Sz", "Sz", sites1=[i], sites2=[j])[0, 0]
138+
print("\nApplying X-gate to each qubit to correct the basis convention...")
139+
circuit_to_be_corrected = tc.MPSCircuit(L, wavefunction=state_raw_quvector)
140+
141+
for k in range(L):
142+
circuit_to_be_corrected.x(k)
143+
144+
corr_tc_corrected = (
145+
tc.backend.real(
146+
circuit_to_be_corrected.expectation((tc.gates.z(), [i]), (tc.gates.z(), [j]))
147+
)
148+
/ 4.0
149+
)
150+
151+
print(f"\nComparing <Sz_{i}Sz_{j}> correlation function for the DMRG ground state:")
152+
print(f"TeNPy (Ground Truth): {corr_tenpy:.8f}")
153+
print(f"TC (after X-gate correction): {corr_tc_corrected:.8f}")
154+
np.testing.assert_allclose(corr_tenpy, corr_tc_corrected, atol=1e-5)
155+
print(
156+
"\n[SUCCESS] The correlation functions match perfectly after applying the X-gate correction."
157+
)
158+
print(
159+
"This demonstrates the recommended physical approach to handle the XXZChain's inverted basis convention."
160+
)
161+
162+
127163
print("\n\nWorkflow demonstration and analysis complete!")

tensorcircuit/quantum.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,8 +1301,18 @@ def tenpy2qop(tenpy_obj: Any) -> QuOperator:
13011301
out_edges = [node["p*"] for node in nodes]
13021302
in_edges = [node["p"] for node in nodes]
13031303
ignore_edges = [nodes[0]["wL"], nodes[-1]["wR"]]
1304-
else:
1305-
nodes = [Node(W.to_ndarray()) for W in tenpy_tensors]
1304+
else: # MPS
1305+
nodes = []
1306+
for i in range(nwires):
1307+
B_obj = tenpy_obj.get_B(i)
1308+
arr = B_obj.to_ndarray()
1309+
labels = B_obj.get_leg_labels()
1310+
vL_idx = labels.index("vL")
1311+
p_idx = labels.index("p")
1312+
vR_idx = labels.index("vR")
1313+
arr_reordered = arr.transpose((vL_idx, p_idx, vR_idx))
1314+
node = Node(arr_reordered, name=f"mps_{i}", axis_names=["vL", "p", "vR"])
1315+
nodes.append(node)
13061316

13071317
if nwires > 1:
13081318
for i in range(nwires - 1):

0 commit comments

Comments
 (0)