def pea_program(ancillary_start, ancillary_num, time, H2_distance,
                trotter_order):
    """
    Creates a pyquil Program for the phase estimation algorithm (PEA)

    :param ancillary_start: index of the first ancillary qubit.
    :param ancillary_num: how many ancillaries to use corresponds
            to precision in PEA algorithm
    :param time: t in exp(-iHt), where H is the Hamiltonian
    :param H2_distance: the distance between to H atoms in H2 molecule

    :return: a pyquil Program for PEA algorithm
    """

    phase_estimation_program = Program()
    unitary = exp_hamiltoniantrot_H2(time, H2_distance, trotter_order)
    phase_estimation_program.inst(create_CRX(), create_CRZ(), create_CH())

    Hadamard_ancilaries = Program()

    for index in range(0, ancillary_num):
        Hadamard_ancilaries.inst(H(ancillary_start + index))

    phase_estimation_program += Hadamard_ancilaries

    for index in range(0, ancillary_num):
        cont_first_order = Program()
        control_program(unitary, cont_first_order, ancillary_start + index)
        control_unitary = repeat_program(cont_first_order, 2**index)
        phase_estimation_program += control_unitary

    ancilary_list = list(
        range(ancillary_start, ancillary_start + ancillary_num))

    inv_qft_prog = inverse_qft(ancilary_list)

    phase_estimation_program += inv_qft_prog

    return phase_estimation_program
示例#2
0
def test_qc_calibration_2q(forest):
    # noise model with 95% symmetrized readout fidelity per qubit
    noise_model = asymmetric_ro_model([0, 1], 0.945, 0.955)
    qc = get_qc("2q-qvm")
    qc.qam.noise_model = noise_model

    # bell state program (doesn't matter)
    p = Program()
    p += RESET()
    p += H(0)
    p += CNOT(0, 1)
    p.wrap_in_numshots_loop(10000)

    # ZZ experiment
    sz = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1))
    e = Experiment(settings=[sz], program=p)

    results = qc.calibrate(e)

    # ZZ expectation should just be (1 - 2 * readout_error_q0) * (1 - 2 * readout_error_q1)
    np.isclose(results[0].expectation, 0.81, atol=0.01)
    assert results[0].total_counts == 40000
示例#3
0
def test_qc_calibration_1q(client_configuration: QCSClientConfiguration):
    # noise model with 95% symmetrized readout fidelity per qubit
    noise_model = asymmetric_ro_model([0], 0.945, 0.955)
    qc = get_qc("1q-qvm", client_configuration=client_configuration)
    qc.qam.noise_model = noise_model

    # bell state program (doesn't matter)
    p = Program()
    p += RESET()
    p += H(0)
    p += CNOT(0, 1)
    p.wrap_in_numshots_loop(10000)

    # Z experiment
    sz = ExperimentSetting(in_state=_pauli_to_product_state(sZ(0)), out_operator=sZ(0))
    e = Experiment(settings=[sz], program=p)

    results = qc.calibrate(e)

    # Z expectation value should just be 1 - 2 * readout_error
    np.isclose(results[0].expectation, 0.9, atol=0.01)
    assert results[0].total_counts == 20000
示例#4
0
def phase_estimation(U: np.ndarray,
                     accuracy: int,
                     reg_offset: int = 0) -> Program:
    """
    Generate a circuit for quantum phase estimation.

    :param U: A unitary matrix.
    :param accuracy: Number of bits of accuracy desired.
    :param reg_offset: Where to start writing measurements (default 0).
    :return: A Quil program to perform phase estimation.
    """
    assert isinstance(accuracy, int)
    rows, cols = U.shape
    m = int(log2(rows))
    output_qubits = range(0, accuracy)
    U_qubits = range(accuracy, accuracy + m)
    p = Program()
    ro = p.declare('ro', 'BIT', len(output_qubits))

    # Hadamard initialization
    for i in output_qubits:
        p.inst(H(i))
    # Controlled unitaries
    for i in output_qubits:
        if i > 0:
            U = np.dot(U, U)
        cU = controlled(U)
        name = "CONTROLLED-U{0}".format(2**i)
        # define the gate
        p.defgate(name, cU)
        # apply it
        p.inst((name, i) + tuple(U_qubits))
    # Compute the QFT
    p = p + inverse_qft(output_qubits)
    # Perform the measurements
    for i in output_qubits:
        p.measure(i, ro[reg_offset + i])

    return p
示例#5
0
def test_run(client_configuration: QCSClientConfiguration):
    quantum_processor = NxQuantumProcessor(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(client_configuration=client_configuration, gate_noise=(0.01, 0.01, 0.01)),
        compiler=DummyCompiler(quantum_processor=quantum_processor, client_configuration=client_configuration),
    )
    bitstrings = qc.run(
        Program(
            Declare("ro", "BIT", 3),
            H(0),
            CNOT(0, 1),
            CNOT(1, 2),
            MEASURE(0, MemoryReference("ro", 0)),
            MEASURE(1, MemoryReference("ro", 1)),
            MEASURE(2, MemoryReference("ro", 2)),
        ).wrap_in_numshots_loop(1000)
    )

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert 0 < np.mean(parity) < 0.15
def test_expectation():
    """expectation() routine can take a PauliSum operator on a matrix.  Check
    this functionality and the return of the correct scalar value"""
    X = np.array([[0, 1], [1, 0]])

    def RX_gate(phi):
        return expm(-1j * phi * X)

    def rotation_wavefunction(phi):
        state = np.array([[1], [0]])
        return RX_gate(phi).dot(state)

    prog = Program([RX(-2.5)(0)])
    hamiltonian = PauliTerm("Z", 0, 1.0)

    minimizer = MagicMock()
    fake_result = Mock()
    fake_result.fun = 1.0
    minimizer.return_value = fake_result

    fake_qvm = Mock(spec=['wavefunction', 'expectation', 'run'])
    fake_qvm.wavefunction.return_value = (Wavefunction(
        rotation_wavefunction(-2.5)))
    fake_qvm.expectation.return_value = [0.28366219]
    # for testing expectation
    fake_qvm.run.return_value = [[0], [0]]

    inst = VQE(minimizer)
    energy = inst.expectation(prog, PauliSum([hamiltonian]), None, fake_qvm)
    assert np.isclose(energy, 0.28366219)

    hamiltonian = np.array([[1, 0], [0, -1]])
    energy = inst.expectation(prog, hamiltonian, None, fake_qvm)
    assert np.isclose(energy, 0.28366219)

    prog = Program(H(0))
    hamiltonian = PauliSum([PauliTerm('X', 0)])
    energy = inst.expectation(prog, hamiltonian, 2, fake_qvm)
    assert np.isclose(energy, 1.0)
示例#7
0
def teleport(start_index, end_index, ancilla_index):
    """Teleport a qubit from start to end using an ancilla qubit
    """
    program = make_bell_pair(end_index, ancilla_index)

    ro = program.declare("ro", memory_size=3)

    # do the teleportation
    program.inst(CNOT(start_index, ancilla_index))
    program.inst(H(start_index))

    # measure the results and store them in classical registers [0] and [1]
    program.measure(start_index, ro[0])
    program.measure(ancilla_index, ro[1])

    program.if_then(ro[1], X(2))
    program.if_then(ro[0], Z(2))

    program.measure(end_index, ro[2])

    print(program)
    return program
def test_run(forest):
    device = NxDevice(nx.complete_graph(3))
    qc = QuantumComputer(
        name="testy!",
        qam=QVM(connection=forest, gate_noise=[0.01] * 3),
        device=device,
        compiler=DummyCompiler(),
    )
    bitstrings = qc.run(
        Program(
            Declare("ro", "BIT", 3),
            H(0),
            CNOT(0, 1),
            CNOT(1, 2),
            MEASURE(0, MemoryReference("ro", 0)),
            MEASURE(1, MemoryReference("ro", 1)),
            MEASURE(2, MemoryReference("ro", 2)),
        ).wrap_in_numshots_loop(1000))

    assert bitstrings.shape == (1000, 3)
    parity = np.sum(bitstrings, axis=1) % 3
    assert 0 < np.mean(parity) < 0.15
示例#9
0
def prepare_bitstring(bitstring: Sequence[int], register: Sequence[int], in_x_basis: bool = False):
    """
    Creates a program to prepare the input bitstring on the qubits given by the corresponding
    label in the register.

    :param bitstring:
    :param register: a list of qubits on which to prepare the bitstring. The first
    :param in_x_basis: if true, prepare the bitstring-representation of the numbers in the x basis.
    :returns: state_prep_prog - program
    """
    state_prep_prog = Program()

    for bit, qubit_label in zip(bitstring, register):
        if bit == 1:
            state_prep_prog += X(qubit_label)

        # if we are doing logic in X basis, follow each bit preparation with a Hadamard
        # H |0> = |+> and H |1> = |-> where + and - label the X basis vectors.
        if in_x_basis:
            state_prep_prog += H(qubit_label)

    return state_prep_prog
示例#10
0
def run_bell_low_level(n_shots=1000):
    # Step 1. Get some device components
    qc = get_qc('9q-generic-qvm')
    compiler = qc.compiler
    qam = qc.qam
    del qc

    q = [4, 5]  # qubits

    # Step 2. Construct your program
    program = Program()
    program += H(q[0])
    program += CNOT(q[0], q[1])

    # Step 2.1. Manage read-out memory
    ro = program.declare('ro', memory_type='BIT', memory_size='2')
    program += MEASURE(q[0], ro[0])
    program += MEASURE(q[1], ro[1])

    # Step 2.2. Run the program in a loop
    program = program.wrap_in_numshots_loop(n_shots)

    # Step 3. Compile and run
    nq_program = compiler.quil_to_native_quil(program)
    executable = compiler.native_quil_to_executable(nq_program)
    bitstrings = qam.load(executable) \
        .run() \
        .wait() \
        .read_memory(region_name="ro")

    # Bincount bitstrings
    basis = np.array([2**i for i in range(len(q))])
    ints = np.sum(bitstrings * basis, axis=1)
    print('bincounts', np.bincount(ints))

    # Check parity
    parities = np.sum(bitstrings, axis=1) % 2
    print('avg parity', np.mean(parities))
示例#11
0
def test_control_flows():
    outer_loop = Program()
    classical_flag_register = outer_loop.declare('classical_flag_register', 'BIT')
    outer_loop += MOVE(classical_flag_register, 1)  # initialize

    inner_loop = Program()
    inner_loop += Program(X(0), H(0))
    inner_loop += MEASURE(0, classical_flag_register)

    # run inner_loop in a loop until classical_flag_register is 0
    outer_loop.while_do(classical_flag_register, inner_loop)
    assert outer_loop.out() == '\n'.join([
        "DECLARE classical_flag_register BIT[1]",
        "MOVE classical_flag_register 1",
        "LABEL @START1",
        "JUMP-UNLESS @END2 classical_flag_register",
        "X 0",
        "H 0",
        "MEASURE 0 classical_flag_register",
        "JUMP @START1",
        "LABEL @END2",
        ""
    ])
示例#12
0
def test_variance_bootstrap():
    qubits = [0, 1]
    qc = get_test_qc(n_qubits=len(qubits))
    state_prep = Program([H(q) for q in qubits])
    state_prep.inst(CZ(qubits[0], qubits[1]))
    tomo_expt = generate_state_tomography_experiment(state_prep, qubits)
    results = list(measure_observables(qc=qc, tomo_experiment=tomo_expt, n_shots=4000))
    estimate, status = iterative_mle_state_estimate(results=results, qubits=qubits,
                                                    dilution=0.5)
    rho_est = estimate.estimate.state_point_est
    purity = np.trace(rho_est @ rho_est)
    purity = np.real_if_close(purity)
    assert purity.imag == 0.0

    def my_mle_estimator(_r, _q):
        return iterative_mle_state_estimate(results=_r, qubits=_q,
                                            dilution=0.5, entropy_penalty=0.0, beta=0.0)[0]

    boot_purity, boot_var = estimate_variance(results=results, qubits=qubits,
                                              tomo_estimator=my_mle_estimator, functional=dm.purity,
                                              n_resamples=5, project_to_physical=False)

    np.testing.assert_allclose(purity, boot_purity, atol=2 * np.sqrt(boot_var), rtol=0.01)
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])
示例#14
0
def test_qc_expectation(forest):
    device = NxDevice(nx.complete_graph(2))
    qc = QuantumComputer(name='testy!',
                         qam=QVM(connection=forest),
                         device=device,
                         compiler=DummyCompiler())

    # bell state program
    p = Program()
    p += RESET()
    p += H(0)
    p += CNOT(0, 1)
    p.wrap_in_numshots_loop(10)

    # XX, YY, ZZ experiment
    sx = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sX(0) * sX(1))
    sy = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sY(0) * sY(1))
    sz = ExperimentSetting(in_state=sZ(0) * sZ(1), out_operator=sZ(0) * sZ(1))

    e = TomographyExperiment(settings=[sx, sy, sz], program=p)

    results = qc.experiment(e)

    # XX expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[0].expectation, 1)
    assert np.isclose(results[0].std_err, 0)
    assert results[0].total_counts == 40

    # YY expectation value for bell state |00> + |11> is -1
    assert np.isclose(results[1].expectation, -1)
    assert np.isclose(results[1].std_err, 0)
    assert results[1].total_counts == 40

    # ZZ expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[2].expectation, 1)
    assert np.isclose(results[2].std_err, 0)
    assert results[2].total_counts == 40
示例#15
0
def amplification_circuit(algorithm,
                          oracle,
                          qubits,
                          num_iter,
                          decompose_diffusion=False):
    """
    Returns a program that does ``num_iter`` rounds of amplification, given a measurement-less
    algorithm, an oracle, and a list of qubits to operate on.

    :param Program algorithm: A program representing a measurement-less algorithm run on qubits.
    :param Program oracle: An oracle maps any basis vector ``|psi>`` to either ``+|psi>`` or
        ``-|psi>`` depending on whether ``|psi>`` is in the desirable subspace or the undesirable
        subspace.
    :param Sequence qubits: the qubits to operate on
    :param int num_iter: number of iterations of amplifications to run
    :param bool decompose_diffusion: If True, decompose the Grover diffusion gate into two qubit
     gates. If False, use a defgate to define the gate.
    :return: The amplified algorithm.
    :rtype: Program
    """
    program = pq.Program()

    uniform_superimposer = pq.Program().inst([H(qubit) for qubit in qubits])
    program += uniform_superimposer
    if decompose_diffusion:
        diffusion = decomposed_diffusion_program(qubits)
    else:
        diffusion = diffusion_program(qubits)
    # To avoid redefining gates, we collect them before building our program.
    defined_gates = oracle.defined_gates + algorithm.defined_gates + diffusion.defined_gates
    for _ in range(num_iter):
        program += (oracle.instructions + algorithm.dagger().instructions +
                    diffusion.instructions + algorithm.instructions)
    # We redefine the gates in the new program.
    for gate in defined_gates:
        program.defgate(gate.name, gate.matrix)
    return program
示例#16
0
    def test_get_expectation_values_for_circuitset(self, backend):
        # Given
        num_circuits = 10
        circuitset = [
            Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) for _ in range(num_circuits)
        ]
        operator = IsingOperator("[]")
        target_expectation_values = np.array([1])

        # When
        backend.n_samples = 1
        expectation_values_set = backend.get_expectation_values_for_circuitset(
            circuitset, operator
        )

        # Then
        assert len(expectation_values_set) == num_circuits

        for expectation_values in expectation_values_set:
            assert isinstance(expectation_values, ExpectationValues)
            assert isinstance(expectation_values.values, np.ndarray)
            assert expectation_values.values == pytest.approx(
                target_expectation_values, abs=1e-15
            )
示例#17
0
    def grover_run(self, bit):
        self._run_init(bit)

        oracle = Program()
        oracle_name = "grover_oracle"
        oracle.defgate(oracle_name, self._grover_oracle_matrix(bit))
        oracle.inst(tuple([oracle_name] + self.qubits))

        diffusion = self._grover_diffusion_op()

        p = Program()
        Hm = Program().inst([H(qubit) for qubit in grover.qubits])
        p += Hm
        ## Repeating part of the algorithm
        for _ in range(self.num_iter):
            p += oracle
            p += Hm
            p += diffusion
            p += Hm

        # run the program on a QVM
        qc = get_qc('9q-square-qvm')
        result = qc.run_and_measure(p, trials=10)
        pprint.pprint(result)
示例#18
0
def get_test_program(measure: bool = False) -> Program:
    PI = float(pi.evalf())
    p = Program()
    p += X(0)
    p += Y(1)
    p += Z(2)
    p += H(3)
    p += S(0)
    p += T(1)
    p += RX(PI / 2, 2)
    p += RY(PI / 2, 3)
    p += RZ(PI / 2, 0)
    p += CZ(0, 1)
    p += CNOT(2, 3)
    p += CCNOT(0, 1, 2)
    p += CPHASE(PI / 4, 2, 1)
    p += SWAP(0, 3)
    if measure:
        ro = p.declare("ro", "BIT", 4)
        p += MEASURE(0, ro[0])
        p += MEASURE(3, ro[1])
        p += MEASURE(2, ro[2])
        p += MEASURE(1, ro[3])
    return p
示例#19
0
def amplification_circuit(algorithm, oracle, qubits, num_iter):
    """
    Returns a program that does n rounds of amplification, given a measurement-less algorithm,
    an oracle, and a list of qubits to operate on.

    :param Program algorithm: A program representing a measurement-less algorithm run on qubits.
    :param Program oracle: An oracle maps any basis vector to either |0> or |1>.
    :param Sequence qubits: the qubits to operate on
    :param int num_iter: number of iterations of amplifications to run
    :return: The amplified algorithm.
    :rtype: Program
    """
    if num_iter <= 0:
        raise ValueError("num_iter must be greater than zero")

    prog = pq.Program()

    uniform_superimposer = pq.Program().inst([H(qubit) for qubit in qubits])
    prog += uniform_superimposer

    for _ in range(num_iter):
        prog += oracle + algorithm.dagger() + diffusion_program(
            qubits) + algorithm
    return prog
示例#20
0
    def test_get_expectation_values_for_circuitset(self):
        # Given
        num_circuits = 10
        circuitset = [
            Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2)))
            for _ in range(num_circuits)
        ]
        operator = IsingOperator('[]')
        target_expectation_values = np.array([1])

        # When
        for backend in self.backends:
            backend.n_samples = 1
            expectation_values_set = backend.get_expectation_values_for_circuitset(
                circuitset, operator)

            # Then
            self.assertEqual(len(expectation_values_set), num_circuits)

            for expectation_values in expectation_values_set:
                self.assertIsInstance(expectation_values, ExpectationValues)
                np.testing.assert_array_almost_equal(expectation_values.values,
                                                     target_expectation_values,
                                                     decimal=15)
示例#21
0
def get_qaoa_program(qubits, driver, reward, betas, gammas) -> Program:
    """
    Return the pyQuil program to construct the QAOA state for the problem given beta
    and gamma angles

    :param driver: The driver PauliSum. Usually X_i on all qubits.
    :param problem_ham: The PauliSum representing the problem reward
    :param betas: Beta angles for parameterizing the driver unitary.
    :param gammas: Gamma angles for parameterizing the problem hamiltonian unitary.
    :return: The program
    """
    assert len(betas) == len(gammas)
    prob_progs = [exponentiate_reward(reward, gamma) for gamma in gammas]
    driver_progs = [exponentiate_driver(driver, beta) for beta in betas]
    interleaved_progs = [
        prob_prog + driver_prog
        for prob_prog, driver_prog in zip(prob_progs, driver_progs)
    ]

    prog = Program([H(q) for q in qubits])
    for iprog in interleaved_progs:
        prog += iprog

    return prog
示例#22
0
def test_qc_expectation_larger_lattice(client_configuration: QCSClientConfiguration, dummy_compiler: DummyCompiler):
    qc = QuantumComputer(name="testy!", qam=QVM(client_configuration=client_configuration), compiler=dummy_compiler)

    q0 = 2
    q1 = 3

    # bell state program
    p = Program()
    p += RESET()
    p += H(q0)
    p += CNOT(q0, q1)
    p.wrap_in_numshots_loop(10)

    # XX, YY, ZZ experiment
    sx = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sX(q0) * sX(q1))
    sy = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sY(q0) * sY(q1))
    sz = ExperimentSetting(in_state=_pauli_to_product_state(sZ(q0) * sZ(q1)), out_operator=sZ(q0) * sZ(q1))

    e = Experiment(settings=[sx, sy, sz], program=p)

    results = qc.experiment(e)

    # XX expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[0].expectation, 1)
    assert np.isclose(results[0].std_err, 0)
    assert results[0].total_counts == 40

    # YY expectation value for bell state |00> + |11> is -1
    assert np.isclose(results[1].expectation, -1)
    assert np.isclose(results[1].std_err, 0)
    assert results[1].total_counts == 40

    # ZZ expectation value for bell state |00> + |11> is 1
    assert np.isclose(results[2].expectation, 1)
    assert np.isclose(results[2].std_err, 0)
    assert results[2].total_counts == 40
示例#23
0
def rotate_density(rho, pauli_term, debug=False):
    """
    Rotate the density so I can read off in the computational basis
    """
    # rotate operator into computational basis
    rot_prog = Program()
    n_qubits = int(np.log2(rho.shape[0]))

    marked_qubits = []
    for key, value in pauli_term._ops.iteritems():
        marked_qubits.append(key)
        if value == "X":
            rot_prog.inst(H(key))
        elif value == "Y":
            rot_prog.inst(RX(np.pi / 2)(key))
    rot_prog.inst(I(n_qubits - 1))

    qvm_unitary = QVMConnection(type_trans='unitary')
    if debug:
        ham_op = tensor_up(PauliSum([pauli_term]), n_qubits)
        e_true = np.trace(ham_op.dot(rho))

    unitary = qvm_unitary.unitary(rot_prog)
    rho = unitary.dot(rho.dot(np.conj(unitary).T))

    if debug:
        z_term = PauliTerm("I", 0)
        for idx in marked_qubits:
            z_term = z_term * PauliTerm("Z", idx)

        ham_op_2 = tensor_up(pauli_term.coefficient * PauliSum([z_term]),
                             n_qubits)
        test_expect = np.trace(np.dot(ham_op_2, rho))
        assert np.isclose(test_expect, e_true)

    return rho, marked_qubits
示例#24
0
def maxcut_qaoa_program(gamma: float) -> Program:
    """
    Generates a 2Q MAXCUT QAOA circuit with beta = pi/8 and with the provided
    gamma.

    Args:
        gamma: One of the two variational parameters (the other is fixed).
    Returns:
        A 2Q MAXCUT QAOA circuit with fixed beta and gamma.
    """
    q0, q1 = (0, 1)
    p = Program()
    p += H(q0)
    p += H(q1)
    p += CNOT(q0, q1)
    p += RZ(2 * gamma, q1)
    p += CNOT(q0, q1)
    p += H(q0)
    p += H(q1)
    p += RZ(np.pi / 4, q0)
    p += RZ(np.pi / 4, q1)
    p += H(q0)
    p += H(q1)
    return p
示例#25
0
def test_append_measure_register():
    q0 = QubitPlaceholder()
    p = Program(H(q0), RX(np.pi/2, 0))
    p = append_measure_register(p)
    assert str(p[-1]) == "MEASURE 0 ro[1]"
示例#26
0
def test_run_and_measure_qubits(client_configuration: QCSClientConfiguration):
    wfnsim = WavefunctionSimulator(client_configuration=client_configuration)
    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
示例#27
0
def test_run_and_measure(client_configuration: QCSClientConfiguration):
    wfnsim = WavefunctionSimulator(client_configuration=client_configuration)
    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)
示例#28
0
def test_trotterize():
    term_one = PauliTerm("X", 0, 1.0)
    term_two = PauliTerm("Z", 0, 1.0)

    with pytest.raises(ValueError):
        trotterize(term_one, term_two, trotter_order=0)
    with pytest.raises(ValueError):
        trotterize(term_one, term_two, trotter_order=5)

    prog, _ = trotterize(term_one, term_one)
    result_prog = Program().inst(
        [H(0), RZ(2.0)(0), H(0),
         H(0), RZ(2.0)(0), H(0)])
    compare_progs(prog, result_prog)

    # trotter_order 1 steps 1
    prog, _ = trotterize(term_one, term_two, trotter_steps=1)
    result_prog = Program().inst([H(0), RZ(2.0)(0), H(0), RZ(2.0)(0)])
    compare_progs(prog, result_prog)

    # trotter_order 1 steps 2
    prog, _ = trotterize(term_one, term_two, trotter_steps=2)
    result_prog = Program().inst([
        H(0),
        RZ(1.0)(0),
        H(0),
        RZ(1.0)(0),
        H(0),
        RZ(1.0)(0),
        H(0),
        RZ(1.0)(0)
    ])
    compare_progs(prog, result_prog)

    # trotter_order 2 steps 1
    prog, _ = trotterize(term_one, term_two, trotter_order=2)
    result_prog = Program().inst(
        [H(0), RZ(1.0)(0),
         H(0), RZ(2.0)(0),
         H(0), RZ(1.0)(0),
         H(0)])
    compare_progs(prog, result_prog)

    # trotter_order 2 steps 2
    prog, _ = trotterize(term_one, term_two, trotter_order=2, trotter_steps=2)
    result_prog = Program().inst([
        H(0),
        RZ(0.5)(0),
        H(0),
        RZ(1.0)(0),
        H(0),
        RZ(0.5)(0),
        H(0),
        H(0),
        RZ(0.5)(0),
        H(0),
        RZ(1.0)(0),
        H(0),
        RZ(0.5)(0),
        H(0)
    ])
    compare_progs(prog, result_prog)

    # trotter_order 3 steps 1
    prog, _ = trotterize(term_one, term_two, trotter_order=3, trotter_steps=1)
    result_prog = Program().inst([
        H(0),
        RZ(14.0 / 24)(0),
        H(0),
        RZ(4.0 / 3.0)(0),
        H(0),
        RZ(1.5)(0),
        H(0),
        RZ(-4.0 / 3.0)(0),
        H(0),
        RZ(-2.0 / 24)(0),
        H(0),
        RZ(2.0)(0)
    ])
    compare_progs(prog, result_prog)
示例#29
0
def test_exponentiate():
    # test rotation of single qubit
    generator = PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0)(0))
    compare_progs(prog, result_prog)

    # testing general 2-circuit
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(CNOT(0, 1)).inst(RZ(2.0)(1)).inst(CNOT(0, 1))
    compare_progs(prog, result_prog)

    # testing change of basis position 0
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("X", 0, 1.0)
    param_prog = exponential_map(generator)
    prog = param_prog(1)
    result_prog = Program().inst(
        [H(0), CNOT(0, 1), RZ(2.0)(1),
         CNOT(0, 1), H(0)])
    compare_progs(prog, result_prog)

    # testing change of basis position 1
    generator = PauliTerm("X", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(
        [H(1), CNOT(0, 1), RZ(2.0)(1),
         CNOT(0, 1), H(1)])
    compare_progs(prog, result_prog)

    # testing change of basis position 0
    generator = PauliTerm("Z", 1, 1.0) * PauliTerm("Y", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(0),
        CNOT(0, 1),
        RZ(2.0)(1),
        CNOT(0, 1),
        RX(-math.pi / 2)(0)
    ])
    compare_progs(prog, result_prog)

    # testing change of basis position 1
    generator = PauliTerm("Y", 1, 1.0) * PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(1),
        CNOT(0, 1),
        RZ(2.0)(1),
        CNOT(0, 1),
        RX(-math.pi / 2.0)(1)
    ])
    compare_progs(prog, result_prog)

    # testing circuit for 3-terms with change of basis
    generator = PauliTerm("X", 2, 1.0) * PauliTerm("Y", 1, 1.0) * PauliTerm(
        "Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(1),
        H(2),
        CNOT(0, 1),
        CNOT(1, 2),
        RZ(2.0)(2),
        CNOT(1, 2),
        CNOT(0, 1),
        RX(-math.pi / 2.0)(1),
        H(2)
    ])
    compare_progs(prog, result_prog)

    # testing circuit for 3-terms non-sequential
    generator = PauliTerm("Y", 3, 1.0) * PauliTerm("Y", 2, 1.0) * PauliTerm(
        "I", 1, 1.0) * PauliTerm("Y", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([
        RX(math.pi / 2.0)(0),
        RX(math.pi / 2.0)(2),
        RX(math.pi / 2.0)(3),
        CNOT(0, 2),
        CNOT(2, 3),
        RZ(2.0)(3),
        CNOT(2, 3),
        CNOT(0, 2),
        RX(-math.pi / 2.0)(0),
        RX(-math.pi / 2.0)(2),
        RX(-math.pi / 2.0)(3)
    ])
    compare_progs(prog, result_prog)
def implementGate(device, gate, qubit, script, frac=0):

    # *This function contains SDK specific code.*
    #
    # Input:
    # * *device* - String specifying the device on which the game is played.
    #              Details about the device will be obtained using getLayout.
    # * *gate* - String that specifies gate type.
    # * *qubit* - Qubit, list of two qubits or qubit register on which the gate is applied.
    # * *script* -
    # * *frac* -
    #
    # Process:
    # * For gates of type 'X', 'Z' and 'XX', the gate $U = \exp(-i \,\times\, gate \,\times\, frac )$ is implemented on the qubit or pair of qubits in *qubit*.
    # * *gate='Finish'* implements the measurement command on the qubit register required for ProjectQ to not complain.
    #
    # Output:
    # * None are returned, but modifications are made to the classes that contain the quantum program.

    num, area, entangleType, pairs, pos, example, sdk, runs = getLayout(device)

    if sdk in ["QISKit", "ManualQISKit"]:
        if gate == 'X':
            script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit)
        elif gate == 'Z':  # actually a Y axis rotation
            script.u3(frac * math.pi, 0, 0, qubit)
        elif gate == 'XX':
            if entangleType == 'CX':
                script.cx(qubit[0], qubit[1])
                script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit[0])
                script.cx(qubit[0], qubit[1])
            elif entangleType == 'CZ':
                script.h(qubit[1])
                script.cz(qubit[0], qubit[1])
                script.u3(frac * math.pi, -math.pi / 2, math.pi / 2, qubit[0])
                script.cz(qubit[0], qubit[1])
                script.h(qubit[1])
            else:
                print("Support for this is yet to be added")

    elif sdk == "ProjectQ":
        if gate == 'X':
            Rx(frac * math.pi) | qubit
        elif gate == 'Z':  # actually a Y axis rotation
            Ry(frac * math.pi) | qubit
        elif gate == 'XX':
            if entangleType == 'CX':
                CNOT | (qubit[0], qubit[1])
                Rx(frac * math.pi) | qubit[0]
                CNOT | (qubit[0], qubit[1])
            elif entangleType == 'CZ':
                H | qubit[1]
                C(Z) | (qubit[0], qubit[1])
                Rx(frac * math.pi) | qubit[0]
                C(Z) | (qubit[0], qubit[1])
                H | qubit[1]
            else:
                print("Support for this is yet to be added")
        elif gate == 'finish':
            Measure | qubit

    elif sdk == "Forest":
        if gate == 'X':
            if qubit in pos.keys():  # only if qubit is active
                script.inst(RX(frac * math.pi, qubit))
        elif gate == 'Z':  # actually a Y axis rotation
            if qubit in pos.keys():  # only if qubit is active
                script.inst(RY(frac * math.pi, qubit))
        elif gate == 'XX':
            if entangleType == 'CX':
                script.inst(CNOT(qubit[0], qubit[1]))
                script.inst(RX(frac * math.pi, qubit[0]))
                script.inst(CNOT(qubit[0], qubit[1]))
            elif entangleType == 'CZ':
                script.inst(H(qubit[1]))
                script.inst(CZ(qubit[0], qubit[1]))
                script.inst(RX(frac * math.pi, qubit[0]))
                script.inst(CZ(qubit[0], qubit[1]))
                script.inst(H(qubit[1]))
            elif entangleType == 'none':
                script.inst(RX(frac * math.pi, qubit[0]))
                script.inst(RX(frac * math.pi, qubit[1]))
            else:
                print("Support for this is yet to be added")