示例#1
0
  def test_locations_empty_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(ValueError, r'locations must not be empty'):
      transform.focus_local_group(circ, [])
示例#2
0
  def test_operations_not_aligned_error(self):
    circ = circuit.Circuit(4, [
        _random_operation(0),
        _random_operation(1),
        _random_operation(1),
        _random_operation(1, 3),
        _random_operation(1),
        _random_operation(2)
    ])

    with self.assertRaises(transform.OperationsNotAlignedError):
      transform.focus_local_group(circ, [1, 2, 4])
示例#3
0
  def test_location_type_error(self):
    circ = circuit.Circuit(5, [
        _random_operation(0),
        _random_operation(0, 1),
        _random_operation(1),
        _random_operation(1, 2)
    ])

    with self.assertRaisesRegex(
        TypeError,
        r'location is not integer-like \(found type: float\)'):
      transform.focus_local_group(circ, [2, 47.11])
    def test_nonlocal_operations_error(self):
        circ = circuit.Circuit(3, [
            _random_operation(0),
            _random_operation(1),
            _random_operation(1),
            _random_operation(1, 2),
            _random_operation(2)
        ])

        with self.assertRaisesRegex(ValueError,
                                    r'focus contains non-local operations'):
            transform.focus_local_group(circ, [1, 2, 3])
    def test_duplicate_locations_error(self):
        circ = circuit.Circuit(3, [
            _random_operation(0),
            _random_operation(0, 1),
            _random_operation(1),
            _random_operation(1),
            _random_operation(2)
        ])

        with self.assertRaisesRegex(ValueError,
                                    r'locations contains duplicate elements'):
            transform.focus_local_group(circ, [2, 2, 3])
示例#6
0
  def test_not_the_same_qubit_error(self):
    circ = circuit.Circuit(3, [
        _random_operation(0),
        _random_operation(1),
        _random_operation(2),
        _random_operation(1),
        _random_operation(2)
    ])

    with self.assertRaisesRegex(
        ValueError,
        r'operations in the focus act on different qubits'):
      transform.focus_local_group(circ, [1, 2, 3])
示例#7
0
  def test_location_out_of_bounds_error(self, locations, illegal_location):
    circ = circuit.Circuit(3, [
        _random_operation(0),
        _random_operation(1),
        _random_operation(1),
        _random_operation(1),
        _random_operation(2)
    ])

    with self.assertRaisesRegex(
        IndexError,
        r'location %d out of bounds for a Circuit of length 5'
        %illegal_location):
      transform.focus_local_group(circ, locations)
示例#8
0
  def test_successful(self, locations):
    # preparation work: create the operations and the circuit
    operation0 = _random_operation(1)
    operation1 = _random_operation(0, 1)
    operation2 = _random_operation(1)
    operation3 = _random_operation(1)
    operation4 = _random_operation(2, 3)
    operation5 = _random_operation(1)
    operation6 = _random_operation(0)
    operation7 = _random_operation(0, 1)

    circ = circuit.Circuit(4, [
        operation0,
        operation1,
        operation2,
        operation3,
        operation4,
        operation5,
        operation6,
        operation7
    ])

    # call the function to be tested
    attention_circ = transform.focus_local_group(circ, locations)

    # check type of attention_circ
    self.assertIs(type(attention_circ), transform.AttentionCircuit)

    # check the focus of attention_circ
    self.assertLen(attention_circ, 3)
    self.assertTrue(_elementwise_is(
        attention_circ.focus(),
        [operation2, operation3, operation5]
    ))

    # check the context of attention_circ
    context = attention_circ.context()
    self.assertTrue(_elementwise_is(
        context.before().get_operation_sequence(),
        [operation0, operation1]
    ))
    self.assertTrue(_elementwise_is(
        context.between().get_operation_sequence(),
        [operation4]
    ))
    self.assertTrue(_elementwise_is(
        context.after().get_operation_sequence(),
        [operation6, operation7]
    ))

    # check the locations of attention_circ
    self.assertTupleEqual(attention_circ.locations(), (2, 3, 5))
示例#9
0
 def test_circ_type_error(self):
   with self.assertRaisesRegex(
       TypeError,
       r'circ is not a Circuit \(found type: range\)'):
     transform.focus_local_group(range(10), [3, 4])
示例#10
0
def scan_for_local_groups(circ):
    """Iterates over all attention circuits with an aligned group of local operations in the focus.

  For each maximal group of local (i.e. single-qubit) operations in the
  circuit which act on the same qubit and are not separated by other
  operations, there will be one AttentionCircuit with only these operations in
  the focus. The exact criterion for whether the operations are considered to
  be not separated by other operations is whether between the first and the
  last operation in the group, there is no other (multi-qubit) operation
  which acts on the same qubit. Maximal means that there are no more local
  operations on this qubit which could be attached (either before the first
  or after the last operation in the group).

  Example: the operations B, E and F (marked with a star) in the following
  circuit form such a local group.

      operation A on qubits [0, 1]
      operation B on qubits [2]      (*)
      operation C on qubits [0]
      operation D on qubits [1, 3]
      operation E on qubits [2]      (*)
      operation F on qubits [2]      (*)
      operation G on qubits [2, 3]
      operation H on qubits [2]

  Operations C and D are no problem because the do not affect qubit 2 (the
  qubit which all operations in the group act on). Also, all operations before
  operation B or after operation F, i.e. the first/last operation in the
  group, are no problem anyway.

  The group in this example is maximal. Note that operation H cannot be
  attached because operation G affects qubit 2 (the qubit which all operations
  in the group act on). An example for a non-maximal group is if operation F
  was missing.

  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 an aligned group of local 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__)

    # for each qubit, allocate a list to store the local operations on it
    candidates = [[] for _ in range(circ.get_num_qubits())]

    for location, operation in enumerate(circ):
        if operation.get_num_qubits() == 1:
            # a local operation was found; we put it into candidates[qubit]
            qubit, = operation.get_qubits()
            candidates[qubit].append(location)
        else:
            # a non-local operation was found
            # this terminates the local groups on all affected qubits
            for qubit in operation.get_qubits():
                candidate = candidates[qubit]
                if candidate:
                    yield transform.focus_local_group(circ, candidate)
                    candidate.clear()

    # we have now gone through the full circuit
    # the qubits for which the last operation has been local have unterminated
    # candidates; we take care of them in the following
    for candidate in candidates:
        if candidate:
            yield transform.focus_local_group(circ, candidate)