def _scan_single_qubit_ops(
        circuit: Circuit, index: Optional[int],
        qubit: ops.QubitId) -> Tuple[List[int], List[ops.Operation]]:
    operations = []  # type: List[ops.Operation]
    indices = []  # type: List[int]
    while index is not None:
        op = cast(ops.Operation, circuit.operation_at(qubit, index))
        if len(op.qubits) != 1 or protocols.unitary(op, None) is None:
            break
        indices.append(index)
        operations.append(op)
        index = circuit.next_moment_operating_on([qubit], index + 1)
    return indices, operations
Ejemplo n.º 2
0
    def _scan_two_qubit_ops_into_matrix(
            self,
            circuit: Circuit,
            index: Optional[int],
            qubits: Tuple[ops.QubitId, ...]
    ) -> Tuple[List[ops.Operation], List[int], np.ndarray]:
        """Accumulates operations affecting the given pair of qubits.

        The scan terminates when it hits the end of the circuit, finds an
        operation without a known matrix, or finds an operation that interacts
        the given qubits with other qubits.

        Args:
            circuit: The circuit to scan for operations.
            index: The index to start scanning forward from.
            qubits: The pair of qubits we care about.

        Returns:
            A tuple containing:
                0. The operations.
                1. The moment indices those operations were on.
                2. A matrix equivalent to the effect of the scanned operations.
        """

        product = np.eye(4, dtype=np.complex128)
        all_operations = []
        touched_indices = []

        while index is not None:
            operations = list({circuit.operation_at(q, index) for q in qubits})
            op_data = [
                self._op_to_matrix(op, qubits)
                for op in operations
                if op is not None
            ]

            # Stop at any non-constant or non-local interaction.
            if any(e is None for e in op_data):
                break
            present_ops = [op for op in operations if op]
            present_op_data = cast(List[np.ndarray], op_data)

            for op_mat in present_op_data:
                product = np.dot(op_mat, product)
            all_operations.extend(present_ops)

            touched_indices.append(index)
            index = circuit.next_moment_operating_on(qubits, index + 1)

        return all_operations, touched_indices, product
Ejemplo n.º 3
0
 def _scan_single_qubit_ops(
         self, circuit: Circuit, index: Optional[int],
         qubit: ops.QubitId) -> Tuple[List[int], List[ops.KnownMatrix]]:
     operations = []  # type: List[ops.KnownMatrix]
     indices = []  # type: List[int]
     while index is not None:
         op = cast(ops.Operation, circuit.operation_at(qubit, index))
         if len(op.qubits) != 1:
             break
         operation = self.extensions.try_cast(ops.KnownMatrix, op)
         if operation is None:
             break
         indices.append(index)
         operations.append(operation)
         index = circuit.next_moment_operating_on([qubit], index + 1)
     return indices, operations
Ejemplo n.º 4
0
def test_operation_at():
    a = cirq.QubitId()
    b = cirq.QubitId()

    c = Circuit()
    assert c.operation_at(a, 0) is None
    assert c.operation_at(a, -1) is None
    assert c.operation_at(a, 102) is None

    c = Circuit([Moment()])
    assert c.operation_at(a, 0) is None

    c = Circuit([Moment([cirq.X(a)])])
    assert c.operation_at(b, 0) is None
    assert c.operation_at(a, 1) is None
    assert c.operation_at(a, 0) == cirq.X(a)

    c = Circuit([Moment(), Moment([cirq.CZ(a, b)])])
    assert c.operation_at(a, 0) is None
    assert c.operation_at(a, 1) == cirq.CZ(a, b)