def optimize_circuit(self, circuit: Circuit): frontier = defaultdict(lambda: 0) # type: Dict[QubitId, int] i = 0 while i < len(circuit): # Note: circuit may mutate as we go. for op in circuit[i].operations: # Don't touch stuff inserted by previous optimizations. if any(frontier[q] > i for q in op.qubits): continue # Skip if an optimization removed the circuit underneath us. if i >= len(circuit): continue # Skip if an optimization removed the op we're considering. if op not in circuit[i].operations: continue opt = self.optimization_at(circuit, i, op) # Skip if the optimization did nothing. if opt is None: continue # Clear target area, and insert new operations. circuit.clear_operations_touching( opt.clear_qubits, [e for e in range(i, i + opt.clear_span)]) new_operations = self.post_clean_up(opt.new_operations) circuit.insert_at_frontier(new_operations, i, frontier) i += 1
def optimize_circuit(self, circuit: Circuit): walls = defaultdict(lambda: 0) # type: Dict[QubitId, int] i = 0 while i < len(circuit.moments): # Note: circuit may mutate as we go. for op in circuit.moments[i].operations: # Don't touch stuff inserted by previous optimizations. if any(walls[q] > i for q in op.qubits): continue # Skip if an optimization removed the circuit underneath us. if i >= len(circuit.moments): continue # Skip if an optimization removed the op we're considering. if op not in circuit.moments[i].operations: continue opt = self.optimization_at(circuit, i, op) # Skip if the optimization did nothing. if opt is None: continue # Clear target area, and insert new operations. circuit.clear_operations_touching( opt.clear_qubits, [e for e in range(i, i + opt.clear_span)]) next_insert_index = circuit.insert_into_range( opt.new_operations, i, i + opt.clear_span) # Prevent redundant optimizations. for q in opt.clear_qubits: walls[q] = max(walls[q], next_insert_index) i += 1
def optimize_circuit(self, circuit: Circuit): frontier = defaultdict(lambda: 0) # type: Dict[QubitId, int] i = 0 while i < len(circuit): # Note: circuit may mutate as we go. for op in circuit[i].operations: # Don't touch stuff inserted by previous optimizations. if any(frontier[q] > i for q in op.qubits): continue # Skip if an optimization removed the circuit underneath us. if i >= len(circuit): continue # Skip if an optimization removed the op we're considering. if op not in circuit[i].operations: continue opt = self.optimization_at(circuit, i, op) # Skip if the optimization did nothing. if opt is None: continue # Clear target area, and insert new operations. circuit.clear_operations_touching( opt.clear_qubits, [e for e in range(i, i + opt.clear_span)]) circuit.insert_at_frontier(opt.new_operations, i, frontier) i += 1
def optimize_circuit(self, circuit: Circuit): frontier: Dict['Qid', int] = defaultdict(lambda: 0) i = 0 while i < len(circuit): # Note: circuit may mutate as we go. for op in circuit[i].operations: # Don't touch stuff inserted by previous optimizations. if any(frontier[q] > i for q in op.qubits): continue # Skip if an optimization removed the circuit underneath us. if i >= len(circuit): continue # Skip if an optimization removed the op we're considering. if op not in circuit[i].operations: continue opt = self.optimization_at(circuit, i, op) # Skip if the optimization did nothing. if opt is None: continue # Clear target area, and insert new operations. circuit.clear_operations_touching( opt.clear_qubits, [e for e in range(i, i + opt.clear_span)]) new_operations = self.post_clean_up( cast(Tuple[ops.Operation], opt.new_operations)) flat_new_operations = tuple(ops.flatten_to_ops(new_operations)) new_qubits = set() for flat_op in flat_new_operations: for q in flat_op.qubits: new_qubits.add(q) if not new_qubits.issubset(set(opt.clear_qubits)): raise ValueError( 'New operations in PointOptimizer should not act on new qubits.' ) circuit.insert_at_frontier(flat_new_operations, i, frontier) i += 1
def optimize_circuit(self, circuit: Circuit): moment_new_ops = defaultdict( list) # type: Dict[int, List['cirq.Operation']] circuit_len = len(circuit) for i in range(circuit_len): moment_new_ops[i] = [] for op in circuit[i].operations: opt = self.optimization_at(circuit, i, op) if opt is None: # keep the old operation if the optimization did nothing. moment_new_ops[i].append(op) circuit.clear_operations_touching(op.qubits, [i]) else: # Clear target area, and insert new operations. circuit.clear_operations_touching( opt.clear_qubits, [e for e in range(i, i + opt.clear_span)]) new_operations = self.post_clean_up( cast(Tuple[ops.Operation], opt.new_operations)) flat_new_operations = tuple( ops.flatten_to_ops(new_operations)) new_qubits = set() for flat_op in flat_new_operations: for q in flat_op.qubits: new_qubits.add(q) if not new_qubits.issubset(set(opt.clear_qubits)): raise ValueError( 'New operations in PointOptimizer should not act on new' ' qubits.') moment_new_ops[i].extend(flat_new_operations) frontier = 0 for i in range(circuit_len): new_frontier = circuit.insert(frontier, moment_new_ops[i], InsertStrategy.EARLIEST_AFTER) if frontier < new_frontier: frontier = new_frontier
def test_clear_operations_touching(): a = cirq.QubitId() b = cirq.QubitId() c = Circuit() c.clear_operations_touching([a, b], range(10)) assert c == Circuit() c = Circuit([ Moment(), Moment([cirq.X(a), cirq.X(b)]), Moment([cirq.X(a)]), Moment([cirq.X(a)]), Moment([cirq.CZ(a, b)]), Moment(), Moment([cirq.X(b)]), Moment(), ]) c.clear_operations_touching([a], [1, 3, 4, 6, 7]) assert c == Circuit([ Moment(), Moment([cirq.X(b)]), Moment([cirq.X(a)]), Moment(), Moment(), Moment(), Moment([cirq.X(b)]), Moment(), ]) c = Circuit([ Moment(), Moment([cirq.X(a), cirq.X(b)]), Moment([cirq.X(a)]), Moment([cirq.X(a)]), Moment([cirq.CZ(a, b)]), Moment(), Moment([cirq.X(b)]), Moment(), ]) c.clear_operations_touching([a, b], [1, 3, 4, 6, 7]) assert c == Circuit([ Moment(), Moment(), Moment([cirq.X(a)]), Moment(), Moment(), Moment(), Moment(), Moment(), ])