diff --git a/scratchpad/qtensor_MPS/constants.py b/scratchpad/qtensor_MPS/constants.py index b997f2d2..3f6bd828 100644 --- a/scratchpad/qtensor_MPS/constants.py +++ b/scratchpad/qtensor_MPS/constants.py @@ -16,7 +16,7 @@ [0.0, 0.0, 1.0, 0.0], ] ) -_cnot_matrix = np.reshape(_cnot_matrix, newshape=(2, 2, 2, 2)) +cnot_matrix = np.reshape(_cnot_matrix, newshape=(2, 2, 2, 2)) _swap_matrix = np.array( [ @@ -26,4 +26,21 @@ [0.0, 0.0, 0.0, 1.0], ] ) -_swap_matrix = np.reshape(_swap_matrix, newshape=(2, 2, 2, 2)) \ No newline at end of file +swap_matrix = np.reshape(_swap_matrix, newshape=(2, 2, 2, 2)) + +_hbar = 1.0545718*10e-34 +_sigma_z = _hbar * 0.5 * _zmatrix +_sigma_x_pos = _hbar * 0.5* (_xmatrix + 1j*_ymatrix) +_sigma_x_neg = _hbar * 0.5* (_xmatrix - 1j*_ymatrix) + +_sigma_z_sigma_z_gate_matrix = np.tensordot(_sigma_z, _sigma_z, 0) +sigma_z_sigma_z_gate_matrix = np.reshape(_sigma_z_sigma_z_gate_matrix, newshape=(2,2,2,2)) + +_sigma_x_pos_sigma_x_neg_gate_matrix = np.tensordot(_sigma_x_pos, _sigma_x_neg, 0) +sigma_x_pos_sigma_x_neg_gate_matrix = np.reshape(_sigma_x_pos_sigma_x_neg_gate_matrix, newshape=(2,2,2,2)) + +_sigma_x_neg_sigma_x_pos_gate_matrix = np.tensordot(_sigma_x_neg, _sigma_x_pos, 0) +sigma_x_neg_sigma_x_pos_gate_matrix = np.reshape(_sigma_x_neg_sigma_x_pos_gate_matrix, newshape=(2,2,2,2)) + +_ising_hamiltonian_matrix = sigma_z_sigma_z_gate_matrix + 0.5 * sigma_x_pos_sigma_x_neg_gate_matrix + 0.5 * sigma_x_neg_sigma_x_pos_gate_matrix +ising_hamiltonian_matrix = np.reshape(_ising_hamiltonian_matrix, newshape=(2,2,2,2)) \ No newline at end of file diff --git a/scratchpad/qtensor_MPS/evolution.py b/scratchpad/qtensor_MPS/evolution.py new file mode 100644 index 00000000..0ae7616c --- /dev/null +++ b/scratchpad/qtensor_MPS/evolution.py @@ -0,0 +1,49 @@ +import tensornetwork as tn +import numpy as np +from mps import MPS +from gates import * +import matplotlib.pyplot as plt + +N = 10 +cutoff = 1e-8 +tau = 0.1 +ttotal = 2.0 + +gates = [] +N = 10 +n = 3 +mps = MPS("q", N, 2) +evolution_range = np.linspace(0, 80, 7) +js = np.arange(0, n) + +magnetization = [] + +for t in evolution_range: + mag_t = [] + for j in range(0, n): + gate = sigmaZZ(t) + print(gate.tensor , t, j) + mps.apply_two_qubit_gate(sigmaZZ(t), [j, j+1]) + mps.apply_two_qubit_gate(sigmaXnegXpos(t), [j, j+1]) + mps.apply_two_qubit_gate(sigmaXposXneg(t), [j, j+1]) + + mag_t += [mps.get_expectation(zgate(), j)] + + magnetization += [mag_t] + +with plt.style.context('default'): + plt.figure(figsize=(12, 7)) + + # plot the magnetization + ax1 = plt.subplot(131) + plt.pcolormesh(js, evolution_range, np.real(magnetization), vmin=-0.5, vmax=0.5) + plt.set_cmap('RdYlBu') + plt.colorbar() + plt.title('Z-Magnetization') + plt.xlabel('Site') + plt.ylabel('time [ $Jt$ ]') + + plt.show() + + + diff --git a/scratchpad/qtensor_MPS/gates.py b/scratchpad/qtensor_MPS/gates.py index 654755fc..1b1b726f 100644 --- a/scratchpad/qtensor_MPS/gates.py +++ b/scratchpad/qtensor_MPS/gates.py @@ -1,15 +1,30 @@ import numpy as np import tensornetwork as tn import numpy as np -from constants import _xmatrix, _cnot_matrix, _hmatrix +from constants import * from copy import deepcopy def xgate() -> tn.Node: - return tn.Node(deepcopy(_xmatrix), name="xgate") + return tn.Node(deepcopy(xmatrix), name="xgate") + +def zgate() -> tn.Node: + return tn.Node(deepcopy(zmatrix), name="xgate") def cnot() -> tn.Node: - return tn.Node(deepcopy(_cnot_matrix), name="cnot") + return tn.Node(deepcopy(cnot_matrix), name="cnot") def hgate() -> tn.Node: - return tn.Node(deepcopy(_hmatrix), name="hgate") + return tn.Node(deepcopy(hmatrix), name="hgate") + +def sigmaZZ(t) -> tn.Node: + return tn.Node(deepcopy(np.exp(sigma_z_sigma_z_gate_matrix * -1j * t * 0.5)), name="sigmaZZ") + +def sigmaXposXneg(t) -> tn.Node: + return tn.Node(deepcopy(np.exp(sigma_x_pos_sigma_x_neg_gate_matrix * -1j * t * 0.5)), name="sigmaXposXneg") + +def sigmaXnegXpos(t) -> tn.Node: + return tn.Node(deepcopy(np.exp(sigma_x_neg_sigma_x_pos_gate_matrix * -1j * t * 0.5 )), name="sigmaXposXneg") + +def isingHamiltonian(t)-> tn.Node: + return tn.Node(deepcopy(np.exp(ising_hamiltonian_matrix * -1j * t * 0.5))) diff --git a/scratchpad/qtensor_MPS/mps.py b/scratchpad/qtensor_MPS/mps.py index 2d25db62..876bf3dc 100644 --- a/scratchpad/qtensor_MPS/mps.py +++ b/scratchpad/qtensor_MPS/mps.py @@ -16,11 +16,11 @@ def __init__(self, tensor_name, N, physical_dim = 1) -> None: raise ValueError("Number of tensors should be >= 2") # Initialise as |0> = [1.0 0.0 # 0.0 0.0] - nodes = [tn.Node(np.array([[1.0], *[[0.0]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name+ "_" +str(0))] + nodes = [tn.Node(np.array([[1.0], *[[0.0]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name + str(0))] for i in range(N-2): - node = tn.Node(np.array([[[1.0]], *[[[0.0]]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name + "_" + str(i+1)) + node = tn.Node(np.array([[[1.0]], *[[[0.0]]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name + str(i+1)) nodes.append(node) - nodes.append(tn.Node(np.array([[1.0], *[[0.0]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name+ "_" +str(0))) + nodes.append(tn.Node(np.array([[1.0], *[[0.0]]*(physical_dim-1)], dtype=np.complex64), name = tensor_name + str(0))) for i in range(1, N-2): tn.connect(nodes[i].get_edge(2), nodes[i+1].get_edge(1)) @@ -170,7 +170,12 @@ def apply_two_qubit_gate(self, gate, operating_qubits): right_connected_edge = None for edge in new_node.get_all_nondangling(): - index = int(edge.node1.name.split(self.name)[-1]) + if self.name in edge.node1.name: + # Use the "node1" node by default + index = int(edge.node1.name.split(self.name)[-1]) + else: + # If "node1" is the new_mps_node, use "node2" + index = int(edge.node2.name.split(self.name)[-1]) if index <= operating_qubits[0]: left_connected_edge = edge @@ -229,9 +234,42 @@ def get_norm(self): Method to calculate norm of mps """ return np.sqrt(self.inner_product(self).real) + + + def left_cannoise(self, i): + nodes = [] + for i in range(i): + left_edges = [] + right_edges = [] + + for edge in to_split.get_all_dangling(): + if edge.name == str(i): + left_edges.append(edge) + else: + right_edges.append(edge) + + if nodes: + for edge in nodes[-1].get_all_nondangling(): + if to_split in edge.get_nodes(): + left_edges.append(edge) + + left, right, _ = tn.split_node(to_split, left_edges, right_edges, left_name="q"+str(i)) + + nodes.append(left) + to_split = right + to_split.name = "q" + str(i) + nodes.append(to_split) + + def __copy__(self): + copy_mps = MPS(self.name, self._N, self._physical_dim) + copy_mps._nodes = self.get_mps_nodes(original=False) + return copy_mps - def get_expectation(self): - pass + def get_expectation(self, observable, idx): + mps_copy = self.__copy__() + mps_copy.apply_single_qubit_gate(observable, idx) + return self.inner_product(mps_copy) +