Exemplo n.º 1
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_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)
Exemplo n.º 3
0
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)
Exemplo n.º 4
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
Exemplo n.º 5
0
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']
Exemplo n.º 6
0
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)
Exemplo n.º 7
0
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)))
Exemplo n.º 8
0
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")
Exemplo n.º 9
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
Exemplo n.º 10
0
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])
Exemplo n.º 11
0
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))
Exemplo n.º 14
0
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))
Exemplo n.º 16
0
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")
Exemplo n.º 17
0
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)
Exemplo n.º 18
0
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
Exemplo n.º 21
0
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))
Exemplo n.º 22
0
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']
Exemplo n.º 24
0
    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)
Exemplo n.º 25
0
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)
Exemplo n.º 27
0
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
Exemplo n.º 28
0
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))
Exemplo n.º 29
0
    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])
Exemplo n.º 30
0
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)
Exemplo n.º 31
0
    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
Exemplo n.º 32
0
    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