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 set_input_state(self, x_list): """入力状態のリストを作成""" x_list_normalized = min_max_scaling(x_list) # xを[-1, 1]の範囲にスケール st_list = [] for x in x_list_normalized: st = QuantumState(self.nqubit) input_gate = self.create_input_gate(x) input_gate.update_quantum_state(st) st_list.append(st.copy()) self.input_state_list = st_list
def set_input_state(self, x_list): """List of input state""" x_list_normalized = min_max_scaling(x_list) # x within [-1, 1] st_list = [] for x in x_list_normalized: st = QuantumState(self.nqubit) input_gate = self.create_input_gate(x) input_gate.update_quantum_state(st) st_list.append(st.copy()) self.input_state_list = st_list
def set_input_state(self, x_list, uin_type): """List of input state""" x_list_normalized = min_max_scaling(x_list) # x within [-1, 1] #x_list_normalized_0to2pi = min_max_scaling_0to2pi(x_list) # x within [0, 2pi] #print('x_list_normalized_0to2pi=',x_list_normalized_0to2pi) st_list = [] for x in x_list_normalized: #for x in x_list_normalized_0to2pi: st = QuantumState(self.nqubit) input_gate = self.create_input_gate(x, uin_type) input_gate.update_quantum_state(st) st_list.append(st.copy()) self.input_state_list = st_list
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 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 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 qite_anti(Quket, id_set, size): ### Parameter setting ansatz = Quket.ansatz n = Quket.n_qubits db = Quket.dt qbit = Quket.det ntime = Quket.maxiter observable = Quket.qulacs.Hamiltonian S2_observable = Quket.qulacs.S2 threshold = Quket.ftol S2 = 0 prints(f"QITE: Pauli operator group size = {size}") if ansatz != "cite": sigma_list, sigma_ij_index, sigma_ij_coef = qite_s_operators(id_set, n) len_list = len(sigma_list) prints(f" Unique sigma list = {len_list}") index = np.arange(n) delta = QuantumState(n) first_state = QuantumState(n) first_state.set_computational_basis(qbit) energy = [] psi_dash = first_state.copy() t1 = time.time() cf.t_old = t1 En = observable.get_expectation_value(psi_dash) energy.append(En) if S2_observable is not None: S2 = S2_observable.get_expectation_value(psi_dash) dE = 100 for t in range(ntime): t2 = time.time() cput = t2 - cf.t_old cf.t_old = t2 if cf.debug: print_state(psi_dash) prints(f"{t*db:6.2f}: E = {En:.12f} <S**2> = {S2:17.15f} " f"CPU Time = {cput: 5.2f}") if abs(dE) < threshold: break if t == 0: xv = np.zeros(size) T0 = time.time() delta = calc_delta(psi_dash, observable, n, db) T1 = time.time() if ansatz == "cite": delta.add_state(psi_dash) psi_dash = delta.copy() else: #for i in range(size): # pauli_id = id_set[i] # circuit_i = make_gate(n, index, pauli_id) # state_i = psi_dash.copy() # circuit_i.update_quantum_state(state_i) # print(i) # for j in range(i+1): # pauli_id = id_set[j] # circuit_j = make_gate(n, index, pauli_id) # state_j = psi_dash.copy() # circuit_j.update_quantum_state(state_j) # s = inner_product(state_j, state_i) # S[i][j] = s # S[j][i] = s ### Compute Sij as expectation values of sigma_list Sij_list = np.zeros(len_list) Sij_my_list = np.zeros(len_list) ipos, my_ndim = mpi.myrange(len_list) T2 = time.time() for iope in range(ipos, ipos + my_ndim): val = sigma_list[iope].get_expectation_value(psi_dash) Sij_my_list[iope] = val T3 = time.time() mpi.comm.Allreduce(Sij_my_list, Sij_list, mpi.MPI.SUM) T4 = time.time() ### Distribute Sij ij = 0 sizeT = size * (size - 1) // 2 ipos, my_ndim = mpi.myrange(sizeT) S = np.zeros((size, size), dtype=complex) my_S = np.zeros((size, size), dtype=complex) for i in range(size): for j in range(i): if ij in range(ipos, ipos + my_ndim): ind = sigma_ij_index[ij] coef = sigma_ij_coef[ij] my_S[i, j] = coef * Sij_list[ind] my_S[j, i] = my_S[i, j].conjugate() ij += 1 mpi.comm.Allreduce(my_S, S, mpi.MPI.SUM) for i in range(size): S[i, i] = 1 T5 = time.time() sigma = [] for i in range(size): pauli_id = id_set[i] circuit_i = make_gate(n, index, pauli_id) state_i = psi_dash.copy() circuit_i.update_quantum_state(state_i) sigma.append(state_i) T6 = time.time() b_l = np.empty(size) for i in range(size): b_i = inner_product(sigma[i], delta) b_i = -2 * b_i.imag b_l[i] = b_i Amat = 2 * np.real(S) T7 = time.time() zct = b_l @ Amat def cost_fun(vct): return LA.norm(Amat @ vct - b_l)**2 def J_cost_fun(vct): wct = Amat.T @ Amat @ vct return 2.0 * (wct - zct) #x = sp.optimize.minimize(cost_fun, x0=xv, method='Newton-CG', # jac=J_cost_fun, tol=1e-8).x #xv = x.copy() #x = sp.optimize.least_squares(cost_fun, x0=xv, ftol=1e-8).x #xv = x.copy() x, res, rnk, s = lstsq(Amat, b_l, cond=1e-8) a = x.copy() ### Just in case, broadcast a... mpi.comm.Bcast(a, root=0) T8 = time.time() psi_dash = calc_psi_lessH(psi_dash, n, index, a, id_set) T9 = time.time() if cf.debug: prints(f"T0 -> T1 {T1-T0}") prints(f"T1 -> T2 {T2-T1}") prints(f"T2 -> T3 {T3-T2}") prints(f"T3 -> T4 {T4-T3}") prints(f"T4 -> T5 {T5-T4}") prints(f"T5 -> T6 {T6-T5}") prints(f"T6 -> T7 {T7-T6}") prints(f"T7 -> T8 {T8-T7}") prints(f"T8 -> T9 {T9-T8}") En = observable.get_expectation_value(psi_dash) if S2_observable is not None: S2 = S2_observable.get_expectation_value(psi_dash) energy.append(En) dE = energy[t + 1] - energy[t] print_state(psi_dash, name="QITE")
class QulacsDevice(QubitDevice): """Qulacs device""" name = "Qulacs device" short_name = "qulacs.simulator" pennylane_requires = ">=0.11.0" version = __version__ author = "Steven Oud and Xanadu" gpu_supported = GPU_SUPPORTED _capabilities = { "model": "qubit", "tensor_observables": True, "inverse_operations": True } _operation_map = { "QubitStateVector": None, "BasisState": None, "QubitUnitary": None, "Toffoli": gate.TOFFOLI, "CSWAP": gate.FREDKIN, "CRZ": crz, "SWAP": gate.SWAP, "CNOT": gate.CNOT, "CZ": gate.CZ, "S": gate.S, "T": gate.T, "RX": gate.RX, "RY": gate.RY, "RZ": gate.RZ, "PauliX": gate.X, "PauliY": gate.Y, "PauliZ": gate.Z, "Hadamard": gate.H, "PhaseShift": phase_shift, } _observable_map = { "PauliX": "X", "PauliY": "Y", "PauliZ": "Z", "Identity": "I", "Hadamard": None, "Hermitian": None, } operations = _operation_map.keys() observables = _observable_map.keys() # Add inverse gates to _operation_map _operation_map.update({k + ".inv": v for k, v in _operation_map.items()}) def __init__(self, wires, shots=1000, analytic=True, gpu=False, **kwargs): super().__init__(wires=wires, shots=shots, analytic=analytic) if gpu: if not QulacsDevice.gpu_supported: raise DeviceError( "GPU not supported with installed version of qulacs. " "Please install 'qulacs-gpu' to use GPU simulation.") self._state = QuantumStateGpu(self.num_wires) else: self._state = QuantumState(self.num_wires) self._circuit = QuantumCircuit(self.num_wires) self._pre_rotated_state = self._state.copy() def apply(self, operations, **kwargs): rotations = kwargs.get("rotations", []) self.apply_operations(operations) self._pre_rotated_state = self._state.copy() # Rotating the state for measurement in the computational basis if rotations: self.apply_operations(rotations) def apply_operations(self, operations): """Apply the circuit operations to the state. This method serves as an auxiliary method to :meth:`~.QulacsDevice.apply`. Args: operations (List[pennylane.Operation]): operations to be applied """ for i, op in enumerate(operations): if i > 0 and isinstance(op, (QubitStateVector, BasisState)): raise DeviceError( "Operation {} cannot be used after other Operations have already been applied " "on a {} device.".format(op.name, self.short_name)) if isinstance(op, QubitStateVector): self._apply_qubit_state_vector(op) elif isinstance(op, BasisState): self._apply_basis_state(op) elif isinstance(op, QubitUnitary): self._apply_qubit_unitary(op) elif isinstance(op, (CRZ, PhaseShift)): self._apply_matrix(op) else: self._apply_gate(op) def _apply_qubit_state_vector(self, op): """Initialize state with a state vector""" wires = op.wires input_state = op.parameters[0] if len(input_state) != 2**len(wires): raise ValueError("State vector must be of length 2**wires.") if input_state.ndim != 1 or len(input_state) != 2**len(wires): raise ValueError("State vector must be of length 2**wires.") if not np.isclose(np.linalg.norm(input_state, 2), 1.0, atol=tolerance): raise ValueError("Sum of amplitudes-squared does not equal one.") input_state = _reverse_state(input_state) # call qulacs' state initialization self._state.load(input_state) def _apply_basis_state(self, op): """Initialize a basis state""" wires = op.wires par = op.parameters # translate from PennyLane to Qulacs wire order bits = par[0][::-1] n_basis_state = len(bits) if not set(bits).issubset({0, 1}): raise ValueError( "BasisState parameter must consist of 0 or 1 integers.") if n_basis_state != len(wires): raise ValueError( "BasisState parameter and wires must be of equal length.") basis_state = 0 for bit in bits: basis_state = (basis_state << 1) | bit # call qulacs' basis state initialization self._state.set_computational_basis(basis_state) def _apply_qubit_unitary(self, op): """Apply unitary to state""" # translate op wire labels to consecutive wire labels used by the device device_wires = self.map_wires(op.wires) par = op.parameters if len(par[0]) != 2**len(device_wires): raise ValueError( "Unitary matrix must be of shape (2**wires, 2**wires).") if op.inverse: par[0] = par[0].conj().T # reverse wires (could also change par[0]) reverse_wire_labels = device_wires.tolist()[::-1] unitary_gate = gate.DenseMatrix(reverse_wire_labels, par[0]) self._circuit.add_gate(unitary_gate) unitary_gate.update_quantum_state(self._state) def _apply_matrix(self, op): """Apply predefined gate-matrix to state (must follow qulacs convention)""" # translate op wire labels to consecutive wire labels used by the device device_wires = self.map_wires(op.wires) par = op.parameters mapped_operation = self._operation_map[op.name] if op.inverse: mapped_operation = self._get_inverse_operation( mapped_operation, device_wires, par) if callable(mapped_operation): gate_matrix = mapped_operation(*par) else: gate_matrix = mapped_operation # gate_matrix is already in correct order => no wire-reversal needed dense_gate = gate.DenseMatrix(device_wires.labels, gate_matrix) self._circuit.add_gate(dense_gate) gate.DenseMatrix(device_wires.labels, gate_matrix).update_quantum_state(self._state) def _apply_gate(self, op): """Apply native qulacs gate""" # translate op wire labels to consecutive wire labels used by the device device_wires = self.map_wires(op.wires) par = op.parameters mapped_operation = self._operation_map[op.name] if op.inverse: mapped_operation = self._get_inverse_operation( mapped_operation, device_wires, par) # Negating the parameters such that it adheres to qulacs par = np.negative(par) # mapped_operation is already in correct order => no wire-reversal needed self._circuit.add_gate(mapped_operation(*device_wires.labels, *par)) mapped_operation(*device_wires.labels, *par).update_quantum_state(self._state) @staticmethod def _get_inverse_operation(mapped_operation, device_wires, par): """Return the inverse of an operation""" if mapped_operation is None: return mapped_operation # if an inverse variant of the operation exists try: inverse_operation = getattr(gate, mapped_operation.get_name() + "dag") except AttributeError: # if the operation is hard-coded try: if callable(mapped_operation): inverse_operation = np.conj(mapped_operation(*par)).T else: inverse_operation = np.conj(mapped_operation).T # if mapped_operation is a qulacs.gate and np.conj is applied on it except TypeError: # else, redefine the operation as the inverse matrix def inverse_operation(*p): # embed the gate in a unitary matrix with shape (2**wires, 2**wires) g = mapped_operation(*p).get_matrix() mat = reduce(np.kron, [np.eye(2)] * len(device_wires)).astype(complex) mat[-len(g):, -len(g):] = g # mat follows PL convention => reverse wire-order reverse_wire_labels = device_wires.tolist()[::-1] gate_mat = gate.DenseMatrix(reverse_wire_labels, np.conj(mat).T) return gate_mat return inverse_operation def analytic_probability(self, wires=None): """Return the (marginal) analytic probability of each computational basis state.""" if self._state is None: return None all_probs = self._abs(self.state)**2 prob = self.marginal_prob(all_probs, wires) return prob def expval(self, observable): if self.analytic: qulacs_observable = Observable(self.num_wires) if isinstance(observable.name, list): observables = [ self._observable_map[obs] for obs in observable.name ] else: observables = [self._observable_map[observable.name]] if None not in observables: applied_wires = self.map_wires(observable.wires).tolist() opp = " ".join([ f"{obs} {applied_wires[i]}" for i, obs in enumerate(observables) ]) qulacs_observable.add_operator(1.0, opp) return qulacs_observable.get_expectation_value( self._pre_rotated_state) # exact expectation value eigvals = self._asarray(observable.eigvals, dtype=self.R_DTYPE) prob = self.probability(wires=observable.wires) return self._dot(eigvals, prob) # estimate the ev return np.mean(self.sample(observable)) @property def state(self): # returns the state after all operations are applied return _reverse_state(self._state.get_vector()) def reset(self): self._state.set_zero_state() self._pre_rotated_state = self._state.copy() self._circuit = QuantumCircuit(self.num_wires)
class QulacsDevice(Device): """Qulacs device""" name = 'Qulacs device' short_name = 'qulacs.simulator' pennylane_requires = '>=0.5.0' version = __version__ author = 'Steven Oud' _capabilities = {'model': 'qubit', 'tensor_observables': True} _operations_map = { 'QubitStateVector': None, 'BasisState': None, 'QubitUnitary': None, 'Toffoli': toffoli, 'CSWAP': CSWAP, 'CRZ': crz, 'Rot': None, 'SWAP': gate.SWAP, 'CNOT': gate.CNOT, 'CZ': gate.CZ, 'S': gate.S, 'Sdg': gate.Sdag, 'T': gate.T, 'Tdg': gate.Tdag, 'RX': gate.RX, 'RY': gate.RY, 'RZ': gate.RZ, 'PauliX': gate.X, 'PauliY': gate.Y, 'PauliZ': gate.Z, 'Hadamard': gate.H } _observable_map = { 'PauliX': X, 'PauliY': Y, 'PauliZ': Z, 'Hadamard': H, 'Identity': I, 'Hermitian': hermitian } operations = _operations_map.keys() observables = _observable_map.keys() def __init__(self, wires, gpu=False, **kwargs): super().__init__(wires=wires) if gpu: if not GPU_SUPPORTED: raise DeviceError( 'GPU not supported with installed version of qulacs. ' 'Please install "qulacs-gpu" to use GPU simulation.') self._state = QuantumStateGpu(wires) else: self._state = QuantumState(wires) self._circuit = QuantumCircuit(wires) self._first_operation = True def apply(self, operation, wires, par): par = np.negative(par) if operation == 'BasisState' and not self._first_operation: raise DeviceError( 'Operation {} cannot be used after other Operations have already been applied ' 'on a {} device.'.format(operation, self.short_name)) self._first_operation = False if operation == 'QubitStateVector': if len(par[0]) != 2**len(wires): raise ValueError('State vector must be of length 2**wires.') self._state.load(par[0]) elif operation == 'BasisState': if len(par[0]) != len(wires): raise ValueError('Basis state must prepare all qubits.') basis_state = 0 for bit in reversed(par[0]): basis_state = (basis_state << 1) | bit self._state.set_computational_basis(basis_state) elif operation == 'QubitUnitary': if len(par[0]) != 2**len(wires): raise ValueError( 'Unitary matrix must be of shape (2**wires, 2**wires).') unitary_gate = gate.DenseMatrix(wires, par[0]) self._circuit.add_gate(unitary_gate) elif operation == 'Rot': self._circuit.add_gate( gate.merge([ gate.RZ(wires[0], par[0]), gate.RY(wires[0], par[1]), gate.RZ(wires[0], par[2]) ])) elif operation in ('CRZ', 'Toffoli', 'CSWAP'): mapped_operation = self._operations_map[operation] if callable(mapped_operation): gate_matrix = mapped_operation(*par) else: gate_matrix = mapped_operation dense_gate = gate.DenseMatrix(wires, gate_matrix) self._circuit.add_gate(dense_gate) else: mapped_operation = self._operations_map[operation] self._circuit.add_gate(mapped_operation(*wires, *par)) @property def state(self): return self._state.get_vector() def pre_measure(self): self._circuit.update_quantum_state(self._state) def expval(self, observable, wires, par): bra = self._state.copy() if isinstance(observable, list): A = self._get_tensor_operator_matrix(observable, par) wires = [item for sublist in wires for item in sublist] else: A = self._get_operator_matrix(observable, par) dense_gate = gate.DenseMatrix(wires, A) dense_gate.update_quantum_state(self._state) expectation = inner_product(bra, self._state) return expectation.real def probabilities(self): states = itertools.product(range(2), repeat=self.num_wires) probs = np.abs(self.state)**2 return OrderedDict(zip(states, probs)) def reset(self): self._state.set_zero_state() self._circuit = QuantumCircuit(self.num_wires) def _get_operator_matrix(self, operation, par): A = self._observable_map[operation] if not callable(A): return A return A(*par) def _get_tensor_operator_matrix(self, obs, par): ops = [self._get_operator_matrix(o, p) for o, p in zip(obs, par)] return functools.reduce(np.kron, ops)
def qite_exact(Quket): nspin = Quket.n_qubits db = Quket.dt ntime = Quket.maxiter qbit = Quket.det observable = Quket.qulacs.Hamiltonian threshold = Quket.ftol active_qubit = [x for x in range(nspin)] n = nspin size = 4**nspin index = np.arange(n) delta = QuantumState(n) first_state = QuantumState(n) first_state.set_computational_basis(qbit) prints(f"Exact QITE: Pauli operator group size = {size}") energy = [] psi_dash = first_state.copy() value = observable.get_expectation_value(psi_dash) energy.append(value) t1 = time.time() cf.t_old = t1 dE = 100 for t in range(ntime): t2 = time.time() cput = t2 - cf.t_old cf.t_old = t2 if cf.debug: print_state(psi_dash) prints(f"{t*db:6.2f}: E = {value:.12f} CPU Time = {cput:5.2f}") if abs(dE) < threshold: break #if t == 0: # xv = np.zeros(size) psi_dash_copy = psi_dash.copy() #mpi.comm.bcast(size, root=0) #S_part = np.zeros((size, size), dtype=complex) #S = np.zeros((size, size), dtype=complex) #sizeT = size*(size+1)//2 #nblock = sizeT//mpi.nprocs #ij = mpi.rank*nblock #start = int(np.sqrt(2*ij + 1/4) - 1/2) #end = int(np.sqrt(2*(ij+nblock) + 1/4) - 1/2) #for i in range(start, end): # for j in range(i+1): # S_part[i, j] = calc_inner1(i, j, n, active_qubit, # index, psi_dash) # ij += 1 # S[:i, i] = S[i, :i] #mpi.comm.Allreduce(S_part, S, mpi.MPI.SUM) S_part = np.zeros((size, size), dtype=complex) S = np.zeros((size, size), dtype=complex) sizeT = size * (size - 1) // 2 ipos, my_ndim = mpi.myrange(sizeT) ij = 0 for i in range(size): for j in range(i): if ij in range(ipos, ipos + my_ndim): S_part[i, j] = calc_inner1(i, j, n, active_qubit, index, psi_dash) S_part[j, i] = S_part[i, j].conjugate() ij += 1 mpi.comm.Allreduce(S_part, S, mpi.MPI.SUM) for i in range(size): S[i, i] = 1 sigma = [] for i in range(size): state_i = make_state1(i, n, active_qubit, index, psi_dash) sigma.append(state_i) delta = calc_delta(psi_dash, observable, n, db) b_l = [] b_l = np.empty(size) for i in range(size): b_i = inner_product(sigma[i], delta) b_i = -2 * b_i.imag b_l[i] = b_i Amat = 2 * np.real(S) zct = b_l @ Amat #def cost_fun(vct): # return LA.norm(Amat@vct - b_l)**2 #def J_cost_fun(vct): # wct = Amat.T@Amat@vct # return 2.0*(wct-zct) #x = sp.optimize.minimize(cost_fun, x0=xv, method="Newton-CG", # jac=J_cost_fun, tol=1e-8).x #xv = x.copy() x, res, rnk, s = lstsq(Amat, b_l, cond=1.0e-8) a = x.copy() ### Just in case, broadcast a... mpi.comm.Bcast(a, root=0) psi_dash = calc_psi(psi_dash_copy, n, index, a, active_qubit) value = observable.get_expectation_value(psi_dash) energy.append(value) dE = energy[t + 1] - energy[t]
def __run_all(qcirc=None, shots=1, cid=None, backend=None, proc='CPU', out_state=False): if qcirc is None: raise ValueError("quantum circuit must be specified.") qubit_num = qcirc.qubit_num cmem_num = qcirc.cmem_num if cid is None: cid = list(range(cmem_num)) if cmem_num < len(cid): raise ValueError( "length of cid must be less than classical resister size of qcirc") # # initialize # if proc == 'CPU': qstate = QuantumState(qubit_num) else: from qulacs import QuantumStateGpu qstate = QuantumStateGpu(qubit_num) cmem = [0] * cmem_num # # before measurement gate # while True: kind = qcirc.kind_first() if kind is None or kind is cfg.MEASURE or kind is cfg.RESET: break (kind, qid, para, c, ctrl) = qcirc.pop_gate() if ctrl is None or (ctrl is not None and cmem[ctrl] == 1): __qulacs_operate_qgate(qstate, qubit_num, kind=kind, qid=qid, phase=para[0], phase1=para[1], phase2=para[2]) if kind is None: result = Result() result.qubit_num = qubit_num result.cmem_num = cmem_num result.cid = cid result.shots = shots result.frequency = None result.backend = backend if out_state is True: result.qstate = __transform_qlazy_qstate(qstate) result.cmem = __transform_qlazy_cmem(cmem) return result # # after measurement gate # if set(qcirc.kind_list()) == {cfg.MEASURE}: q_list = [] while True: kind = qcirc.kind_first() if kind is None: break (kind, qid, para, c, ctrl) = qcirc.pop_gate() q_list.append(qid[0]) frequency, qstate = __qulacs_measure_shots(qstate, q_list, shots) result = Result() result.qubit_num = qubit_num result.cmem_num = cmem_num result.cid = cid result.shots = shots result.frequency = frequency result.backend = backend if out_state is True: result.qstate = __transform_qlazy_qstate(qstate) result.cmem = __transform_qlazy_cmem(cmem) return result frequency = Counter() qstate_tmp = None for _ in range(shots): qstate_tmp = qstate.copy() qcirc_tmp = qcirc.clone() while True: kind = qcirc_tmp.kind_first() if kind is None: break if kind == cfg.MEASURE: (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate() mval = __qulacs_measure(qstate_tmp, qubit_num, qid[0]) if c is not None: cmem[c] = mval elif kind == cfg.RESET: (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate() __qulacs_reset(qstate_tmp, qubit_num, qid[0]) else: (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate() if (ctrl is None or (ctrl is not None and cmem[ctrl] == 1)): __qulacs_operate_qgate(qstate_tmp, qubit_num, kind=kind, qid=qid, phase=para[0], phase1=para[1], phase2=para[2]) if len(cmem) > 0: mval = ''.join(map(str, [cmem[i] for i in cid])) frequency[mval] += 1 if qstate_tmp is not None: qstate.load(qstate_tmp.get_vector()) if len(frequency) == 0: frequency = None result = Result() result.qubit_num = qubit_num result.cmem_num = cmem_num result.cid = cid result.shots = shots result.frequency = frequency result.backend = backend if out_state is True: result.qstate = __transform_qlazy_qstate(qstate) result.cmem = __transform_qlazy_cmem(cmem) return result