예제 #1
0
def test_circuit_from_quil():
    q0, q1, q2 = LineQubit.range(3)
    cirq_circuit = Circuit([
        I(q0),
        I(q1),
        I(q2),
        X(q0),
        Y(q1),
        Z(q2),
        H(q0),
        S(q1),
        T(q2),
        Z(q0)**(1 / 8),
        Z(q1)**(1 / 8),
        Z(q2)**(1 / 8),
        rx(np.pi / 2)(q0),
        ry(np.pi / 2)(q1),
        rz(np.pi / 2)(q2),
        CZ(q0, q1),
        CNOT(q1, q2),
        cphase(np.pi / 2)(q0, q1),
        cphase00(np.pi / 2)(q1, q2),
        cphase01(np.pi / 2)(q0, q1),
        cphase10(np.pi / 2)(q1, q2),
        ISWAP(q0, q1),
        pswap(np.pi / 2)(q1, q2),
        SWAP(q0, q1),
        xy(np.pi / 2)(q1, q2),
        CCNOT(q0, q1, q2),
        CSWAP(q0, q1, q2),
        MeasurementGate(1, key="ro[0]")(q0),
        MeasurementGate(1, key="ro[1]")(q1),
        MeasurementGate(1, key="ro[2]")(q2),
    ])
    # build the same Circuit, using Quil
    quil_circuit = circuit_from_quil(QUIL_PROGRAM)
    # test Circuit equivalence
    assert cirq_circuit == quil_circuit

    pyquil_circuit = Program(QUIL_PROGRAM)
    # drop declare and measures, get Program unitary
    pyquil_unitary = program_unitary(pyquil_circuit[1:-3], n_qubits=3)
    # fix qubit order convention
    cirq_circuit_swapped = Circuit(SWAP(q0, q2), cirq_circuit[:-1],
                                   SWAP(q0, q2))
    # get Circuit unitary
    cirq_unitary = cirq_circuit_swapped.unitary()
    # test unitary equivalence
    assert np.isclose(pyquil_unitary, cirq_unitary).all()
예제 #2
0
def _measure_to_proto_dict(gate: ops.MeasurementGate,
                           qubits: Sequence[ops.QubitId]):
    if len(qubits) == 0:
        raise ValueError('Measurement gate on no qubits.')

    invert_mask = None
    if gate.invert_mask:
        invert_mask = gate.invert_mask + (False,) * (
            gate.num_qubits() - len(gate.invert_mask))

    if invert_mask and len(invert_mask) != len(qubits):
        raise ValueError('Measurement gate had invert mask of length '
                         'different than number of qubits it acts on.')
    measurement = {
        'targets': [cast(devices.GridQubit, q).to_proto_dict() for q in qubits],
        'key': protocols.measurement_key(gate),
    }
    if invert_mask:
        measurement['invert_mask'] = [json.dumps(x) for x in invert_mask]
    return {'measurement': measurement}
예제 #3
0
def circuit_from_quil(quil: str) -> Circuit:
    """Convert a Quil program to a Cirq Circuit.

    Args:
        quil: The Quil program to convert.

    Returns:
        A Cirq Circuit generated from the Quil program.

    Raises:
        UnsupportedQuilInstruction: Cirq does not support the specified Quil instruction.
        UndefinedQuilGate: Cirq does not support the specified Quil gate.

    References:
        https://github.com/rigetti/pyquil
    """
    circuit = Circuit()
    defined_gates = SUPPORTED_GATES.copy()
    instructions = parse(quil)

    for inst in instructions:
        # Add DEFGATE-defined gates to defgates dict using MatrixGate.
        if isinstance(inst, DefGate):
            if inst.parameters:
                raise UnsupportedQuilInstruction(
                    "Parameterized DEFGATEs are currently unsupported.")
            defined_gates[inst.name] = MatrixGate(inst.matrix)

        # Pass when encountering a DECLARE.
        elif isinstance(inst, Declare):
            pass

        # Convert pyQuil gates to Cirq operations.
        elif isinstance(inst, PyQuilGate):
            quil_gate_name = inst.name
            quil_gate_params = inst.params
            line_qubits = list(LineQubit(q.index) for q in inst.qubits)
            if quil_gate_name not in defined_gates:
                raise UndefinedQuilGate(
                    f"Quil gate {quil_gate_name} not supported in Cirq.")
            cirq_gate_fn = defined_gates[quil_gate_name]
            if quil_gate_params:
                circuit += cirq_gate_fn(*quil_gate_params)(*line_qubits)
            else:
                circuit += cirq_gate_fn(*line_qubits)

        # Convert pyQuil MEASURE operations to Cirq MeasurementGate objects.
        elif isinstance(inst, PyQuilMeasurement):
            line_qubit = LineQubit(inst.qubit.index)
            if inst.classical_reg is None:
                raise UnsupportedQuilInstruction(
                    f"Quil measurement {inst} without classical register "
                    f"not currently supported in Cirq.")
            quil_memory_reference = inst.classical_reg.out()
            circuit += MeasurementGate(1,
                                       key=quil_memory_reference)(line_qubit)

        # Raise a targeted error when encountering a PRAGMA.
        elif isinstance(inst, Pragma):
            raise UnsupportedQuilInstruction(PRAGMA_ERROR)

        # Raise a targeted error when encountering a RESET.
        elif isinstance(inst, (Reset, ResetQubit)):
            raise UnsupportedQuilInstruction(RESET_ERROR)

        # Raise a general error when encountering an unconsidered type.
        else:
            raise UnsupportedQuilInstruction(
                f"Quil instruction {inst} of type {type(inst)} not currently supported in Cirq."
            )

    return circuit