def test_convert(qvm): wf_sim = WavefunctionSimulator() p = get_test_program() initial_wf = wf_sim.wavefunction(p) tkc = pyquil_to_tk(p) p2 = tk_to_pyquil(tkc) final_wf = wf_sim.wavefunction(p2) initial_phaseless, final_phaseless = adjust_for_relative_phase( initial_wf.amplitudes, final_wf.amplitudes) assert np.allclose(initial_phaseless, final_phaseless, atol=1e-10)
def printWF(p): ''' Prints the wavefunction from simulating a program p ''' wf_sim = WavefunctionSimulator() waveFunction = wf_sim.wavefunction(p) print(waveFunction)
def test_two_qubit_state_change(prog): wf_sim = WavefunctionSimulator() with local_qvm(): state = wf_sim.wavefunction(prog) amp_cos = (1/math.sqrt(2))*math.cos(math.pi/14) amp_sin = (1/math.sqrt(2))*math.sin(math.pi/14) if (abs(state[0].real - amp_cos) < 0.0001) and (abs(state[-1].real + amp_sin) < 0.0001): print(state[1], 'sin is:', amp_sin) print(state[2], 'cos is:', amp_cos) if (abs(state[1].real - amp_sin) < 0.0001) and (abs(state[2].real - amp_cos) < 0.0001): print(state[1], 'sin is:', amp_sin) print(state[2], 'cos is:', amp_cos) print("\nNice one, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Try again...\n") else: print("oops, you built the state:") print(state)
def quil_run(prog): wf_sim = WavefunctionSimulator() print("Running Quil Program:\n", prog) print("---------------------------") print("Output: ") wf = wf_sim.wavefunction(Program(prog)) print(wf.amplitudes)
def test_pi_three_phase(prog): wf_sim = WavefunctionSimulator() with local_qvm(): if len(prog._instructions) == 0: print( "Hmm, I'm not sure you have any gates applied to the state. Better add some.." ) else: state = wf_sim.wavefunction(prog) amp_plus = 1 / math.sqrt(2) amp_phase = np.exp(1j * np.pi / 3) / math.sqrt(2) if abs(state[0].real - amp_plus) < 0.0001 and abs( state[1].real - amp_phase.real) < 0.0001 and abs( state[1].imag - amp_phase.imag) < 0.0001: print( "\nGood job! You built the state with the relative phase:") print(state) else: print("\nHmm, you built the state:") print(state) print("Maybe try a different gate?\n")
def test_minus_input_to_one(prog): wf_sim = WavefunctionSimulator() with local_qvm(): if len(prog._instructions) == 0: print( "Hmm, I'm not sure you have any gates applied to the state. Better add some.." ) else: state = wf_sim.wavefunction(prog) amp = 1 if abs(state[0].real - amp) < 0.0001: print("\nExcellent! You built the state:") print(state) elif abs(state[1].real - amp) < 0.0001 and len( prog._instructions) < 4: print("\nAh shucks, you made:") print(state) print("Maybe you need more gates?") else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n")
def test_qaoa_on_wfsim(): # ham = PauliSum.from_compact_str("(-1.0)*Z0*Z1 + 0.8*Z0 + (-0.5)*Z1") term1 = PauliTerm("Z", 0, -1) * PauliTerm("Z", 1) term2 = PauliTerm("Z", 0, 0.8) term3 = PauliTerm("Z", 1, -0.5) ham = PauliSum([term1, term2, term3]) params = FourierParams.linear_ramp_from_hamiltonian(ham, n_steps=10, q=2) p0 = params.raw() sim = WavefunctionSimulator() cost_fun = QAOACostFunctionOnWFSim(ham, params, sim, scalar_cost_function=True, nshots=100, noisy=True) with local_qvm(): out = minimize(cost_fun, p0, tol=1e-3, method="Cobyla", options={"maxiter": 500}) wf = sim.wavefunction(cost_fun.prepare_ansatz, memory_map=cost_fun.make_memory_map(params)) assert np.allclose(out["fun"], -1.3, rtol=1.1) assert out["success"] assert np.allclose(wf.probabilities(), [0, 0, 0, 1], rtol=1.5, atol=0.05) print(out)
def test_penalties(): sim = WavefunctionSimulator() pq = prepare_qubits(1) initial_wf = sim.wavefunction(pq) print("Initial WF is {}".format(initial_wf)) #000 Test expectation = sim.expectation(pq, prepare_cost()) print("Expectation value is {}".format(expectation))
def qft_tests(n=4): phi = [QubitPlaceholder() for i in range(n)] tests = [ init_pure(phi) + H(phi[0]) + qft(phi, n) + iqft(phi, n), # Should be H(0) init_pure(phi) + iqft(phi, n) + qft(phi, n), # Should be pure |1>'s ] wf_sim = WavefunctionSimulator() for test in tests: print(wf_sim.wavefunction(address_qubits(test)))
def test_wavefunction(client_configuration: QCSClientConfiguration): wfnsim = WavefunctionSimulator(client_configuration=client_configuration) bell = Program(H(0), CNOT(0, 1)) wfn = wfnsim.wavefunction(bell) np.testing.assert_allclose(wfn.amplitudes, 1 / np.sqrt(2) * np.array([1, 0, 0, 1])) np.testing.assert_allclose(wfn.probabilities(), [0.5, 0, 0, 0.5]) assert wfn.pretty_print() == "(0.71+0j)|00> + (0.71+0j)|11>" bitstrings = wfn.sample_bitstrings(1000) parity = np.sum(bitstrings, axis=1) % 2 assert np.all(parity == 0)
def get_amplitudes(circuit): if isinstance(circuit, qiskit.circuit.quantumcircuit.QuantumCircuit): backend = BasicAer.get_backend('statevector_simulator') job = execute(circuit, backend) amplitudes = job.result().get_statevector(circuit) elif isinstance(circuit, pyquil.quil.Program): wf_sim = WavefunctionSimulator(connection=fc) wavefunction = wf_sim.wavefunction(circuit) amplitudes = wavefunction.amplitudes else: raise ValueError("Unknown circuit type") return amplitudes
def test_vqe_on_WFSim(): sim = WavefunctionSimulator() cost_fun = PrepareAndMeasureOnWFSim(prepare_ansatz=prepare_ansatz, make_memory_map=lambda p: {"params": p}, hamiltonian=hamiltonian, sim=sim, scalar_cost_function=True) out = minimize(cost_fun, p0, tol=1e-3, method="COBYLA") wf = sim.wavefunction(prepare_ansatz, {"params": out['x']}) assert np.allclose(wf.probabilities(), [0, 0, 0, 1], rtol=1.5, atol=0.01) assert np.allclose(out['fun'], -1.3) assert out['success']
def test_vs_lisp_qvm(qvm, n_qubits, prog_length): for _ in range(10): prog = _generate_random_program(n_qubits=n_qubits, length=prog_length) lisp_wf = WavefunctionSimulator() # force lisp wfs to allocate all qubits lisp_wf = lisp_wf.wavefunction(Program(I(q) for q in range(n_qubits)) + prog) lisp_wf = lisp_wf.amplitudes ref_qam = PyQVM(n_qubits=n_qubits, quantum_simulator_type=ReferenceWavefunctionSimulator) ref_qam.execute(prog) ref_wf = ref_qam.wf_simulator.wf np.testing.assert_allclose(lisp_wf, ref_wf, atol=1e-15)
def entangle_test(n=5): phi = QubitPlaceholder() p = [QubitPlaceholder() for i in range(n)] test_pqs = [ init_p(p) + entangle(phi, p), init_p(p) + entangle(phi, p) + disentangle(phi, p), init_p(p) + H(phi) + entangle(phi, p), init_p(p) + H(phi) + entangle(phi, p) + disentangle(phi, p), ] wf_sim = WavefunctionSimulator() for pq in test_pqs: print(wf_sim.wavefunction(address_qubits(pq)))
def test_wavefunction(forest: ForestConnection): # The forest fixture (argument) to this test is to ensure this is # skipped when a forest web api key is unavailable. You could also # pass it to the constructor of WavefunctionSimulator() but it is not # necessary. wfnsim = WavefunctionSimulator() bell = Program(H(0), CNOT(0, 1)) wfn = wfnsim.wavefunction(bell) np.testing.assert_allclose(wfn.amplitudes, 1 / np.sqrt(2) * np.array([1, 0, 0, 1])) np.testing.assert_allclose(wfn.probabilities(), [0.5, 0, 0, 0.5]) assert wfn.pretty_print() == "(0.71+0j)|00> + (0.71+0j)|11>" bitstrings = wfn.sample_bitstrings(1000) parity = np.sum(bitstrings, axis=1) % 2 assert np.all(parity == 0)
def verify_final_circuit(self, theta): """ Returns a wavefunction and state probabilities of equal probability circuit for given theta Parameters: ----------- theta : Value of the parameter for which a wavefunction and state probabilities are returned to verify the final wavefunction """ wf = WavefunctionSimulator() final_circuit = self.get_parameteric_circuit(theta=theta, verify=True) state = wf.wavefunction(final_circuit) state_probabilities = state.get_outcome_probs() return state, state_probabilities
def test_bell_state_unitary(prog, flag): wf_sim = WavefunctionSimulator() with local_qvm(): state = wf_sim.wavefunction(prog) amp_plus = 1/math.sqrt(2) amp_minus = -1/math.sqrt(2) if (flag == 'phi+'): if (abs(state[0].real - amp_plus) < 0.0001) and (abs(state[-1].real - amp_plus) < 0.0001): print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n") elif (flag == 'phi-'): if (abs(state[0].real - amp_plus) < 0.0001) and (abs(state[-1].real - amp_minus) < 0.0001): print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n") elif (flag == 'psi+'): if (abs(state[1].real - amp_plus) < 0.0001) and (abs(state[-2].real - amp_plus) < 0.0001): print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n") elif (flag == 'psi-'): if (abs(state[1].real - amp_plus) < 0.0001) and (abs(state[-2].real - amp_minus) < 0.0001): print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n") else: raise ValueError('The inputted flag choice is not supported')
def test_initial_state(prog): wf_sim = WavefunctionSimulator() with local_qvm(): state = wf_sim.wavefunction(prog) amp = 1 if abs(state[1].real - amp) < 0.0001: print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n")
def test_state(prog): wf_sim = WavefunctionSimulator() with local_qvm(): state = wf_sim.wavefunction(prog) amp = 1 / math.sqrt(2) if abs(state[0].real - amp) < 0.0001 and abs(state[1].real - amp) < 0.0001: print("Congratulations, you built the state") print(state) else: print("oops, you built the state") print(state)
def test_superposition_unitary(prog): wf_sim = WavefunctionSimulator() with local_qvm(): if len(prog._instructions) == 0: print( "Hmm, I'm not sure you have any gates applied to the state. Better add some.." ) else: state = wf_sim.wavefunction(prog) amp_plus = 1 / math.sqrt(2) amp_minus = -1 / math.sqrt(2) if abs(state[0].real - amp_plus) < 0.0001 and abs( state[1].real - amp_plus) < 0.0001: print("\nGood job! You built the superposition state:") print(state) elif abs(state[0].real - amp_plus) < 0.0001 and abs( state[1].real - amp_minus) < 0.0001: print( "\nNot quite :(, you built a different superposition state:" ) print(state) elif abs(state[0].real - amp_minus) < 0.0001 and abs( state[1].real - amp_plus) < 0.0001: print( "\nNot quite :(, you built a different superposition state:" ) print(state) elif abs(state[0].real - amp_minus) < 0.0001 and abs( state[1].real - amp_minus) < 0.0001: print( "\nNot quite :(, you built a different superposition state:" ) print(state) print( "This state is actually physically indistinguisable from the correct state up to a global phase. However, it's still not quite right." ) else: print("\nHmm, you built the state:") print(state) print("Maybe try a different gate?\n")
def test_two_qubit_reset(prog): wf_sim = WavefunctionSimulator() with local_qvm(): state = wf_sim.wavefunction(prog) amp = 1 if (abs(state[0].real - amp) < 0.0001): print("\nGood job, you built the state:") print(state) else: print("Unfortunately, you built the state:") print(state) print("Possibly try some other unitary?\n")
def discre_of_time(n, t, no_of_step): '''Definition of a function to implement discretization of time for an Ising chain with Hamiltonian H = -0.5*(1/|i-j|)*sigma_x_i*sigma_x_j - 0.5*sigma_x_j - 0.5*sigma_z_j where index i j run from 0th to (n-1)th site and i is always smaller than j. Here 2nd-order Trotter approximant is applied. Function returns a wavefunc after evolution time of 1s with no_of_step number of Trotter steps implemented. param n: number of qubits (n>=2). param t: total evolution time. param no_of_step: number of Trotter steps.''' wavefunction_simulator = WavefunctionSimulator() prog_ini = Program() prog = Ising_prog_2(n, t / no_of_step) for i in np.arange(no_of_step): prog_ini += prog wavefunc = wavefunction_simulator.wavefunction(prog_ini) return wavefunc
def test_plus_input_to_zero(prog): wf_sim = WavefunctionSimulator() with local_qvm(): if len(prog._instructions) == 0: print( "Hmm, I'm not sure you have any gates applied to the state. Better add some.." ) else: state = wf_sim.wavefunction(prog) if abs(state[0].real - 1) < 0.0001: print("\nExcellent! You built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n")
def test_statevector(self): """ This function demonstrates how to get the statevector of a register in Forest. """ qubits = QubitPlaceholder.register(3) program = Program() program += H(qubits[0]) program += X(qubits[2]) program += CNOT(qubits[0], qubits[1]) measurement = program.declare("ro", "BIT", 3) for i in range(0, 3): program += MEASURE(qubits[i], measurement[i]) assigned_program = address_qubits(program) simulator = WavefunctionSimulator() statevector = simulator.wavefunction(assigned_program) print(statevector.amplitudes)
def test_vqe_on_WFSim(): sim = WavefunctionSimulator() cost_fun = PrepareAndMeasureOnWFSim( prepare_ansatz=prepare_ansatz, make_memory_map=lambda p: {"params": p}, hamiltonian=hamiltonian, sim=sim, return_standard_deviation=True, noisy=False) with local_qvm(): out = scipy_optimizer(cost_fun, p0, epsilon=1e-3) print(out) wf = sim.wavefunction(prepare_ansatz, {"params": out['x']}) assert np.allclose(np.abs(wf.amplitudes**2), [0, 0, 0, 1], rtol=1.5, atol=0.01) assert np.allclose(out['fun'], -1.3) assert out['success']
def test_one_phase(prog): wf_sim = WavefunctionSimulator() with local_qvm(): if len(prog._instructions) == 0: print( "Hmm, I'm not sure you have any gates applied to the state. Better add some.." ) else: state = wf_sim.wavefunction(prog) amp = -1 if abs(state[1].real - amp) < 0.0001: print("\nCongratulations, you built the state:") print(state) else: print("oops, you built the state:") print(state) print("Perhaps an alternative unitary would work?\n")
def QuantumKernel(qc, N_kernel_samples, sample1, sample2): '''This function computes the Quantum kernel for a single pair of samples''' if type(sample1) is np.ndarray and sample1.ndim != 1: #Check if there is only a single sample in the array of samples raise IOError('sample1 must be a 1D numpy array') if type(sample2) is np.ndarray and sample2.ndim != 1: #Check if there is only a single sample in the array of samples raise IOError('sample2 must be a 1D numpy array') qubits = qc.qubits() N_qubits = len(qubits) make_wf = WavefunctionSimulator() #run quantum circuit for a single pair of encoded samples prog = KernelCircuit(qc, sample1, sample2) kernel_outcomes = make_wf.wavefunction(prog).get_outcome_probs() #Create zero string to read off probability zero_string = '0'*N_qubits kernel_exact = kernel_outcomes[zero_string] if (N_kernel_samples == 'infinite'): #If the kernel is computed exactly, approximate kernel is equal to exact kernel kernel_approx = kernel_exact else: #Index list for classical registers we want to put measurement outcomes into. #Measure the kernel circuit to compute the kernel approximately, the kernel is the probability of getting (00...000) outcome. #All (N_qubits) qubits are measured at once into dictionary, convert into array kernel_measurements_all_qubits_dict = qc.run_and_measure(prog, N_kernel_samples) kernel_measurements_used_qubits = np.flip(np.vstack(kernel_measurements_all_qubits_dict[q] for q in sorted(qubits)).T, 1) #m is total number of samples, n is the number of used qubits (m,n) = kernel_measurements_used_qubits.shape N_zero_strings = m - np.count_nonzero(np.count_nonzero(kernel_measurements_used_qubits, 1)) #The kernel is given by = [Number of times outcome (00...000) occurred]/[Total number of measurement runs] kernel_approx = N_zero_strings/N_kernel_samples return kernel_exact, kernel_approx
def construct_results_dict(self, qubit_program): ''' Constructs results dictionary of the evaluated quantum circuit ''' wf_sim = WavefunctionSimulator() wavefunction = wf_sim.wavefunction(qubit_program) amp_arr = wavefunction.amplitudes prob_dict = wavefunction.get_outcome_probs() results_dict = {} for index, item in enumerate(prob_dict): struct = {} # Integer value of the qubit state struct["int"] = "{:.0f}".format(int(item, 2)) # Complex number representing the qubit state struct["val"] = "{:+.5f}".format(amp_arr[index]).strip("()") # Probability of obtaining the qubit state struct["prob"] = "{:.5f}".format(prob_dict[item]) # Magnitude of the qubit state struct["mag"] = "{:.5f}".format(abs(amp_arr[index])) # Phase of the qubit state (obtained by measuring complex number phase, converting to °) struct["phase"] = "{:+.2f}".format(np.degrees(cmath.phase(amp_arr[index]))) + "°" results_dict[item] = struct self.results = results_dict
def test_vqe_on_WFSim_QubitPlaceholders(): qubit_mapping = get_default_qubit_mapping(prepare_ansatz) sim = WavefunctionSimulator() cost_fun = PrepareAndMeasureOnWFSim( prepare_ansatz=prepare_ansatz, make_memory_map=lambda p: {"params": p}, hamiltonian=hamiltonian, sim=sim, scalar_cost_function=True, qubit_mapping=qubit_mapping) out = scipy.optimize.minimize(cost_fun, p0, tol=1e-3, method="Cobyla") print(out) prog = address_qubits(prepare_ansatz, qubit_mapping=qubit_mapping) wf = sim.wavefunction(prog, {"params": out['x']}) print(wf.probabilities()) assert np.allclose(np.abs(wf.amplitudes**2), [0, 0, 0, 1], rtol=1.5, atol=0.01) assert np.allclose(out['fun'], -4) assert out['success']
def test_z_gates(errors): # pq = prepare_qubits(0) # Z = np.array([[1,0],[0,-1]]) # Z1Z2Z3 = np.kron(Z, np.kron(Z,Z)) # first_penalty = 0.5 * (np.eye(8) + Z1Z2Z3) # helper_op = 0.5 * (np.eye(2) - Z) # penalty_111 = np.kron(helper_op, np.kron(helper_op, helper_op)) # final_penalty = first_penalty # penalty_dfn = DefGate("PENALTY", final_penalty) # PENALTY = penalty_dfn.get_constructor() sim = WavefunctionSimulator() pq = prepare_qubits(errors) initial_wf = sim.wavefunction(pq) print("Initial is {}".format(initial_wf)) #ps = (sI(0) - sZ(0))*(sI(1) - sZ(1))*(sI(2) - sZ(2)) ps = sI(0) + (sZ(0) * sZ(1) * sZ(2)) expectation = sim.expectation(pq, ps) print("Expectation value for {} errors is {}".format(errors, expectation))
def get_mean_val(self, var_num_to_rads): """ This method returns the empirically determined Hamiltonian mean value. It takes as input the values of placeholder variables. It passes those values into the Rigetti method run() when num_samples !=0. When num_samples=0, WavefunctionSimulator is used to calculate the output mean value exactly. Parameters ---------- var_num_to_rads : dict[int, float] Returns ------- float """ # hamil loop mean_val = 0 for term, coef in self.hamil.terms.items(): # we have checked before that coef is real coef = complex(coef).real vprefix = self.translator.vprefix var_name_to_rads = {vprefix + str(vnum): [rads] for vnum, rads in var_num_to_rads.items()} if self.num_samples: # send and receive from cloud, get obs_vec bitstrings = self.qc.run(self.term_to_exec[term], memory_map=var_name_to_rads) obs_vec = RigettiTools.obs_vec_from_bitstrings( bitstrings, self.num_bits, bs_is_array=True) # go from obs_vec to effective state vec counts_dict = StateVec.get_counts_from_obs_vec(self.num_bits, obs_vec) emp_pd = StateVec.get_empirical_pd_from_counts(self.num_bits, counts_dict) effective_st_vec = StateVec.get_emp_state_vec_from_emp_pd( self.num_bits, emp_pd) else: # num_samples = 0 sim = WavefunctionSimulator() pg = Program() # don't know how to declare number of qubits # so do this for k in range(self.num_bits): pg += I(k) for key, val in var_name_to_rads.items(): exec(key + '=' + str(val[0])) for line in self.translation_line_list: line = line.strip('\n') if line: exec(line) bit_pos_to_xy_str =\ {bit: action for bit, action in term if action != 'Z'} RigettiTools.add_xy_meas_coda_to_program( pg, bit_pos_to_xy_str) st_vec_arr = sim.wavefunction(pg).amplitudes st_vec_arr = st_vec_arr.reshape([2]*self.num_bits) perm = list(reversed(range(self.num_bits))) st_vec_arr = np.transpose(st_vec_arr, perm) effective_st_vec = StateVec(self.num_bits, st_vec_arr) # add contribution to mean real_arr = self.get_real_vec(term) mean_val += coef*effective_st_vec.\ get_mean_value_of_real_diag_mat(real_arr) return mean_val
def get_mean_val(self, var_num_to_rads): """ This method returns a list partials_list consisting of 4 floats which are the partial derivatives wrt the 4 possible derivative directions ( deriv_direc), of the multi-controlled gate U specified by self.deriv_gate_str. Parameters ---------- var_num_to_rads : dict[int, float] Returns ------- list[float] """ partials_list = [0., 0., 0., 0.] # number of bits with (i.e., including) ancilla num_bits_w_anc = self.num_bits for has_neg_polarity, deriv_direc in it.product( *[[False, True], range(4)]): if self.deriv_gate_str == 'prior': if has_neg_polarity: has_neg_polarity = None else: continue # this skips iteration in loop for dpart_name in self.deriv_direc_to_dpart_range[deriv_direc]: emb = CktEmbedder(num_bits_w_anc, num_bits_w_anc) wr = StairsDerivCkt_writer(self.deriv_gate_str, has_neg_polarity, deriv_direc, dpart_name, self.gate_str_to_rads_list, self.file_prefix, emb) wr.close_files() # wr.print_pic_file() # wr.print_eng_file() t_list = self.gate_str_to_rads_list[self.deriv_gate_str] coef_of_dpart = StairsDerivCkt_writer.\ get_coef_of_dpart(t_list, deriv_direc, dpart_name, var_num_to_rads) fun_name_to_fun = StairsDerivCkt_writer.\ get_fun_name_to_fun(t_list, deriv_direc, dpart_name) vman = PlaceholderManager( var_num_to_rads=var_num_to_rads, fun_name_to_fun=fun_name_to_fun) # CGateExpander and the translator Qubiter_to_RigettiPyQuil # are both children of SEO_reader. SEO_reader and any of its # subclasses will accept a vman ( object of # PlaceholderManager) in one of its keyword args. If a # SEO_reader is given a vman as input, it will use it to # replace placeholder variable strings by floats. # PyQuil does not support multi-controlled u2 gates so # expand them to lowest common denominator, CNOTs and single # qubit gates, using CGateExpander. Give CGateExpander a # vman input so as to float all variables before expansion expan = CGateExpander(self.file_prefix, num_bits_w_anc, vars_manager=vman) # this gives name of new file with expansion out_file_prefix = SEO_reader.xed_file_prefix(self.file_prefix) # expan.wr.print_pic_file() # expan.wr.print_eng_file() # this creates a file with all PyQuil gates that are # independent of hamil. self.translator = Qubiter_to_RigettiPyQuil( out_file_prefix, self.num_bits, aqasm_name='RigPyQuil', prelude_str='', ending_str='') with open(self.translator.aqasm_path, 'r') as fi: self.translation_line_list = fi.readlines() pg = Program() for line in self.translation_line_list: line = line.strip('\n') if line: exec(line) len_pg_in = len(pg) for term, coef in self.hamil.terms.items(): # we have checked before that coef is real coef = complex(coef).real # print('nnnnnbbbbb', term) new_term = tuple(list(term) + [(num_bits_w_anc-1, 'X')]) # print('jjjjjjj', new_term) # Throw out previous coda. # Remember bug in Pyquil. Slicing a program turns it into # a list pg = Program(pg[:len_pg_in]) # add measurement coda for this term of hamil # and for X at ancilla bit_pos_to_xy_str =\ {bit: action for bit, action in new_term if action != 'Z'} RigettiTools.add_xy_meas_coda_to_program( pg, bit_pos_to_xy_str) # get effective state vec if self.num_samples: # send and receive from cloud, get obs_vec bitstrings = self.qc.run_and_measure(pg, trials=self.num_samples) obs_vec = RigettiTools.obs_vec_from_bitstrings( bitstrings, self.num_bits, bs_is_array=False) # go from obs_vec to effective state vec counts_dict = StateVec.get_counts_from_obs_vec( self.num_bits, obs_vec) emp_pd = StateVec.get_empirical_pd_from_counts( self.num_bits, counts_dict) effective_st_vec = StateVec.\ get_emp_state_vec_from_emp_pd( self.num_bits, emp_pd) else: # num_samples = 0 sim = WavefunctionSimulator() st_vec_arr = sim.wavefunction(pg).amplitudes st_vec_arr = st_vec_arr.reshape([2]*self.num_bits) perm = list(reversed(range(self.num_bits))) st_vec_arr = np.transpose(st_vec_arr, perm) effective_st_vec = StateVec(self.num_bits, st_vec_arr) # add contribution to mean real_arr = self.get_real_vec(new_term) mean_val_change = coef*effective_st_vec.\ get_mean_value_of_real_diag_mat(real_arr) mean_val_change *= coef_of_dpart if has_neg_polarity: mean_val_change *= -1 partials_list[deriv_direc] += mean_val_change return partials_list