def _extend_matrix(self, sub_matrix: np.ndarray) -> np.ndarray:
     qid_shape = protocols.qid_shape(self)
     sub_n = len(qid_shape) - len(self.controls)
     tensor = qis.eye_tensor(qid_shape, dtype=sub_matrix.dtype)
     sub_tensor = sub_matrix.reshape(qid_shape[len(self.controls) :] * 2)
     for control_vals in itertools.product(*self.control_values):
         active = (*(v for v in control_vals), *(slice(None),) * sub_n) * 2
         tensor[active] = sub_tensor
     return tensor.reshape((np.prod(qid_shape, dtype=int),) * 2)
Beispiel #2
0
 def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
     sub_matrix = protocols.unitary(self.sub_operation, None)
     if sub_matrix is None:
         return NotImplemented
     qid_shape = protocols.qid_shape(self)
     sub_n = len(qid_shape) - len(self.controls)
     tensor = qis.eye_tensor(qid_shape, dtype=sub_matrix.dtype)
     sub_tensor = sub_matrix.reshape(qid_shape[len(self.controls):] * 2)
     for control_vals in itertools.product(*self.control_values):
         active = (*(v for v in control_vals), *(slice(None),) * sub_n) * 2
         tensor[active] = sub_tensor
     return tensor.reshape((np.prod(qid_shape, dtype=int),) * 2)
Beispiel #3
0
def assert_has_consistent_apply_unitary(val: Any,
                                        *,
                                        atol: float = 1e-8) -> None:
    """Tests whether a value's _apply_unitary_ is correct.

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

    Args:
        val: The value under test. Should have a `__pow__` method.
        atol: Absolute error tolerance.
    """
    # pylint: disable=unused-variable
    __tracebackhide__ = True
    # pylint: enable=unused-variable

    _assert_apply_unitary_works_when_axes_transposed(val, atol=atol)

    expected = protocols.unitary(val, default=None)

    qid_shape = protocols.qid_shape(val)

    eye = qis.eye_tensor((2, ) + qid_shape, dtype=np.complex128)
    actual = protocols.apply_unitary(
        unitary_value=val,
        args=protocols.ApplyUnitaryArgs(
            target_tensor=eye,
            available_buffer=np.ones_like(eye) * float('nan'),
            axes=list(range(1,
                            len(qid_shape) + 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((np.prod(
            (2, ) + qid_shape, dtype=int), ) * 2),
                                   expected,
                                   atol=atol)
Beispiel #4
0
def _strat_unitary_from_decompose(val: Any) -> Optional[np.ndarray]:
    """Attempts to compute a value's unitary via its _decompose_ method."""
    # Check if there's a decomposition.
    operations, qubits, val_qid_shape = _try_decompose_into_operations_and_qubits(
        val)
    if operations is None:
        return NotImplemented

    # Apply sub-operations' unitary effects to an identity matrix.
    state = qis.eye_tensor(val_qid_shape, dtype=np.complex128)
    buffer = np.empty_like(state)
    result = apply_unitaries(
        operations, qubits,
        ApplyUnitaryArgs(state, buffer, range(len(val_qid_shape))), None)

    # Package result.
    if result is None:
        return None
    state_len = np.prod(val_qid_shape, dtype=np.int64)
    return result.reshape((state_len, state_len))
Beispiel #5
0
def _strat_unitary_from_apply_unitary(val: Any) -> Optional[np.ndarray]:
    """Attempts to compute a value's unitary via its _apply_unitary_ method."""
    # Check for the magic method.
    method = getattr(val, '_apply_unitary_', None)
    if method is None:
        return NotImplemented

    # Get the qid_shape.
    val_qid_shape = qid_shape_protocol.qid_shape(val, None)
    if val_qid_shape is None:
        return NotImplemented

    # Apply unitary effect to an identity matrix.
    state = qis.eye_tensor(val_qid_shape, dtype=np.complex128)
    buffer = np.empty_like(state)
    result = method(ApplyUnitaryArgs(state, buffer, range(len(val_qid_shape))))

    if result is NotImplemented or result is None:
        return result
    state_len = np.prod(val_qid_shape, dtype=np.int64)
    return result.reshape((state_len, state_len))