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