Exemplo n.º 1
0
  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_export_large_matrix_gate_error(self):
        matrix_gate = circuit.MatrixGate(stats.unitary_group.rvs(8))

        with self.assertRaisesRegex(
                ValueError,
                r'MatrixGate for 3 qubits not supported \(Cirq has matrix gates only up'
                r' to 2 qubits\)'):
            cirq_converter.export_to_cirq(matrix_gate)
Exemplo n.º 3
0
class InvertCnot(PointTransformationRule):
  """Invert the direction of a CNOT, creating additional Hadamard gates."""

  hadamard = circuit.MatrixGate(np.sqrt(0.5) * np.array([
      [1.0, 1.0],
      [1.0, -1.0]
  ]))
  cnot = circuit.MatrixGate(np.array([
      [1.0, 0.0, 0.0, 0.0],
      [0.0, 1.0, 0.0, 0.0],
      [0.0, 0.0, 0.0, 1.0],
      [0.0, 0.0, 1.0, 0.0]
  ]))
  inverted_cnot = cnot.permute_qubits([1, 0])

  def __init__(self, architecture):
    self.architecture = architecture

  def accept(self, operation):
    # implements abstract method from parent class PointTransformationRule

    gate = operation.get_gate()
    return gate == self.cnot or gate == self.inverted_cnot

  def perform(self, operation):
    # implements abstract method from parent class PointTransformationRule

    if not self.accept(operation):
      raise RuleNotApplicableError

    hadamard_pauli_transform = self.hadamard.get_pauli_transform()

    hadamard_on_both = itertools.product(
        operation.get_qubits(),
        self.architecture.decompose_single_qubit_gate(hadamard_pauli_transform)
    )
    hadamard_on_both = [
        circuit.Operation(gate, [qubit])
        for qubit, gate in hadamard_on_both
    ]

    inverted = operation.permute_qubits([1, 0])

    return hadamard_on_both + [inverted] + hadamard_on_both
Exemplo n.º 4
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__)
Exemplo n.º 5
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)
Exemplo n.º 6
0
def _random_operation(*qubits):
  return circuit.Operation(
      circuit.MatrixGate(stats.unitary_group.rvs(2 ** len(qubits))),
      qubits
  )