コード例 #1
0
  def test_location_second_type_error(self):
    circ = circuit.Circuit(3, [
        _random_operation(0),
        _random_operation(0, 1),
        _random_operation(1),
        _random_operation(1, 2),
        _random_operation(2)
    ])

    with self.assertRaisesRegex(
        TypeError,
        r'location_second is not integer-like \(found type: float\)'):
      transform.focus_operation_pair(circ, 3, 47.11)
コード例 #2
0
  def test_locations_not_sorted_error(self, location_first, location_second):
    circ = circuit.Circuit(3, [
        _random_operation(0),
        _random_operation(0, 1),
        _random_operation(1),
        _random_operation(1, 2),
        _random_operation(2),
    ])

    with self.assertRaisesRegex(
        ValueError,
        r'location_first not smaller than location_second:'
        r' 4 \(or -1\) vs 3 \(or -2\)'):
      transform.focus_operation_pair(circ, location_first, location_second)
コード例 #3
0
  def test_location_second_out_of_bounds_error(self, location_second):
    circ = circuit.Circuit(3, [
        _random_operation(0),
        _random_operation(0, 1),
        _random_operation(1),
        _random_operation(1, 2),
        _random_operation(2),
    ])

    with self.assertRaisesRegex(
        IndexError,
        r'location_second %d out of bounds for a Circuit of length 5'
        %location_second):
      transform.focus_operation_pair(circ, 3, location_second)
コード例 #4
0
    def test_positive(self, circ, att_circ_expected):
        assert len(att_circ_expected) == 2
        location_first, location_second = att_circ_expected.locations()

        # call the function to be tested
        att_circ = transform.focus_operation_pair(circ, location_first,
                                                  location_second)

        # check the type for att_circ
        self.assertIsInstance(att_circ, transform.AttentionCircuit)

        # check the focus for att_circ
        self.assertLen(att_circ, 2)
        self.assertTrue(
            _elementwise_is(att_circ.focus(), att_circ_expected.focus()))

        # check the locations for att_circ
        self.assertTupleEqual(att_circ.locations(),
                              (location_first, location_second))

        # check the context for att_circ
        self.assertTrue(
            _elementwise_is(
                att_circ.context().before().get_operation_sequence(),
                att_circ_expected.context().before().get_operation_sequence()))
        self.assertTrue(
            _elementwise_is(
                att_circ.context().between().get_operation_sequence(),
                att_circ_expected.context().between().get_operation_sequence())
        )
        self.assertTrue(
            _elementwise_is(
                att_circ.context().after().get_operation_sequence(),
                att_circ_expected.context().after().get_operation_sequence()))
コード例 #5
0
 def test_circ_type_error(self):
   with self.assertRaisesRegex(
       TypeError,
       r'circ is not a Circuit \(found type: range\)'):
     transform.focus_operation_pair(range(10), 3, 5)
コード例 #6
0
 def test_negative(self, circ, location_first, location_second):
   with self.assertRaises(transform.OperationsNotAlignedError):
     transform.focus_operation_pair(circ, location_first, location_second)
コード例 #7
0
def scan_for_operation_pairs(circ):
    """Iterates over all attention circuits with two aligned operations in the focus.

  For each pair of operations in the circuit which are not separated by other
  operations, there will be one AttentionCircuit with only these two operations
  in the focus. The exact criterion for whether the operations are considered
  to be not separated by other operations is whether it is possible, by only
  exchanging trivially commuting operations, to transform the circuit such that
  there is no operation between them.

  Example: the two operations B and D (marked with a star) in the following
  circuit form such a pair.

      operation A on qubits [0, 1]
      operation B on qubits [1, 3]   (*)
      operation C on qubits [0]
      operation D on qubits [3, 4]   (*)
      operation E on qubits [1, 3]

  Operation C is no problem because it does not act on any qubit affected by B
  and D. Also, all operations before B or after D are no problem anyways.

  Note that "no operation in between acts on one of the qubits affected by one
  of the operations in the pair" is only a sufficient, but not a necessary
  criterion. For example, operations A' and C' in

      operation A' on qubits [1, 3]   (*)
      operation B' on qubits [1]
      operation C' on qubits [3, 4]   (*)

  still form a pair even though operation B' acts on qubit 1 which is affected
  by operation A'. The reason is that operation B' and C' commute trivially, so
  we can arrive at the circuit (A', C', B') for which the pair relation for
  operations A' and C' is obvious.

  This function always takes into account the minimal requirement to form a
  pair.

  This function is lazy, i.e. items are not computed before they are actually
  requested.

  Args:
      circ: the circuit to be scanned.

  Yields:
      all attention circuits with two aligned operations in the focus.

  Raises:
      TypeError: if circ is not a Circuit.
  """
    if not isinstance(circ, circuit.Circuit):
        raise TypeError('circ is not a Circuit (found type: %s)' %
                        type(circ).__name__)

    last_operation_on_qubit = np.full(circ.get_num_qubits(), -1)

    for curr_location, curr_operation in enumerate(circ):
        qubits = np.array(curr_operation.get_qubits())

        # look up the locations for the latest operations (so far) on all qubits
        # affected by curr_operation
        prev_locations = np.unique(last_operation_on_qubit[qubits])
        assert np.all(np.isin(prev_locations, range(-1, curr_location)))
        prev_locations = prev_locations[prev_locations >= 0]

        for prev_location in prev_locations:
            # we have a candidate
            # now, there is no better way than "trial and error"
            try:
                yield transform.focus_operation_pair(circ, prev_location,
                                                     curr_location)
            except transform.OperationsNotAlignedError:
                continue

        # update last_operation_on_qubit to curr_location for all qubits affected
        # by curr_operation
        last_operation_on_qubit[qubits] = curr_location