Skip to content

Commit 6a44563

Browse files
Merge branch 'MPS-to-vector-feature' into Noise_Characterization
2 parents fa9b3e9 + e7815d2 commit 6a44563

28 files changed

+417
-120
lines changed

examples/1_Noisy_Ising_Model.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111

1212
# Define the system Hamiltonian
1313
L = 10
14-
d = 2
1514
J = 1
1615
g = 0.5
1716
H_0 = MPO()
18-
H_0.init_Ising(L, d, J, g)
17+
H_0.init_Ising(L, J, g)
1918

2019
# Define the initial state
2120
state = MPS(L, state='zeros')

examples/2_Equivalence_Checking.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from qiskit.circuit.library.n_local import TwoLocal
55
import qiskit.compiler
66

7-
from yaqs.circuits.equivalence_checking import equivalence_checker
7+
from yaqs.circuits import equivalence_checker
88

99
# Define the initial circuit
1010
num_qubits = 5

examples/5_Benchmarker.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
num_qubits = 10
66
model = {'name': 'Ising', 'L': num_qubits, 'J': 1, 'g': 0.5}
77
demo_circuit = create_Ising_circuit(model, dt=0.1, timesteps=10)
8-
9-
# Run the benchmark on the demo circuit.
10-
benchmarker.run(demo_circuit, style='dots')
8+
if __name__ == "__main__":
9+
# Run the benchmark on the demo circuit.
10+
benchmarker.run(demo_circuit, style='dots')

src/yaqs/circuits/CircuitTJM.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from yaqs.core.methods.dissipation import apply_dissipation
1111
from yaqs.core.methods.stochastic_process import stochastic_process
1212
from yaqs.core.methods.operations import measure
13-
from yaqs.circuits.dag.dag_utils import convert_dag_to_tensor_algorithm
13+
from yaqs.circuits.utils.dag_utils import convert_dag_to_tensor_algorithm
1414

1515

1616
from typing import TYPE_CHECKING, Union
@@ -78,7 +78,6 @@ def construct_generator_MPO(gate, length: int) -> MPO | int | int:
7878
W = np.zeros((1, 1, 2, 2), dtype=complex)
7979
W[0, 0] = gate.generator[second_gen]
8080
tensors.append(W)
81-
# break
8281
else:
8382
W = np.zeros((1, 1, 2, 2), dtype=complex)
8483
W[0, 0] = np.eye(2)

src/yaqs/circuits/equivalence_checking/equivalence_checker.py renamed to src/yaqs/circuits/equivalence_checker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import time
44

55
from yaqs.core.data_structures.networks import MPO
6-
from yaqs.circuits.equivalence_checking.mpo_utils import iterate
6+
from yaqs.circuits.utils.mpo_utils import iterate
77

88
from typing import TYPE_CHECKING
99
if TYPE_CHECKING:

src/yaqs/circuits/equivalence_checking/mpo_utils.py renamed to src/yaqs/circuits/utils/mpo_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import opt_einsum as oe
44
from qiskit.converters import dag_to_circuit
55

6-
from yaqs.circuits.dag.dag_utils import check_longest_gate, convert_dag_to_tensor_algorithm, get_temporal_zone, select_starting_point
6+
from yaqs.circuits.utils.dag_utils import check_longest_gate, convert_dag_to_tensor_algorithm, get_temporal_zone, select_starting_point
77

88
from typing import TYPE_CHECKING
99
if TYPE_CHECKING:

src/yaqs/core/data_structures/networks.py

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# Convention (sigma, chi_l-1, chi_l)
1414
class MPS:
1515
def __init__(self, length: int, tensors: list = None, physical_dimensions: list = None, state: str = 'zeros'):
16+
self.flipped = False
1617
if tensors is not None:
1718
assert len(tensors) == length
1819
self.tensors = tensors
@@ -65,14 +66,19 @@ def __init__(self, length: int, tensors: list = None, physical_dimensions: list
6566
vector[0] = 1
6667
else:
6768
vector[1] = 1
69+
elif state == 'random':
70+
vector[0] = np.random.rand()
71+
vector[1] = 1 - vector[0]
6872
else:
6973
raise ValueError("Invalid state string")
7074

7175
tensor = np.expand_dims(vector, axis=(0, 1))
7276

7377
tensor = np.transpose(tensor, (2, 0, 1))
7478
self.tensors.append(tensor)
75-
self.flipped = False
79+
80+
if state == 'random':
81+
self.normalize()
7682

7783
def write_max_bond_dim(self) -> int:
7884
global_max = 0
@@ -279,10 +285,44 @@ def convert_to_vector(self) -> np.ndarray:
279285
vec = vec.flatten()
280286
return vec
281287

288+
def convert_to_vector(self) -> np.ndarray:
289+
"""
290+
Converts the MPS to a full state vector representation.
291+
292+
Returns:
293+
A one-dimensional NumPy array of length \(\prod_{\ell=1}^L d_\ell\)
294+
representing the state vector.
295+
"""
296+
# Start with the first tensor.
297+
# Assume each tensor has shape (d, chi_left, chi_right) with chi_left=1 for the first tensor.
298+
vec = self.tensors[0] # shape: (d_1, 1, chi_1)
299+
300+
# Contract sequentially with the remaining tensors.
301+
for i in range(1, self.length):
302+
# Contract the last bond of vec with the middle index (left bond) of the next tensor.
303+
vec = np.tensordot(vec, self.tensors[i], axes=([-1], [1]))
304+
# After tensordot, if vec had shape (..., chi_i) and the new tensor has shape (d_{i+1}, chi_i, chi_{i+1}),
305+
# then vec now has shape (..., d_{i+1}, chi_{i+1}).
306+
# Reshape to merge all physical indices into one index.
307+
new_shape = (-1, vec.shape[-1])
308+
vec = np.reshape(vec, new_shape)
309+
310+
# At the end, the final bond dimension should be 1.
311+
vec = np.squeeze(vec, axis=-1)
312+
# Flatten the resulting multi-index into a one-dimensional state vector.
313+
vec = vec.flatten()
314+
return vec
315+
316+
317+
318+
319+
320+
282321

283322
# Convention (sigma, sigma', chi_l, chi_l+1)
284323
class MPO:
285-
def init_Ising(self, length: int, physical_dimension: int, J: float, g: float):
324+
def init_Ising(self, length: int, J: float, g: float):
325+
physical_dimension = 2
286326
zero = np.zeros((physical_dimension, physical_dimension), dtype=complex)
287327
identity = np.eye(physical_dimension, dtype=complex)
288328
X = getattr(GateLibrary, "x")().matrix
@@ -323,7 +363,8 @@ def init_Ising(self, length: int, physical_dimension: int, J: float, g: float):
323363
self.length = length
324364
self.physical_dimension = physical_dimension
325365

326-
def init_Heisenberg(self, length: int, physical_dimension: int, Jx: float, Jy: float, Jz: float, h: float):
366+
def init_Heisenberg(self, length: int, Jx: float, Jy: float, Jz: float, h: float):
367+
physical_dimension = 2
327368
zero = np.zeros((physical_dimension, physical_dimension), dtype=complex)
328369
identity = np.eye(physical_dimension, dtype=complex)
329370
X = getattr(GateLibrary, "x")().matrix

src/yaqs/core/data_structures/simulation_parameters.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def __init__(self, name: str, site: int):
1111
self.trajectories = None
1212

1313
def initialize(self, sim_params):
14+
self.results = None
1415
if type(sim_params) == PhysicsSimParams:
1516
if sim_params.sample_timesteps:
1617
self.trajectories = np.empty((sim_params.N, len(sim_params.times)), dtype=float)

src/yaqs/core/libraries/circuit_library.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,22 @@ def create_Ising_circuit(model, dt, timesteps):
1717
circ.rx(theta=alpha, qubit=site)
1818

1919
for site in range(model['L'] // 2):
20-
circ.cx(control_qubit=2*site, target_qubit=2*site+1)
21-
circ.rz(phi=beta, qubit=2*site+1)
22-
circ.cx(control_qubit=2*site, target_qubit=2*site+1)
20+
circ.rzz(beta, qubit1=2*site, qubit2=2*site+1)
21+
# circ.cx(control_qubit=2*site, target_qubit=2*site+1)
22+
# circ.rz(phi=beta, qubit=2*site+1)
23+
# circ.cx(control_qubit=2*site, target_qubit=2*site+1)
2324

2425
for site in range(1, model['L'] // 2):
25-
circ.cx(control_qubit=2*site-1, target_qubit=2*site)
26-
circ.rz(phi=beta, qubit=2*site)
27-
circ.cx(control_qubit=2*site-1, target_qubit=2*site)
26+
circ.rzz(beta, qubit1=2*site-1, qubit2=2*site)
27+
# circ.cx(control_qubit=2*site-1, target_qubit=2*site)
28+
# circ.rz(phi=beta, qubit=2*site)
29+
# circ.cx(control_qubit=2*site-1, target_qubit=2*site)
2830

2931
if model['L'] % 2 != 0 and model['L'] != 1:
30-
circ.cx(control_qubit=model['L']-2, target_qubit=model['L']-1)
31-
circ.rz(phi=beta, qubit=model['L']-1)
32-
circ.cx(control_qubit=model['L']-2, target_qubit=model['L']-1)
32+
circ.rzz(beta, qubit1=model['L']-2, qubit2=model['L']-1)
33+
# circ.cx(control_qubit=model['L']-2, target_qubit=model['L']-1)
34+
# circ.rz(phi=beta, qubit=model['L']-1)
35+
# circ.cx(control_qubit=model['L']-2, target_qubit=model['L']-1)
3336

3437
return circ
3538

0 commit comments

Comments
 (0)