예제 #1
0
 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
예제 #2
0
    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)
예제 #3
0
 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
예제 #6
0
 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]
예제 #7
0
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
예제 #8
0
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
예제 #9
0
 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]
예제 #10
0
 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
예제 #11
0
    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
예제 #13
0
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
예제 #14
0
 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)