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)
# 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)
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]))
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)