示例#1
0
def test_program_gates():
    ig = Program()
    ig.inst(H(0), X(1))
    assert len(ig.actions) == 2
    assert ig.out() == "H 0\nX 1\n"
示例#2
0
def test_simple_instructions():
    p = Program().inst(HALT, WAIT, RESET, NOP)
    assert p.out() == 'HALT\nWAIT\nRESET\nNOP\n'
示例#3
0
def test_measurement_calls():
    p = Program()
    p.inst(MEASURE(0, 1), MEASURE(0, Addr(1)))
    assert p.out() == 'MEASURE 0 [1]\n' * 2
示例#4
0
def test_plus_operator():
    p = Program()
    p += H(0)
    p += [X(0), Y(0), Z(0)]
    assert len(p) == 4
    assert p.out() == "H 0\nX 0\nY 0\nZ 0\n"
示例#5
0
def test_prog_init():
    p = Program()
    p.inst(X(0)).measure(0, 0)
    assert p.out() == 'X 0\nMEASURE 0 [0]\n'
示例#6
0
def test_conjugate_request(server, mock_rb_cxn):
    response = mock_rb_cxn.apply_clifford_to_pauli(Program("H 0"), PauliTerm("X", 0, 1.0))
    assert isinstance(response, PauliTerm)
    assert str(response) == "(1+0j)*Z0"
示例#7
0
def test_len_one():
    prog = Program(X(0))
    assert len(prog) == 1
示例#8
0
def _S(q: int) -> Program:
    """
    An S in terms of RZ(theta)
    """
    return Program(RZ(np.pi / 2, q))
示例#9
0
def basic_compile(program: Program) -> Program:
    """
    A rudimentary but predictable compiler.

    No rewiring or optimization is done by this compilation step. There may be
    some gates that are not yet supported. Gates defined in the input program
    are included without change in the output program.

    :param program: A program to be compiled to native quil with simple
        replacements.
    :return: A program with some of the input non-native quil gates replaced
        with basic native quil gate implementations.
    """
    new_prog = Program()
    new_prog.num_shots = program.num_shots
    new_prog.inst(program.defined_gates)

    for inst in program:
        if isinstance(inst, Gate):
            if inst.name == "CCNOT":
                new_prog += _CCNOT(*inst.qubits)
            elif inst.name == "CNOT":
                new_prog += _CNOT(*inst.qubits)
            # NB: we haven't implemented CPHASE00/01/10
            elif inst.name == "CPHASE":
                angle_param = inst.params[0]
                new_prog += _CPHASE(angle_param, *inst.qubits)
            elif inst.name == "CZ":
                new_prog += CZ(*inst.qubits)  # remove dag modifiers
            elif inst.name == "H":
                new_prog += _H(inst.qubits[0])
            elif inst.name == "I":
                new_prog += I(inst.qubits[0])  # remove dag modifiers
            elif inst.name == "ISWAP":
                new_prog += _ISWAP(*inst.qubits)  # remove dag modifiers
            elif inst.name == "PHASE":
                angle_param = inst.params[0]
                new_prog += _PHASE(angle_param, inst.qubits[0])
            elif inst.name == "RX":
                angle_param = inst.params[0]
                if is_magic_angle(inst.params[0]):
                    # in case dagger
                    new_prog += RX(angle_param, inst.qubits[0])
                else:
                    new_prog += _RX(angle_param, inst.qubits[0])
            elif inst.name == "RY":
                angle_param = inst.params[0]
                new_prog += _RY(angle_param, inst.qubits[0])
            elif inst.name == "RZ":
                # in case dagger
                angle_param = inst.params[0]
                new_prog += RZ(angle_param, inst.qubits[0])
            elif inst.name == "S":
                new_prog += _S(inst.qubits[0])
            # NB: we haven't implemented CSWAP or PSWAP
            elif inst.name == "SWAP":
                new_prog += _SWAP(*inst.qubits)
            elif inst.name == "T":
                new_prog += _T(inst.qubits[0])
            elif inst.name == "X":
                new_prog += _X(inst.qubits[0])
            elif inst.name == "XY":
                angle_param = inst.params[0]
                new_prog += XY(angle_param, *inst.qubits)
            elif inst.name == "Y":
                new_prog += _Y(inst.qubits[0])
            elif inst.name == "Z":
                new_prog += _Z(inst.qubits[0])
            elif inst.name in [gate.name for gate in new_prog.defined_gates]:
                new_prog += inst
            else:
                raise ValueError(f"Unknown gate instruction {inst}")
        else:
            new_prog += inst

    new_prog.native_quil_metadata = {
        "final_rewiring": None,
        "gate_depth": None,
        "gate_volume": None,
        "multiqubit_gate_depth": None,
        "program_duration": None,
        "program_fidelity": None,
        "topological_swaps": 0,
    }
    return new_prog
示例#10
0
def test_exponentiate_prog():
    ham = PauliTerm("Z", 0)
    result_prog = Program(RZ(2.0, 0))
    prog = exponentiate(ham)
    compare_progs(result_prog, prog)
示例#11
0
def basic_compile(program: Program):
    """
    A rudimentary but predictable compiler.

    No rewiring or optimization is done by this compilation step. There may be some gates that
    are not yet supported. Gates defined in the input program are included without change in the
    output program.

    :param program: a program to be compiled to native quil with simple replacements.
    :return: a program with some of the input non-native quil gates replaced with basic native quil
        gate implementations.
    """
    new_prog = Program()
    new_prog.num_shots = program.num_shots
    new_prog.inst(program.defined_gates)

    daggered_defgates = []

    for inst in program:
        if isinstance(inst, Gate):
            # TODO: this is only a stopgap while the noisy QVM does not support modifiers.
            # dagger this gate if odd number of daggers. Ignore controlled for now.
            needs_dagger = inst.modifiers.count('DAGGER') % 2 == 1
            angle_param = None
            if len(inst.params) > 0:
                angle_param = inst.params[0]
                if needs_dagger:
                    angle_param = -angle_param

            if 'CONTROLLED' in inst.modifiers:
                raise ValueError("Controlled gates are not currently supported.")

            if inst.name == 'CZ':
                new_prog += CZ(*inst.qubits)  # remove dag modifiers
            elif inst.name == 'XY':
                new_prog += XY(angle_param, *inst.qubits)
            elif inst.name == 'I':
                new_prog += I(inst.qubits[0])  # remove dag modifiers
            elif inst.name == 'RZ':
                # in case dagger
                new_prog += RZ(angle_param, inst.qubits[0])
            elif inst.name == 'RX':
                if is_magic_angle(inst.params[0]):
                    # in case dagger
                    new_prog += RX(angle_param, inst.qubits[0])
                else:
                    new_prog += _RX(angle_param, inst.qubits[0])
            elif inst.name == 'RY':
                new_prog += _RY(angle_param, inst.qubits[0])
            elif inst.name == 'CNOT':
                new_prog += _CNOT(*inst.qubits)
            elif inst.name == 'CCNOT':
                new_prog += _CCNOT(*inst.qubits)
            elif inst.name == 'SWAP':
                new_prog += _SWAP(*inst.qubits)
            elif inst.name == 'T':
                new_prog += _T(inst.qubits[0], needs_dagger)
            elif inst.name == "H":
                new_prog += _H(inst.qubits[0])
            elif inst.name == "X":
                new_prog += _X(inst.qubits[0])
            elif inst.name in [gate.name for gate in new_prog.defined_gates]:
                if needs_dagger and inst.name not in daggered_defgates:
                    new_prog.defgate(inst.name + 'DAG', inst.matrix.T.conj())
                    daggered_defgates.append(inst.name)
                new_prog += inst
            else:
                raise ValueError(f"Unknown gate instruction {inst}")

        else:
            new_prog += inst

    new_prog.native_quil_metadata = {
        'final_rewiring': None,
        'gate_depth': None,
        'gate_volume': None,
        'multiqubit_gate_depth': None,
        'program_duration': None,
        'program_fidelity': None,
        'topological_swaps': 0,
    }
    return new_prog
def test_default_wf_simulator():
    qam = PyQVM(n_qubits=2)
    qam.execute(Program(H(0), H(1)))
    assert qam.wf_simulator.wf.reshape(-1).shape == (4, )
def test_larger_qaoa_circuit():
    square_qaoa_circuit = [
        H(0),
        H(1),
        H(2),
        H(3),
        X(0),
        PHASE(0.3928244130249029, 0),
        X(0),
        PHASE(0.3928244130249029, 0),
        CNOT(0, 1),
        RZ(0.78564882604980579, 1),
        CNOT(0, 1),
        X(0),
        PHASE(0.3928244130249029, 0),
        X(0),
        PHASE(0.3928244130249029, 0),
        CNOT(0, 3),
        RZ(0.78564882604980579, 3),
        CNOT(0, 3),
        X(0),
        PHASE(0.3928244130249029, 0),
        X(0),
        PHASE(0.3928244130249029, 0),
        CNOT(1, 2),
        RZ(0.78564882604980579, 2),
        CNOT(1, 2),
        X(0),
        PHASE(0.3928244130249029, 0),
        X(0),
        PHASE(0.3928244130249029, 0),
        CNOT(2, 3),
        RZ(0.78564882604980579, 3),
        CNOT(2, 3),
        H(0),
        RZ(-0.77868204192240842, 0),
        H(0),
        H(1),
        RZ(-0.77868204192240842, 1),
        H(1),
        H(2),
        RZ(-0.77868204192240842, 2),
        H(2),
        H(3),
        RZ(-0.77868204192240842, 3),
        H(3),
    ]

    prog = Program(square_qaoa_circuit)
    qam = PyQVM(n_qubits=4,
                quantum_simulator_type=ReferenceWavefunctionSimulator)
    qam.execute(prog)
    wf = qam.wf_simulator.wf

    wf_true = np.array([
        8.43771693e-05 - 0.1233845 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -2.50040954e-01 + 0.12661547 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -4.99915497e-01 - 0.12363516 * 1j,
        -2.50040954e-01 + 0.12661547 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -2.50040954e-01 + 0.12661547 * 1j,
        -4.99915497e-01 - 0.12363516 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -2.50040954e-01 + 0.12661547 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        -1.24927731e-01 + 0.00329533 * 1j,
        8.43771693e-05 - 0.1233845 * 1j,
    ])

    np.testing.assert_allclose(wf_true, wf)
def test_against_ref_hadamard():
    p = Program(H(0))
    qam = PyQVM(n_qubits=1,
                quantum_simulator_type=ReferenceWavefunctionSimulator)
    qam.execute(p)
    np.testing.assert_allclose(HADAMARD_WF, qam.wf_simulator.wf)
示例#15
0
                           NativeQuilRequest, NativeQuilResponse, NativeQuilMetadata,
                           ConjugateByCliffordRequest, ConjugateByCliffordResponse,
                           RandomizedBenchmarkingRequest, RandomizedBenchmarkingResponse)

from pyquil.api import (QVMConnection, QPUCompiler, BenchmarkConnection,
                        get_qc, QVMCompiler)
from pyquil.api._base_connection import validate_noise_probabilities, validate_qubit_list, \
    prepare_register_list
from pyquil.api._config import PyquilConfig
from pyquil.device import ISA, NxDevice
from pyquil.gates import CNOT, H, MEASURE, PHASE, Z, RZ, RX, CZ
from pyquil.paulis import PauliTerm
from pyquil.quil import Program
from pyquil.quilbase import Pragma, Declare

EMPTY_PROGRAM = Program()
BELL_STATE = Program(H(0), CNOT(0, 1))
BELL_STATE_MEASURE = Program(H(0), CNOT(0, 1), MEASURE(0, 0), MEASURE(1, 1))
COMPILED_BELL_STATE = Program([
    Declare("ro", "BIT", 2),
    Pragma("EXPECTED_REWIRING", ('"#(0 1)"',)),
    RZ(pi / 2, 0),
    RX(pi / 2, 0),
    RZ(-pi / 2, 1),
    RX(pi / 2, 1),
    CZ(1, 0),
    RZ(-pi / 2, 0),
    RX(-pi / 2, 1),
    RZ(pi / 2, 1),
    Pragma("CURRENT_REWIRING", ('"#(0 1)"',)),
    Pragma("EXPECTED_REWIRING", ('"#(0 1)"',)),
示例#16
0
"""Random bit generator circuit in PyQuil 2.1.1."""

# imports
from pyquil.quil import Program
import pyquil.gates as gates
from pyquil import api

# get a program and classical memory register
qprog = Program()
creg = qprog.declare(name="ro", memory_size=1)

# REQUIRES: api key, qvm running in background ("qvm -S" in a linux terminal
# after it is installed. See Rigetti website for download instructions
# https://www.rigetti.com/forest)
qvm = api.QVMConnection()

# add instructions to the program
qprog += [gates.H(0), gates.MEASURE(0, creg[0])]

print(qprog)
print(qvm.run(qprog, trials=1))
示例#17
0
def test_sync_expectation(qvm):
    result = qvm.expectation(BELL_STATE, [Program(Z(0)), Program(Z(1)), Program(Z(0), Z(1))])
    exp_expected = [0.0, 0.0, 1.0]
    np.testing.assert_allclose(exp_expected, result)
示例#18
0
from pyquil.quil import Program
import pyquil.api as api
from pyquil.gates import *
qvm = api.QVMConnection()
p = Program()
p.inst(H(0), CNOT(0, 1), MEASURE(1, [1]))
wavefunction = qvm.wavefunction(p)
print(wavefunction)
示例#19
0
def test_len_zero():
    prog = Program()
    assert len(prog) == 0
示例#20
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))
    assert 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))
    assert 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)])
    assert 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)])
    assert 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)])
    assert 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)])
    assert 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)])
    assert 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)])
    assert prog == result_prog
示例#21
0
def test_len_nested():
    p = Program(H(0)).measure(0, 0)
    q = Program(H(0), CNOT(0, 1))
    p.if_then(0, q)
    assert len(p) == 8
示例#22
0
def test_exponentiate_commuting_pauli_sum():
    pauli_sum = PauliSum([PauliTerm('Z', 0, 0.5), PauliTerm('Z', 1, 0.5)])
    prog = Program().inst(RZ(1.)(0)).inst(RZ(1.)(1))
    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
    assert prog == result_prog
示例#23
0
def test_program_tuple():
    p = Program()
    p.inst(("Y", 0), ("X", 1))
    assert len(p) == 2
    assert p.out() == "Y 0\nX 1\n"
示例#24
0
def test_exponentiate_prog():
    ham = PauliTerm("Z", 0)
    result_prog = Program(RZ(2.0, 0))
    prog = exponentiate(ham)
    assert prog == result_prog
示例#25
0
def test_classical_regs():
    p = Program()
    p.inst(X(0)).measure(0, 1)
    assert p.out() == 'X 0\nMEASURE 0 [1]\n'
示例#26
0
from pyquil.quil import Program
from pyquil.gates import H
from pyquil.paulis import sI, sX, sZ, exponentiate_commuting_pauli_sum
from pyquil.api import QVMConnection

# Create a 4-node array graph: 0-1-2-3.
graph = [(0, 1), (1, 2), (2, 3)]
# Nodes [0, 1, 2, 3].
nodes = range(4)

# Create the initial state program, a sum over all bitstrings, via Hadamards on all qubits.
init_state_prog = Program([H(i) for i in nodes])

# The cost Hamiltonian is sum of the application of 0.5 * (1 - \sigma_z^i * \sigma_z^j) for all
# qubit pairs (i, j).
h_cost = -0.5 * sum(sI(nodes[0]) - sZ(i) * sZ(j) for i, j in graph)

# The driver Hamiltonian is the sum of the application of \sigma_x^i for all qubits i.
h_driver = -1. * sum(sX(i) for i in nodes)


def qaoa_ansatz(gammas, betas):
    """
    Function that returns a QAOA ansatz program for a list of angles betas and gammas. len(betas) ==
    len(gammas) == P for a QAOA program of order P.
    :param list(float) gammas: Angles over which to parameterize the cost Hamiltonian.
    :param list(float) betas: Angles over which to parameterize the driver Hamiltonian.
    :return: The QAOA ansatz program.
    :rtype: Program.
    """
    return Program([exponentiate_commuting_pauli_sum(h_cost)(g) + exponentiate_commuting_pauli_sum(h_driver)(b) \
示例#27
0
def test_unary_classicals():
    p = Program()
    p.inst(TRUE(0), FALSE(Addr(1)), NOT(2))
    assert p.out() == 'TRUE [0]\n' \
                      'FALSE [1]\n' \
                      'NOT [2]\n'
示例#28
0
def test_noise_helpers():
    gates = RX(np.pi / 2, 0), RX(-np.pi / 2, 1), I(1), CZ(0, 1)
    prog = Program(*gates)
    inferred_gates = _get_program_gates(prog)
    assert set(inferred_gates) == set(gates)
示例#29
0
def test_singles():
    p = Program(I(0), X(0), Y(1), Z(1), H(2), T(2), S(1))
    assert p.out() == 'I 0\nX 0\nY 1\nZ 1\nH 2\nT 2\nS 1\n'
示例#30
0
def test_prog_merge():
    prog_0 = Program(X(0))
    prog_1 = Program(Y(0))
    assert merge_programs([prog_0, prog_1]).out() == (prog_0 + prog_1).out()