nodes: 0, module; 1, function_definition; 2, function_name:findall_operations_between; 3, parameters; 4, type; 5, block; 6, identifier:self; 7, typed_parameter; 8, typed_parameter; 9, typed_default_parameter; 10, generic_type; 11, expression_statement; 12, expression_statement; 13, expression_statement; 14, comment:# Note: only sorted to ensure a deterministic result ordering.; 15, for_statement; 16, return_statement; 17, identifier:start_frontier; 18, type; 19, identifier:end_frontier; 20, type; 21, identifier:omit_crossing_operations; 22, type; 23, False; 24, identifier:List; 25, type_parameter; 26, comment:"""Finds operations between the two given frontiers.
  
          If a qubit is in `start_frontier` but not `end_frontier`, its end index
          defaults to the end of the circuit. If a qubit is in `end_frontier` but
          not `start_frontier`, its start index defaults to the start of the
          circuit. Operations on qubits not mentioned in either frontier are not
          included in the results.
  
          Args:
              start_frontier: Just before where to start searching for operations,
                  for each qubit of interest. Start frontier indices are
                  inclusive.
              end_frontier: Just before where to stop searching for operations,
                  for each qubit of interest. End frontier indices are exclusive.
              omit_crossing_operations: Determines whether or not operations that
                  cross from a location between the two frontiers to a location
                  outside the two frontiers are included or excluded. (Operations
                  completely inside are always included, and operations completely
                  outside are always excluded.)
  
          Returns:
              A list of tuples. Each tuple describes an operation found between
              the two frontiers. The first item of each tuple is the index of the
              moment containing the operation, and the second item is the
              operation itself. The list is sorted so that the moment index
              increases monotonically.
          """; 27, assignment; 28, assignment; 29, identifier:q; 30, call; 31, block; 32, call; 33, generic_type; 34, generic_type; 35, identifier:bool; 36, type; 37, identifier:result; 38, call; 39, identifier:involved_qubits; 40, binary_operator:set(start_frontier.keys()) | set(end_frontier.keys()); 41, identifier:sorted; 42, argument_list; 43, for_statement; 44, identifier:list; 45, argument_list; 46, identifier:Dict; 47, type_parameter; 48, identifier:Dict; 49, type_parameter; 50, generic_type; 51, subscript; 52, argument_list; 53, call; 54, call; 55, identifier:involved_qubits; 56, identifier:i; 57, call; 58, block; 59, identifier:result; 60, type; 61, type; 62, type; 63, type; 64, identifier:Tuple; 65, type_parameter; 66, identifier:BucketPriorityQueue; 67, attribute; 68, keyword_argument; 69, identifier:set; 70, argument_list; 71, identifier:set; 72, argument_list; 73, identifier:range; 74, argument_list; 75, expression_statement; 76, if_statement; 77, if_statement; 78, expression_statement; 79, attribute; 80, identifier:int; 81, attribute; 82, identifier:int; 83, type; 84, type; 85, identifier:ops; 86, identifier:Operation; 87, identifier:drop_duplicate_entries; 88, True; 89, call; 90, call; 91, call; 92, call; 93, assignment; 94, comparison_operator:op is None; 95, block; 96, parenthesized_expression; 97, block; 98, call; 99, identifier:ops; 100, identifier:Qid; 101, identifier:ops; 102, identifier:Qid; 103, identifier:int; 104, attribute; 105, attribute; 106, argument_list; 107, attribute; 108, argument_list; 109, attribute; 110, argument_list; 111, attribute; 112, argument_list; 113, identifier:op; 114, call; 115, identifier:op; 116, None; 117, continue_statement; 118, boolean_operator; 119, continue_statement; 120, attribute; 121, argument_list; 122, identifier:ops; 123, identifier:Operation; 124, identifier:start_frontier; 125, identifier:keys; 126, identifier:end_frontier; 127, identifier:keys; 128, identifier:start_frontier; 129, identifier:get; 130, identifier:q; 131, integer:0; 132, identifier:end_frontier; 133, identifier:get; 134, identifier:q; 135, call; 136, attribute; 137, argument_list; 138, identifier:omit_crossing_operations; 139, not_operator; 140, identifier:result; 141, identifier:enqueue; 142, identifier:i; 143, identifier:op; 144, identifier:len; 145, argument_list; 146, identifier:self; 147, identifier:operation_at; 148, identifier:q; 149, identifier:i; 150, call; 151, identifier:self; 152, attribute; 153, argument_list; 154, identifier:involved_qubits; 155, identifier:issuperset; 156, attribute; 157, identifier:op; 158, identifier:qubits
code: def findall_operations_between(self,
                                     start_frontier: Dict[ops.Qid, int],
                                     end_frontier: Dict[ops.Qid, int],
                                     omit_crossing_operations: bool = False
                                     ) -> List[Tuple[int, ops.Operation]]:
          """Finds operations between the two given frontiers.
  
          If a qubit is in `start_frontier` but not `end_frontier`, its end index
          defaults to the end of the circuit. If a qubit is in `end_frontier` but
          not `start_frontier`, its start index defaults to the start of the
          circuit. Operations on qubits not mentioned in either frontier are not
          included in the results.
  
          Args:
              start_frontier: Just before where to start searching for operations,
                  for each qubit of interest. Start frontier indices are
                  inclusive.
              end_frontier: Just before where to stop searching for operations,
                  for each qubit of interest. End frontier indices are exclusive.
              omit_crossing_operations: Determines whether or not operations that
                  cross from a location between the two frontiers to a location
                  outside the two frontiers are included or excluded. (Operations
                  completely inside are always included, and operations completely
                  outside are always excluded.)
  
          Returns:
              A list of tuples. Each tuple describes an operation found between
              the two frontiers. The first item of each tuple is the index of the
              moment containing the operation, and the second item is the
              operation itself. The list is sorted so that the moment index
              increases monotonically.
          """
          result = BucketPriorityQueue[ops.Operation](
              drop_duplicate_entries=True)
  
          involved_qubits = set(start_frontier.keys()) | set(end_frontier.keys())
          # Note: only sorted to ensure a deterministic result ordering.
          for q in sorted(involved_qubits):
              for i in range(start_frontier.get(q, 0),
                             end_frontier.get(q, len(self))):
                  op = self.operation_at(q, i)
                  if op is None:
                      continue
                  if (omit_crossing_operations and
                          not involved_qubits.issuperset(op.qubits)):
                      continue
                  result.enqueue(i, op)
  
          return list(result)