Example #1
0
  def test_circuit(self):
    # construct the original circuit
    circ_orig = circuit.Circuit(2, [
        circuit.Operation(circuit.PhasedXGate(0.47, 0.11), [0]),
        circuit.Operation(circuit.ControlledZGate(), [0, 1]),
        circuit.Operation(circuit.RotZGate(0.42), [1]),
    ])

    # export the circuit to Cirq
    circ_exported = cirq_converter.export_to_cirq(circ_orig)

    # check the type of circ_exported
    self.assertIsInstance(circ_exported, cirq.Circuit)

    # TODO(tfoesel):
    # a direct comparison between circ_orig and circ_exported would be better

    # reimport the circuit from Cirq
    circ_reimported = cirq_converter.import_from_cirq(circ_exported)

    # check that the number of operations and the gate types are conserved
    self.assertEqual(len(circ_orig), len(circ_reimported))
    self.assertEqual(
        [type(operation.get_gate()) for operation in circ_orig],
        [type(operation.get_gate()) for operation in circ_orig]
    )
Example #2
0
def main(argv):
  if len(argv) > 1:
    raise app.UsageError('Too many command-line arguments.')

  rule = rules.ExchangeCommutingOperations()
  circ = circuit.Circuit(7, [
      circuit.Operation(circuit.ControlledZGate(), [0, 1]),
      circuit.Operation(circuit.RotZGate(0.42), [0]),
      circuit.Operation(circuit.ControlledZGate(), [1, 2]),
      circuit.Operation(circuit.PhasedXGate(0.815, 0.4711), [1]),
      circuit.Operation(circuit.ControlledZGate(), [0, 1]),
      circuit.Operation(circuit.ControlledZGate(), [1, 2])
  ])

  transformations = tuple(rule.scan(circ))

  # Show 4 transformations.
  print(transformations)
Example #3
0
def import_from_cirq(obj):
    """Imports a gate, operation or circuit from Cirq.

  Args:
      obj: the Cirq object to be imported.

  Returns:
      the imported object (an instance of circuit.Circuit, circuit.Operation, or
      a subclass of circuit.Gate).

  Raises:
      TypeError: if import is not supported for the given type.
      ValueError: if the object cannot be imported successfully.
  """

    if isinstance(obj, cirq.PhasedXPowGate):
        return circuit.PhasedXGate(obj.exponent * np.pi,
                                   obj.phase_exponent * np.pi)
    elif isinstance(obj, cirq.ZPowGate):
        return circuit.RotZGate(obj.exponent * np.pi)
    elif isinstance(obj, cirq.CZPowGate):
        if not np.isclose(np.mod(obj.exponent, 2.0), 1.0):
            raise ValueError('partial ControlledZ gates are not supported')
        return circuit.ControlledZGate()
    elif isinstance(obj,
                    (cirq.SingleQubitMatrixGate, cirq.TwoQubitMatrixGate)):
        return circuit.MatrixGate(cirq.unitary(obj))
    elif isinstance(obj, cirq.GateOperation):
        return circuit.Operation(import_from_cirq(obj.gate),
                                 [qubit.x for qubit in obj.qubits])
    elif isinstance(obj, cirq.Circuit):
        qubits = obj.all_qubits()
        if not all(isinstance(qubit, cirq.LineQubit) for qubit in qubits):
            qubit_types = set(type(qubit) for qubit in qubits)
            qubit_types = sorted(qubit_type.__name__
                                 for qubit_type in qubit_types)
            raise ValueError(
                'import is supported for circuits on LineQubits only'
                ' [found qubit type(s): %s]' % ', '.join(qubit_types))
        return circuit.Circuit(
            max(qubit.x for qubit in qubits) + 1, [
                import_from_cirq(operation)
                for operation in itertools.chain.from_iterable(obj)
            ])
    else:
        raise TypeError('unknown type: %s' % type(obj).__name__)
Example #4
0
class TestExportAndImport(parameterized.TestCase):

  @parameterized.parameters([
      circuit.PhasedXGate(0.47, 0.11),
      circuit.RotZGate(0.42),
      circuit.ControlledZGate(),
      circuit.MatrixGate(stats.unitary_group.rvs(2)),  # random 1-qubit unitary
      circuit.MatrixGate(stats.unitary_group.rvs(4)),  # random 2-qubit unitary
      circuit.MatrixGate(stats.unitary_group.rvs(8)),  # random 3-qubit unitary
      circuit.MatrixGate(stats.unitary_group.rvs(16))  # random 4-qubit unitary
  ])
  def test_gates(self, gate_orig):
    # export the gate to Cirq
    gate_exported = cirq_converter.export_to_cirq(gate_orig)

    # check that the gates are equivalent
    self.assertIsInstance(gate_exported, cirq.Gate)
    np.testing.assert_allclose(
        gate_orig.get_pauli_transform(),
        circuit.compute_pauli_transform(cirq.unitary(gate_exported)),
        rtol=1e-5, atol=1e-8
    )

    # reimport the gate from Cirq
    gate_reimported = cirq_converter.import_from_cirq(gate_exported)

    # check that the original and the reimported gate are equivalent
    self.assertIs(type(gate_reimported), type(gate_orig))
    self.assertEqual(
        gate_reimported.get_num_qubits(),
        gate_orig.get_num_qubits()
    )
    np.testing.assert_allclose(
        gate_orig.get_operator(),
        gate_reimported.get_operator(),
        rtol=1e-5, atol=1e-8
    )

  @parameterized.parameters([1, 2])
  def test_operations(self, num_qubits):
    # construct the original operation
    op_orig = circuit.Operation(
        circuit.MatrixGate(stats.unitary_group.rvs(2 ** num_qubits)),
        np.random.permutation(10)[:num_qubits]
    )

    # export the operation to Cirq
    op_exported = cirq_converter.export_to_cirq(op_orig)

    # check that the operations are equivalent
    self.assertIsInstance(op_exported, cirq.GateOperation)
    np.testing.assert_allclose(
        op_orig.get_gate().get_operator(),
        cirq.unitary(op_exported.gate),
        rtol=1e-5, atol=1e-8
    )
    self.assertTupleEqual(
        op_orig.get_qubits(),
        tuple(qubit.x for qubit in op_exported.qubits)
    )

    # reimport the operation from Cirq
    op_reimported = cirq_converter.import_from_cirq(op_exported)

    # check that the original and the reimported operation are equivalent
    self.assertIs(type(op_reimported), circuit.Operation)
    self.assertEqual(op_reimported.get_num_qubits(), op_orig.get_num_qubits())
    np.testing.assert_allclose(
        op_orig.get_gate().get_operator(),
        op_reimported.get_gate().get_operator()
    )
    self.assertTupleEqual(op_orig.get_qubits(), op_reimported.get_qubits())

  def test_circuit(self):
    # construct the original circuit
    circ_orig = circuit.Circuit(2, [
        circuit.Operation(circuit.PhasedXGate(0.47, 0.11), [0]),
        circuit.Operation(circuit.ControlledZGate(), [0, 1]),
        circuit.Operation(circuit.RotZGate(0.42), [1]),
    ])

    # export the circuit to Cirq
    circ_exported = cirq_converter.export_to_cirq(circ_orig)

    # check the type of circ_exported
    self.assertIsInstance(circ_exported, cirq.Circuit)

    # TODO(tfoesel):
    # a direct comparison between circ_orig and circ_exported would be better

    # reimport the circuit from Cirq
    circ_reimported = cirq_converter.import_from_cirq(circ_exported)

    # check that the number of operations and the gate types are conserved
    self.assertEqual(len(circ_orig), len(circ_reimported))
    self.assertEqual(
        [type(operation.get_gate()) for operation in circ_orig],
        [type(operation.get_gate()) for operation in circ_orig]
    )

  def test_export_unknown_type_error(self):
    with self.assertRaisesRegex(TypeError, r'unknown type: range'):
      cirq_converter.export_to_cirq(range(42))

  def test_import_unknown_type_error(self):
    with self.assertRaisesRegex(TypeError, r'unknown type: range'):
      cirq_converter.import_from_cirq(range(42))

  def test_import_partial_cz_error(self):
    partial_cz = cirq.CZPowGate(exponent=0.37)

    with self.assertRaisesRegex(
        ValueError,
        r'partial ControlledZ gates are not supported'):
      cirq_converter.import_from_cirq(partial_cz)

  def test_import_non_line_qubits_error(self):
    qubit_a = cirq.GridQubit(0, 1)
    qubit_b = cirq.GridQubit(0, 2)

    circ = cirq.Circuit(
        cirq.PhasedXPowGate(exponent=0.47, phase_exponent=0.11).on(qubit_a),
        cirq.CZPowGate(exponent=1.0).on(qubit_a, qubit_b),
        cirq.ZPowGate(exponent=0.42).on(qubit_b)
    )

    with self.assertRaisesRegex(
        ValueError,
        r'import is supported for circuits on LineQubits only \[found qubit'
        r' type\(s\): GridQubit\]'):
      cirq_converter.import_from_cirq(circ)
Example #5
0
def parse_gates(gates, *gate_types):
    """Parses gates into expected gate types."""

    if len(gates) != len(gate_types):
        raise ValueError(
            'inconsistent length of gates and gate_types (%d vs %d)' %
            (len(gates), len(gate_types)))

    parsed_gates = []

    for gate_in, gate_type in zip(gates, gate_types):
        if not isinstance(gate_in, circuit.Gate):
            raise TypeError('%s is not a Gate' % type(gate_in).__name__)
        if not isinstance(gate_type, type):
            raise TypeError('%s instance is not a type' %
                            type(gate_type).__name__)
        if not issubclass(gate_type, circuit.Gate):
            raise TypeError('%s is not a Gate type' % gate_type.__name__)

        if gate_type == circuit.PhasedXGate:
            if gate_in.get_num_qubits() != 1:
                return None
            elif isinstance(gate_in, circuit.PhasedXGate):
                gate_out = gate_in
            elif isinstance(gate_in, circuit.RotZGate):
                if gate_in.is_identity(phase_invariant=True):
                    gate_out = circuit.PhasedXGate(0.0, 0.0)
                else:
                    return None
            else:
                pauli_transform = gate_in.get_pauli_transform()
                if np.isclose(pauli_transform[2, 2], -1.0):
                    gate_out = circuit.PhasedXGate(
                        np.pi, 0.5 * np.arctan2(pauli_transform[0, 1],
                                                pauli_transform[0, 0]))
                else:
                    rotation = scipy.spatial.transform.Rotation.from_dcm(
                        pauli_transform)
                    alpha, beta, gamma = rotation.as_euler('zxz')
                    if np.isclose(alpha, -gamma):
                        gate_out = circuit.PhasedXGate(beta, -alpha)
                    else:
                        return None
        elif gate_type == circuit.RotZGate:
            if gate_in.get_num_qubits() != 1:
                return None
            elif isinstance(gate_in, circuit.RotZGate):
                gate_out = gate_in
            elif isinstance(gate_in, circuit.PhasedXGate):
                if gate_in.is_identity(phase_invariant=True):
                    gate_out = circuit.RotZGate(0.0)
                else:
                    return None
            else:
                pauli_transform = gate_in.get_pauli_transform()
                if np.isclose(pauli_transform[2, 2], 1.0):
                    gate_out = circuit.RotZGate(
                        np.arctan2(pauli_transform[1, 0], pauli_transform[0,
                                                                          0]))
                else:
                    return None
        elif gate_type == circuit.ControlledZGate:
            if gate_in.get_num_qubits() != 2:
                return None
            elif isinstance(gate_in, circuit.ControlledZGate):
                gate_out = gate_in
            elif gate_in == circuit.ControlledZGate():
                gate_out = circuit.ControlledZGate()
            else:
                return None
        else:
            raise ValueError('unknown Gate type: %s' % gate_type.__name__)

        assert isinstance(gate_out, gate_type)

        parsed_gates.append(gate_out)

    assert len(parsed_gates) == len(gates)

    return parsed_gates