Пример #1
0
 def dump_phases(qubits, index):
     for q in qubits:
         p = turns_state[q]
         if not is_negligible_turn(p, self.tolerance):
             dump_op = ExpZGate(half_turns=p * 2).on(q)
             insertions.append((index, dump_op))
         turns_state[q] = 0
Пример #2
0
def _potential_cross_whole_w(moment_index: int, op: ops.Operation,
                             tolerance: float, state: _OptimizerState) -> None:
    """Grabs or cancels a held W gate against an existing W gate.

    Uses the following identity:
        ───W(a)───W(b)───
        ≡ ───Z^-a───X───Z^a───Z^-b───X───Z^b───
        ≡ ───Z^-a───Z^-a───Z^b───X───X───Z^b───
        ≡ ───Z^-a───Z^-a───Z^b───Z^b───
        ≡ ───Z^2(b-a)───
    """
    state.deletions.append((moment_index, op))

    w = cast(ExpWGate, _try_get_known_w(op))
    q = op.qubits[0]
    a = state.held_w_phases.get(q)
    b = cast(float, w.axis_half_turns)

    if a is None:
        # Collect the gate.
        state.held_w_phases[q] = b
    else:
        # Cancel the gate.
        state.held_w_phases[q] = None
        t = 2 * (b - a)
        if not decompositions.is_negligible_turn(t / 2, tolerance):
            leftover_phase = ExpZGate(half_turns=t).on(q)
            state.inline_intos.append((moment_index, leftover_phase))
Пример #3
0
    def optimize_circuit(self, circuit: circuits.Circuit):
        state = _OptimizerState()

        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                affected = [
                    q for q in op.qubits
                    if state.held_w_phases.get(q) is not None
                ]

                # Collect, phase, and merge Ws.
                w = _try_get_known_w(op)
                if w is not None:
                    if decompositions.is_negligible_turn(
                            cast(float, w.half_turns) - 1, self.tolerance):
                        _potential_cross_whole_w(moment_index, op,
                                                 self.tolerance, state)
                    else:
                        _potential_cross_partial_w(moment_index, op, state)
                    continue

                if not affected:
                    continue

                # Absorb Z rotations.
                t = _try_get_known_z_half_turns(op)
                if t is not None:
                    _absorb_z_into_w(moment_index, op, state)
                    continue

                # Dump coherent flips into measurement bit flips.
                if ops.MeasurementGate.is_measurement(op):
                    _dump_into_measurement(moment_index, op, state)

                # Cross CZs using kickback.
                if _try_get_known_cz_half_turns(op) is not None:
                    if len(affected) == 1:
                        _single_cross_over_cz(moment_index, op, affected[0],
                                              state)
                    else:
                        _double_cross_over_cz(op, state)
                    continue

                # Don't know how to handle this situation. Dump the gates.
                _dump_held(op.qubits, moment_index, state)

        # Put anything that's still held at the end of the circuit.
        _dump_held(state.held_w_phases.keys(), len(circuit), state)

        circuit.batch_remove(state.deletions)
        circuit.batch_insert_into(state.inline_intos)
        circuit.batch_insert(state.insertions)
Пример #4
0
    def optimize_circuit(self, circuit: circuits.Circuit):
        turns_state = defaultdict(lambda: 0)  # type: Dict[ops.QubitId, float]

        def dump_phases(qubits, index):
            for q in qubits:
                p = turns_state[q]
                if not is_negligible_turn(p, self.tolerance):
                    dump_op = ExpZGate(half_turns=p * 2).on(q)
                    insertions.append((index, dump_op))
                turns_state[q] = 0

        deletions = []  # type: List[Tuple[int, ops.Operation]]
        inline_intos = []  # type: List[Tuple[int, ops.Operation]]
        insertions = []  # type: List[Tuple[int, ops.Operation]]
        for moment_index, moment in enumerate(circuit):
            for op in moment.operations:
                h = _try_get_known_z_half_turns(op)
                if h is not None:
                    q = op.qubits[0]
                    turns_state[q] += h / 2
                    deletions.append((moment_index, op))
                    continue

                if ops.MeasurementGate.is_measurement(op):
                    for q in op.qubits:
                        turns_state[q] = 0

                phases = [turns_state[q] for q in op.qubits]
                if all(is_negligible_turn(p, self.tolerance) for p in phases):
                    continue

                phaseable = self.ext.try_cast(ops.PhaseableEffect, op)
                if phaseable is not None:
                    for i, p in enumerate(phases):
                        if p:
                            phaseable = phaseable.phase_by(-p, i)
                    deletions.append((moment_index, op))
                    inline_intos.append(
                        (moment_index, cast(ops.Operation, phaseable)))
                    continue

                dump_phases(op.qubits, moment_index)

        dump_phases(turns_state.keys(), len(circuit))
        circuit.batch_remove(deletions)
        circuit.batch_insert_into(inline_intos)
        circuit.batch_insert(insertions)
Пример #5
0
    def _drain_into(self, circuit: Circuit, qubit: ops.QubitId,
                    drain: int, accumulated_phase: float):
        if is_negligible_turn(accumulated_phase, self.tolerance):
            return

        # Drain type: end of circuit.
        if drain == len(circuit.moments):
            circuit.append(
                ExpZGate(half_turns=2*accumulated_phase).on(qubit),
                InsertStrategy.INLINE)
            return

        # Drain type: another Z gate.
        op = cast(ops.Operation, circuit.operation_at(qubit, drain))
        if isinstance(op.gate, ExpZGate):
            half_turns = cast(float, op.gate.half_turns) + accumulated_phase * 2
            circuit.clear_operations_touching([qubit], [drain])
            circuit.insert(
                drain + 1,
                ExpZGate(half_turns=half_turns).on(qubit),
                InsertStrategy.INLINE)
            return