コード例 #1
0
 def _matrix_to_pauli_string_phasors(self,
                                     mat: np.ndarray,
                                     qubit: ops.Qid) -> ops.OP_TREE:
     rotations = optimizers.single_qubit_matrix_to_pauli_rotations(
         mat, self.atol)
     out_ops = []  # type: List[ops.Operation]
     for pauli, half_turns in rotations:
         if (self.keep_clifford
                 and linalg.all_near_zero_mod(half_turns, 0.5)):
             cliff_gate = ops.SingleQubitCliffordGate.from_quarter_turns(
                 pauli, round(half_turns * 2))
             if out_ops and not isinstance(out_ops[-1],
                                           ops.PauliStringPhasor):
                 op = cast(ops.GateOperation, out_ops[-1])
                 gate = cast(ops.SingleQubitCliffordGate, op.gate)
                 out_ops[-1] = gate.merged_with(cliff_gate)(qubit)
             else:
                 out_ops.append(
                     cliff_gate(qubit))
         else:
             pauli_string = ops.PauliString.from_single(qubit, pauli)
             out_ops.append(
                 ops.PauliStringPhasor(pauli_string,
                                       exponent_neg=round(half_turns, 10)))
     return out_ops
コード例 #2
0
    def try_merge_clifford(cliff_op: ops.GateOperation, start_i: int) -> bool:
        (orig_qubit, ) = cliff_op.qubits
        remaining_cliff_gate = ops.SingleQubitCliffordGate.I
        for pauli, quarter_turns in reversed(
                cast(ops.SingleQubitCliffordGate,
                     cliff_op.gate).decompose_rotation()):
            trans = remaining_cliff_gate.transform(pauli)
            pauli = trans.to
            quarter_turns *= -1 if trans.flip else 1
            string_op = ops.PauliStringPhasor(ops.PauliString(
                pauli(cliff_op.qubits[0])),
                                              exponent_neg=quarter_turns / 2)

            merge_i, merge_op, num_passed = find_merge_point(
                start_i, string_op, quarter_turns == 2)
            assert merge_i > start_i
            assert len(merge_op.pauli_string) == 1, 'PauliString length != 1'

            qubit, pauli = next(iter(merge_op.pauli_string.items()))
            quarter_turns = round(merge_op.exponent_relative * 2)
            quarter_turns *= int(merge_op.pauli_string.coefficient.real)
            quarter_turns %= 4
            part_cliff_gate = ops.SingleQubitCliffordGate.from_quarter_turns(
                pauli, quarter_turns)

            other_op = all_ops[merge_i] if merge_i < len(all_ops) else None
            if other_op is not None and qubit not in set(other_op.qubits):
                other_op = None

            if isinstance(other_op, ops.GateOperation) and isinstance(
                    other_op.gate, ops.SingleQubitCliffordGate):
                # Merge with another SingleQubitCliffordGate
                new_op = part_cliff_gate.merged_with(other_op.gate)(qubit)
                all_ops[merge_i] = new_op
            elif (isinstance(other_op, ops.GateOperation)
                  and isinstance(other_op.gate, ops.CZPowGate)
                  and other_op.gate.exponent == 1 and quarter_turns == 2):
                # Pass whole Pauli gate over CZ, possibly adding a Z gate
                if pauli != ops.pauli_gates.Z:
                    other_qubit = other_op.qubits[other_op.qubits.index(qubit)
                                                  - 1]
                    all_ops.insert(merge_i + 1,
                                   ops.SingleQubitCliffordGate.Z(other_qubit))
                all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
            elif isinstance(other_op, ops.PauliStringPhasor):
                # Pass over a non-Clifford gate
                mod_op = other_op.pass_operations_over(
                    [part_cliff_gate(qubit)])
                all_ops[merge_i] = mod_op
                all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
            elif merge_i > start_i + 1 and num_passed > 0:
                # Moved Clifford through the circuit but nothing to merge
                all_ops.insert(merge_i, part_cliff_gate(qubit))
            else:
                # Couldn't move Clifford
                remaining_cliff_gate = remaining_cliff_gate.merged_with(
                    part_cliff_gate)

        if remaining_cliff_gate == ops.SingleQubitCliffordGate.I:
            all_ops.pop(start_i)
            return True
        all_ops[start_i] = remaining_cliff_gate(orig_qubit)
        return False
コード例 #3
0
    def try_merge_clifford(cliff_op: ops.GateOperation, start_i: int) -> bool:
        orig_qubit, = cliff_op.qubits
        remaining_cliff_gate = ops.SingleQubitCliffordGate.I
        for pauli, quarter_turns in reversed(
                cast(ops.SingleQubitCliffordGate,
                     cliff_op.gate).decompose_rotation()):
            trans = remaining_cliff_gate.transform(pauli)
            pauli = trans.to
            quarter_turns *= -1 if trans.flip else 1
            string_op = ops.PauliStringPhasor(ops.PauliString(
                pauli(cliff_op.qubits[0])),
                                              exponent_neg=quarter_turns / 2)

            merge_i, merge_op, num_passed = find_merge_point(
                start_i, string_op, quarter_turns == 2)
            assert merge_i > start_i
            assert len(merge_op.pauli_string) == 1, 'PauliString length != 1'

            qubit, pauli = next(iter(merge_op.pauli_string.items()))
            quarter_turns = round(merge_op.exponent_relative * 2)
            if merge_op.pauli_string.coefficient not in [1, -1]:
                # TODO: Add support for more general phases.
                # Github issue: https://github.com/quantumlib/Cirq/issues/2962
                # Legacy coverage ignore, we need test code that hits this.
                # coverage: ignore
                raise NotImplementedError(
                    'Only +1/-1 pauli string coefficients currently supported')
            quarter_turns *= int(merge_op.pauli_string.coefficient.real)
            quarter_turns %= 4
            part_cliff_gate = ops.SingleQubitCliffordGate.from_quarter_turns(
                pauli, quarter_turns)

            other_op = all_ops[merge_i] if merge_i < len(all_ops) else None
            if other_op is not None and qubit not in set(other_op.qubits):
                other_op = None

            if (isinstance(other_op, ops.GateOperation) and isinstance(
                    other_op.gate, ops.SingleQubitCliffordGate)):
                # Merge with another SingleQubitCliffordGate
                new_op = part_cliff_gate.merged_with(other_op.gate)(qubit)
                all_ops[merge_i] = new_op
            elif (isinstance(other_op, ops.GateOperation)
                  and isinstance(other_op.gate, ops.CZPowGate)
                  and other_op.gate.exponent == 1 and quarter_turns == 2):
                # Pass whole Pauli gate over CZ, possibly adding a Z gate
                if pauli != ops.pauli_gates.Z:
                    other_qubit = other_op.qubits[other_op.qubits.index(qubit)
                                                  - 1]
                    all_ops.insert(merge_i + 1,
                                   ops.SingleQubitCliffordGate.Z(other_qubit))
                all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
            elif isinstance(other_op, ops.PauliStringPhasor):
                # Pass over a non-Clifford gate
                mod_op = other_op.pass_operations_over(
                    [part_cliff_gate(qubit)])
                all_ops[merge_i] = mod_op
                all_ops.insert(merge_i + 1, part_cliff_gate(qubit))
            elif merge_i > start_i + 1 and num_passed > 0:
                # Moved Clifford through the circuit but nothing to merge
                all_ops.insert(merge_i, part_cliff_gate(qubit))
            else:
                # Couldn't move Clifford
                remaining_cliff_gate = remaining_cliff_gate.merged_with(
                    part_cliff_gate)

        if remaining_cliff_gate == ops.SingleQubitCliffordGate.I:
            all_ops.pop(start_i)
            return True
        all_ops[start_i] = remaining_cliff_gate(orig_qubit)
        return False