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()
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}
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