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
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
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
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))