Beispiel #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]
    )
Beispiel #2
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())
Beispiel #3
0
    def perform(self, operation_first, operation_second):
        # implements abstract method from parent class PairTransformationRule

        if not self.accept(operation_first, operation_second):
            raise RuleNotApplicableError

        parsed = parsing.parse_operations([operation_first, operation_second],
                                          circuit.PhasedXGate,
                                          circuit.ControlledZGate)
        if parsed is not None:
            phased_x, cz = parsed
        else:
            parsed = parsing.parse_operations(
                [operation_first, operation_second], circuit.ControlledZGate,
                circuit.PhasedXGate)
            if parsed is not None:
                cz, phased_x = parsed
            else:
                raise RuleNotApplicableError

        if not np.isclose(np.cos(phased_x.get_gate().get_rotation_angle()),
                          -1.0):
            raise RuleNotApplicableError

        other_qubit, = set(cz.get_qubits()).difference(phased_x.get_qubits())

        z_flip = np.diag([-1.0, -1.0, 1.0])  # the pauli_transform for a Z flip
        z_flip = [
            circuit.Operation(gate, [other_qubit])
            for gate in self.architecture.decompose_single_qubit_gate(z_flip)
        ]

        return [operation_second], z_flip + [operation_first]
Beispiel #4
0
def parse_operations(operations, *gate_types):
    """Parse operations into expected gate types."""

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

    for operation in operations:
        if not isinstance(operation, circuit.Operation):
            raise TypeError('%s is not an Operation' %
                            type(operation).__name__)

    parsed_gates = parse_gates(
        [operation.get_gate() for operation in operations], *gate_types)

    if parsed_gates is None:
        return None
    else:
        parsed_operations = []

        for operation, parsed_gate in zip(operations, parsed_gates):
            if operation.get_gate() is not parsed_gate:
                operation = circuit.Operation(parsed_gate,
                                              operation.get_qubits())
            parsed_operations.append(operation)

        return parsed_operations
Beispiel #5
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__)
Beispiel #6
0
    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
Beispiel #7
0
    def perform(self, operations):
        # implements abstract method from parent class LocalGroupTransformationRule

        if not self.accept(operations):
            raise RuleNotApplicableError

        qubits = [operation.get_qubits() for operation in operations]
        if not all(len(qu) == 1 for qu in qubits):
            raise RuntimeError()  # cmp. TODO at the beginning of this file
        qubits = set().union(*qubits)
        if len(qubits) != 1:
            raise RuntimeError()  # cmp. TODO at the beginning of this file
        qubit, = qubits

        pauli_transform = np.eye(3)
        for operation in operations:
            pauli_transform = np.dot(
                operation.get_gate().get_pauli_transform(), pauli_transform)

        gates = self.architecture.decompose_single_qubit_gate(pauli_transform)

        return [circuit.Operation(gate, [qubit]) for gate in gates]
Beispiel #8
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)
Beispiel #9
0
def _random_operation(*qubits):
  return circuit.Operation(
      circuit.MatrixGate(stats.unitary_group.rvs(2 ** len(qubits))),
      qubits
  )