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