Esempio n. 1
0
    def _apply_unitary_to_tensor_(
        self,
        target_tensor: np.ndarray,
        available_buffer: np.ndarray,
        axes: Sequence[int],
    ) -> np.ndarray:
        control = axes[0]
        rest = axes[1:]
        active = linalg.slice_for_qubits_equal_to([control], 1)
        sub_axes = [r - int(r > control) for r in rest]
        target_view = target_tensor[active]
        buffer_view = available_buffer[active]
        result = protocols.apply_unitary_to_tensor(self.sub_gate,
                                                   target_view,
                                                   buffer_view,
                                                   sub_axes,
                                                   default=NotImplemented)

        if result is NotImplemented:
            return NotImplemented

        if result is target_view:
            return target_tensor

        if result is buffer_view:
            inactive = linalg.slice_for_qubits_equal_to([control], 0)
            available_buffer[inactive] = target_tensor[inactive]
            return available_buffer

        # HACK: assume they didn't somehow escape the slice view and edit the
        # rest of target_tensor.
        target_tensor[active] = result
        return target_tensor
Esempio n. 2
0
def assert_apply_unitary_to_tensor_is_consistent_with_unitary(
        val: Any,
        exponents: Sequence[Any] = (1,),
        qubit_count: Optional[int] = None) -> None:

    n = qubit_count if qubit_count is not None else _infer_qubit_count(val)

    for exponent in exponents:
        val_exp = val if exponent == 1 else val**exponent
        eye = np.eye(2 << n, dtype=np.complex128).reshape((2,) * (2 * n + 2))
        actual = protocols.apply_unitary_to_tensor(
            val=val_exp,
            target_tensor=eye,
            available_buffer=np.ones_like(eye) * float('nan'),
            axes=list(range(n)),
            default=None)
        expected = protocols.unitary(val_exp, default=None)

        # If you don't have a unitary, you shouldn't be able to apply a unitary.
        if expected is None:
            assert actual is None
        else:
            expected = np.kron(expected, np.eye(2))

        # If you applied a unitary, it should match the one you say you have.
        if actual is not None:
            np.testing.assert_allclose(
                actual.reshape(2 << n, 2 << n),
                expected)
Esempio n. 3
0
    def _base_iterator(
        self,
        circuit: circuits.Circuit,
        qubit_order: ops.QubitOrderOrList,
        initial_state: Union[int, np.ndarray],
        perform_measurements: bool = True,
    ) -> Iterator[simulator.StepResult]:
        qubits = ops.QubitOrder.as_qubit_order(qubit_order).order_for(
            circuit.all_qubits())
        num_qubits = len(qubits)
        qubit_map = {q: i for i, q in enumerate(qubits)}
        state = wave_function.to_valid_state_vector(initial_state, num_qubits,
                                                    self._dtype)

        def on_stuck(bad_op: ops.Operation):
            return TypeError(
                "Can't simulate unknown operations that don't specify a "
                "_unitary_ method, a _decompose_ method, or "
                "(_has_unitary_ + _apply_unitary_to_tensor_) methods"
                ": {!r}".format(bad_op))

        def keep(potential_op: ops.Operation) -> bool:
            return (protocols.has_unitary(potential_op)
                    or ops.MeasurementGate.is_measurement(potential_op))

        state = np.reshape(state, (2, ) * num_qubits)
        buffer = np.empty((2, ) * num_qubits, dtype=self._dtype)
        for moment in circuit:
            measurements = collections.defaultdict(
                list)  # type: Dict[str, List[bool]]

            unitary_ops_and_measurements = protocols.decompose(
                moment.operations, keep=keep, on_stuck_raise=on_stuck)

            for op in unitary_ops_and_measurements:
                indices = [qubit_map[qubit] for qubit in op.qubits]
                if ops.MeasurementGate.is_measurement(op):
                    gate = cast(ops.MeasurementGate,
                                cast(ops.GateOperation, op).gate)
                    if perform_measurements:
                        invert_mask = gate.invert_mask or num_qubits * (
                            False, )
                        # Measure updates inline.
                        bits, _ = wave_function.measure_state_vector(
                            state, indices, state)
                        corrected = [
                            bit ^ mask for bit, mask in zip(bits, invert_mask)
                        ]
                        measurements[cast(str, gate.key)].extend(corrected)
                else:
                    result = protocols.apply_unitary_to_tensor(
                        op, state, buffer, indices)
                    if result is buffer:
                        buffer = state
                    state = result
            yield SimulatorStep(state, measurements, qubit_map, self._dtype)
Esempio n. 4
0
 def _apply_unitary_to_tensor_(self,
                               target_tensor: np.ndarray,
                               available_buffer: np.ndarray,
                               axes: Sequence[int],
                               ) -> np.ndarray:
     return protocols.apply_unitary_to_tensor(
         controlled_gate.ControlledGate(common_gates.SWAP),
         target_tensor,
         available_buffer,
         axes,
         default=NotImplemented)
Esempio n. 5
0
 def _apply_unitary_to_tensor_(
     self,
     target_tensor: np.ndarray,
     available_buffer: np.ndarray,
     axes: Sequence[int],
 ) -> Union[np.ndarray, NotImplementedType]:
     return protocols.apply_unitary_to_tensor(self.gate,
                                              target_tensor,
                                              available_buffer,
                                              axes,
                                              default=NotImplemented)
Esempio n. 6
0
 def _apply_unitary_to_tensor_(
     self,
     target_tensor: np.ndarray,
     available_buffer: np.ndarray,
     axes: Sequence[int],
 ) -> np.ndarray:
     if protocols.is_parameterized(self):
         return NotImplemented
     p = 1j**(2 * self._exponent * self._global_shift)
     if p != 1:
         target_tensor *= p
     return protocols.apply_unitary_to_tensor(
         controlled_gate.ControlledGate(
             controlled_gate.ControlledGate(common_gates.X**self.exponent)),
         target_tensor,
         available_buffer,
         axes,
         default=NotImplemented)
Esempio n. 7
0
def assert_has_consistent_apply_unitary(
        val: Any,
        *,
        qubit_count: Optional[int] = None) -> None:
    """Tests whether a value's _apply_unitary_to_tensor_ is correct.

    Contrasts the effects of the value's `_apply_unitary_to_tensor_` with the
    matrix returned by the value's `_unitary_` method.

    Args:
        val: The value under test. Should have a `__pow__` method.
        qubit_count: Usually inferred. The number of qubits the value acts on.
            This argument isn't needed if the gate has a unitary matrix or
            implements `cirq.SingleQubitGate`/`cirq.TwoQubitGate`/
            `cirq.ThreeQubitGate`.
    """

    expected = protocols.unitary(val, default=None)
    if qubit_count is not None:
        n = qubit_count
    elif expected is not None:
        n = expected.shape[0].bit_length() - 1
    else:
        n = _infer_qubit_count(val)

    eye = np.eye(2 << n, dtype=np.complex128).reshape((2,) * (2 * n + 2))
    actual = protocols.apply_unitary_to_tensor(
        val=val,
        target_tensor=eye,
        available_buffer=np.ones_like(eye) * float('nan'),
        axes=list(range(1, n + 1)),
        default=None)

    # If you don't have a unitary, you shouldn't be able to apply a unitary.
    if expected is None:
        assert actual is None
    else:
        expected = np.kron(np.eye(2), expected)

    # If you applied a unitary, it should match the one you say you have.
    if actual is not None:
        np.testing.assert_allclose(
            actual.reshape(2 << n, 2 << n),
            expected)