def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation) -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, cirq.MatrixGate) and len(op.qubits) == 1: return None converted = self.convert(op) if len(converted) == 1 and converted[0] is op: return None return cirq.PointOptimizationSummary(clear_span=1, new_operations=converted, clear_qubits=op.qubits)
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation') -> Optional[cirq.PointOptimizationSummary]: if (isinstance(op, cirq.ops.GateOperation) and isinstance(op.gate, cirq.CZPowGate)): return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=[ cirq.CZ(*op.qubits), cirq.X.on_each(*op.qubits), cirq.X.on_each(*op.qubits), ])
def test_combines_sequence(): m = cirq.google.MergeRotations(0.000001) q = cirq.QubitId() c = cirq.Circuit([ cirq.Moment([cirq.X(q)**0.5]), cirq.Moment([cirq.Z(q)**0.5]), cirq.Moment([cirq.X(q)**-0.5]), ]) assert (m.optimization_at(c, 0, c.operation_at( q, 0)) == cirq.PointOptimizationSummary(clear_span=3, clear_qubits=[q], new_operations=cirq.Y(q)**0.5))
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation) -> Optional[cirq.PointOptimizationSummary]: if op.gate is None and not isinstance(op.untagged, cirq.CircuitOperation): return None # Check for a SWAP and ZZPowGate together if isinstance(op.gate, cirq.ZZPowGate) or op.gate == cirq.SWAP: op2 = None next_index = circuit.next_moment_operating_on(op.qubits, index + 1) if next_index is not None: ops_in_front = list( {circuit.operation_at(q, next_index) for q in op.qubits}) if len(ops_in_front) == 1 and ops_in_front[0] is not None: op2 = ops_in_front[0] else: next_index = 0 if op2 is not None and ( (op.gate == cirq.SWAP and isinstance(op2.gate, cirq.ZZPowGate)) or (isinstance(op.gate, cirq.ZZPowGate) and op2.gate == cirq.SWAP)): swap_rzz_decomposed = two_qubit_to_sycamore.known_2q_op_to_sycamore_operations( cirq.CircuitOperation(cirq.FrozenCircuit(op, op2))) assert swap_rzz_decomposed is not None return cirq.PointOptimizationSummary( clear_span=next_index - index + 1, clear_qubits=op.qubits, new_operations=swap_rzz_decomposed, ) converted = self.convert(op) if len(converted) == 1 and converted[0] is op: return None return cirq.PointOptimizationSummary(clear_span=1, new_operations=converted, clear_qubits=op.qubits)
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation' ) -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, DriverUnitary): gate = op.gate # type: DriverUnitary return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=_rx(2 * gate.beta).on_each(op.qubits) )
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation') -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, ProblemUnitary): gate = op.gate # type: ProblemUnitary return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=_hardware_graph(gate.problem_graph, gate.gamma, self._node_coordinates, op.qubits), preserve_moments=True, )
def optimization_at(self, circuit, index, op): # Is the gate an X gate? if index > 0 and isinstance(op, cirq.GateOperation) and (op.gate == cirq.CNOT): # print("found a CNOT") """ Checking for the Hadamards """ control_qubit = op.qubits[0] target_qubit = op.qubits[1] # is the next gate a cnot? nxt_1 = circuit.next_moment_operating_on([control_qubit], start_moment_index=index + 1, max_distance=1) if nxt_1 is None: return None nxt_2 = circuit.next_moment_operating_on([target_qubit], start_moment_index=index + 1, max_distance=1) if nxt_2 is None: return None # Get the operation at the next index next_op_h1 = circuit.operation_at(control_qubit, nxt_1) next_op_h2 = circuit.operation_at(target_qubit, nxt_2) # print("next are ", next_op_h1, next_op_h2) # Are the operations Hadamards? if isinstance(next_op_h1, cirq.GateOperation) and (next_op_h1.gate == cirq.H) \ and isinstance(next_op_h2, cirq.GateOperation) and (next_op_h2.gate == cirq.H) : # theoretically nxt_1 and nxt_2 should be equal if (nxt_1 != nxt_2): # print(nxt_1, nxt_2) return None # If yes, replace the CNOT with a reversed CNOT new_ops = [cirq.H.on(control_qubit), cirq.H.on(target_qubit), cirq.CNOT(target_qubit, control_qubit)] # see https://cirq.readthedocs.io/en/stable/generated/cirq.PointOptimizationSummary.html?highlight=pointoptimizationsummary return cirq.PointOptimizationSummary( clear_span=nxt_1 - index + 1, # Range of moments to affect. clear_qubits=op.qubits, # The set of qubits that should be cleared with each affected moment new_operations=new_ops # The operations to replace )
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation ) -> Optional[cirq.PointOptimizationSummary]: if op.gate is None and not isinstance(op.untagged, cirq.CircuitOperation): return None gate = op.gate # Check for a SWAP and ZZPowGate together if isinstance(gate, cirq.ZZPowGate) or gate == cirq.SWAP: gate2 = None rads = None next_index = circuit.next_moment_operating_on(op.qubits, index + 1) if next_index is not None: ops_in_front = list({circuit.operation_at(q, next_index) for q in op.qubits}) if len(ops_in_front) == 1 and ops_in_front[0] is not None: gate2 = ops_in_front[0].gate else: next_index = 0 if isinstance(gate, cirq.SwapPowGate) and isinstance(gate2, cirq.ZZPowGate): rads = gate2.exponent * np.pi / 2 if isinstance(gate, cirq.ZZPowGate) and gate2 == cirq.SWAP: rads = gate.exponent * np.pi / 2 if rads is not None: return cirq.PointOptimizationSummary( clear_span=next_index - index + 1, clear_qubits=op.qubits, new_operations=swap_rzz(rads, op.qubits[0], op.qubits[1]), ) converted = self.convert(op) if len(converted) == 1 and converted[0] is op: return None return cirq.PointOptimizationSummary( clear_span=1, new_operations=converted, clear_qubits=op.qubits )
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation') -> Optional[cirq.PointOptimizationSummary]: if (isinstance(op, cirq.ops.GateOperation) and isinstance(op.gate, cirq.CZPowGate)): return cirq.PointOptimizationSummary( clear_span=-2, clear_qubits=op. qubits, #also run endlessly when I set (cirq.GridQubit(2,1),cirq.GridQubit(1,2)) new_operations=[ cirq.X.on_each(*op.qubits), cirq.X.on_each(*op.qubits), cirq.CZ(*op.qubits), ])
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation' ) -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, SwapNetworkProblemUnitary): gate = op.gate # type: SwapNetworkProblemUnitary return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=compile_problem_unitary_to_zzswap( gate.problem_graph, gate.gamma, op.qubits) )
def optimization_at( self, circuit: 'cirq.Circuit', index: int, op: 'cirq.Operation' ) -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, ProblemUnitary): gate = op.gate # type: ProblemUnitary return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=_problem_to_zz( problem_graph=gate.problem_graph, qubits=op.qubits, gamma=gate.gamma), )
def test_stopped_at_2qubit(): m = cirq.google.MergeRotations(0.000001) q = cirq.QubitId() q2 = cirq.QubitId() c = cirq.Circuit([ cirq.Moment([cirq.Z(q)]), cirq.Moment([cirq.H(q)]), cirq.Moment([cirq.X(q)]), cirq.Moment([cirq.H(q)]), cirq.Moment([cirq.CZ(q, q2)]), cirq.Moment([cirq.H(q)]), ]) assert (m.optimization_at(c, 0, c.operation_at( q, 0)) == cirq.PointOptimizationSummary(clear_span=4, clear_qubits=[q], new_operations=[]))
def optimization_at(self, circuit, index, op): if not (isinstance(op, cirq.GateOperation) and (op.gate == cirq.H)): return None n_idx = circuit.next_moment_operating_on(op.qubits, index + 1) if n_idx is None or n_idx != index + 1: return None next_op = circuit.operation_at(op.qubits[0], n_idx) if next_op.gate == cirq.H: return cirq.PointOptimizationSummary(clear_span= 2, clear_qubits=op.qubits, new_operations=[])# Two opposite rotations are erased return None
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation) -> Optional[cirq.PointOptimizationSummary]: if len(op.qubits) != 1: return None start = {op.qubits[0]: index} op_list = circuit.findall_operations_until_blocked( start, is_blocker=lambda next_op: len(next_op.qubits) != 1) operations = [op for idx, op in op_list] indices = [idx for idx, op in op_list] rewritten = self._rewrite(operations) if rewritten is None: return None return cirq.PointOptimizationSummary(clear_span=max(indices) + 1 - index, clear_qubits=op.qubits, new_operations=rewritten)
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation) -> Optional[cirq.PointOptimizationSummary]: if len(op.qubits) != self.n_qubits: return None frontier = {q: index for q in op.qubits} op_list = circuit.findall_operations_until_blocked( frontier, is_blocker=lambda next_op: next_op.qubits != op.qubits) if len(op_list) <= 1: return None operations = [op for idx, op in op_list] indices = [idx for idx, op in op_list] matrix = cirq.linalg.dot(*(cirq.unitary(op) for op in operations[::-1])) return cirq.PointOptimizationSummary( clear_span=max(indices) + 1 - index, clear_qubits=op.qubits, new_operations=[cirq.MatrixGate(matrix).on(*op.qubits)])
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation ) -> Optional[cirq.PointOptimizationSummary]: if isinstance(op.gate, (cirq.MeasurementGate, cirq.SingleQubitGate, cirq.WaitGate)): new_op = op else: if op.gate is None: raise IncompatibleMomentError(f'Operation {op} has a missing gate') translated = self._simulator.gates_translator(op.gate) if translated is None: raise IncompatibleMomentError( f'Moment contains non-single qubit operation ' f'{op} with unsupported gate' ) a, b = op.qubits new_op = self._simulator.create_gate_with_drift(a, b, translated).on(a, b) return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=new_op )
def optimization_at( self, circuit: cirq.Circuit, index: int, op: cirq.Operation ) -> Optional[cirq.PointOptimizationSummary]: if len(op.qubits) > 3: raise DeviceMappingError(f"Four qubit ops not yet supported: {op}") new_ops = None if op.gate == cirq.SWAP or op.gate == cirq.CNOT: new_ops = cirq.google.optimized_for_sycamore(cirq.Circuit(op)) if isinstance(op, cirq.ControlledOperation): if not all(v == 1 for values in op.control_values for v in values): raise DeviceMappingError(f"0-controlled ops not yet supported: {op}") qubits = op.sub_operation.qubits if op.gate.sub_gate == cirq.ISWAP: new_ops = controlled_iswap.controlled_iswap(*qubits, *op.controls) if op.gate.sub_gate == cirq.ISWAP ** -1: new_ops = controlled_iswap.controlled_iswap( *qubits, *op.controls, inverse=True ) if op.gate.sub_gate == cirq.ISWAP ** 0.5: new_ops = controlled_iswap.controlled_sqrt_iswap(*qubits, *op.controls) if op.gate.sub_gate == cirq.ISWAP ** -0.5: new_ops = controlled_iswap.controlled_inv_sqrt_iswap( *qubits, *op.controls ) if op.gate.sub_gate == cirq.X: if len(op.qubits) == 2: new_ops = cirq.google.optimized_for_sycamore( cirq.Circuit(cirq.CNOT(*op.controls, *qubits)) ) if len(op.qubits) == 3: new_ops = cirq.google.optimized_for_sycamore( cirq.Circuit(cirq.TOFFOLI(*op.controls, *qubits)) ) if new_ops: return cirq.PointOptimizationSummary( clear_span=1, clear_qubits=op.qubits, new_operations=new_ops )
def test_repr(): assert (repr( cirq.PointOptimizationSummary( clear_span=0, clear_qubits=[], new_operations=[])) == 'cirq.PointOptimizationSummary(0, (), ())')
def optimization_at(self, circuit, index, op): if len(op.qubits) == 1: new_op = op.gate(cirq.LineQubit(42)) return cirq.PointOptimizationSummary(clear_span=1, clear_qubits=op.qubits, new_operations=new_op)