Fourier Parametrization¶
The class QAOAVariationalFourierParams
implements a heuristic proposed by Zhou et al. [1] which instead of optimizing for \(\beta\) and \(\gamma\) at each layer aims at finding the amplitudes of their discrete Fourier transforms given by:
where \(i = 0,...,p\).
For the curious
In the paper the series run from 1, while in our notation they run from 0, which changes slightly eq.(1) and eq.(2). Under the hood, we use the Scipy
implementation of discrete cosine and sine Fourier transform of type II.
The idea comes from the empirical observation that the optimal parameters are often found to be smoothly varying functions for certain problems (such as the one implemented by the QAOAVariationalAnnealingParams
class). Hence, it should be possible to use a reduced parameter set consisting of only the lowest \(q\) frequency components of those functions. Clearly, for \(q\geq p\) we have the full expressivity of the original parameter set (i.e. the \(\beta\) and \(\gamma\)). In this parametrisation, for fixed \(q\), the optimisation problem therefore becomes that of finding the optimal Fourier components \(v_k\) and \(u_k\).
In [1], the authors show that certain variants of this basic Fourier parametrisation can perform significantly better than a randomised brute force search through parameter space, for MaxCut problems on 3-regular and 4-regular graphs.
Number of parameters
The depth of the circuit is still linear in the number of layers, \(p\). The advantage is in the smaller number of variational parameters to be optimized, as long as \(q \leq p\).
Initialize with fourier parameters¶
Let us once again take the cost Hamiltonian to be \(H_C = 2.5 (Z_0Z_1 + Z_1Z_2 + Z_0Z_2) + 3.5 (Z_0 + Z_1 + Z_2)\) and construct a circuit of 4 layers (p=4). In the standard parametrization this would give \(2*4 = 8\) variational parameters. The fourier parametrization, however, allows to work with less. Let's set \(q=2\), giving only \(4\) parameters to be optimized. We can further specify the initial values of those using the custom initialization, for example with the following:
q.set_circuit_properties(p=4,
q=2,
param_type='fourier',
init_type='custom',
variational_params_dict={
"u":[0.1, 0.2],
"v":[0.9, 0.8]}
)
As a circuit, this looks like:
Let us now understand how the custom values we set for u and v translate to the rotational angles we see in the circuit above.
For example, the RX rotation between qubit 1 and 2 in the first layer is obtained by evaluating eq.(2) for i=0, p=4, q=2 and then simply multiplying by 2, as conventional.
This simplifies nicely since \(\cos(0)=1\) and we are left only with a sum over the chosen values of v which gives
For another, a bit more involved, example let us focus on the ZZ rotation between qubits 0 and 1 in the 3rd layer. This comes from evaluating eq.(1) for i=3, p=4, q=2 and then multiplying by the weight of the quadratic term of the cost hamiltonian and by 2, as conventional.
After substituting for the weight and the parameters we chose for u and after expanding the sum, we arrive at
which after simplifying gives
Indeed, this is what we see in the brackets next to this gate.
Fourier with ramp
When the fourier parametrization is initialized with ramp
, the optimization starts from \(\vec{v} = \vec{u} = [0.35, 0, 0, ..., 0]\) where the length of the vectors is \(q\). This is because at a single layer, \(p=1\), and no user-specified time, the standard parameters \(\beta\) and \(\gamma\) are 0.35.
Control the bias terms¶
The class QAOAVariationalFourierWithBiasParams
extends upon the above by allowing for an additional parameter controlling the single qubit rotations around the Z axis, analogous to what StandardWithBiasParams
implements.
One way to use this class is by setting the circuit properties as:
q.set_circuit_properties(p=4,
q=2,
param_type='fourier_w_bias',
init_type='custom',
variational_params_dict={
"u_pairs":[0.1, 0.2],
"u_singles":[0.5, 0.6],
"v":[0.9, 0.8]}
)
Since we kept the parameters controlling \(\beta\) and \(\gamma\) same as before and only gave new parameters for the single qubit rotations around the Z axis, the circuits look identical apart from the RZ gates.
Number of parameters
When using the QAOAVariationalFourierWithBiasParams
class the number of parameters to be optimized is \(3q\).
Control all terms¶
The class QAOAVariationalFourierExtendedParams
, similarly to the ExtendedParams
class, unlocks the full flexibility of the ansatz for this particular parametrization.
It can be used with the following piece of code:
q = QAOA()
q.set_circuit_properties(p=4,
q=2,
param_type='fourier_extended',
init_type='custom',
variational_params_dict={
"u_pairs":[[0.11, 0.12, 0.13], [0.21, 0.22, 0.23]],
"u_singles":[[0.51, 0.52, 0.53],[0.61, 0.62, 0.63]],
"v_pairs":[],
"v_singles":[[0.91, 0.92, 0.93], [0.81, 0.82, 0.83]]}
)
Number of parameters
Care must be taken when using the QAOAVariationalFourierExtendedParams
as the number of variational parameters scales linearly with n. As shown above, for 3 qubits circuit, \(n=3\) with \(q=2\) and the standard X mixer, the number of parameters is \(n*q*3=18\). Although this is still less than for the ExtendedParams
class, as long as \(q<p\), it can result in long optimization times.
References¶
- L. Zhou, S. Wang, S. Choi, H. Pichler, M. D. Lukin, Phys.Rev.X 10, 021067 (2020) Quantum Approximate Optimization Algorithm: Performance, Mechanism, and Implementation on Near-Term Devices, https://arxiv.org/abs/1812.01041.