Hi!
I am trying to using qml.fourier
module to approximate a function say cos(x)
. I am able to approximate the function with my quantum circuit. However, I was trying to extract the fourier coefficients of this trained quantum circuit and plot the Fourier series expansion. As I already know that the Fourier coefficients are c_0= 0 c_-1 = 0.5 and c_1=0.5. I need only one data encoding gate (RX) to approximate this simple function. However, if I use 2 rotation gates in the encoding layer, the output of the qml.fourier.coefficients
is c_-2=0.5 and c_2=0.5 and the other coefficients to zero. I get the correct results if I use only one gate, by setting r=1
and removing qml.RX(x, wires=1, id='x')
in the code. Can someone please let me know how to resolve this issue? I know that lowpass filter is used to solve the problem of showing higher order coefficients to the lower degree expansion. The problem I stated is the other way around. Thank you in advance for your kind support! Please see the code that I use below:
import pennylane as qml
from pennylane import numpy as np
from pennylane.fourier import *
from functools import partial
import numpy as nnp
import matplotlib.pyplot as plt
r = 2 #number of wires
dev = qml.device('default.qubit', wires=r)
@qml.qnode(dev)
def circuit(w, x):
qml.RX(w[0], wires=0)
qml.RX(x, wires=0, id="x")
qml.RX(x, wires=1, id='x')
qml.RX(w[1], wires=0)
return qml.expval(qml.PauliZ(wires=0))
weights = np.array([0.1, 0.1], requires_grad=True) #initial weights
X = np.linspace(0, 2 * np.pi, 20, requires_grad=True) #input points
opt = qml.AdamOptimizer(0.3) #optimizer
def cost(circuit, w, x):
'''Cost function which account for function approximation of cos(x)'''
return np.mean((circuit(w, x) - nnp.cos(x)) ** 2)
#Training the model
for step in range(20):
# select batch of data
batch_index = np.random.randint(0, len(X), (20,))
x_batch = X[batch_index]
# update the weights by one optimizer step
weights = opt.step(lambda w: cost(circuit, w, x_batch), weights)
freqs = circuit_spectrum(circuit)(weights, 0.2) #frequencies available in the circuit
print(freqs['x'])
degree = r
partial_circuit = partial(circuit, weights) #fixing the weights of the circuit
coeffs = coefficients(partial_circuit, 1, degree, lowpass_filter=True) #fourier coeffcients
print(coeffs)
conj_coeff = np.conjugate(coeffs)
def fourier_expansion(x):
"""Generate a truncated Fourier series of degree"""
res = coeffs[0]
for i in range(1, 2 * degree):
exponent = complex(0, (freqs['x'][i-1]) * x)
res += coeffs[i] * np.exp(exponent) + conj_coeff[i] * np.exp(-exponent)
return np.real(res)
f_points = []
p_points = []
a_points = []
for j in X:
f_points.append(fourier_expansion(j))
p_points.append(circuit(weights, j))
a_points.append(nnp.cos(j))
plt.plot(f_points, label='fourier series')
plt.plot(p_points, label='output')
plt.plot(a_points, label='target func')
plt.legend()
plt.show()
And, finally, make sure to include the versions of your packages. Specifically, show us the output of qml.about()
:
Name: PennyLane
Version: 0.35.1
Summary: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Home-page: GitHub - PennyLaneAI/pennylane: PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Train a quantum computer the same way as a neural network.
Author:
Author-email:
License: Apache License 2.0
Location: c:\users\hedge\miniconda3\envs\quantum_fourier_model\lib\site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane_Lightning
Platform info: Windows-10-10.0.22631-SP0
Python version: 3.10.13
Numpy version: 1.26.4
Scipy version: 1.12.0
Installed devices:
- default.clifford (PennyLane-0.35.1)
- default.gaussian (PennyLane-0.35.1)
- default.mixed (PennyLane-0.35.1)
- default.qubit (PennyLane-0.35.1)
- default.qubit.autograd (PennyLane-0.35.1)
- default.qubit.jax (PennyLane-0.35.1)
- default.qubit.legacy (PennyLane-0.35.1)
- default.qubit.tf (PennyLane-0.35.1)
- default.qubit.torch (PennyLane-0.35.1)
- default.qutrit (PennyLane-0.35.1)
- null.qubit (PennyLane-0.35.1)
- lightning.qubit (PennyLane_Lightning-0.35.1)