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 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 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 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 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 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