def U_in(x): U = QuantumCircuit(nqubit) angle_y = np.arcsin(x) angle_z = np.arccos(x**2) for i in range(nqubit): U.add_RY_gate(i, angle_y) U.add_RZ_gate(i, angle_z) return U
def test_CU_Y0Y1(self): n_qubits = 3 a_idx = 2 theta = np.pi/4 state = QuantumState(n_qubits) input_states_bin = [0b001, 0b010, 0b101, 0b110] input_states = [] output_states = [] circuit = QuantumCircuit(n_qubits) # change basis from Z to Y circuit.add_S_gate(0) circuit.add_S_gate(1) circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_CNOT_gate(1, 0) # RZ circuit.add_RZ_gate(0, -0.5*theta) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, 0.5*theta) circuit.add_CNOT_gate(a_idx, 0) circuit.add_CNOT_gate(1, 0) # change basis from Z to Y circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_Sdag_gate(0) circuit.add_Sdag_gate(1) for b in input_states_bin: psi = state.copy() psi.set_computational_basis(b) input_states += [psi] psi_out = psi.copy() circuit.update_quantum_state(psi_out) output_states += [psi_out] p_list = [] for in_state in input_states: for out_state in output_states: prod = inner_product(in_state, out_state) p_list += [prod] # |001> exp_list = [1.0, 0.0, 0.0, 0.0] # |010> exp_list += [0.0, 1.0, 0.0, 0.0] # |101> exp_list += [0.0, 0.0, np.cos(theta/2), complex(0, -np.sin(theta/2))] # |110> exp_list += [0.0, 0.0, complex(0, -np.sin(theta/2)), np.cos(theta/2)] for result, expected in zip(p_list, exp_list): self.assertAlmostEqual(result, expected, places=6)
def create_input_gate(self, x): # 単一のxをエンコードするゲートを作成する関数 # xは入力特徴量(2次元) # xの要素は[-1, 1]の範囲内 u = QuantumCircuit(self.nqubit) angle_y = np.arcsin(x) angle_z = np.arccos(x**2) for i in range(self.nqubit): if i % 2 == 0: u.add_RY_gate(i, angle_y[0]) u.add_RZ_gate(i, angle_z[0]) else: u.add_RY_gate(i, angle_y[1]) u.add_RZ_gate(i, angle_z[1]) return u
def test_CU_Z0(self): n_qubits = 2 a_idx = 1 theta = np.pi/8 state = QuantumState(n_qubits) input_states_bin = [0b00, 0b10] input_states = [] output_states = [] circuit_H = QuantumCircuit(n_qubits) circuit_H.add_H_gate(0) # |0>|+> and |1>|+> for b in input_states_bin: psi = state.copy() psi.set_computational_basis(b) input_states += [psi] circuit_H.update_quantum_state(psi) circuit = QuantumCircuit(n_qubits) circuit.add_RZ_gate(0, -0.5*theta) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, 0.5*theta) circuit.add_CNOT_gate(a_idx, 0) for in_state in input_states: psi = in_state.copy() circuit.update_quantum_state(psi) output_states += [psi] p_list = [] for in_state in input_states: for out_state in output_states: p_list += [inner_product(in_state, out_state)] # <0|<+|0>|+> = 1 # <0|<+|1>|H> = 0 # <1|<+|0>|+> = 0 # <1|<+|1>|H> = cos(pi/16) exp_list = [1.0, 0.0, 0.0, np.cos(theta/2)] for result, expected in zip(p_list, exp_list): self.assertAlmostEqual(result, expected, places=6)
def create_input_gate(self, x): # Encode x into quantum state # x = 2-dim. variables, [-1,1] u = QuantumCircuit(self.nqubit) angle_y = np.arcsin(x) angle_z = np.arccos(x**2) for i in range(self.nqubit): ''' if i % 2 == 0: u.add_RY_gate(i, angle_y[0]) u.add_RZ_gate(i, angle_z[0]) else: u.add_RY_gate(i, angle_y[1]) u.add_RZ_gate(i, angle_z[1]) ''' u.add_RY_gate(i, angle_y[i]) u.add_RZ_gate(i, angle_z[i]) return u
def suspend_test_phase_estimation_debug(self): theta = 5*np.pi/16 n_qubits = 2 a_idx = 1 k = 2 circuit = QuantumCircuit(n_qubits) psi = QuantumState(n_qubits) # |ancilla>|logical> phi = 1.25/2 print('k={}, phi={} mod (np.pi)'.format(k, phi)) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) # Apply kickback phase rotation to ancilla bit circuit.add_RZ_gate(a_idx, -np.pi * phi) # Apply C-U(Z0) theta_k = 2 ** (k-1) * theta print('phase:{} mod (np.pi)'.format(theta_k/np.pi)) circuit.add_RZ_gate(0, -theta_k) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, theta_k) circuit.add_CNOT_gate(a_idx, 0) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) # run circuit circuit.update_quantum_state(psi) print(psi.get_vector()) # partial trace p0 = psi.get_marginal_probability([2, 0]) p1 = psi.get_marginal_probability([2, 1]) print(p0, p1)
def create_input_gate(self, x, uin_type): # Encode x into quantum state # x = 2-dim. variables, [-1,1] 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) return u
def ctrl_RZ_circuit(theta_k, kickback_phase): n_qubits = 2 a_idx = 1 phi = kickback_phase / 2 circuit = QuantumCircuit(n_qubits) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) # Apply kickback phase rotation to ancilla bit circuit.add_RZ_gate(a_idx, -np.pi * phi) # Apply C-U(Z0) # print('phase:{} mod (np.pi)'.format(theta_k/np.pi)) circuit.add_RZ_gate(0, -theta_k) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, theta_k) circuit.add_CNOT_gate(a_idx, 0) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) return circuit
def test_iterative_phase_estimation(self): theta = 5*np.pi/16 # theta = np.pi/3 # -0.5235987755982988 # print(-theta/2) n_itter = 6 n_qubits = 2 a_idx = 1 state = QuantumState(n_qubits) # |ancilla>|logical> kickback_phase = 0.0 for k in reversed(range(1, n_itter)): psi = state.copy() phi = kickback_phase/2 # print('k={}, phi={} mod (np.pi)'.format(k, phi)) circuit = QuantumCircuit(n_qubits) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) # Apply kickback phase rotation to ancilla bit circuit.add_RZ_gate(a_idx, -np.pi * phi) # Apply C-U(Z0) theta_k = 2 ** (k-1) * theta # print('phase:{} mod (np.pi)'.format(theta_k/np.pi)) circuit.add_RZ_gate(0, -theta_k) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, theta_k) circuit.add_CNOT_gate(a_idx, 0) # Apply H to ancilla bit to get |+> state circuit.add_H_gate(a_idx) # run circuit circuit.update_quantum_state(psi) # print(psi.get_vector()) # partial trace p0 = psi.get_marginal_probability([2, 0]) p1 = psi.get_marginal_probability([2, 1]) # print(p0, p1) # update kickback phase kth_digit = 1 if (p0 < p1) else 0 kickback_phase = kickback_phase/2 + kth_digit # print(kickback_phase) # print(-np.pi * kickback_phase/2) self.assertAlmostEqual(-np.pi * kickback_phase/2, -theta/2)
def _try_append_gate(self, op: ops.GateOperation, qulacs_circuit: qulacs.QuantumCircuit, indices: np.array): # One qubit gate if isinstance(op.gate, ops.pauli_gates._PauliX): qulacs_circuit.add_X_gate(indices[0]) elif isinstance(op.gate, ops.pauli_gates._PauliY): qulacs_circuit.add_Y_gate(indices[0]) elif isinstance(op.gate, ops.pauli_gates._PauliZ): qulacs_circuit.add_Z_gate(indices[0]) elif isinstance(op.gate, ops.common_gates.HPowGate): qulacs_circuit.add_H_gate(indices[0]) elif isinstance(op.gate, ops.common_gates.XPowGate): qulacs_circuit.add_RX_gate(indices[0], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.common_gates.YPowGate): qulacs_circuit.add_RY_gate(indices[0], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.common_gates.ZPowGate): qulacs_circuit.add_RZ_gate(indices[0], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.SingleQubitMatrixGate): mat = op.gate._matrix qulacs_circuit.add_dense_matrix_gate(indices[0], mat) elif isinstance(op.gate, circuits.qasm_output.QasmUGate): lmda = op.gate.lmda theta = op.gate.theta phi = op.gate.phi gate = qulacs.gate.U3(indices[0], theta * np.pi, phi * np.pi, lmda * np.pi) qulacs_circuit.add_gate(gate) # Two qubit gate elif isinstance(op.gate, ops.common_gates.CNotPowGate): if op.gate._exponent == 1.0: qulacs_circuit.add_CNOT_gate(indices[0], indices[1]) else: mat = _get_google_rotx(op.gate._exponent) gate = qulacs.gate.DenseMatrix(indices[1], mat) gate.add_control_qubit(indices[0], 1) qulacs_circuit.add_gate(gate) elif isinstance(op.gate, ops.common_gates.CZPowGate): if op.gate._exponent == 1.0: qulacs_circuit.add_CZ_gate(indices[0], indices[1]) else: mat = _get_google_rotz(op.gate._exponent) gate = qulacs.gate.DenseMatrix(indices[1], mat) gate.add_control_qubit(indices[0], 1) qulacs_circuit.add_gate(gate) elif isinstance(op.gate, ops.common_gates.SwapPowGate): if op.gate._exponent == 1.0: qulacs_circuit.add_SWAP_gate(indices[0], indices[1]) else: qulacs_circuit.add_dense_matrix_gate(indices, op._unitary_()) elif isinstance(op.gate, ops.parity_gates.XXPowGate): qulacs_circuit.add_multi_Pauli_rotation_gate( indices, [1, 1], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.parity_gates.YYPowGate): qulacs_circuit.add_multi_Pauli_rotation_gate( indices, [2, 2], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.parity_gates.ZZPowGate): qulacs_circuit.add_multi_Pauli_rotation_gate( indices, [3, 3], -np.pi * op.gate._exponent) elif isinstance(op.gate, ops.TwoQubitMatrixGate): indices.reverse() mat = op.gate._matrix qulacs_circuit.add_dense_matrix_gate(indices, mat) # Three qubit gate """ # deprecated because these functions cause errors in gpu elif isinstance(op.gate, ops.three_qubit_gates.CCXPowGate): mat = _get_google_rotx(op.gate._exponent) gate = qulacs.gate.DenseMatrix(indices[2], mat) gate.add_control_qubit(indices[0],1) gate.add_control_qubit(indices[1],1) qulacs_circuit.add_gate(gate) elif isinstance(op.gate, ops.three_qubit_gates.CCZPowGate): mat = _get_google_rotz(op.gate._exponent) gate = qulacs.gate.DenseMatrix(indices[2], mat) gate.add_control_qubit(indices[0],1) gate.add_control_qubit(indices[1],1) qulacs_circuit.add_gate(gate) """ elif isinstance(op.gate, ops.three_qubit_gates.CSwapGate): mat = np.zeros(shape=(4, 4)) mat[0, 0] = 1 mat[1, 2] = 1 mat[2, 1] = 1 mat[3, 3] = 1 gate = qulacs.gate.DenseMatrix(indices[1:], mat) gate.add_control_qubit(indices[0], 1) qulacs_circuit.add_gate(gate) # Misc elif protocols.has_unitary(op): indices.reverse() mat = op._unitary_() qulacs_circuit.add_dense_matrix_gate(indices, mat) # Not unitary else: return False return True
def time_evolution_circuit_improved(g_list, t, kickback_phase, k, n_trotter_step=1): n_qubits = 3 a_idx = 2 phi = -(t / n_trotter_step) * g_list # print(phi) circuit = QuantumCircuit(n_qubits) circuit.add_H_gate(a_idx) # Apply kickback phase rotation to ancilla bit circuit.add_RZ_gate(a_idx, -np.pi * kickback_phase / 2) for _ in range(n_trotter_step): for _ in range(2**k): # CU(Z0) circuit.add_RZ_gate(0, -phi[0]) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, phi[0]) circuit.add_CNOT_gate(a_idx, 0) # CU(Y0 Y1) circuit.add_S_gate(0) circuit.add_S_gate(1) circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_CNOT_gate(1, 0) circuit.add_RZ_gate(0, -phi[1]) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, phi[1]) circuit.add_CNOT_gate(a_idx, 0) circuit.add_CNOT_gate(1, 0) circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_Sdag_gate(0) circuit.add_Sdag_gate(1) # CU(Z1) circuit.add_RZ_gate(1, -phi[2]) circuit.add_CNOT_gate(a_idx, 1) circuit.add_RZ_gate(1, phi[2]) circuit.add_CNOT_gate(a_idx, 1) # CU(X0 X1) circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_CNOT_gate(1, 0) circuit.add_RZ_gate(0, -phi[3]) circuit.add_CNOT_gate(a_idx, 0) circuit.add_RZ_gate(0, phi[3]) circuit.add_CNOT_gate(a_idx, 0) circuit.add_CNOT_gate(1, 0) circuit.add_H_gate(0) circuit.add_H_gate(1) circuit.add_H_gate(a_idx) return circuit
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