def target_function(x): """Generate a truncated Fourier series, where the data gets re-scaled.""" res = coeff0 for idx, coeff in enumerate(coeffs): exponent = np.complex(0, scaling * (idx + 1) * x) conj_coeff = np.conjugate(coeff) res += coeff * np.exp(exponent) + conj_coeff * np.exp(-exponent) return np.real(res)
def mt(*params): state = qnode(*params) rqnode = lambda *params: np.real(qnode(*params)) iqnode = lambda *params: np.imag(qnode(*params)) rjac = qml.jacobian(rqnode)(*params) ijac = qml.jacobian(iqnode)(*params) if isinstance(rjac, tuple): out = [] for rc, ic in zip(rjac, ijac): c = rc + 1j * ic psidpsi = np.tensordot(np.conj(state), c, axes=([0], [0])) out.append( np.real( np.tensordot(np.conj(c), c, axes=([0], [0])) - np.tensordot(np.conj(psidpsi), psidpsi, axes=0))) return tuple(out) jac = rjac + 1j * ijac psidpsi = np.tensordot(np.conj(state), jac, axes=([0], [0])) return np.real( np.tensordot(np.conj(jac), jac, axes=([0], [0])) - np.tensordot(np.conj(psidpsi), psidpsi, axes=0))
# 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) # theoretical transformation mat = F @ np.diag(scale_abs * np.exp(1J * scale_arg)) @ F_H # applied theoretical result to the input theo_res = np.real(mat @ x) # difference int the theoretical transform and the actual result of the circuit print('theo') print(theo_res) print('actual') print(circ_res)
ang = get_angles(x) @qml.qnode(dev) def test(angles=None): statepreparation(angles) return qml.expval(qml.PauliZ(0)) test(angles=ang) print("x : ", x) print("angles : ", ang) print("amplitude vector: ", np.real(dev._state)) ############################################################################## # Note that the ``default.qubit`` simulator provides a shortcut to # ``statepreparation`` with the command # ``qml.QubitStateVector(x, wires=[0, 1])``. However, some devices may not # support an arbitrary state-preparation routine. # # Since we are working with only 2 qubits now, we need to update the layer # function as well. def layer(W): qml.Rot(W[0, 0], W[0, 1], W[0, 2], wires=0) qml.Rot(W[1, 0], W[1, 1], W[1, 2], wires=1) qml.CNOT(wires=[0, 1])
def loss_fn(x): res = func(x) return anp.real( res ) # This errors without the real. Likely an issue with complex
n_coeffs = 5 n_samples = 100 coeffs = [] for i in range(n_samples): weights = random_weights() def f(x): return np.array([quantum_model(weights, x_) for x_ in x]) coeffs_sample = fourier_coefficients(f, n_coeffs) coeffs.append(coeffs_sample) coeffs = np.array(coeffs) coeffs_real = np.real(coeffs) coeffs_imag = np.imag(coeffs) ###################################################################### # Let's plot the real vs. the imaginary part of the coefficients. As a # sanity check, the :math:`c_0` coefficient should be real, and therefore # have no contribution on the y-axis. # n_coeffs = len(coeffs_real[0]) fig, ax = plt.subplots(1, n_coeffs, figsize=(15, 4)) for idx, ax_ in enumerate(ax): ax_.set_title(r"$c_{}$".format(idx)) ax_.scatter(coeffs_real[:, idx],
def second_renyi_entropy(rho): """Computes the second Renyi entropy of a given density matrix.""" # DO NOT MODIFY anything in this code block rho_diag_2 = np.diagonal(rho)**2.0 return -np.real(np.log(np.sum(rho_diag_2)))
# Finally, we see how the approximation improves as we increase the # number of snapshots. We run the estimator 10 times for each :math:`N`. number_of_runs = 10 snapshots_range = [100, 1000, 6000] distances = np.zeros((number_of_runs, len(snapshots_range))) # run the estimation multiple times so that we can include error bars for i in range(number_of_runs): for j, num_snapshots in enumerate(snapshots_range): shadow = calculate_classical_shadow( bell_state_circuit, params, num_snapshots, num_qubits ) shadow_state = shadow_state_reconstruction(shadow) distances[i, j] = np.real(operator_2_norm(bell_state - shadow_state)) plt.errorbar( snapshots_range, np.mean(distances, axis=0), yerr=np.std(distances, axis=0), ) plt.title("Distance between Ideal and Shadow Bell States") plt.xlabel("Number of Snapshots") plt.ylabel("Distance") plt.show() ############################################################################## # As expected, when the number of snapshots increases, the state reconstruction # becomes closer to the ideal state.
def cost(self, weights, inputs_1=None, inputs_2=None): ensemble_1 = self.embedding.generate_ensemble(inputs_1, weights) ensemble_2 = self.embedding.generate_ensemble(inputs_2, weights) observable = self.class_priors[0] * ensemble_1 - self.class_priors[ 1] * ensemble_2 return 1 - np.real(np.trace(observable @ observable))