Пример #1
0
    def test_displaced_squeezed_state(self):
        """Test the displaced squeezed state is correct."""
        self.logTestName()
        alpha = 0.541+0.109j
        a = abs(alpha)
        phi_a = np.angle(alpha)
        r = 0.432
        phi_r = 0.123
        means, cov = displaced_squeezed_state(a, phi_a, r, phi_r, hbar=hbar)

        # test vector of means is correct
        self.assertAllAlmostEqual(means, np.array([alpha.real, alpha.imag])*np.sqrt(2*hbar), delta=self.tol)

        R = rotation(phi_r/2)
        expected = R @ np.array([[np.exp(-2*r), 0],
                                 [0, np.exp(2*r)]]) * hbar/2 @ R.T
        # test covariance matrix is correct
        self.assertAllAlmostEqual(cov, expected, delta=self.tol)
Пример #2
0
# random values to transform
x = np.random.random(M)
phi_x = np.zeros(M)
phi_r = np.zeros(M)
np.random.seed(1)

# initialize some random vals for the periodic convolution
init = np.random.uniform(low=-1, high=1, size=(2))

c = np.zeros(M)
c[0] = init[0]
c[1] = init[1]

# get the fourier transformed values and seperate argument and absolute value
complex_vals = np.fft.fft(c)
scale_arg = np.angle(complex_vals)
scale_abs = np.absolute(complex_vals)

# get the required squeeze scaling argument
r1 = -np.log(scale_abs)

# perform a neural network feed forward using the transformed Fourier matrix, the required phase shift using a rotation gate (phase gate),
# the required squeeze scaling and the Fourier matrix

circ_res = quantum_circ1(x=x,
                         phi_x=phi_x,
                         U1=F_H,
                         U2=F,
                         r=r1,
                         phi_r=phi_r,
                         phi_rot=scale_arg)
Пример #3
0
class AutogradBox(qml.math.TensorBox):
    """Implements the :class:`~.TensorBox` API for ``pennylane.numpy`` tensors.

    For more details, please refer to the :class:`~.TensorBox` documentation.
    """

    abs = wrap_output(lambda self: np.abs(self.data))
    angle = wrap_output(lambda self: np.angle(self.data))
    arcsin = wrap_output(lambda self: np.arcsin(self.data))
    cast = wrap_output(lambda self, dtype: np.tensor(self.data, dtype=dtype))
    diag = staticmethod(wrap_output(lambda values, k=0: np.diag(values, k=k)))
    expand_dims = wrap_output(
        lambda self, axis: np.expand_dims(self.data, axis=axis))
    ones_like = wrap_output(lambda self: np.ones_like(self.data))
    reshape = wrap_output(lambda self, shape: np.reshape(self.data, shape))
    sqrt = wrap_output(lambda self: np.sqrt(self.data))
    sum = wrap_output(lambda self, axis=None, keepdims=False: np.sum(
        self.data, axis=axis, keepdims=keepdims))
    T = wrap_output(lambda self: self.data.T)
    squeeze = wrap_output(lambda self: self.data.squeeze())

    @staticmethod
    def astensor(tensor):
        return np.tensor(tensor)

    @staticmethod
    @wrap_output
    def concatenate(values, axis=0):
        return np.concatenate(AutogradBox.unbox_list(values), axis=axis)

    @staticmethod
    @wrap_output
    def dot(x, y):
        x, y = AutogradBox.unbox_list([x, y])

        if x.ndim == 0 and y.ndim == 0:
            return x * y

        if x.ndim == 2 and y.ndim == 2:
            return x @ y

        return np.dot(x, y)

    @property
    def interface(self):
        return "autograd"

    def numpy(self):
        if hasattr(self.data, "_value"):
            # Catches the edge case where the data is an Autograd arraybox,
            # which only occurs during backpropagation.
            return self.data._value

        return self.data.numpy()

    @property
    def requires_grad(self):
        return self.data.requires_grad

    @wrap_output
    def scatter_element_add(self, index, value):
        size = self.data.size
        flat_index = np.ravel_multi_index(index, self.shape)
        t = [0] * size
        t[flat_index] = value
        self.data = self.data + np.array(t).reshape(self.shape)
        return self.data

    @property
    def shape(self):
        return self.data.shape

    @staticmethod
    @wrap_output
    def stack(values, axis=0):
        return np.stack(AutogradBox.unbox_list(values), axis=axis)

    @wrap_output
    def take(self, indices, axis=None):
        indices = self.astensor(indices)

        if axis is None:
            return self.data.flatten()[indices]

        fancy_indices = [slice(None)] * axis + [indices]
        return self.data[tuple(fancy_indices)]

    @staticmethod
    @wrap_output
    def where(condition, x, y):
        return np.where(condition, *AutogradBox.unbox_list([x, y]))
Пример #4
0
    def test_apply(self):
        """Test the application of gates to a state"""
        self.logTestName()

        # loop through all supported operations
        for gate_name, fn in self.dev._operation_map.items():
            log.debug("\tTesting %s gate...", gate_name)
            self.dev.reset()

            # start in the displaced squeezed state
            alpha = 0.542 + 0.123j
            a = abs(alpha)
            phi_a = np.angle(alpha)
            r = 0.652
            phi_r = -0.124

            self.dev.apply('DisplacedSqueezedState',
                           wires=[0],
                           par=[a, phi_a, r, phi_r])
            self.dev.apply('DisplacedSqueezedState',
                           wires=[1],
                           par=[a, phi_a, r, phi_r])

            # get the equivalent pennylane operation class
            op = qml.ops.__getattribute__(gate_name)
            # the list of wires to apply the operation to
            w = list(range(op.num_wires))

            if op.par_domain == 'A':
                # the parameter is an array
                if gate_name == 'GaussianState':
                    p = [
                        np.array([0.432, 0.123, 0.342, 0.123]),
                        np.diag([0.5234] * 4)
                    ]
                    w = list(range(2))
                    expected_out = p
                elif gate_name == 'Interferometer':
                    w = list(range(2))
                    p = [U]
                    S = fn(*p)
                    expected_out = S @ self.dev._state[0], S @ self.dev._state[
                        1] @ S.T
            else:
                # the parameter is a float
                p = [0.432423, -0.12312, 0.324, 0.751][:op.num_params]

                if gate_name == 'Displacement':
                    alpha = p[0] * np.exp(1j * p[1])
                    state = self.dev._state
                    mu = state[0].copy()
                    mu[w[0]] += alpha.real * np.sqrt(2 * hbar)
                    mu[w[0] + 2] += alpha.imag * np.sqrt(2 * hbar)
                    expected_out = mu, state[1]
                elif 'State' in gate_name:
                    mu, cov = fn(*p, hbar=hbar)
                    expected_out = self.dev._state
                    expected_out[0][[w[0], w[0] + 2]] = mu

                    ind = np.concatenate(
                        [np.array([w[0]]),
                         np.array([w[0]]) + 2])
                    rows = ind.reshape(-1, 1)
                    cols = ind.reshape(1, -1)
                    expected_out[1][rows, cols] = cov
                else:
                    # if the default.gaussian is an operation accepting parameters,
                    # initialise it using the parameters generated above.
                    S = fn(*p)

                    # calculate the expected output
                    if op.num_wires == 1:
                        # reorder from symmetric ordering to xp-ordering
                        S = block_diag(
                            S, np.identity(2))[:, [0, 2, 1, 3]][[0, 2, 1, 3]]

                    expected_out = S @ self.dev._state[0], S @ self.dev._state[
                        1] @ S.T

            self.dev.apply(gate_name, wires=w, par=p)

            # verify the device is now in the expected state
            self.assertAllAlmostEqual(self.dev._state[0],
                                      expected_out[0],
                                      delta=self.tol)
            self.assertAllAlmostEqual(self.dev._state[1],
                                      expected_out[1],
                                      delta=self.tol)