Esempio n. 1
0
def test_memory_commands():
    parse_equals(
        "DECLARE mem OCTET[32] SHARING mem2 OFFSET 16 REAL OFFSET 32 REAL",
        Declare("mem",
                "OCTET",
                32,
                shared_region="mem2",
                offsets=[(16, "REAL"), (32, "REAL")]),
    )
    parse_equals(
        "STORE mem ro[2] ro[0]",
        STORE("mem", MemoryReference("ro", 2), MemoryReference("ro", 0)))
    parse_equals("STORE mem ro[2] 7", STORE("mem", MemoryReference("ro", 2),
                                            7))
    parse_equals(
        "LOAD ro[8] mem mem[4]",
        LOAD(MemoryReference("ro", 8), "mem", MemoryReference("mem", 4)))
    parse_equals("CONVERT ro[1] ro[2]",
                 CONVERT(MemoryReference("ro", 1), MemoryReference("ro", 2)))
    parse_equals("EXCHANGE ro[0] ro[1]",
                 EXCHANGE(MemoryReference("ro", 0), MemoryReference("ro", 1)))
    parse_equals("MOVE mem[2] 4", MOVE(MemoryReference("mem", 2), 4))
    parse_equals("MOVE mem[2] -4", MOVE(MemoryReference("mem", 2), -4))
    parse_equals("MOVE mem[2] -4.1", MOVE(MemoryReference("mem", 2), -4.1))
Esempio n. 2
0
def _prepend_real_declarations(
        *, program: Program,
        resolvers: Sequence[cirq.ParamResolverOrSimilarType]) -> Program:
    """Adds memory declarations for all variables in each of the `resolver`'s
    param dict. Note, this function assumes that the first parameter resolver
    will contain all variables subsequently referenced in `resolvers`.

    Args:
        program: The program that the quantum computer will execute.
        resolvers: A sequence of parameters resolvers that provide values
            for parameter references in the original `cirq.Circuit`.
    Returns:
        A program that includes the QUIL memory declarations as described above.
    """
    if len(resolvers) > 0:
        resolver = resolvers[0]
        param_dict = _get_param_dict(resolver)
        for key in param_dict.keys():
            declaration = Declare(str(key), "REAL")
            program._instructions.insert(0, declaration)
            program._synthesized_instructions = None
            program.declarations[declaration.name] = declaration
            logger.debug(f"prepended declaration {declaration}")
    return program
Esempio n. 3
0
def test_get_qvm_with_topology_2(client_configuration: QCSClientConfiguration):
    topo = nx.from_edgelist([(5, 6), (6, 7)])
    qc = _get_qvm_with_topology(
        name="test-qvm",
        topology=topo,
        noisy=False,
        qvm_type="qvm",
        compiler_timeout=5.0,
        execution_timeout=5.0,
        client_configuration=client_configuration,
    )
    results = qc.run(
        qc.compile(
            Program(
                Declare("ro", "BIT", 3),
                X(5),
                MEASURE(5, ("ro", 0)),
                MEASURE(6, ("ro", 1)),
                MEASURE(7, ("ro", 2)),
            ).wrap_in_numshots_loop(5)
        )
    )
    assert results.shape == (5, 3)
    assert all(r[0] == 1 for r in results)
Esempio n. 4
0
def rewrite_arithmetic(prog: Program) -> RewriteArithmeticResponse:
    """Rewrite compound arithmetic expressions.

    The basic motivation is that a parametric program may have gates with
    compound arguments which cannot be evaluated natively on the underlying
    control hardware. The solution provided here is to translate a program like

      DECLARE theta REAL
      DECLARE beta REAL
      RZ(3 * theta) 0
      RZ(beta+theta) 0

    into something like

      DECLARE theta REAL
      DECLARE beta REAL
      DECLARE __P REAL[2]
      RZ(__P[0]) 0
      RZ(__P[1]) 0

    along with a "recalculation table" mapping new memory references to their
    corresponding arithmetic expressions,

      {
        ParameterAref('__P', 0): "((3.0)*theta[0])",
        ParameterAref('__P', 1): "(beta[0]+theta[0])"
      }

    When executing the parametric program with specific values for `theta` and
    `beta`, the PyQuil client will patch in values for `__P` by evaluating the
    expressions in the recalculation table.

    :param prog: A program.
    :returns: A RewriteArithmeticResponse, containing the updated program along
      with its memory descriptors and a recalculation table.

    """
    def spec(inst: Declare) -> ParameterSpec:
        return ParameterSpec(type=inst.memory_type, length=inst.memory_size)

    def aref(ref: MemoryReference) -> ParameterAref:
        return ParameterAref(name=ref.name, index=ref.offset)

    updated = prog.copy_everything_except_instructions()
    old_descriptors = {
        inst.name: spec(inst)
        for inst in prog if isinstance(inst, Declare)
    }
    recalculation_table = {}
    seen_exprs = {}

    # generate a unique name. it's nice to do this in a deterministic fashion
    # rather than globbing in a UUID
    suffix = len(old_descriptors)
    while f"__P{suffix}" in old_descriptors:
        suffix += 1
    mref_name = f"__P{suffix}"
    mref_idx = 0

    for inst in prog:
        if isinstance(inst, Gate):
            new_params = []
            for param in inst.params:
                if isinstance(param, (Real, MemoryReference)):
                    new_params.append(param)
                elif isinstance(param, Expression):
                    expr = str(param)
                    if expr in seen_exprs:
                        new_params.append(seen_exprs[expr])
                    else:
                        new_mref = MemoryReference(mref_name, mref_idx)
                        seen_exprs[expr] = new_mref
                        mref_idx += 1
                        recalculation_table[aref(new_mref)] = expr
                        new_params.append(new_mref)
                else:
                    raise ValueError(
                        f"Unknown parameter type {type(param)} in {inst}.")
            updated.inst(Gate(inst.name, new_params, inst.qubits))
        else:
            updated.inst(inst)

    if mref_idx > 0:
        updated._instructions.insert(0, Declare(mref_name, "REAL", mref_idx))

    return RewriteArithmeticResponse(
        quil=updated.out(),
        original_memory_descriptors=old_descriptors,
        recalculation_table=recalculation_table,
    )
Esempio n. 5
0
def test_classical_regs():
    p = Program()
    p.inst(Declare("ro", "BIT", 2), X(0)).measure(0, MemoryReference("ro", 1))
    assert p.out() == ("DECLARE ro BIT[2]\nX 0\nMEASURE 0 ro[1]\n")
Esempio n. 6
0
    validate_noise_probabilities,
    validate_qubit_list,
    prepare_register_list,
)
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 Halt, Declare
from pyquil.quilatom import MemoryReference
from pyquil.simulation.tools import program_unitary

EMPTY_PROGRAM = Program()
BELL_STATE = Program(H(0), CNOT(0, 1))
BELL_STATE_MEASURE = Program(
    Declare("ro", "BIT", 2),
    H(0),
    CNOT(0, 1),
    MEASURE(0, MemoryReference("ro", 0)),
    MEASURE(1, MemoryReference("ro", 1)),
)
COMPILED_BELL_STATE = Program([
    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),
    Halt(),
Esempio n. 7
0
def test_classical_regs():
    p = Program()
    p.inst(Declare('ro', 'BIT', 2), X(0)).measure(0, MemoryReference("ro", 1))
    assert p.out() == ('DECLARE ro BIT[2]\n'
                       'X 0\n'
                       'MEASURE 0 ro[1]\n')
Esempio n. 8
0
def rewrite_arithmetic(prog: Program) -> RewriteArithmeticResponse:
    """Rewrite compound arithmetic expressions.

    The basic motivation is that a parametric program may have gates with
    compound arguments which cannot be evaluated natively on the underlying
    control hardware. The solution provided here is to translate a program like

      DECLARE theta REAL
      DECLARE beta REAL
      RZ(3 * theta) 0
      RZ(beta+theta) 0

    into something like

      DECLARE theta REAL
      DECLARE beta REAL
      DECLARE __P REAL[2]
      RZ(__P[0]) 0
      RZ(__P[1]) 0

    along with a "recalculation table" mapping new memory references to their
    corresponding arithmetic expressions,

      {
        ParameterAref('__P', 0): "((3.0)*theta[0])",
        ParameterAref('__P', 1): "(beta[0]+theta[0])"
      }

    When executing the parametric program with specific values for `theta` and
    `beta`, the PyQuil client will patch in values for `__P` by evaluating the
    expressions in the recalculation table.

    :param prog: A program.
    :returns: A RewriteArithmeticResponse, containing the updated program along
      with its memory descriptors and a recalculation table.

    """
    def spec(inst: Declare) -> ParameterSpec:
        return ParameterSpec(type=inst.memory_type, length=inst.memory_size)

    def aref(ref: MemoryReference) -> ParameterAref:
        return ParameterAref(name=ref.name, index=ref.offset)

    updated = prog.copy_everything_except_instructions()
    old_descriptors = {
        inst.name: spec(inst)
        for inst in prog if isinstance(inst, Declare)
    }
    recalculation_table: Dict[ParameterAref, str] = {}
    seen_exprs: Dict[str, MemoryReference] = {}

    # generate a unique name. it's nice to do this in a deterministic fashion
    # rather than globbing in a UUID
    suffix = len(old_descriptors)
    while f"__P{suffix}" in old_descriptors:
        suffix += 1
    mref_name = f"__P{suffix}"
    mref_idx = 0

    def expr_mref(expr: object) -> MemoryReference:
        """ Get a suitable MemoryReference for a given expression. """
        nonlocal mref_idx
        expr = str(expr)
        if expr in seen_exprs:
            return seen_exprs[expr]
        new_mref = MemoryReference(mref_name, mref_idx)
        seen_exprs[expr] = new_mref
        mref_idx += 1
        recalculation_table[aref(new_mref)] = expr
        return new_mref

    for inst in prog:
        if isinstance(inst, Gate):
            new_params: List[Union[Real, MemoryReference]] = []
            for param in inst.params:
                if isinstance(param, Real):
                    new_params.append(param)
                elif isinstance(param, Expression):
                    # Quil gate angles are in radians,
                    # but downstream processing expects revolutions
                    expr = str(Div(param, 2 * np.pi))
                    new_params.append(expr_mref(expr))
                else:
                    raise ValueError(
                        f"Unknown parameter type {type(param)} in {inst}.")
            updated.inst(Gate(inst.name, new_params, inst.qubits))
        elif isinstance(inst, (SetFrequency, ShiftFrequency)):
            if isinstance(inst.freq, Real):
                updated.inst(inst)
                continue
            try:
                fdefn = prog.frames[inst.frame]
            except KeyError:
                raise ValueError(
                    f"Unable to rewrite {inst} without DEFFRAME {inst.frame}.")
            if fdefn.sample_rate is None:
                raise ValueError(
                    f"Unable to rewrite {inst} on frame with undefined SAMPLE-RATE."
                )
            if fdefn.center_frequency:
                expr = Sub(inst.freq, fdefn.center_frequency)
            else:
                expr = inst.freq
            expr = Div(expr, fdefn.sample_rate)
            expr = str(expr)
            updated.inst(inst.__class__(inst.frame, expr_mref(expr)))
        elif isinstance(inst, (SetPhase, ShiftPhase)):
            if isinstance(inst.phase, Real):
                updated.inst(inst)
            else:
                # Quil phases are in radians
                # but downstream processing expects revolutions
                expr = str(Div(inst.phase, 2 * np.pi))
                updated.inst(inst.__class__(inst.frame, expr_mref(expr)))
        elif isinstance(inst, SetScale):
            if isinstance(inst.scale, Real):
                updated.inst(inst)
            else:
                # scale is in [-4,4)
                # binary patching assumes periodic with period 1
                # so we divide by 8...
                expr = str(Div(inst.scale, 8))
                updated.inst(SetScale(inst.frame, expr_mref(expr)))
        else:
            updated.inst(inst)

    if mref_idx > 0:
        updated._instructions.insert(0, Declare(mref_name, "REAL", mref_idx))

    return RewriteArithmeticResponse(
        quil=updated.out(),
        original_memory_descriptors=old_descriptors,
        recalculation_table=recalculation_table,
    )
Esempio n. 9
0
def test_get_qubit_placeholders():
    qs = QubitPlaceholder.register(8)
    pq = Program(Declare("ro", "BIT"), X(qs[0]), CNOT(qs[0], qs[4]),
                 MEASURE(qs[5], MemoryReference("ro", 0)))
    assert pq.get_qubits() == {qs[i] for i in [0, 4, 5]}
Esempio n. 10
0
def test_len_nested():
    p = Program(Declare("ro", "BIT"), H(0)).measure(0,
                                                    MemoryReference("ro", 0))
    q = Program(H(0), CNOT(0, 1))
    p.if_then(MemoryReference("ro", 0), q)
    assert len(p) == 9
# y0ka1
# July 16th, 2021

from pyquil import get_qc, Program
from pyquil.gates import *
from pyquil.api import local_forest_runtime
from pyquil.quilbase import Declare

# Defining my quantum program
quantumprog = Program(
    Declare(
        "ro", "BIT", 2
    ),  # This declares a classical register named ro with 2 bits to measure qubits with
    H(
        0
    ),  # places my first bit into a state of super position between states |0> and |1>
    CNOT(0, 1),  # This entangles the two bits into a connected super position
    X(
        1
    ),  # Because I have entangled these qubits I can apply X to their linear combo
    MEASURE(0, ("ro", 0)),
    MEASURE(1, ("ro", 1))).wrap_in_numshots_loop(10)

# Defining a second program
quantumprog2 = Program(Declare("co", "BIT", 2), H(0), CNOT(0, 1), Z(0), X(0),
                       MEASURE(0, ("co", 0)),
                       MEASURE(1, ("co", 1))).wrap_in_numshots_loop(10)

# returning my circuit parameterizations and metrics
print(
    "============================================================================"
Esempio n. 12
0
def test_unitary_measure():
    prog = Program(Declare("ro", "BIT"), H(0), H(1),
                   MEASURE(0, MemoryReference("ro", 0)))
    with pytest.raises(ValueError):
        program_unitary(prog, n_qubits=2)
Esempio n. 13
0
from rpcq.messages import BinaryExecutableRequest, BinaryExecutableResponse

from pyquil.api import QVMConnection, QPUCompiler, get_qc, QVMCompiler
from pyquil.api._base_connection import (validate_noise_probabilities,
                                         validate_qubit_list,
                                         prepare_register_list)
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 Halt, Declare
from pyquil.quilatom import MemoryReference

EMPTY_PROGRAM = Program()
BELL_STATE = Program(H(0), CNOT(0, 1))
BELL_STATE_MEASURE = Program(Declare('ro', 'BIT', 2), H(0), CNOT(0, 1),
                             MEASURE(0, MemoryReference('ro', 0)),
                             MEASURE(1, MemoryReference('ro', 1)))
COMPILED_BELL_STATE = Program([
    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),
    Halt()
])
DUMMY_ISA_DICT = {"1Q": {"0": {}, "1": {}}, "2Q": {"0-1": {}}}
DUMMY_ISA = ISA.from_dict(DUMMY_ISA_DICT)
Esempio n. 14
0
def test_get_classical_addresses_from_program():
    p = Program(Declare("ro", "BIT", 4), [H(i) for i in range(4)])
    assert get_classical_addresses_from_program(p) == {}

    p += [MEASURE(i, MemoryReference("ro", i)) for i in [0, 3, 1]]
    assert get_classical_addresses_from_program(p) == {"ro": [0, 1, 3]}
Esempio n. 15
0
# necessary pyquil modules
import pyquil
from pyquil import get_qc, Program
from pyquil.gates import *
from pyquil.api import local_forest_runtime
from pyquil.quilbase import Declare

# altair for plotting
import altair as alt

# Defining a circuit to run
quantumprog = Program(
    Declare(
        "ro", "BIT", 2
    ),  # This declares a classical register named ro with 4 bits to measure qubits with
    CNOT(0, 1),
    H(0),
    Z(0),
    H(0),  # The outcome should prove HZH=X
    X(1),
    MEASURE(0, ("ro", 0)),
    MEASURE(1, ("ro", 1)),
).wrap_in_numshots_loop(10)

# returning my circuit parameterizations and metrics
print("=====================================================\n")
print("CIRCUIT DEFINITIONS:")
print(quantumprog)
print("=====================================================\n")

# run the program on a QVM
Esempio n. 16
0
def test_no_implicit_declare():
    program = Program(Declare("read_out", "BIT", 5),
                      MEASURE(0, MemoryReference("read_out", 4)))
    assert program.out() == (
        "DECLARE read_out BIT[5]\nMEASURE 0 read_out[4]\n")
Esempio n. 17
0
                        get_qc, LocalQVMCompiler, QVMCompiler,
                        LocalBenchmarkConnection)
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 2 3)"', )),
    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 2 3)"', )),
    Pragma("EXPECTED_REWIRING", ('"#(0 1 2 3)"', )),
    Pragma("CURRENT_REWIRING", ('"#(0 1 2 3)"', )),
])
DUMMY_ISA_DICT = {"1Q": {"0": {}, "1": {}}, "2Q": {"0-1": {}}}
DUMMY_ISA = ISA.from_dict(DUMMY_ISA_DICT)
Esempio n. 18
0
def test_prog_init():
    p = Program()
    p.inst(Declare("ro", "BIT"), X(0)).measure(0, MemoryReference("ro", 0))
    assert p.out() == ("DECLARE ro BIT[1]\nX 0\nMEASURE 0 ro[0]\n")
Esempio n. 19
0
def test_prog_init():
    p = Program()
    p.inst(Declare('ro', 'BIT'), X(0)).measure(0, MemoryReference("ro", 0))
    assert p.out() == ('DECLARE ro BIT[1]\n'
                       'X 0\n'
                       'MEASURE 0 ro[0]\n')
Esempio n. 20
0
def test_get_qubits_not_as_indices():
    pq = Program(Declare("ro", "BIT"), X(0), CNOT(0, 4),
                 MEASURE(5, MemoryReference("ro", 0)))
    assert pq.get_qubits(indices=False) == {Qubit(i) for i in [0, 4, 5]}
Esempio n. 21
0
def test_qvm__default_client(client_configuration: QCSClientConfiguration):
    qvm = QVM(client_configuration=client_configuration)
    p = Program(Declare("ro", "BIT"), X(0), MEASURE(0, MemoryReference("ro")))
    result = qvm.run(p.wrap_in_numshots_loop(1000))
    bitstrings = result.readout_data.get("ro")
    assert bitstrings.shape == (1000, 1)