Exemple #1
0
def single_qubit_matrix_to_native_gates(mat: np.ndarray,
                                        tolerance: float = 0
                                        ) -> List[ops.SingleQubitGate]:
    """Implements a single-qubit operation with few native gates.

    Args:
        mat: The 2x2 unitary matrix of the operation to implement.
        tolerance: A limit on the amount of error introduced by the
            construction.

    Returns:
        A list of gates that, when applied in order, perform the desired
            operation.
    """

    xy_turn, xy_phase_turn, total_z_turn = (
        _deconstruct_single_qubit_matrix_into_gate_turns(mat))

    # Build the intended operation out of non-negligible XY and Z rotations.
    result = [
        ExpWGate(exponent=2 * xy_turn, phase_exponent=2 * xy_phase_turn),
        ops.Z**(2 * total_z_turn)
    ]
    result = [
        g for g in result if protocols.trace_distance_bound(g) > tolerance
    ]

    # Special case: XY half-turns can absorb Z rotations.
    if len(result) == 2 and abs(xy_turn) >= 0.5 - tolerance:
        return [ExpWGate(phase_exponent=2 * xy_phase_turn + total_z_turn)]

    return result
Exemple #2
0
def _dump_held(qubits: Iterable[ops.QubitId], moment_index: int,
               state: _OptimizerState):
    # Note: sorting is to avoid non-determinism in the insertion order.
    for q in sorted(qubits):
        p = state.held_w_phases.get(q)
        if p is not None:
            dump_op = ExpWGate(axis_half_turns=p).on(q)
            state.insertions.append((moment_index, dump_op))
        state.held_w_phases[q] = None
Exemple #3
0
def _dump_held(qubits: Iterable[ops.QubitId], moment_index: int,
               state: _OptimizerState):
    # Avoid non-determinism in in the inserted operations.
    sorted_qubits = ops.QubitOrder.DEFAULT.order_for(qubits)

    for q in sorted_qubits:
        p = state.held_w_phases.get(q)
        if p is not None:
            dump_op = ExpWGate(axis_half_turns=p).on(q)
            state.insertions.append((moment_index, dump_op))
        state.held_w_phases[q] = None
Exemple #4
0
def _potential_cross_partial_w(moment_index: int, op: ops.Operation,
                               state: _OptimizerState) -> None:
    """Cross the held W over a partial W gate.

    Uses the following identity:
        ───W(a)───W(b)^t───
        ≡ ───Z^-a───X───Z^a───W(b)^t────── (expand W(a))
        ≡ ───Z^-a───X───W(b-a)^t───Z^a──── (move Z^a across, phasing axis)
        ≡ ───Z^-a───W(a-b)^t───X───Z^a──── (move X across, negating axis angle)
        ≡ ───W(2a-b)^t───Z^-a───X───Z^a─── (move Z^-a across, phasing axis)
        ≡ ───W(2a-b)^t───W(a)───
    """
    a = state.held_w_phases.get(op.qubits[0])
    if a is None:
        return
    w = cast(ExpWGate, _try_get_known_w(op))
    b = cast(float, w.axis_half_turns)
    t = cast(float, w.half_turns)
    new_op = ExpWGate(half_turns=t, axis_half_turns=2 * a - b).on(op.qubits[0])
    state.deletions.append((moment_index, op))
    state.inline_intos.append((moment_index, new_op))