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 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 main(): import numpy as np n_qubit = 2 obs = Observable(n_qubit) initial_state = QuantumState(n_qubit) obs.add_operator(1, "Z 0 Z 1") circuit_list = [] p_list = [0.02, 0.04, 0.06, 0.08] #prepare circuit list for p in p_list: circuit = QuantumCircuit(n_qubit) circuit.add_H_gate(0) circuit.add_RY_gate(1, np.pi / 6) circuit.add_CNOT_gate(0, 1) circuit.add_gate( Probabilistic([p / 4, p / 4, p / 4], [X(0), Y(0), Z(0)])) #depolarizing noise circuit.add_gate( Probabilistic([p / 4, p / 4, p / 4], [X(1), Y(1), Z(1)])) #depolarizing noise circuit_list.append(circuit) #get mitigated output mitigated, non_mitigated_array, fit_coefs = error_mitigation_extrapolate_linear( circuit_list, p_list, initial_state, obs, n_circuit_sample=100000, return_full=True) #plot the result p = np.linspace(0, max(p_list), 100) plt.plot(p, fit_coefs[0] * p + fit_coefs[1], linestyle="--", label="linear fit") plt.scatter(p_list, non_mitigated_array, label="un-mitigated") plt.scatter(0, mitigated, label="mitigated output") #prepare the clean result state = QuantumState(n_qubit) circuit = QuantumCircuit(n_qubit) circuit.add_H_gate(0) circuit.add_RY_gate(1, np.pi / 6) circuit.add_CNOT_gate(0, 1) circuit.update_quantum_state(state) plt.scatter(0, obs.get_expectation_value(state), label="True output") plt.xlabel("error rate") plt.ylabel("expectation value") plt.legend() plt.show()
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 sample_observable_noisy_circuit(circuit, initial_state, obs, n_circuit_sample=1000, n_sample_per_circuit=1): """ Args: circuit (:class:`qulacs.QuantumCircuit`) initial_state (:class:`qulacs.QuantumState`) obs (:class:`qulacs.Observable`) n_circuit_sample (:class:`int`): number of circuit samples n_sample (:class:`int`): number of samples per one circuit samples Return: :float: sampled expectation value of the observable """ n_term = obs.get_term_count() n_qubit = obs.get_qubit_count() pauli_terms = [obs.get_term(i) for i in range(n_term)] coefs = [p.get_coef() for p in pauli_terms] pauli_ids = [p.get_pauli_id_list() for p in pauli_terms] pauli_indices = [p.get_index_list() for p in pauli_terms] exp = 0 state = initial_state.copy() for c in range(n_circuit_sample): state.load(initial_state) circuit.update_quantum_state(state) for i in range(n_term): measurement_circuit = QuantumCircuit(n_qubit) if len(pauli_ids[i]) == 0: # means identity exp += coefs[i] continue mask = ''.join([ '1' if n_qubit - 1 - k in pauli_indices[i] else '0' for k in range(n_qubit) ]) for single_pauli, index in zip(pauli_ids[i], pauli_indices[i]): if single_pauli == 1: measurement_circuit.add_H_gate(index) elif single_pauli == 2: measurement_circuit.add_Sdag_gate(index) uncompute_circuit.add_H_gate(index) measurement_circuit.update_quantum_state(state) samples = state.sampling(n_sample_per_circuit) mask = int(mask, 2) exp += coefs[i] * sum( list(map(lambda x: (-1)**(bin(x & mask).count('1')), samples))) / n_sample_per_circuit exp /= n_circuit_sample return exp
def ansatz_circuit(n_qubit, depth, theta_list): circuit = QuantumCircuit(n_qubit) for i in range(n_qubit): circuit.add_gate(RY(i, theta_list[i])) for d in range(depth): for i in range(1, n_qubit): circuit.add_H_gate(i) for j in range(n_qubit - 1): circuit.add_CNOT_gate(j, j + 1) circuit.add_gate(RY(j, theta_list[n_qubit * (1 + d) + j])) circuit.add_H_gate(j + 1) circuit.add_gate( RY(n_qubit - 1, theta_list[n_qubit * (1 + d) + n_qubit - 1])) return circuit
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 sample_observable(state, obs, n_sample): """Function Args: state (qulacs.QuantumState): obs (qulacs.Observable) n_sample (int): number of samples for each observable Return: :float: sampled expectation value of the observable Author(s): Takashi Tsuchimochi """ n_term = obs.get_term_count() n_qubits = obs.get_qubit_count() exp = 0 buf_state = QuantumState(n_qubits) for i in range(n_term): pauli_term = obs.get_term(i) coef = pauli_term.get_coef() pauli_id = pauli_term.get_pauli_id_list() pauli_index = pauli_term.get_index_list() if len(pauli_id) == 0: # means identity exp += coef continue buf_state.load(state) measurement_circuit = QuantumCircuit(n_qubits) mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0" for k in range(n_qubits)]) for single_pauli, index in zip(pauli_id, pauli_index): if single_pauli == 1: measurement_circuit.add_H_gate(index) elif single_pauli == 2: measurement_circuit.add_Sdag_gate(index) measurement_circuit.add_H_gate(index) measurement_circuit.update_quantum_state(buf_state) samples = buf_state.sampling(n_sample) mask = int(mask, 2) exp += (coef *sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")), samples))) /n_sample) return exp
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 sample_observable(state, obs, n_sample): """ Args: state (qulacs.QuantumState): obs (qulacs.Observable) n_sample (int): number of samples for each observable Return: :float: sampled expectation value of the observable """ n_term = obs.get_term_count() n_qubit = obs.get_qubit_count() pauli_terms = [obs.get_term(i) for i in range(n_term)] coefs = [p.get_coef() for p in pauli_terms] pauli_ids = [p.get_pauli_id_list() for p in pauli_terms] pauli_indices = [p.get_index_list() for p in pauli_terms] exp = 0 measured_state = state.copy() for i in range(n_term): state.load(measured_state) measurement_circuit = QuantumCircuit(n_qubit) if len(pauli_ids[i]) == 0: # means identity exp += coefs[i] continue mask = ''.join([ '1' if n_qubit - 1 - k in pauli_indices[i] else '0' for k in range(n_qubit) ]) for single_pauli, index in zip(pauli_ids[i], pauli_indices[i]): if single_pauli == 1: measurement_circuit.add_H_gate(index) elif single_pauli == 2: measurement_circuit.add_Sdag_gate(index) measurement_circuit.add_H_gate(index) measurement_circuit.update_quantum_state(state) samples = state.sampling(n_sample) mask = int(mask, 2) exp += coefs[i] * sum( list(map(lambda x: (-1)**(bin(x & mask).count('1')), samples))) / n_sample return exp
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 test_transition_observable(state, obs, poststate0, poststate1, n_sample): """ Args: state (qulacs.QuantumState): This includes entangled ancilla (n_qubits = n_qubit_system + 1) obs (qulacs.Observable): This does not include ancilla Z (n_qubit_system) poststate0 (qulacs.QuantumState): post-measurement state when ancilla = 0 (n_qubit_system) poststate1 (qulacs.QuantumState): post-measurement state when ancilla = 1 (n_qubit_system) n_sample (int): number of samples for each observable Return: :float: sampled expectation value of the observable """ n_term = obs.get_term_count() n_qubits = obs.get_qubit_count() p0 = state.get_zero_probability(n_qubits - 1) p1 = 1 - p0 opt = f"0{n_qubits}b" prints(f"p0: {p0} p1: {p1}") print_state(poststate0, name="post(0)") prints("post(1)") print_state(poststate1, name="post(1)") expH = 0 exp = [] coef = [] buf_state = QuantumState(n_qubits) for i in range(n_term): pauli_term = obs.get_term(i) coef.append(pauli_term.get_coef().real) pauli_id = pauli_term.get_pauli_id_list() pauli_index = pauli_term.get_index_list() if len(pauli_id) == 0: # means identity exp.extend(coef) continue buf_state.load(state) measurement_circuit = QuantumCircuit(n_qubits) mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0" for k in range(n_qubits)]) measure_observable = QubitOperator((), 1) #measure_observable = QubitOperator('Z%d' % n_qubits) for single_pauli, index in zip(pauli_id, pauli_index): if single_pauli == 1: ### X measurement_circuit.add_H_gate(index) measure_observable *= QubitOperator(f"X{index}") elif single_pauli == 2: ### Y measurement_circuit.add_Sdag_gate(index) measurement_circuit.add_H_gate(index) measure_observable *= QubitOperator(f"Y{index}") elif single_pauli == 3: ### Z measure_observable *= QubitOperator(f"Z{index}") qulacs_measure_observable \ = create_observable_from_openfermion_text( str(measure_observable)) ### p0 ### H0 = qulacs_measure_observable.get_expectation_value(poststate0) ### p1 ### H1 = qulacs_measure_observable.get_expectation_value(poststate1) prob = p0*H0 - p1*H1 # print(prob, qulacs_measure_observable.get_expectation_value(state), obs.get_expectation_value(state)) prob = qulacs_measure_observable.get_expectation_value(state) expH += coef[i]*prob # measurement_circuit.update_quantum_state(buf_state) # samples = buf_state.sampling(n_sample) # print('samples? ',format(samples[0],opt)) # print("I = :",'%5d' % i, " h_I ", '%10.5f' % coef[i], " <P_I> ", '%10.5f' % exp[i]) # mask = int(mask, 2) # print(sum(list(map(lambda x: (-1) **(bin(x & mask).count('1')), samples)))) # print(coef*sum(list(map(lambda x: (-1) ** # (bin(x & mask).count('1')), samples)))) # expH += coef[i] * exp[i] # samples = buf_state.sampling(n_sample) # mask = int(mask, 2) # prob = sum(list(map(lambda x: (-1) ** # (bin(x & mask).count('1')), samples)))/n_sample # measure_list = list(map(int,np.ones(n_qubits)*2)) # for j in pauli_index: # measure_list[j] = 1 # print(qulacs_measure_observable.get_expectation_value(state)) # expH += coef[i] * prob print(f"coef: {coef[i]:10.5f} prob: {prob:10.5f}") return expH
def test_observable(state, obs, obsZ, n_sample): """Function Args: state (qulacs.QuantumState): This includes entangled ancilla (n_qubits = n_qubit_system + 1) obs (qulacs.Observable): This does not include ancilla Z (n_qubit_system) obsZ (qulacs.Observable): Single Pauli Z for ancilla (1) poststate0 (qulacs.QuantumState): post-measurement state when ancilla = 0 (n_qubit_system) poststate1 (qulacs.QuantumState): post-measurement state when ancilla = 1 (n_qubit_system) n_sample (int): number of samples for each observable Return: :float: sampled expectation value of the observable Author(s): Takashi Tsuchimochi """ n_term = obs.get_term_count() n_qubits = obs.get_qubit_count() p0 = state.get_zero_probability(n_qubits) p1 = 1 - p0 opt = f"0{n_qubits}b" expH = 0 exp = [] coef = [] buf_state = QuantumState(n_qubits) for i in range(n_term): pauli_term = obs.get_term(i) coef.append(pauli_term.get_coef().real) pauli_id = pauli_term.get_pauli_id_list() pauli_index = pauli_term.get_index_list() if len(pauli_id) == 0: # means identity exp.extend(coef) continue buf_state.load(state) measurement_circuit = QuantumCircuit(n_qubits) mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0" for k in range(n_qubits)]) measure_observable = QubitOperator((), 1) for single_pauli, index in zip(pauli_id, pauli_index): if single_pauli == 1: ### X measurement_circuit.add_H_gate(index) measure_observable *= QubitOperator(f"X{index}") elif single_pauli == 2: ### Y measurement_circuit.add_Sdag_gate(index) measurement_circuit.add_H_gate(index) measure_observable *= QubitOperator(f"Y{index}") elif single_pauli == 3: ### Z measure_observable *= QubitOperator(f"Z{index}") qulacs_measure_observable \ = create_observable_from_openfermion_text( str(measure_observable)) measurement_circuit.update_quantum_state(buf_state) #exp.append(obsZ.get_expectation_value(buf_state).real) samples = buf_state.sampling(n_sample) #print(f"samples? {format(samples[0], opt)}") #print(f"I = {i:5d} h_I = {coef[i]:10.5f} <P_I> = {exp[i]:10.5f}") #mask = int(mask, 2) #print(sum(list(map(lambda x: (-1)**(bin(x & mask).count('1')), # samples)))) #print(coef*sum(list(map(lambda x: (-1)**(bin(x & mask).count('1')), # samples)))) expH += coef[i]*exp[i] samples = buf_state.sampling(n_sample) mask = int(mask, 2) prob = (sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")), samples))) /n_sample) measure_list = list(map(int, np.ones(n_qubits)*2)) for j in pauli_index: measure_list[j] = 1 #print(qulacs_measure_observable.get_expectation_value(state)) expH += coef[i]*prob #print(f"coef: {coef[i]:10.5f} prob: {prob:10.5f}") return expH
def cost_proj(Quket, print_level, qulacs_hamiltonianZ, qulacs_s2Z, coef0_H, coef0_S2, kappa_list, theta_list=0, threshold=0.01): """Function: Energy functional for projected methods (phf, puccsd, puccd, opt_puccd) Author(s): Takashi Tsuchimochi """ t1 = time.time() noa = Quket.noa nob = Quket.nob nva = Quket.nva nvb = Quket.nvb n_electrons = Quket.n_electrons rho = Quket.rho DS = Quket.DS anc = Quket.anc n_qubit_system = Quket.n_qubits n_qubits = n_qubit_system + 1 # opt_psauccdとかはndimの計算が異なるけどこっちを使う? #ndim1 = noa * nva + nob * nvb #ndim2aa = int(noa * (noa - 1) * nva * (nva - 1) / 4) #ndim2ab = int(noa * nob * nva * nvb) #ndim2bb = int(nob * (nob - 1) * nvb * (nvb - 1) / 4) #ndim2 = ndim2aa + ndim2ab + ndim2bb ndim1 = Quket.ndim1 ndim2 = Quket.ndim2 ndim = Quket.ndim ref = Quket.ansatz state = QuantumState(n_qubits) if noa == nob: circuit_rhf = set_circuit_rhfZ(n_qubits, n_electrons) else: circuit_rhf = set_circuit_rohfZ(n_qubits, noa, nob) circuit_rhf.update_quantum_state(state) if ref == "phf": circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, kappa_list) circuit_uhf.update_quantum_state(state) elif ref == "sghf": circuit_ghf = set_circuit_ghfZ(n_qubits, noa + nob, nva + nvb, kappa_list) circuit_ghf.update_quantum_state(state) elif ref == "puccsd": # First prepare UHF determinant circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, kappa_list) circuit_uhf.update_quantum_state(state) # Then prepare UCCSD theta_list_rho = theta_list / rho circuit = set_circuit_uccsd(n_qubits, noa, nob, nva, nvb, 0, theta_list_rho, ndim1) for i in range(rho): circuit.update_quantum_state(state) elif ref == "puccd": # First prepare UHF determinant circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, kappa_list) circuit_uhf.update_quantum_state(state) # Then prepare UCCD theta_list_rho = theta_list / rho circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb, theta_list_rho) for i in range(rho): circuit.update_quantum_state(state) elif ref == "opt_puccd": if DS: # First prepare UHF determinant circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, theta_list) circuit_uhf.update_quantum_state(state) # Then prepare UCCD theta_list_rho = theta_list[ndim1:] / rho circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb, theta_list_rho) for i in range(rho): circuit.update_quantum_state(state) else: # First prepare UCCD theta_list_rho = theta_list[ndim1:] / rho circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb, theta_list_rho) for i in range(rho): circuit.update_quantum_state(state) # then rotate circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, theta_list) circuit_uhf.update_quantum_state(state) elif ref == "opt_psauccd": # ここが問題 # ndim2が他と異なる #theta_list_rho = theta_list[ndim1 : ndim1+ndim2]/rho theta_list_rho = theta_list[ndim1:] / rho circuit = set_circuit_sauccd(n_qubits, noa, nva, theta_list_rho) for i in range(rho): circuit.update_quantum_state(state) circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, theta_list) circuit_uhf.update_quantum_state(state) if print_level > 0: if ref in ("uhf", "phf", "suhf", "sghf"): SaveTheta(ndim, kappa_list, cf.tmp) else: SaveTheta(ndim, theta_list, cf.tmp) if print_level > 1: prints("State before projection") print_state(state, n_qubits=n_qubit_system) if ref in ("puccsd", "opt_puccd"): print_amplitudes(theta_list, noa, nob, nva, nvb, threshold) ### grid loop ### ### a list to compute the probability to observe 0 in ancilla qubit ### Array for <HUg>, <S2Ug>, <Ug> Ep = S2 = Norm = 0 nalpha = max(Quket.projection.euler_ngrids[0], 1) nbeta = max(Quket.projection.euler_ngrids[1], 1) ngamma = max(Quket.projection.euler_ngrids[2], 1) HUg = np.empty(nalpha * nbeta * ngamma) S2Ug = np.empty(nalpha * nbeta * ngamma) Ug = np.empty(nalpha * nbeta * ngamma) ig = 0 for ialpha in range(nalpha): alpha = Quket.projection.sp_angle[0][ialpha] alpha_coef = Quket.projection.sp_weight[0][ialpha] for ibeta in range(nbeta): beta = Quket.projection.sp_angle[1][ibeta] beta_coef = (Quket.projection.sp_weight[1][ibeta] * Quket.projection.dmm[ibeta]) for igamma in range(ngamma): gamma = Quket.projection.sp_angle[2][igamma] gamma_coef = Quket.projection.sp_weight[2][igamma] ### Copy quantum state of UHF (cannot be done in real device) ### state_g = QuantumState(n_qubits) state_g.load(state) ### Construct Ug test circuit_ug = QuantumCircuit(n_qubits) ### Hadamard on anc circuit_ug.add_H_gate(anc) #circuit_ug.add_X_gate(anc) #controlled_Ug(circuit_ug, n_qubits, anc, beta) controlled_Ug_gen(circuit_ug, n_qubits, anc, alpha, beta, gamma) #circuit_ug.add_X_gate(anc) circuit_ug.add_H_gate(anc) circuit_ug.update_quantum_state(state_g) ### Compute expectation value <HUg> ### HUg[ig] = qulacs_hamiltonianZ.get_expectation_value(state_g) ### <S2Ug> ### # print_state(state_g) S2Ug[ig] = qulacs_s2Z.get_expectation_value(state_g) ### <Ug> ### p0 = state_g.get_zero_probability(anc) p1 = 1 - p0 Ug[ig] = p0 - p1 ### Norm accumulation ### Norm += alpha_coef * beta_coef * gamma_coef * Ug[ig] Ep += alpha_coef * beta_coef * gamma_coef * HUg[ig] S2 += alpha_coef * beta_coef * gamma_coef * S2Ug[ig] ig += 1 # print('p0 : ',p0,' p1 : ',p1, ' p0 - p1 : ',p0-p1) # print("Time: ",t2-t1) ### Energy calculation <HP>/<P> and <S**2P>/<P> ### Ep /= Norm S2 /= Norm Ep += coef0_H S2 += coef0_S2 t2 = time.time() cpu1 = t2 - t1 if print_level == -1: prints(f"Initial E[{ref}] = {Ep:.12f} <S**2> = {S2:17.15f} " f"rho = {rho}") elif print_level == 1: cput = t2 - cf.t_old cf.t_old = t2 cf.icyc += 1 prints(f"{cf.icyc:5d}: E[{ref}] = {Ep:.12f} <S**2> = {S2:17.15f} " f"CPU Time = {cput:5.2f} ({cpu1:2.2f} / step)") elif print_level > 1: prints(f"Final: E[{ref}] = {Ep:.12f} <S**2> = {S2:17.15f} " f"rho = {rho}") print_state(state, n_qubits=n_qubits - 1) if ref in ("puccsd", "opt_puccd"): print_amplitudes(theta_list, noa, nob, nva, nvb) prints("HUg", HUg) prints("Ug", Ug) # Store wave function Quket.state = state return Ep, S2
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 cost_phf_sample_oneshot(print_level, qulacs_hamiltonianZ, qulacs_s2Z, qulacs_ancZ, coef0_H, coef0_S2, kappa_list): """Function: Test function for sampling Hamiltonian and S** expectation values with PHF just for once. Author(s): Takashi Tsuchimochi 使われてない? """ t1 = time.time() noa = Quket.noa nob = Quket.nob nva = Quket.nva nvb = Quket.nvb n_electrons = Quket.n_electrons n_qubit_system = n_qubits n_qubits = Quket.n_qubits + 1 anc = n_qubit_system state = QuantumState(n_qubits) circuit_rhf = set_circuit_rhfZ(n_qubits, n_electrons) circuit_rhf.update_quantum_state(state) circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, kappa_list) circuit_uhf.update_quantum_state(state) ### Set post-measurement states #### poststate0 = state.copy() poststate1 = state.copy() circuit0 = QuantumCircuit(n_qubits) circuit1 = QuantumCircuit(n_qubits) ### Projection to anc = 0 or anc = 1 ### circuit0.add_gate(P0(0)) circuit1.add_gate(P1(0)) circuit0.update_quantum_state(poststate0) circuit1.update_quantum_state(poststate1) ### Renormalize each state ### norm0 = poststate0.get_squared_norm() norm1 = poststate1.get_squared_norm() poststate0.normalize(norm0) poststate1.normalize(norm1) ### grid loop ### Ng = 4 beta = [-0.861136311594053, -0.339981043584856, 0.339981043584856, 0.861136311594053] wg = [0.173927422568724, 0.326072577431273, 0.326072577431273, 0.173927422568724] ### a list to compute the probability to observe 0 in ancilla qubit p0_list = np.full(n_qubits, 2) p0_list[-1] = 0 ### Array for <HUg>, <S2Ug>, <Ug> samplelist = [5, 50, 500, 5000, 50000, 500000, 5000000] Ng = 4 ncyc = 10 prints("", filepath="./log.txt", opentype="w") for i_sample in samplelist: sampleEn = [] sampleS2 = [] for icyc in range(ncyc): prints(f"n_sample : {i_sample} ({icyc} / {ncyc})", filepath="./log.txt") HUg = [] S2Ug = [] Ug = [] Ephf = S2 = Norm = 0 for i in range(Ng): ### Copy quantum state of UHF (cannot be done in real device) ### state_g = QuantumState(n_qubits) circuit_rhf.update_quantum_state(state_g) circuit_uhf.update_quantum_state(state_g) ### Construct Ug test circuit_ug = QuantumCircuit(n_qubits) ### Hadamard on anc circuit_ug.add_H_gate(anc) controlled_Ug(circuit_ug, n_qubits, anc, np.arccos(beta[i])) circuit_ug.add_H_gate(anc) circuit_ug.update_quantum_state(state_g) ### Probabilities for getting 0 and 1 in ancilla qubit ### p0 = state_g.get_marginal_probability(p0_list) p1 = 1 - p0 ### Compute expectation value <HUg> ### HUg.append(sample_observable(state_g, qulacs_hamiltonianZ, i_sample).real) ### <S2Ug> ### S2Ug.append(sample_observable(state_g, qulacs_s2Z, i_sample).real) #S2Ug.append(qulacs_s2Z.get_expectation_value(state_g)) #Ug.append(p0 - p1) Ug.append(sample_observable(state_g, qulacs_ancZ, i_sample).real) ### Norm accumulation ### Norm += wg[i]*g[i] sampleHUg[icyc, i] = HUg[i] sampleS2Ug[icyc, i] = S2Ug[i] sampleUg[icyc, i] = Ug[i] #print(f"{p0=} {p1=} {p0-p1=}") sampleHUg1.append(HUg[0]) sampleHUg2.append(HUg[1]) sampleHUg3.append(HUg[2]) sampleHUg4.append(HUg[3]) sampleS2Ug1.append(S2Ug[0]) sampleS2Ug2.append(S2Ug[1]) sampleS2Ug3.append(S2Ug[2]) SAMpleS2Ug4.append(S2Ug[3]) sampleUg1.append(Ug[0]) sampleUg2.append(Ug[1]) sampleUg3.append(Ug[2]) sampleUg4.append(Ug[3]) ### Energy calculation <HP>/<P> and <S**2P>/<P> ### Ephf = 0 for i in range(Ng): Ephf += wg[i]*HUg[i]/Norm S2 += wg[i]*S2Ug[i]/Norm #print(f" E[PHF] = {Ephf} <S**2> = {S2} (Nsample = {i_sample})") Ephf += coef0_H S2 += coef0_S2 sampleEn[icyc, 0] = Ephf sampleS2[icyc, 0] = S2 #print(f"(n_sample = {i_sample}): sample HUg1\n", sampleHUg1) #print(f"(n_sample = {i_sample}): sample HUg2\n", sampleHUg2) #print(f"(n_sample = {i_sample}): sample HUg3\n", sampleHUg3) #print(f"(n_sample = {i_sample}): sample HUg4\n", sampleHUg4) #print(f"(n_sample = {i_sample}): sample S2Ug1\n", sampleS2Ug1) #print(f"(n_sample = {i_sample}): sample S2Ug2\n", sampleS2Ug2) #print(f"(n_sample = {i_sample}): sample S2Ug3\n", sampleS2Ug3) #print(f"(n_sample = {i_sample}): sample S2Ug4\n", sampleS2Ug4) #print(f"(n_sample = {i_sample}): sample Ug1\n", sampleUg1) #print(f"(n_sample = {i_sample}): sample Ug2\n", sampleUg2) #print(f"(n_sample = {i_sample}): sample Ug3\n", sampleUg3) #print(f"(n_sample = {i_sample}): sample Ug4\n", sampleUg4) #print(f"(n_sample = {i_sample}): sample HUg1\n", sampleHUg1) #print(f"(n_sample = {i_sample}): sample HUg2\n", sampleHUg2) #print(f"(n_sample = {i_sample}): sample HUg3\n", sampleHUg3) #print(f"(n_sample = {i_sample}): sample HUg4\n", sampleHUg4) #print(f"(n_sample = {i_sample}): sample En\n", sampleEn) #print(f"(n_sample = {i_sample}): sample S2\n", sampleS2) with open(f"./HUg_{i_sample}.csv", "w") as fHUg: writer = csv.writer(fHUg) writer.writerows(sampleHUg) with open(f"./S2Ug_{i_sample}.csv", "w") as fS2Ug: writer = csv.writer(fS2Ug) writer.writerows(sampleS2Ug) with open(f"./Ug_{i_sample}.csv", "w") as fUg: writer = csv.writer(fUg) writer.writerows(sampleUg) with open(f"./En_{i_sample}.csv", "w") as fEn: writer = csv.writer(fEn) writer.writerows(sampleEn) with open(f"./S2_{i_sample}.csv", "w") as fS2: writer = csv.writer(fS2) writer.writerows(sampleS2) return Ephf, S2
def cost_phf_sample(Quket, print_level, qulacs_hamiltonian, qulacs_hamiltonianZ, qulacs_s2Z, qulacs_ancZ, coef0_H, coef0_S2, ref, theta_list, samplelist): """Function: Sample Hamiltonian and S**2 expectation values with PHF and PUCCSD. Write out the statistics in csv files. Author(s): Takashi Tsuchimochi """ t1 = time.time() noa = Quket.noa nob = Quket.nob nva = Quket.nva nvb = Quket.nvb n_electrons = Quket.n_electrons n_qubit_system = n_qubits n_qubits = Quket.n_qubits + 1 anc = n_qubit_system ndim1 = Quket.ndim1 state = QuantumState(n_qubits) circuit_rhf = set_circuit_rhfZ(n_qubits, n_electrons) circuit_rhf.update_quantum_state(state) if ref == "phf": circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, theta_list) circuit_uhf.update_quantum_state(state) print("pHF") elif ref == "puccsd": circuit = set_circuit_uccsd(n_qubits, noa, nob, nva, nvb, theta_list, ndim1) for i in range(rho): circuit.update_quantum_state(state) print("UCCSD") if print_level > -1: print("State before projection") utils.print_state(state, n_qubit_system) #### Set post-measurement states #### #poststate0 = state.copy() #poststate1 = state.copy() #circuit0 = QuantumCircuit(n_qubits) #circuit1 = QuantumCircuit(n_qubits) #### Projection to anc = 0 or anc = 1 ### #circuit0.add_gate(P0(0)) #circuit1.add_gate(P1(0)) #circuit0.update_quantum_state(poststate0) #circuit1.update_quantum_state(poststate1) #### Renormalize each state ### #norm0 = poststate0.get_squared_norm() #norm1 = poststate1.get_squared_norm() #poststate0.normalize(norm0) #poststate1.normalize(norm1) ### grid loop ### Ng = 4 beta = [-0.861136311594053, -0.339981043584856, 0.339981043584856, 0.861136311594053] wg = [0.173927422568724, 0.326072577431273, 0.326072577431273, 0.173927422568724] Ng = 2 beta = [0.577350269189626, -0.577350269189626] wg = [0.5, 0.5] ### a list to compute the probability to observe 0 in ancilla qubit p0_list = np.full(n_qubits, 2) p0_list[-1] = 0 ### Array for <HUg>, <S2Ug>, <Ug> # samplelist = [10,100,1000,10000,100000,1000000,10000000] ncyc = 4 prints("", filepath="./log2.txt") for i_sample in samplelist: i_sample_x = i_sample if i_sample == 10000000: print("OK") ncyc = ncyc*10 i_sample_x = 1000000 sampleHUg1 = [] sampleHUg2 = [] sampleHUg3 = [] sampleHUg4 = [] sampleS2Ug1 = [] sampleS2Ug2 = [] sampleS2Ug3 = [] sampleS2Ug4 = [] sampleUg1 = [] sampleUg2 = [] sampleUg3 = [] sampleUg4 = [] # sampleEn = [] # sampleS2 = [] sampleHUg = np.zeros((ncyc, Ng)) sampleS2Ug = np.zeros((ncyc, Ng)) sampleUg = np.zeros((ncyc, Ng)) sampleEn = np.zeros((ncyc, 1)) sampleS2 = np.zeros((ncyc, 1)) for icyc in range(ncyc): prints(f"n_sample = {i_sample_x} ({icyc} / {ncyc})", filepath="./log2.txt") HUg = [] S2Ug = [] Ug = [] Ephf = S2 = Norm = 0 for i in range(Ng): ### Copy quantum state of UHF (cannot be done in real device) ### state_g = QuantumState(n_qubits) state_g.load(state) ### Construct Ug test circuit_ug = QuantumCircuit(n_qubits) ### Hadamard on anc circuit_ug.add_H_gate(anc) controlled_Ug(circuit_ug, n_qubits, anc, np.arccos(beta[i])) circuit_ug.add_H_gate(anc) circuit_ug.update_quantum_state(state_g) ### Set post-measurement states #### poststate0 = state_g.copy() poststate1 = state_g.copy() circuit0 = QuantumCircuit(n_qubits) circuit1 = QuantumCircuit(n_qubits) ### Projection to anc = 0 or anc = 1 ### circuit0.add_gate(P0(anc)) circuit1.add_gate(P1(anc)) circuit0.update_quantum_state(poststate0) circuit1.update_quantum_state(poststate1) ### Renormalize each state ### norm0 = poststate0.get_squared_norm() norm1 = poststate1.get_squared_norm() poststate0.normalize(norm0) poststate1.normalize(norm1) ### Set ancilla qubit of poststate1 to zero (so that it won't be used) ### circuit_anc = QuantumCircuit(n_qubits) circuit_anc.add_X_gate(anc) circuit_anc.update_quantum_state(poststate1) print( test_transition_observable( state_g, qulacs_hamiltonianZ, poststate0, poststate1, 100000)) # exit() ### Probabilities for getting 0 and 1 in ancilla qubit ### p0 = state_g.get_marginal_probability(p0_list) p1 = 1 - p0 ### Compute expectation value <HUg> ### HUg.append(sample_observable(state_g, qulacs_hamiltonianZ, i_sample_x).real) #HUg.append(adaptive_sample_observable(state_g, # qulacs_hamiltonianZ, # i_sample_x).real) ### <S2Ug> ### S2Ug.append(sample_observable(state_g, qulacs_s2Z, i_sample_x).real) #S2Ug.append(adaptive_sample_observable(state_g, # qulacs_s2Z, # i_sample_x).real) #S2Ug.append(qulacs_s2Z.get_expectation_value(state_g)) #HUg.append(0) #S2Ug.append(0) #Ug.append(p0 - p1) n_term = qulacs_hamiltonianZ.get_term_count() n_sample_total = i_sample_x * n_term # in the worst-case scenario, # Ug is measured as many times as n_sample_total #(required to evaluate HUg) Ug.append(sample_observable(state_g, qulacs_ancZ, i_sample_x*n_term).real) #p0_sample = 0 #for j_sample in range(n_sample_total): # if(p0 > np.random.rand()): # p0_sample += 1 #Ug.append(2*p0_sample/n_sample_total - 1) ### Norm accumulation ### Norm += wg[i]*Ug[i] sampleHUg[icyc, i] = HUg[i] sampleS2Ug[icyc, i] = S2Ug[i] sampleUg[icyc, i] = Ug[i] #print('p0 : ',p0,' p1 : ',p1, ' p0 - p1 : ',p0-p1) sampleHUg1.append(HUg[0]) sampleHUg2.append(HUg[1]) #sampleHUg3.append(HUg[2]) #sampleHUg4.append(HUg[3]) sampleS2Ug1.append(S2Ug[0]) sampleS2Ug2.append(S2Ug[1]) #sampleS2Ug3.append(S2Ug[2]) #sampleS2Ug4.append(S2Ug[3]) sampleUg1.append(Ug[0]) sampleUg2.append(Ug[1]) #sampleUg3.append(Ug[2]) #sampleUg4.append(Ug[3]) ### Energy calculation <HP>/<P> and <S**2P>/<P> ### Ephf = 0 for i in range(Ng): Ephf += wg[i]*HUg[i]/Norm S2 += wg[i]*S2Ug[i]/Norm # print(" <S**2> = ", S2, '\n') Ephf += coef0_H S2 += coef0_S2 sampleEn[icyc, 0] = Ephf sampleS2[icyc, 0] = S2 # print(" <E[PHF]> (Nsample = ",i_sample,") = ", Ephf) #print(f"(n_sample = {i_sample}): sample HUg1\n",sampleHUg1) #print(f"(n_sample = {i_sample}): sample HUg2\n",sampleHUg2) #print(f"(n_sample = {i_sample}): sample HUg3\n",sampleHUg3) #print(f"(n_sample = {i_sample}): sample HUg4\n",sampleHUg4) #print(f"(n_sample = {i_sample}): sample S2Ug1\n",sampleS2Ug1) #print(f"(n_sample = {i_sample}): sample S2Ug2\n",sampleS2Ug2) #print(f"(n_sample = {i_sample}): sample S2Ug3\n",sampleS2Ug3) #print(f"(n_sample = {i_sample}): sample S2Ug4\n",sampleS2Ug4) #print(f"(n_sample = {i_sample}): sample Ug1\n",sampleUg1) #print(f"(n_sample = {i_sample}): sample Ug2\n",sampleUg2) #print(f"(n_sample = {i_sample}): sample Ug3\n",sampleUg3) #print(f"(n_sample = {i_sample}): sample Ug4\n",sampleUg4) #print(f"(n_sample = {i_sample}): sample HUg1\n",sampleHUg1) #print(f"(n_sample = {i_sample}): sample HUg2\n",sampleHUg2) #print(f"(n_sample = {i_sample}): sample HUg3\n",sampleHUg3) #print(f"(n_sample = {i_sample}): sample HUg4\n",sampleHUg4) #print(f"(n_sample = {i_sample}): sample En\n",sampleEn) #print(f"(n_sample = {i_sample}): sample S2\n",sampleS2) with open(f"./Ug_{i_sample}.csv", "w") as fUg: writer = csv.writer(fUg) writer.writerows(sampleUg) with open(f"./HUg_{i_sample}.csv", "w") as fHUg: writer = csv.writer(fHUg) writer.writerows(sampleHUg) with open(f"./S2Ug_{i_sample}.csv", "w") as fS2Ug: writer = csv.writer(fS2Ug) writer.writerows(sampleS2Ug) with open(f"./En_{i_sample}.csv", "w") as fEn: writer = csv.writer(fEn) writer.writerows(sampleEn) with open(f"./S2_{i_smaple}.csv", "w") as fS2: writer = csv.writer(fS2) writer.writerows(sampleS2) return Ephf, S2
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 adaptive_sample_observable(state, obs, n_sample): """ Args: state (qulacs.QuantumState): obs (qulacs.Observable) n_sample (int): number of samples for each observable Return: :float: sampled expectation value of the observable """ n_term = obs.get_term_count() n_qubits = obs.get_qubit_count() exp = 0 buf_state = QuantumState(n_qubits) ### check the coefficients for each term... coef_list = np.array([abs(obs.get_term(i).get_coef()) for i in range(n_term)]) sum_coef = np.sum(coef_list) ### sort sorted_indices = np.argsort(-coef_list) coef_list.sort() #sorted_coef_list = [coef_list[i] for i in sorted_indices] ### determine sampling wight n_sample_total = n_sample*n_term n_sample_list = n_sample_total*coef_list//sum_coef n_count = np.sum(n_sample_list) n_rest = n_sample_total - n_count n_sample_list[sorted_indices[:n_rest]] += 1 j = 0 for i in range(n_term): if n_sample_list[i] == 0: continue j += n_sample_list[i] pauli_term = obs.get_term(i) coef = pauli_term.get_coef() pauli_id = pauli_term.get_pauli_id_list() pauli_index = pauli_term.get_index_list() if len(pauli_id) == 0: # means identity exp += coef continue buf_state.load(state) measurement_circuit = QuantumCircuit(n_qubits) mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0" for k in range(n_qubits)]) for single_pauli, index in zip(pauli_id, pauli_index): if single_pauli == 1: measurement_circuit.add_H_gate(index) elif single_pauli == 2: measurement_circuit.add_Sdag_gate(index) measurement_circuit.add_H_gate(index) measurement_circuit.update_quantum_state(buf_state) samples = buf_state.sampling(n_sample_list[i]) mask = int(mask, 2) exp += (coef *sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")), samples))) /n_sample_list[i]) return exp
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