Exemplo n.º 1
0
    def with_operations(self, *contents: 'cirq.OP_TREE') -> 'cirq.Moment':
        """Returns a new moment with the given contents added.

        Args:
            contents: New operations to add to this moment.

        Returns:
            The new moment.
        """
        from cirq.ops import op_tree

        operations = list(self._operations)
        qubits = set(self._qubits)
        for op in op_tree.flatten_to_ops(contents):
            if any(q in qubits for q in op.qubits):
                raise ValueError('Overlapping operations: {}'.format(op))
            operations.append(op)
            qubits.update(op.qubits)

        # Use private variables to facilitate a quick copy.
        m = Moment()
        m._operations = tuple(operations)
        m._qubits = frozenset(qubits)
        m._qubit_to_op = self._qubit_to_op.copy()
        for op in operations:
            for q in op.qubits:
                m._qubit_to_op[q] = op

        return m
Exemplo n.º 2
0
    def __init__(self, *contents: 'cirq.OP_TREE') -> None:
        """Constructs a moment with the given operations.

        Args:
            operations: The operations applied within the moment.
                Will be flattened and frozen into a tuple before storing.

        Raises:
            ValueError: A qubit appears more than once.
        """
        from cirq.ops import op_tree

        self._operations = tuple(op_tree.flatten_to_ops(contents))

        # An internal dictionary to support efficient operation access by qubit.
        self._qubit_to_op: Dict['cirq.Qid', 'cirq.Operation'] = {}
        for op in self.operations:
            for q in op.qubits:
                # Check that operations don't overlap.
                if q in self._qubit_to_op:
                    raise ValueError('Overlapping operations: {}'.format(
                        self.operations))
                self._qubit_to_op[q] = op

        self._qubits = frozenset(self._qubit_to_op.keys())
Exemplo n.º 3
0
def _decompose_into_cliffords(op: 'cirq.Operation') -> List['cirq.Operation']:
    # An operation that can be ignored?
    if isinstance(op, global_phase_op.GlobalPhaseOperation):
        return []

    # Already a known Clifford?
    if isinstance(op.gate, (clifford_gate.SingleQubitCliffordGate,
                            pauli_interaction_gate.PauliInteractionGate)):
        return [op]

    # Specifies a decomposition into Cliffords?
    v = getattr(op, '_decompose_into_clifford_', None)
    if v is not None:
        result = v()
        if result is not None and result is not NotImplemented:
            return list(op_tree.flatten_to_ops(result))

    # Specifies a decomposition that happens to contain only Cliffords?
    decomposed = protocols.decompose_once(op, None)
    if decomposed is not None:
        return [
            out for sub_op in decomposed
            for out in _decompose_into_cliffords(sub_op)
        ]

    raise TypeError(f'Operation is not a known Clifford and did not decompose '
                    f'into known Cliffords: {op!r}')
Exemplo n.º 4
0
    def __init__(self, *contents: 'cirq.OP_TREE') -> None:
        """Constructs a moment with the given operations.

        Args:
            contents: The operations applied within the moment.
                Will be flattened and frozen into a tuple before storing.

        Raises:
            ValueError: A qubit appears more than once.
        """
        self._operations = tuple(op_tree.flatten_to_ops(contents))

        # An internal dictionary to support efficient operation access by qubit.
        self._qubit_to_op: Dict['cirq.Qid', 'cirq.Operation'] = {}
        for op in self.operations:
            for q in op.qubits:
                # Check that operations don't overlap.
                if q in self._qubit_to_op:
                    raise ValueError(
                        f'Overlapping operations: {self.operations}')
                self._qubit_to_op[q] = op

        self._qubits = frozenset(self._qubit_to_op.keys())
        self._measurement_key_objs: Optional[
            AbstractSet['cirq.MeasurementKey']] = None
        self._control_keys: Optional[FrozenSet['cirq.MeasurementKey']] = None
Exemplo n.º 5
0
    def validate(self, circuit_or_optree: Union['cirq.AbstractCircuit', op_tree.OP_TREE]) -> bool:
        """Validates gates forming `circuit_or_optree` should be contained in Gateset.

        Args:
            circuit_or_optree: The `cirq.Circuit` or `cirq.OP_TREE` to validate.
        """
        # To avoid circular import.
        from cirq.circuits import circuit

        optree = circuit_or_optree
        if isinstance(circuit_or_optree, circuit.AbstractCircuit):
            optree = circuit_or_optree.all_operations()
        return all(self._validate_operation(op) for op in op_tree.flatten_to_ops(optree))
Exemplo n.º 6
0
    def __sub__(self, other: 'cirq.OP_TREE') -> 'cirq.Moment':

        must_remove = set(op_tree.flatten_to_ops(other))
        new_ops = []
        for op in self.operations:
            if op in must_remove:
                must_remove.remove(op)
            else:
                new_ops.append(op)
        if must_remove:
            raise ValueError(f"Subtracted missing operations from a moment.\n"
                             f"Missing operations: {must_remove!r}\n"
                             f"Moment: {self!r}")
        return Moment(new_ops)
Exemplo n.º 7
0
    def __init__(self, *contents: 'cirq.OP_TREE') -> None:
        """Constructs a moment with the given operations.

        Args:
            operations: The operations applied within the moment.
                Will be flattened and frozen into a tuple before storing.

        Raises:
            ValueError: A qubit appears more than once.
        """
        from cirq.ops import op_tree
        self._operations = tuple(op_tree.flatten_to_ops(contents))

        # Check that operations don't overlap.
        affected_qubits = [q for op in self.operations for q in op.qubits]
        self._qubits = frozenset(affected_qubits)
        if len(affected_qubits) != len(self._qubits):
            raise ValueError(
                'Overlapping operations: {}'.format(self.operations))
Exemplo n.º 8
0
    def with_operations(self, *contents: 'cirq.OP_TREE') -> 'cirq.Moment':
        """Returns a new moment with the given contents added.

        Args:
            *contents: New operations to add to this moment.

        Returns:
            The new moment.

        Raises:
            ValueError: If the contents given overlaps a current operation in the moment.
        """
        flattened_contents = tuple(op_tree.flatten_to_ops(contents))

        m = Moment()
        # Use private variables to facilitate a quick copy.
        m._qubit_to_op = self._qubit_to_op.copy()
        qubits = set(self._qubits)
        for op in flattened_contents:
            if any(q in qubits for q in op.qubits):
                raise ValueError(f'Overlapping operations: {op}')
            qubits.update(op.qubits)
            for q in op.qubits:
                m._qubit_to_op[q] = op
        m._qubits = frozenset(qubits)

        m._operations = self._operations + flattened_contents
        m._sorted_operations = None
        m._measurement_key_objs = self._measurement_key_objs_().union(
            set(
                itertools.chain(*(protocols.measurement_key_objs(op)
                                  for op in flattened_contents))))
        m._control_keys = self._control_keys_().union(
            set(
                itertools.chain(*(protocols.control_keys(op)
                                  for op in flattened_contents))))

        return m
Exemplo n.º 9
0
    def conjugated_by(self, clifford: 'cirq.OP_TREE') -> 'PauliString':
        r"""Returns the Pauli string conjugated by a clifford operation.

        The product-of-Paulis $P$ conjugated by the Clifford operation $C$ is

            $$
            C^\dagger P C
            $$

        For example, conjugating a +Y operation by an S operation results in a
        +X operation (as opposed to a -X operation).

        In a circuit diagram where `P` is a pauli string observable immediately
        after a Clifford operation `C`, the pauli string `P.conjugated_by(C)` is
        the equivalent pauli string observable just before `C`.

            --------------------------C---P---

            = ---C---P------------------------

            = ---C---P---------C^-1---C-------

            = ---C---P---C^-1---------C-------

            = --(C^-1 · P · C)--------C-------

            = ---P.conjugated_by(C)---C-------

        Analogously, a Pauli product P can be moved from before a Clifford C in
        a circuit diagram to after the Clifford C by conjugating P by the
        inverse of C:

            ---P---C---------------------------

            = -----C---P.conjugated_by(C^-1)---

        Args:
            clifford: The Clifford operation to conjugate by. This can be an
                individual operation, or a tree of operations.

                Note that the composite Clifford operation defined by a sequence
                of operations is equivalent to a circuit containing those
                operations in the given order. Somewhat counter-intuitively,
                this means that the operations in the sequence are conjugated
                onto the Pauli string in reverse order. For example,
                `P.conjugated_by([C1, C2])` is equivalent to
                `P.conjugated_by(C2).conjugated_by(C1)`.

        Examples:
            >>> a, b = cirq.LineQubit.range(2)
            >>> print(cirq.X(a).conjugated_by(cirq.CZ(a, b)))
            X(0)*Z(1)
            >>> print(cirq.X(a).conjugated_by(cirq.S(a)))
            -Y(0)
            >>> print(cirq.X(a).conjugated_by([cirq.H(a), cirq.CNOT(a, b)]))
            Z(0)*X(1)

        Returns:
            The Pauli string conjugated by the given Clifford operation.
        """
        pauli_map = dict(self._qubit_pauli_map)
        should_negate = False
        for op in list(op_tree.flatten_to_ops(clifford))[::-1]:
            if pauli_map.keys().isdisjoint(set(op.qubits)):
                continue
            for clifford_op in _decompose_into_cliffords(op)[::-1]:
                if pauli_map.keys().isdisjoint(set(clifford_op.qubits)):
                    continue
                should_negate ^= PauliString._pass_operation_over(
                    pauli_map, clifford_op, False)
        coef = -self._coefficient if should_negate else self.coefficient
        return PauliString(qubit_pauli_map=pauli_map, coefficient=coef)