def _pass_single_clifford_gate_over(pauli_map: Dict[raw_types.QubitId, Pauli], gate: SingleQubitCliffordGate, qubit: raw_types.QubitId, after_to_before: bool = False) -> bool: if qubit not in pauli_map: return False if not after_to_before: gate = gate.inverse() pauli, inv = gate.transform(pauli_map[qubit]) pauli_map[qubit] = pauli return inv
def _decompose_(self, qubits: Sequence['cirq.Qid']) -> 'cirq.OP_TREE': q0, q1 = qubits right_gate0 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli0, self.invert0)) right_gate1 = SingleQubitCliffordGate.from_single_map(z_to=(self.pauli1, self.invert1)) left_gate0 = right_gate0 ** -1 left_gate1 = right_gate1 ** -1 yield left_gate0(q0) yield left_gate1(q1) yield common_gates.CZ(q0, q1) ** self._exponent yield right_gate0(q0) yield right_gate1(q1)
def default_decompose( self, qubits: Sequence[raw_types.QubitId]) -> op_tree.OP_TREE: q0, q1 = qubits right_gate0 = SingleQubitCliffordGate.from_single_map( z_to=(self.pauli0, self.invert0)) right_gate1 = SingleQubitCliffordGate.from_single_map( z_to=(self.pauli1, self.invert1)) left_gate0 = right_gate0.inverse() left_gate1 = right_gate1.inverse() yield left_gate0(q0) yield left_gate1(q1) yield common_gates.Rot11Gate(half_turns=self._exponent)(q0, q1) yield right_gate0(q0) yield right_gate1(q1)
def _strat_act_on_stabilizer_ch_form_from_single_qubit_decompose( val: Any, args: 'cirq.ActOnStabilizerCHFormArgs') -> bool: if num_qubits(val) == 1: if not has_unitary(val): return NotImplemented u = unitary(val) clifford_gate = SingleQubitCliffordGate.from_unitary(u) if clifford_gate is not None: # Gather the effective unitary applied so as to correct for the # global phase later. final_unitary = np.eye(2) for axis, quarter_turns in clifford_gate.decompose_rotation(): gate = None # type: Optional[cirq.Gate] if axis == pauli_gates.X: gate = common_gates.XPowGate(exponent=quarter_turns / 2) assert gate._act_on_(args) elif axis == pauli_gates.Y: gate = common_gates.YPowGate(exponent=quarter_turns / 2) assert gate._act_on_(args) else: assert axis == pauli_gates.Z gate = common_gates.ZPowGate(exponent=quarter_turns / 2) assert gate._act_on_(args) final_unitary = np.matmul(unitary(gate), final_unitary) # Find the entry with the largest magnitude in the input unitary. k = max(np.ndindex(*u.shape), key=lambda t: abs(u[t])) # Correct the global phase that wasn't conserved in the above # decomposition. args.state.omega *= u[k] / final_unitary[k] return True return NotImplemented
def _strat_act_from_single_qubit_decompose( self, val: Any, qubits: Sequence['cirq.Qid'] ) -> bool: if num_qubits(val) == 1: if not has_unitary(val): return NotImplemented u = unitary(val) clifford_gate = SingleQubitCliffordGate.from_unitary(u) if clifford_gate is not None: # Gather the effective unitary applied so as to correct for the # global phase later. final_unitary = np.eye(2) for axis, quarter_turns in clifford_gate.decompose_rotation(): gate = axis ** (quarter_turns / 2) self._strat_apply_gate(gate, qubits) final_unitary = np.matmul(unitary(gate), final_unitary) # Find the entry with the largest magnitude in the input unitary. k = max(np.ndindex(*u.shape), key=lambda t: abs(u[t])) # Correct the global phase that wasn't conserved in the above # decomposition. self._state.apply_global_phase(u[k] / final_unitary[k]) return True return NotImplemented
def is_supported_operation(op: 'cirq.Operation') -> bool: """Checks whether given operation can be simulated by this simulator.""" if protocols.is_measurement(op): return True if isinstance(op, GlobalPhaseOperation): return True if not protocols.has_unitary(op): return False u = cirq.unitary(op) if u.shape == (2, 2): return not SingleQubitCliffordGate.from_unitary(u) is None else: return op.gate in [cirq.CNOT, cirq.CZ]
def _strat_has_stabilizer_effect_from_unitary(val: Any) -> Optional[bool]: """Attempts to infer whether val has stabilizer effect from its unitary. Returns whether unitary of `val` normalizes the Pauli group. Works only for 2x2 unitaries. """ if not protocols.has_unitary(val): return None unitary = protocols.unitary(val) if unitary.shape == (2, 2): return SingleQubitCliffordGate.from_unitary(unitary) is not None return None
def _strat_has_stabilizer_effect_from_unitary(val: Any) -> Optional[bool]: """Attempts to infer whether val has stabilizer effect from its unitary. Returns whether unitary of `val` normalizes the Pauli group. Works only for 2x2 unitaries. """ # Do not try this strategy if there is no unitary or if the number of # qubits is not 1 since that would be expensive. if not protocols.has_unitary(val) or protocols.num_qubits(val) != 1: return None unitary = protocols.unitary(val) return SingleQubitCliffordGate.from_unitary(unitary) is not None
def is_supported_operation(op: 'cirq.Operation') -> bool: """Checks whether given operation can be simulated by this simulator.""" # TODO: support more general Pauli measurements if isinstance(op.gate, cirq.MeasurementGate): return True if isinstance(op, GlobalPhaseOperation): return True if not protocols.has_unitary(op): return False if len(op.qubits) == 1: u = unitary(op) return SingleQubitCliffordGate.from_unitary(u) is not None else: return op.gate in [cirq.CNOT, cirq.CZ]
def _pass_single_clifford_gate_over( pauli_map: Dict[raw_types.Qid, pauli_gates.Pauli], gate: clifford_gate.SingleQubitCliffordGate, qubit: 'cirq.Qid', after_to_before: bool = False) -> bool: if qubit not in pauli_map: return False if not after_to_before: gate **= -1 pauli, inv = gate.transform(pauli_map[qubit]) pauli_map[qubit] = pauli return inv
def apply_single_qubit_unitary(self, op: 'cirq.Operation'): qubit = self.qubit_map[op.qubits[0]] if op.gate == cirq.I: return if op.gate == cirq.X: self._apply_X(qubit) return if op.gate == cirq.Y: self._apply_Y(qubit) return if op.gate == cirq.Z: self._apply_Z(qubit) return if op.gate == cirq.H: self._apply_H(qubit) return u = unitary(op) clifford_gate = SingleQubitCliffordGate.from_unitary(u) if clifford_gate is None: raise ValueError('%s cannot be run with Clifford simulator.' % str(op.gate)) h = unitary(ops.H) s = unitary(ops.S) applied_unitary = np.eye(2) for axis, quarter_turns in clifford_gate.decompose_rotation(): for _ in range(quarter_turns % 4): if axis == pauli_gates.X: self._apply_H(qubit) self._apply_S(qubit) self._apply_H(qubit) applied_unitary = h @ s @ h @ applied_unitary elif axis == pauli_gates.Y: self._apply_S(qubit) self._apply_S(qubit) self._apply_H(qubit) applied_unitary = h @ s @ s @ applied_unitary else: assert axis == pauli_gates.Z self._apply_S(qubit) applied_unitary = s @ applied_unitary max_idx = max(np.ndindex(*u.shape), key=lambda t: abs(u[t])) phase_shift = u[max_idx] / applied_unitary[max_idx] self.ch_form.omega *= phase_shift
def _strat_act_from_single_qubit_decompose( self, val: Any, qubits: Sequence['cirq.Qid'] ) -> bool: if num_qubits(val) == 1: if not has_unitary(val): return NotImplemented u = unitary(val) gate_and_phase = SingleQubitCliffordGate.from_unitary_with_global_phase(u) if gate_and_phase is not None: clifford_gate, global_phase = gate_and_phase # Apply gates. for gate in clifford_gate.decompose_gate(): self._strat_apply_gate(gate, qubits) # Apply global phase. self._state.apply_global_phase(global_phase) return True return NotImplemented
def _strat_act_on_clifford_tableau_from_single_qubit_decompose( val: Any, args: 'cirq.ActOnCliffordTableauArgs', qubits: Sequence['cirq.Qid'] ) -> bool: if num_qubits(val) == 1: if not has_unitary(val): return NotImplemented u = unitary(val) clifford_gate = SingleQubitCliffordGate.from_unitary(u) if clifford_gate is not None: for axis, quarter_turns in clifford_gate.decompose_rotation(): if axis == pauli_gates.X: common_gates.XPowGate(exponent=quarter_turns / 2)._act_on_(args, qubits) elif axis == pauli_gates.Y: common_gates.YPowGate(exponent=quarter_turns / 2)._act_on_(args, qubits) else: assert axis == pauli_gates.Z common_gates.ZPowGate(exponent=quarter_turns / 2)._act_on_(args, qubits) return True return NotImplemented
def to_z_basis_ops(self) -> op_tree.OP_TREE: """Returns operations to convert the qubits to the computational basis. """ for qubit, pauli in self.items(): yield SingleQubitCliffordGate.from_single_map( {pauli: (Pauli.Z, False)})(qubit)