def test_Toffoli(benchmark, nqubits): benchmark.group = "Toffoli" toffoli = DenseMatrix(0, [[0, 1], [1, 0]]) toffoli.add_control_qubit(1, 1) toffoli.add_control_qubit(2, 1) st = QuantumState(nqubits) benchmark(toffoli.update_quantum_state, st)
def test_circuit_add_gate(self): from qulacs import QuantumCircuit, QuantumState from qulacs.gate import Identity, X, Y, Z, H, S, Sdag, T, Tdag, sqrtX, sqrtXdag, sqrtY, sqrtYdag from qulacs.gate import P0, P1, U1, U2, U3, RX, RY, RZ, CNOT, CZ, SWAP, TOFFOLI, FREDKIN, Pauli, PauliRotation from qulacs.gate import DenseMatrix, SparseMatrix, DiagonalMatrix, RandomUnitary, ReversibleBoolean, StateReflection from qulacs.gate import BitFlipNoise, DephasingNoise, IndependentXZNoise, DepolarizingNoise, TwoQubitDepolarizingNoise, AmplitudeDampingNoise, Measurement from qulacs.gate import merge, add, to_matrix_gate, Probabilistic, CPTP, Instrument, Adaptive from scipy.sparse import lil_matrix qc = QuantumCircuit(3) qs = QuantumState(3) ref = QuantumState(3) sparse_mat = lil_matrix((4, 4)) sparse_mat[0, 0] = 1 sparse_mat[1, 1] = 1 def func(v, d): return (v + 1) % d def adap(v): return True gates = [ Identity(0), X(0), Y(0), Z(0), H(0), S(0), Sdag(0), T(0), Tdag(0), sqrtX(0), sqrtXdag(0), sqrtY(0), sqrtYdag(0), Probabilistic([0.5, 0.5], [X(0), Y(0)]), CPTP([P0(0), P1(0)]), Instrument([P0(0), P1(0)], 1), Adaptive(X(0), adap), CNOT(0, 1), CZ(0, 1), SWAP(0, 1), TOFFOLI(0, 1, 2), FREDKIN(0, 1, 2), Pauli([0, 1], [1, 2]), PauliRotation([0, 1], [1, 2], 0.1), DenseMatrix(0, np.eye(2)), DenseMatrix([0, 1], np.eye(4)), SparseMatrix([0, 1], sparse_mat), DiagonalMatrix([0, 1], np.ones(4)), RandomUnitary([0, 1]), ReversibleBoolean([0, 1], func), StateReflection(ref), BitFlipNoise(0, 0.1), DephasingNoise(0, 0.1), IndependentXZNoise(0, 0.1), DepolarizingNoise(0, 0.1), TwoQubitDepolarizingNoise(0, 1, 0.1), AmplitudeDampingNoise(0, 0.1), Measurement(0, 1), merge(X(0), Y(1)), add(X(0), Y(1)), to_matrix_gate(X(0)), P0(0), P1(0), U1(0, 0.), U2(0, 0., 0.), U3(0, 0., 0., 0.), RX(0, 0.), RY(0, 0.), RZ(0, 0.), ] gates.append(merge(gates[0], gates[1])) gates.append(add(gates[0], gates[1])) ref = None for gate in gates: qc.add_gate(gate) for gate in gates: qc.add_gate(gate) qc.update_quantum_state(qs) qc = None qs = None for gate in gates: gate = None gates = None parametric_gates = None
def prepstate(n_qubit, statevec): dim = 2**n_qubit if isinstance(statevec, dict): sv = np.zeros((dim, ), complex) for k, v in statevec.items(): sv[k] = v statevec = sv matrix = np.zeros((dim, dim), complex) matrix[:, 0] = statevec from qulacs.gate import DenseMatrix from qulacs import QuantumState state = QuantumState(n_qubit) state.set_zero_state() gate = DenseMatrix(list(range(n_qubit)), matrix) gate.update_quantum_state(state) return state
def create_Ising_time_evol_gate(nqubit, time_step=0.77): """ Ising hamiltonian with random magnetic field and random couplings :param time_step: elapsed time of random hamiltonian evolution :return qulacs gate object """ ham = np.zeros((2**nqubit,2**nqubit), dtype = complex) for i in range(nqubit): # i runs 0 to nqubit-1 Jx = -1. + 2.*np.random.rand() # [-1,1] ham += Jx * make_fullgate( [ [i, X_mat] ], nqubit) for j in range(i+1, nqubit): J_ij = -1. + 2.*np.random.rand() ham += J_ij * make_fullgate ([ [i, Z_mat], [j, Z_mat]], nqubit) ## Build time-evolution operator by diagonalizing the Ising hamiltonian H*P = P*D <-> H = P*D*P^dagger diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot(np.dot(eigen_vecs, np.diag(np.exp(-1j*time_step*diag))), eigen_vecs.T.conj()) # e^-iHT # Convert to qulacs gate time_evol_gate = DenseMatrix([i for i in range(nqubit)], time_evol_op) return time_evol_gate
def create_Heisenberg_time_evol_gate(nqubit, time_step=0.77): """ Heisenberg hamiltonian with random magnetic field and random couplings :param time_step: elapsed time of random hamiltonian evolution :return qulacs gate object """ # every two possible spin-conbination has interaction ham = np.zeros((2**nqubit, 2**nqubit), dtype = complex) for i in range(nqubit): J_x = -1. + 2. * np.random.rand() ham += J_x * make_fullgate([[i, X_mat]], nqubit) for j in range(i+1, nqubit): J_xx = -1. + 2. * np.random.rand() J_yy = -1. + 2. * np.random.rand() J_zz = -1. + 2. * np.random.rand() ham += J_xx * make_fullgate([[i, X_mat], [j, X_mat]], nqubit) ham += J_yy * make_fullgate([[i, Y_mat], [j, Y_mat]], nqubit) ham += J_xx * make_fullgate([[i, Z_mat], [j, Z_mat]], nqubit) ''' # nearest neighbor spin-conbination has interaction ham = np.zeros((2**nqubit, 2**nqubit), dtype = complex) for i in range(nqubit): J_x = -1. + 2. * np.random.rand() ham += J_x * make_fullgate([[i, X_mat]], nqubit) J_xx = -1. + 2. * np.random.rand() J_yy = -1. + 2. * np.random.rand() J_zz = -1. + 2. * np.random.rand() ham += J_xx * make_fullgate([[i, X_mat], [(i+1) % nqubit, X_mat]], nqubit)#Periodic boundary condition ham += J_yy * make_fullgate([[i, Y_mat], [(i+1) % nqubit, Y_mat]], nqubit) ham += J_xx * make_fullgate([[i, Z_mat], [(i+1) % nqubit, Z_mat]], nqubit) ''' ## Build time-evolution operator by diagonalizing the Heisenberg hamiltonian H*P = P*D <-> e^-iHt = P*(e^-iDt)*P^dagger diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot(np.dot(eigen_vecs, np.diag(np.exp(-1j*time_step*diag))), eigen_vecs.T.conj()) # e^-iHT # Convert to qulacs gate time_evol_gate = DenseMatrix([i for i in range(nqubit)], time_evol_op) return time_evol_gate
def create_time_evol_gate(nqubit, time_step=0.77): """ ランダム磁場・ランダム結合イジングハミルトニアンをつくって時間発展演算子をつくる :param time_step: ランダムハミルトニアンによる時間発展の経過時間 :return qulacsのゲートオブジェクト """ ham = np.zeros((2**nqubit, 2**nqubit), dtype=complex) for i in range(nqubit): # i runs 0 to nqubit-1 Jx = -1. + 2. * np.random.rand() # -1~1の乱数 ham += Jx * make_fullgate([[i, X_mat]], nqubit) for j in range(i + 1, nqubit): J_ij = -1. + 2. * np.random.rand() ham += J_ij * make_fullgate([[i, Z_mat], [j, Z_mat]], nqubit) # 対角化して時間発展演算子をつくる. H*P = P*D <-> H = P*D*P^dagger diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * time_step * diag))), eigen_vecs.T.conj()) # e^-iHT # qulacsのゲートに変換 time_evol_gate = DenseMatrix([i for i in range(nqubit)], time_evol_op) return time_evol_gate
def main(): ## Example1 circuit = QuantumCircuit(3) circuit.add_X_gate(0) circuit.add_Y_gate(1) circuit.add_Z_gate(2) circuit.add_dense_matrix_gate([0,1], [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]) circuit.add_CNOT_gate(2,0) circuit.add_X_gate(2) draw_circuit(circuit, verbose=1) ## Example2 circuit = QuantumCircuit(3) circuit.add_X_gate(0) circuit.add_Y_gate(1) circuit.add_dense_matrix_gate([0,1], [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]]) circuit.add_Z_gate(2) circuit.add_CNOT_gate(2,0) circuit.add_X_gate(2) draw_circuit(circuit, verbose=1) ## Example3 circuit = QuantumCircuit(3) circuit.add_X_gate(1) circuit.add_CZ_gate(0,2) circuit.add_X_gate(1) draw_circuit(circuit) ## Example4 circuit = QuantumCircuit(4) ##CCX0,2, 3 cx_gate = CNOT(2,3) cx_mat_gate = to_matrix_gate(cx_gate) control_index = 0 control_with_value = 1 cx_mat_gate.add_control_qubit(control_index, control_with_value) circuit.add_gate(cx_mat_gate) ##CCX1,2, 3 ccx = TOFFOLI(1,2, 3) circuit.add_gate(ccx) ##CCX1,2, 0 ccx = TOFFOLI(1,2, 0) circuit.add_gate(ccx) ##CCX1,3, 0 ccx = TOFFOLI(1,3, 0) circuit.add_gate(ccx) ##CCX1,3, 2 ccx = TOFFOLI(1,3, 2) circuit.add_gate(ccx) ##SWAP0,1 circuit.add_SWAP_gate(0,1) ##SWAP0,2 circuit.add_SWAP_gate(0,2) ##SWAP1,3 circuit.add_SWAP_gate(1,3) draw_circuit(circuit, verbose=1) ## Example5 circuit = QuantumCircuit(5) ## 3-qubit gate applied to [0,1,2] mat = np.identity(2**3) circuit.add_dense_matrix_gate([0,1,2], mat) ## 3-qubit gate applied to [0,3,4], and [1] qubit is control-qubit c_dense_gate = DenseMatrix([0,3,4], mat) control_index = 1 control_with_value = 1 c_dense_gate.add_control_qubit(control_index, control_with_value) circuit.add_gate(c_dense_gate) ## 3-qubit gate applied to [0,2,4] circuit.add_dense_matrix_gate([0,2,4], mat) ## SWAP gate aplied to [1,3], and [2] qubit is control-qubit swp_gate = to_matrix_gate(SWAP(1,3)) control_index = 2 control_with_value = 1 swp_gate.add_control_qubit(control_index, control_with_value) circuit.add_gate(swp_gate) draw_circuit(circuit)
print(''.join([str(b) for b in cu_mat[i]])) state = QuantumState(num_bits + 1) state.set_computational_basis(0) print("\nInitial State:") show_quantum_state(state) for i in range(1, num_bits + 1): h_gate = H(i) h_gate.update_quantum_state(state) print("\nAfter H Gate:") show_quantum_state(state) cu_gate = DenseMatrix(tuple(range(num_bits + 1)), cu_mat) cu_gate.update_quantum_state(state) print("\nAfter CU Gate:") show_quantum_state(state) z_gate = Z(0) z_gate.update_quantum_state(state) print("\nAfter Z Gate:") show_quantum_state(state) cu_gate = DenseMatrix(tuple(range(num_bits + 1)), cu_mat) cu_gate.update_quantum_state(state) print("\nAfter CU Gate:")
#### Operator for the time-evolution ham = np.zeros((2**nqubit,2**nqubit), dtype = complex) for i in range(nqubit): ## i runs 0 to nqubit-1 Jx = -1. + 2.*np.random.rand() ## randm in -1~1 ham += Jx * make_fullgate( [ [i, X_mat] ], nqubit) for j in range(i+1, nqubit): J_ij = -1. + 2.*np.random.rand() ham += J_ij * make_fullgate ([ [i, Z_mat], [j, Z_mat]], nqubit) ## Diagonize to make a time-evolution operator; H*P = P*D <-> H = P*D*P^dagger diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot(np.dot(eigen_vecs, np.diag(np.exp(-1j*time_step*diag))), eigen_vecs.T.conj()) # e^-iHT # Convert it to a qulacs gate from qulacs.gate import DenseMatrix time_evol_gate = DenseMatrix([i for i in range(nqubit)], time_evol_op) from qulacs import ParametricQuantumCircuit # Construct an output gate U_out and initialization. U_out = ParametricQuantumCircuit(nqubit) for d in range(c_depth): U_out.add_gate(time_evol_gate) for i in range(nqubit): angle = 2.0 * np.pi * np.random.rand() U_out.add_parametric_RX_gate(i,angle) angle = 2.0 * np.pi * np.random.rand() U_out.add_parametric_RZ_gate(i,angle) angle = 2.0 * np.pi * np.random.rand() U_out.add_parametric_RX_gate(i,angle)
def __get_CP(q0, q1, phase): exp = cmath.exp(1.j * phase) gate = DenseMatrix(q1, [[1., 0.], [0., exp]]) gate.add_control_qubit(q0, 1) return gate
def __get_P(q0, phase): exp = cmath.exp(1.j * phase) gate = DenseMatrix(q0, [[1., 0.], [0., exp]]) return gate
def create_input_gate(self, x, uin_type): # Encode x into quantum state # uin_type: unitary data-input type 0, 1, 20, 21, 30, 31, 40, 41, 50, 51, 60, 61 # x = 1dim. variables, [-1,1] I_mat = np.eye(2, dtype=complex) X_mat = X(0).get_matrix() Y_mat = Y(0).get_matrix() Z_mat = Z(0).get_matrix() #make operators s.t. exp(i*theta * sigma^z_j@sigma^z_k) @:tensor product def ZZ(u, theta, j, k): u.add_CNOT_gate(j, k) u.add_RZ_gate(k, -2 * theta * self.time_step) u.add_CNOT_gate(j, k) return u def XX(u, theta, j, k): u.add_H_gate(j) u.add_H_gate(k) ZZ(u, theta, j, k) u.add_H_gate(j) u.add_H_gate(k) return u def YY(u, theta, j, k): u.add_U1_gate(j, -np.pi / 2.) u.add_U1_gate(k, -np.pi / 2.) XX(u, theta, j, k) u.add_U1_gate(j, np.pi / 2.) u.add_U1_gate(k, np.pi / 2.) return u theta = x u = QuantumCircuit(self.nqubit) angle_y = np.arcsin(x) angle_z = np.arccos(x**2) if uin_type == 0: for i in range(self.nqubit): u.add_RY_gate(i, angle_y[i]) u.add_RZ_gate(i, angle_z[i]) elif uin_type == 1: #for d in range(2): for i in range(self.nqubit): u.add_H_gate(i) u.add_RY_gate(i, angle_y[i]) u.add_RZ_gate(i, angle_z[i]) # KT: add second order expansion for i in range(self.nqubit - 1): for j in range(i + 1, self.nqubit): angle_z2 = np.arccos(x[i] * x[j]) u.add_CNOT_gate(i, j) u.add_RZ_gate(j, angle_z2) u.add_CNOT_gate(i, j) elif uin_type == 20: for i in range(self.nqubit): u.add_RX_gate(i, -2 * x[i] * self.time_step) elif uin_type == 21: ham = np.zeros((2**self.nqubit, 2**self.nqubit), dtype=complex) for i in range(self.nqubit): # i runs 0 to nqubit-1 J_x = x[i] print(x) ham += J_x * make_fullgate([[i, X_mat]], self.nqubit) ## Build time-evolution operator by diagonalizing the Ising hamiltonian H*P = P*D <-> H = P*D*P^dagger diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * self.time_step * diag))), eigen_vecs.T.conj()) # e^-iHT # Convert to qulacs gate time_evol_gate = DenseMatrix([i for i in range(self.nqubit)], time_evol_op) u.add_gate(time_evol_gate) elif uin_type == 30: #Ising hamiltonian with input coefficient # nearest neighbor spin-conbination has interaction for i in range(self.nqubit): u.add_RX_gate(i, -2 * x[i] * self.time_step) ZZ(u, theta[i] * theta[(i + 1) % self.nqubit], i, i + 1) elif uin_type == 31: ham = np.zeros((2**self.nqubit, 2**self.nqubit), dtype=complex) for i in range(self.nqubit): J_x = x[i] ham += J_x * make_fullgate([[i, X_mat]], self.nqubit) J_zz = x[i] * x[(i + 1) % self.nqubit] ham += J_zz * make_fullgate( [[i, Z_mat], [(i + 1) % self.nqubit, Z_mat]], self.nqubit) diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * self.time_step * diag))), eigen_vecs.T.conj()) time_evol_gate = DenseMatrix([i for i in range(self.nqubit)], time_evol_op) u.add_gate(time_evol_gate) elif uin_type == 40: #Ising hamiltonian with input coefficient # every two possible spin-conbination has interaction for i in range(self.nqubit): u.add_RX_gate(i, -2 * x[i] * self.time_step) for j in range(i + 1, self.nqubit): ZZ(u, theta[i] * theta[j], i, j) elif uin_type == 41: ham = np.zeros((2**self.nqubit, 2**self.nqubit), dtype=complex) for i in range(self.nqubit): J_x = x[i] ham += J_x * make_fullgate([[i, X_mat]], self.nqubit) for j in range(i + 1, self.nqubit): J_ij = x[i] * x[j] ham += J_ij * make_fullgate([[i, Z_mat], [j, Z_mat]], self.nqubit) diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * self.time_step * diag))), eigen_vecs.T.conj()) time_evol_gate = DenseMatrix([i for i in range(self.nqubit)], time_evol_op) u.add_gate(time_evol_gate) elif uin_type == 50: #Heisenberg hamiltonian with input coefficient # nearest neighbor spin-conbination has interaction for i in range(self.nqubit): u.add_RX_gate(i, -2 * x[i] * self.time_step) XX(u, theta[i] * theta[(i + 1) % self.nqubit], i, i + 1) YY(u, theta[i] * theta[(i + 1) % self.nqubit], i, i + 1) ZZ(u, theta[i] * theta[(i + 1) % self.nqubit], i, i + 1) elif uin_type == 51: ham = np.zeros((2**self.nqubit, 2**self.nqubit), dtype=complex) for i in range(self.nqubit): J_x = x[i] ham += J_x * make_fullgate([[i, X_mat]], self.nqubit) J_xx = x[i] * x[(i + 1) % self.nqubit] J_yy = x[i] * x[(i + 1) % self.nqubit] J_zz = x[i] * x[(i + 1) % self.nqubit] ham += J_xx * make_fullgate( [[i, X_mat], [(i + 1) % self.nqubit, X_mat]], self.nqubit) ham += J_yy * make_fullgate( [[i, Y_mat], [(i + 1) % self.nqubit, Y_mat]], self.nqubit) ham += J_xx * make_fullgate( [[i, Z_mat], [(i + 1) % self.nqubit, Z_mat]], self.nqubit) diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * self.time_step * diag))), eigen_vecs.T.conj()) time_evol_gate = DenseMatrix([i for i in range(self.nqubit)], time_evol_op) u.add_gate(time_evol_gate) elif uin_type == 60: #Heisenberg hamiltonian with input coefficient # every two possible spin-conbination has interaction for i in range(self.nqubit): u.add_RX_gate(i, -2 * x[i] * self.time_step) for j in range(i + 1, self.nqubit): XX(u, theta[i] * theta[j], i, j) YY(u, theta[i] * theta[j], i, j) ZZ(u, theta[i] * theta[j], i, j) elif uin_type == 61: ham = np.zeros((2**self.nqubit, 2**self.nqubit), dtype=complex) for i in range(self.nqubit): J_x = x[i] ham += J_x * make_fullgate([[i, X_mat]], self.nqubit) for j in range(i + 1, self.nqubit): J_xx = x[i] * x[j] J_yy = x[i] * x[j] J_zz = x[i] * x[j] ham += J_xx * make_fullgate([[i, X_mat], [j, X_mat]], self.nqubit) ham += J_yy * make_fullgate([[i, Y_mat], [j, Y_mat]], self.nqubit) ham += J_xx * make_fullgate([[i, Z_mat], [j, Z_mat]], self.nqubit) diag, eigen_vecs = np.linalg.eigh(ham) time_evol_op = np.dot( np.dot(eigen_vecs, np.diag(np.exp(-1j * self.time_step * diag))), eigen_vecs.T.conj()) time_evol_gate = DenseMatrix([i for i in range(self.nqubit)], time_evol_op) u.add_gate(time_evol_gate) else: pass return u