def S2Proj(Quket, Q, threshold=1e-8): """Function Perform spin-projection to QuantumState |Q> |Q'> = Ps |Q> where Ps is a spin-projection operator (non-unitary). Ps = \sum_i^ng wg[i] Ug[i] This function provides a shortcut to |Q'>, which is unreal. One actually needs to develop a quantum circuit for this (See PRR 2, 043142 (2020)). Author(s): Takashi Tsuchimochi """ spin = Quket.projection.spin s = (spin - 1) / 2 Ms = Quket.projection.Ms / 2 n_qubits = Q.get_qubit_count() state_P = QuantumState(n_qubits) state_P.multiply_coef(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) for ialpha in range(nalpha): alpha = Quket.projection.sp_angle[0][ialpha] alpha_coef = Quket.projection.sp_weight[0][ialpha] * np.exp( 1j * alpha * Ms) 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] * np.exp(1j * gamma * Ms)) # Total Weight coef = (2 * s + 1) / (8 * np.pi) * (alpha_coef * beta_coef * gamma_coef) state_g = QuantumState(n_qubits) state_g.load(Q) circuit_Rg = QuantumCircuit(n_qubits) set_circuit_Rg(circuit_Rg, n_qubits, alpha, beta, gamma) circuit_Rg.update_quantum_state(state_g) state_g.multiply_coef(coef) state_P.add_state(state_g) # Normalize norm2 = state_P.get_squared_norm() if norm2 < threshold: error( "Norm of spin-projected state is too small!\n", "This usually means the broken-symmetry state has NO component ", "of the target spin.") state_P.normalize(norm2) # print_state(state_P,name="P|Q>",threshold=1e-6) return state_P
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 __qulacs_measure_shots(qstate, qid, shots=1): # error check qubit_num = qstate.get_qubit_count() if max(qid) >= qubit_num: raise ValueError # list of binary vectors for len(qid) bit integers qid_sorted = sorted(qid) mbits_list = [] for i in range(2**len(qid)): # ex) # qid = [5,0,2] -> qid_sorted = [0,2,5] # i = (0,1,2), idx = (2,0,1) # bits = [q0,q1,q2] -> mbits = [q1,q2,q0] bits = list(map(int, list(format(i, '0{}b'.format(len(qid)))))) mbits = [0] * len(qid) for i, q in enumerate(qid): idx = qid_sorted.index(q) mbits[idx] = bits[i] mbits_list.append(mbits) # list of probabilities prob_list = [] prob = 0.0 for mbits in mbits_list: args = [2] * qubit_num for j, q in enumerate(qid): args[q] = mbits[j] prob += qstate.get_marginal_probability(args) prob_list.append(prob) if prob_list[-1] != 1.0: prob_list[-1] = 1.0 # frequency mval_data = [] if shots > 1: for i in range(shots - 1): rand = random.random() for mbits, prob in zip(mbits_list, prob_list): if rand <= prob: mval = ''.join(map(str, mbits)) mval_data.append(mval) break # last quantum state circ = QuantumCircuit(qubit_num) for i, q in enumerate(qid): circ.add_gate(Measurement(q, i)) circ.update_quantum_state(qstate) last = ''.join( map(str, [qstate.get_classical_value(i) for i in range(len(qid))])) mval_data.append(last) frequency = Counter(mval_data) return frequency, qstate
def calc_psi_lessH(psi_dash, n, index, a, id_set): circuit = QuantumCircuit(n) for i, a_i in enumerate(a): if abs(a_i) > 0: pauli_id = id_set[i] gate = PauliRotation(index, pauli_id, a_i * (-2)) circuit.add_gate(gate) circuit.update_quantum_state(psi_dash) norm = psi_dash.get_squared_norm() psi_dash.normalize(norm) return psi_dash
def _simulate_on_qulacs( self, data: _StateAndBuffer, shape: tuple, qulacs_state: qulacs.QuantumState, qulacs_circuit: qulacs.QuantumCircuit, ) -> None: data.buffer = data.state cirq_state = np.array(data.state).flatten().astype(np.complex64) qulacs_state.load(cirq_state) qulacs_circuit.update_quantum_state(qulacs_state) data.state = qulacs_state.get_vector().reshape(shape)
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 __qulacs_measure(qstate, qubit_num, q): # error check if q >= qubit_num: raise ValueError("measurement qubit id is out of bound") circ = QuantumCircuit(qubit_num) circ.add_gate(Measurement(q, 0)) circ.update_quantum_state(qstate) mval = qstate.get_classical_value(0) return mval
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 __qulacs_reset(qstate, qubit_num, q): # error check if q >= qubit_num: raise ValueError("reset qubit id is out of bound") circ = QuantumCircuit(qubit_num) circ.add_gate(Measurement(q, 0)) circ.update_quantum_state(qstate) circ_flip = QuantumCircuit(qubit_num) if qstate.get_classical_value(0) == 1: circ_flip.add_gate(X(q)) circ_flip.update_quantum_state(qstate)
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 test_add_same_gate_multiple_time(self): from qulacs import QuantumCircuit, QuantumState from qulacs.gate import X, DepolarizingNoise, DephasingNoise, Probabilistic, RX state = QuantumState(1) circuit = QuantumCircuit(1) noise = DepolarizingNoise(0, 0) circuit.add_gate(noise) circuit.add_gate(noise.copy()) circuit.add_gate(DephasingNoise(0, 0)) circuit.add_gate(Probabilistic([0.1], [RX(0, 0)])) gate = RX(0, 0) circuit.add_gate(gate) circuit.add_gate(gate) circuit.add_gate(gate) circuit.add_gate(gate) circuit.add_gate(gate) del gate circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.update_quantum_state(state) circuit.to_string() del circuit del state
def test_circuit_add_gate(self): from qulacs import QuantumCircuit, QuantumState from qulacs.gate import Identity, X, Y, Z, H, S, Sdag, T, Tdag, sqrtX, sqrtXdag, sqrtY, sqrtYdag from qulacs.gate import P0, P1, U1, U2, U3, RX, RY, RZ, CNOT, CZ, SWAP, TOFFOLI, FREDKIN, Pauli, PauliRotation from qulacs.gate import DenseMatrix, SparseMatrix, DiagonalMatrix, RandomUnitary, ReversibleBoolean, StateReflection from qulacs.gate import BitFlipNoise, DephasingNoise, IndependentXZNoise, DepolarizingNoise, TwoQubitDepolarizingNoise, AmplitudeDampingNoise, Measurement from qulacs.gate import merge, add, to_matrix_gate, Probabilistic, CPTP, Instrument, Adaptive from scipy.sparse import lil_matrix qc = QuantumCircuit(3) qs = QuantumState(3) ref = QuantumState(3) sparse_mat = lil_matrix((4, 4)) sparse_mat[0, 0] = 1 sparse_mat[1, 1] = 1 def func(v, d): return (v + 1) % d def adap(v): return True gates = [ Identity(0), X(0), Y(0), Z(0), H(0), S(0), Sdag(0), T(0), Tdag(0), sqrtX(0), sqrtXdag(0), sqrtY(0), sqrtYdag(0), Probabilistic([0.5, 0.5], [X(0), Y(0)]), CPTP([P0(0), P1(0)]), Instrument([P0(0), P1(0)], 1), Adaptive(X(0), adap), CNOT(0, 1), CZ(0, 1), SWAP(0, 1), TOFFOLI(0, 1, 2), FREDKIN(0, 1, 2), Pauli([0, 1], [1, 2]), PauliRotation([0, 1], [1, 2], 0.1), DenseMatrix(0, np.eye(2)), DenseMatrix([0, 1], np.eye(4)), SparseMatrix([0, 1], sparse_mat), DiagonalMatrix([0, 1], np.ones(4)), RandomUnitary([0, 1]), ReversibleBoolean([0, 1], func), StateReflection(ref), BitFlipNoise(0, 0.1), DephasingNoise(0, 0.1), IndependentXZNoise(0, 0.1), DepolarizingNoise(0, 0.1), TwoQubitDepolarizingNoise(0, 1, 0.1), AmplitudeDampingNoise(0, 0.1), Measurement(0, 1), merge(X(0), Y(1)), add(X(0), Y(1)), to_matrix_gate(X(0)), P0(0), P1(0), U1(0, 0.), U2(0, 0., 0.), U3(0, 0., 0., 0.), RX(0, 0.), RY(0, 0.), RZ(0, 0.), ] gates.append(merge(gates[0], gates[1])) gates.append(add(gates[0], gates[1])) ref = None for gate in gates: qc.add_gate(gate) for gate in gates: qc.add_gate(gate) qc.update_quantum_state(qs) qc = None qs = None for gate in gates: gate = None gates = None parametric_gates = None
def __qulacs_operate_qgate(qstate, qubit_num, kind, qid, phase, phase1, phase2): if __is_supported_qgate(kind) is False: raise ValueError("not supported quantum gate") circ = QuantumCircuit(qubit_num) term_num = get_qgate_qubit_num(kind) para_num = get_qgate_param_num(kind) gate_function_name = GateFunctionName[kind] phase = phase * np.pi phase1 = phase1 * np.pi phase2 = phase2 * np.pi # the sign-definition of rotation gate on qulacs if (kind in (cfg.ROTATION_X, cfg.ROTATION_Y, cfg.ROTATION_Z, cfg.CONTROLLED_RX, cfg.CONTROLLED_RY, cfg.CONTROLLED_RZ)): phase = -phase # the argument-order-definition of U2 gate on qulacs elif kind in (cfg.ROTATION_U2, cfg.CONTROLLED_U2): phase1, phase = phase, phase1 # the argument-order-definition of U3 gate on qulacs elif kind in (cfg.ROTATION_U3, cfg.CONTROLLED_U3): phase2, phase = phase, phase2 if term_num == 1 and para_num == 0: circ.add_gate(eval(gate_function_name)(qid[0])) elif term_num == 1 and para_num == 1: circ.add_gate(eval(gate_function_name)(qid[0], phase)) elif term_num == 1 and para_num == 2: circ.add_gate(eval(gate_function_name)(qid[0], phase, phase1)) elif term_num == 1 and para_num == 3: circ.add_gate(eval(gate_function_name)(qid[0], phase, phase1, phase2)) elif term_num == 2 and para_num == 0: circ.add_gate(eval(gate_function_name)(qid[0], qid[1])) elif term_num == 2 and para_num == 1: circ.add_gate(eval(gate_function_name)(qid[0], qid[1], phase)) elif term_num == 2 and para_num == 2: circ.add_gate(eval(gate_function_name)(qid[0], qid[1], phase, phase1)) elif term_num == 2 and para_num == 3: circ.add_gate( eval(gate_function_name)(qid[0], qid[1], phase, phase1, phase2)) else: raise ValueError("not supported terminal or parameter-number") circ.update_quantum_state(qstate)
def qtest(angle): state = QuantumState(3) state.set_Haar_random_state() circuit = QuantumCircuit(3) circuit.add_X_gate(0) merged_gate = merge(CNOT(0, 1), Y(1)) circuit.add_gate(merged_gate) circuit.add_RX_gate(1, angle) circuit.update_quantum_state(state) observable = Observable(3) observable.add_operator(2.0, "X 2 Y 1 Z 0") observable.add_operator(-3.0, "Z 2") result = observable.get_expectation_value(state) output = {'energy': result} return (output)
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_ibm_gateset() -> None: state = QuantumState(3) state.set_zero_state() circ = Circuit(3) circ.add_gate(OpType.U1, 0.19, [0]) circ.add_gate(OpType.U2, [0.19, 0.24], [1]) circ.add_gate(OpType.U3, [0.19, 0.24, 0.32], [2]) qulacs_circ = tk_to_qulacs(circ) qulacs_circ.update_quantum_state(state) state1 = QuantumState(3) state1.set_zero_state() qulacs_circ1 = QuantumCircuit(3) qulacs_circ1.add_U1_gate(0, 0.19 * np.pi) qulacs_circ1.add_U2_gate(1, 0.19 * np.pi, 0.24 * np.pi) qulacs_circ1.add_U3_gate(2, 0.19 * np.pi, 0.24 * np.pi, 0.32 * np.pi) qulacs_circ1.update_quantum_state(state1) overlap = inner_product(state1, state) assert np.isclose(1, overlap)
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_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 NProj(Quket, Q, threshold=1e-8): """Function Perform number-projection to QuantumState |Q> |Q'> = PN |Q> where PN is a number-projection operator (non-unitary). PN = \sum_i^ng wg[i] Ug[i] This function provides a shortcut to |Q'>, which is unreal. One actually needs to develop a quantum circuit for this (See QST 6, 014004 (2021)). Author(s): Takashi Tsuchimochi """ n_qubits = Q.get_qubit_count() state_P = QuantumState(n_qubits) state_P.multiply_coef(0) state_g = QuantumState(n_qubits) nphi = max(Quket.projection.number_ngrids, 1) #print_state(Q) for iphi in range(nphi): coef = (Quket.projection.np_weight[iphi] * np.exp(1j * Quket.projection.np_angle[iphi] * (Quket.projection.n_active_electrons - Quket.projection.n_active_orbitals))) state_g = Q.copy() circuit = QuantumCircuit(n_qubits) set_circuit_ExpNa(circuit, n_qubits, Quket.projection.np_angle[iphi]) set_circuit_ExpNb(circuit, n_qubits, Quket.projection.np_angle[iphi]) circuit.update_quantum_state(state_g) state_g.multiply_coef(coef) state_P.add_state(state_g) norm2 = state_P.get_squared_norm() if norm2 < threshold: error( "Norm of number-projected state is too small!\n", "This usually means the broken-symmetry state has NO component ", "of the target number.") state_P.normalize(norm2) return state_P
def apply_circuit(self, x, theta): """ Apply unitary gates U(x) and U(theta) to |0> Argument: x: dx1 numpy array (vector), the sample vector to be encoded. theta: n_qubitsx(3*D) numpy array, the decision variables. Return: circuit: quantum state after applying the circuit with the given theta. """ state = QuantumState(self.n_qubits) state.set_zero_state() # Construct a circuit circuit = QuantumCircuit(self.n_qubits) circuit = self.unitary_x(circuit, x) circuit = self.unitary_theta(circuit, theta) # apply the circuit to the zero state circuit.update_quantum_state(state) return state
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 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
observable = Observable(nqubit) observable.add_operator(1, "Z 0") observable.add_operator(2, "Z 1") #observable.add_operator(4, "Z 2") data = list() x_value = list() y_value = list() for i in range(n_data): #state.set_Haar_random_state() x = random.random() state.set_zero_state() # U_in|000> U_in(x).update_quantum_state(state) state_vec = state.get_vector() circuit.update_quantum_state(state) value = observable.get_expectation_value(state) #print(value) # data.append((state_vec, value)) data.append((x, value)) x_value.append(x) y_value.append(value) with open('Training.data', 'wb') as f: pickle.dump(data, f) plt.plot(x_value, y_value, 'o', color='black') plt.show() plt.savefig('qcl_training.png')
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
import matplotlib.pyplot as plt obs = Observable(1) obs.add_operator(1, "Z 0") state = QuantumState(1) circuit = QuantumCircuit(1) p = 0.1 # probability of bit flip n_circuit_sample = 10000 n_depth = 20 # the number of probabilistic gate probabilistic_pauli_gate = Probabilistic([p], [X(0)]) #define probabilistic gate circuit.add_gate(probabilistic_pauli_gate) # add the prob. gate to the circuit exp_array = [] for depth in range(n_depth): exp = 0 for i in [0] * n_circuit_sample: state.set_zero_state() for _ in range(depth): circuit.update_quantum_state(state) # apply the prob. gate exp += obs.get_expectation_value( state) # get expectation value for one sample of circuit exp /= n_circuit_sample # get overall average exp_array.append(exp) #plot plt.plot(range(n_depth), exp_array) plt.show()
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)