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_expectation_vs_lisp_qvm(n_qubits, client_configuration): for _ in range(20): prog = _generate_random_program(n_qubits=n_qubits, length=10) operator = _generate_random_pauli(n_qubits=n_qubits, n_terms=5) lisp_wf = WavefunctionSimulator( client_configuration=client_configuration) lisp_exp = lisp_wf.expectation(prep_prog=prog, pauli_terms=operator) ref_wf = ReferenceWavefunctionSimulator( n_qubits=n_qubits).do_program(prog) ref_exp = ref_wf.expectation(operator=operator) np.testing.assert_allclose(lisp_exp, ref_exp, atol=1e-15)
def test_run_and_measure(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), ) bitstrings = wfnsim.run_and_measure(bell, trials=1000) parity = np.sum(bitstrings, axis=1) % 2 assert np.all(parity == 0)
def test_run_and_measure_qubits(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), ) bitstrings = wfnsim.run_and_measure(bell, qubits=[0, 100], trials=1000) assert np.all(bitstrings[:, 1] == 0) assert 0.4 < np.mean(bitstrings[:, 0]) < 0.6
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_noise(client_configuration: QCSClientConfiguration): wfnsim = WavefunctionSimulator( client_configuration=client_configuration, gate_noise=(0.2, 0.3, 0.5), measurement_noise=(0.5, 0.2, 0.3), ) assert wfnsim.gate_noise == (0.2, 0.3, 0.5) assert wfnsim.measurement_noise == (0.5, 0.2, 0.3) with pytest.raises(TypeError): WavefunctionSimulator(client_configuration=client_configuration, gate_noise="NOT A TUPLE") with pytest.raises(TypeError): WavefunctionSimulator(client_configuration=client_configuration, measurement_noise="NOT A TUPLE")
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_expectation(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)) expects = wfnsim.expectation(bell, [sZ(0) * sZ(1), sZ(0), sZ(1), sX(0) * sX(1)]) assert expects.size == 4 np.testing.assert_allclose(expects, [1, 0, 0, 1]) pauli_sum = PauliSum([sZ(0) * sZ(1)]) expects = wfnsim.expectation(bell, pauli_sum) assert expects.size == 1 np.testing.assert_allclose(expects, [1])
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 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_PrepareAndMeasureOnWFSim(): p = Program() params = p.declare("params", memory_type="REAL", memory_size=2) p.inst(RX(params[0], 0)) p.inst(RX(params[1], 1)) def make_memory_map(params): return {"params": params} # ham = PauliSum.from_compact_str("1.0*Z0 + 1.0*Z1") term1 = PauliTerm("Z", 0) term2 = PauliTerm("Z", 1) ham = PauliSum([term1, term2]) sim = WavefunctionSimulator() with local_qvm(): cost_fn = PrepareAndMeasureOnWFSim(p, make_memory_map, ham, sim, scalar_cost_function=False, enable_logging=True) out = cost_fn([np.pi, np.pi / 2], nshots=100) print(cost_fn.log) assert np.allclose(cost_fn.log[0].fun, (-1.0, 0.1)) assert np.allclose(out, (-1, 0.1))
def test_run_and_measure_async(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), ) job_id = wfnsim.run_and_measure_async(bell, trials=1000) assert isinstance(job_id, str) bitstrings = wfnsim.wait_for_job(job_id).result() assert bitstrings.shape == (1000, 2) parity = np.sum(bitstrings, axis=1) % 2 assert np.all(parity == 0)
def test_PrepareAndMeasureOnWFSim_QubitPlaceholders(): q1, q2 = QubitPlaceholder(), QubitPlaceholder() p = Program() params = p.declare("params", memory_type="REAL", memory_size=2) p.inst(RX(params[0], q1)) p.inst(RX(params[1], q2)) def make_memory_map(params): return {"params": params} ham = PauliSum([PauliTerm("Z", q1), PauliTerm("Z", q2)]) qubit_mapping = get_default_qubit_mapping(p) sim = WavefunctionSimulator() with local_qvm(): cost_fn = PrepareAndMeasureOnWFSim( p, make_memory_map, ham, sim, enable_logging=True, qubit_mapping=qubit_mapping, scalar_cost_function=False, ) out = cost_fn([np.pi, np.pi / 2], nshots=100) assert np.allclose(cost_fn.log[0].fun, (-1.0, 0.1)) assert np.allclose(out, (-1, 0.1))
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 simulate_controlled_y(): y = np.array([[0, -1j], [1j, 0]]) controlled_y_definition = DefGate("CONTROLLED-Y", controlled(y)) CONTROLLED_Y = controlled_y_definition.get_constructor() p = Program(controlled_y_definition) p += NOT(0) p += CONTROLLED_Y(0, 1) print(WavefunctionSimulator().wavefunction(p))
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_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_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_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 test_QAOACostFunctionOnWFSim(): sim = WavefunctionSimulator() params = AnnealingParams.linear_ramp_from_hamiltonian(hamiltonian, n_steps=4) cost_function = QAOACostFunctionOnWFSim(hamiltonian, params=params, sim=sim, scalar_cost_function=False, enable_logging=True) out = cost_function(params.raw(), nshots=100) print(out)
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 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 retrieve(self, num_bobs: int) -> Program: # Assert: Has received all components for the target entanglement set assert None not in self.received_shares, \ "Bob #" + str(self.id) + ": retrieve() attempted without receiving all shares" self.protocol += iqft(self.received_shares, num_bobs) self.protocol += disentangle(self.received_shares[0], self.received_shares[1:]) self.protocol += qft(self.received_shares[0], 1) wf_sim = WavefunctionSimulator() for i, share in enumerate(self.received_shares): self.protocol += MEASURE(share, self.memory[i])
def test_measure_observables_many_progs(forest): expts = [ ExperimentSetting(sI(), o1 * o2) for o1, o2 in itertools.product([sI(0), sX(0), sY(0), sZ(0)], [sI(1), sX(1), sY(1), sZ(1)]) ] qc = get_qc('2q-qvm') qc.qam.random_seed = 51 for prog in _random_2q_programs(): suite = TomographyExperiment(expts, program=prog, qubits=[0, 1]) assert len(suite) == 4 * 4 gsuite = group_experiments(suite) assert len(gsuite) == 3 * 3 # can get all the terms with I for free in this case wfn = WavefunctionSimulator() wfn_exps = {} for expt in expts: wfn_exps[expt] = wfn.expectation(gsuite.program, PauliSum([expt.out_operator])) for res in measure_observables(qc, gsuite, n_shots=1_000): np.testing.assert_allclose(wfn_exps[res.setting], res.expectation, atol=0.1)
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