Example #1
0
    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)
Example #2
0
 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),
             ])
Example #3
0
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))
Example #4
0
    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)
Example #5
0
 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)
         )
Example #6
0
 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,
         )
Example #7
0
    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
                )
Example #8
0
    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
        )
Example #9
0
 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),
             ])
Example #10
0
 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)
         )
Example #11
0
 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=[]))
Example #13
0
    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
Example #14
0
    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)
Example #15
0
    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)])
Example #16
0
    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, (), ())')
Example #19
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)