Пример #1
0
def assert_commutes_magic_method_consistent_with_unitaries(
    *vals: Sequence[Any], atol: Union[int, float] = 1e-8
) -> None:
    if any(isinstance(val, ops.Operation) for val in vals):
        raise TypeError('`_commutes_` need not be consistent with unitaries for `Operation`.')
    unitaries = [protocols.unitary(val, None) for val in vals]
    pairs = itertools.permutations(zip(vals, unitaries), 2)
    for (left_val, left_unitary), (right_val, right_unitary) in pairs:
        if left_unitary is None or right_unitary is None:
            continue
        commutes = protocols.commutes(left_val, right_val, atol=atol, default=None)
        if commutes is None:
            continue
        assert commutes == protocols.commutes(left_unitary, right_unitary)
Пример #2
0
 def _commutes_(
     self,
     other: Any,
     *,
     atol: Union[int,
                 float] = 1e-8) -> Union[bool, NotImplementedType, None]:
     return protocols.commutes(self.sub_operation, other, atol=atol)
Пример #3
0
    def _commutes_(
        self, other: Any, *, atol: Union[int, float] = 1e-8
    ) -> Union[bool, NotImplementedType]:
        """Determines whether Moment commutes with the Operation.

        Args:
            other: An Operation object. Other types are not implemented yet.
                In case a different type is specified, NotImplemented is
                returned.
            atol: Absolute error tolerance. If all entries in v1@v2 - v2@v1
                have a magnitude less than this tolerance, v1 and v2 can be
                reported as commuting. Defaults to 1e-8.

        Returns:
            True: The Moment and Operation commute OR they don't have shared
            quibits.
            False: The two values do not commute.
            NotImplemented: In case we don't know how to check this, e.g.
                the parameter type is not supported yet.
        """
        if not isinstance(other, ops.Operation):
            return NotImplemented

        other_qubits = set(other.qubits)
        for op in self.operations:
            if not other_qubits.intersection(set(op.qubits)):
                continue

            commutes = protocols.commutes(op, other, atol=atol, default=NotImplemented)

            if not commutes or commutes is NotImplemented:
                return commutes

        return True
Пример #4
0
    def _commutes_(self, other: Any,
                   atol: float) -> Union[None, NotImplementedType, bool]:
        if not isinstance(other, Gate):
            return NotImplemented
        if protocols.qid_shape(self) != protocols.qid_shape(other):
            return None

        qs = line_qubit.LineQid.for_qid_shape(protocols.qid_shape(self))
        return protocols.commutes(self(*qs), other(*qs))
Пример #5
0
    def _pass_pauli_interaction_gate_over(
            pauli_map: Dict[raw_types.Qid, pauli_gates.Pauli],
            gate: pauli_interaction_gate.PauliInteractionGate,
            qubit0: 'cirq.Qid',
            qubit1: 'cirq.Qid',
            after_to_before: bool = False) -> bool:

        def merge_and_kickback(qubit: 'cirq.Qid',
                               pauli_left: Optional[pauli_gates.Pauli],
                               pauli_right: Optional[pauli_gates.Pauli],
                               inv: bool) -> int:
            assert pauli_left is not None or pauli_right is not None
            if pauli_left is None or pauli_right is None:
                pauli_map[qubit] = cast(pauli_gates.Pauli,
                                        pauli_left or pauli_right)
                return 0
            if pauli_left == pauli_right:
                del pauli_map[qubit]
                return 0

            pauli_map[qubit] = pauli_left.third(pauli_right)
            if (pauli_left < pauli_right) ^ after_to_before:
                return int(inv) * 2 + 1

            return int(inv) * 2 - 1

        quarter_kickback = 0
        if (qubit0 in pauli_map and
                not protocols.commutes(pauli_map[qubit0], gate.pauli0)):
            quarter_kickback += merge_and_kickback(qubit1,
                                                   gate.pauli1,
                                                   pauli_map.get(qubit1),
                                                   gate.invert1)
        if (qubit1 in pauli_map and
                not protocols.commutes(pauli_map[qubit1], gate.pauli1)):
            quarter_kickback += merge_and_kickback(qubit0,
                                                   pauli_map.get(qubit0),
                                                   gate.pauli0,
                                                   gate.invert0)
        assert quarter_kickback % 2 == 0, (
            'Impossible condition.  '
            'quarter_kickback is either incremented twice or never.')
        return quarter_kickback % 4 == 2
Пример #6
0
 def _commutes_(
     self,
     other: Any,
     *,
     atol: Union[int,
                 float] = 1e-8) -> Union[bool, NotImplementedType, None]:
     if not isinstance(other, PauliString):
         return NotImplemented
     return sum(not protocols.commutes(p0, p1)
                for p0, p1 in self.zip_paulis(other)) % 2 == 0
Пример #7
0
 def _commutes_(
     self,
     other: Any,
     *,
     atol: Union[int,
                 float] = 1e-8) -> Union[bool, NotImplementedType, None]:
     if not isinstance(other, Gate):
         return NotImplemented
     if protocols.qid_shape(self) != protocols.qid_shape(other):
         return None
     # HACK: break cycle
     from cirq.devices import line_qubit
     qs = line_qubit.LineQid.for_qid_shape(protocols.qid_shape(self))
     return protocols.commutes(self(*qs), other(*qs))
Пример #8
0
def _sorted_best_string_placements(
    possible_nodes: Iterable[Any],
    output_ops: Sequence[ops.Operation],
    key: Callable[[Any], ops.PauliStringPhasor] = lambda node: node.val,
) -> List[Tuple[ops.PauliStringPhasor, int,
                circuitdag.Unique[ops.PauliStringPhasor]]]:

    sort_key = lambda placement: (-len(placement[0].pauli_string), placement[1]
                                  )

    node_maxes = []
    for possible_node in possible_nodes:
        string_op = key(possible_node)
        # Try moving the Pauli string through, stop at measurements
        node_max = (string_op, 0, possible_node)

        for i, out_op in enumerate(output_ops):
            if not set(out_op.qubits) & set(string_op.qubits):
                # Skip if operations don't share qubits
                continue
            if isinstance(out_op,
                          ops.PauliStringPhasor) and protocols.commutes(
                              out_op.pauli_string, string_op.pauli_string):
                # Pass through another Pauli string if they commute
                continue
            if not (isinstance(out_op, ops.GateOperation) and isinstance(
                    out_op.gate,
                (ops.SingleQubitCliffordGate, ops.PauliInteractionGate,
                 ops.CZPowGate),
            )):
                # This is as far through as this Pauli string can move
                break
            string_op = string_op.pass_operations_over([out_op],
                                                       after_to_before=True)
            curr = (string_op, i + 1, possible_node)
            if sort_key(curr) > sort_key(node_max):
                node_max = curr

        node_maxes.append(node_max)

    return sorted(node_maxes, key=sort_key, reverse=True)
Пример #9
0
def pauli_string_reorder_pred(op1: ops.Operation, op2: ops.Operation) -> bool:
    ps1 = cast(ops.PauliStringGateOperation, op1).pauli_string
    ps2 = cast(ops.PauliStringGateOperation, op2).pauli_string
    return protocols.commutes(ps1, ps2)
Пример #10
0
def _all_pauli_strings_commute(pauli_sum: 'cirq.PauliSum') -> bool:
    for x in pauli_sum:
        for y in pauli_sum:
            if not protocols.commutes(x, y):
                return False
    return True