Running variational algorithms
This framework comes with a collection of tools to efficiently describe and run variational quantum algorithm. This page introduces the basic mechanics allowing you to write variational schemes.
Writing variational circuits is discussed in another section.
Extending a QPU to support variational jobs
The simplest way to run a variational algorithm is to use a dedicated Plugin that will take care of the energy minimization.
The default variational Plugin wraps the scipy.optimize.minimize function: ScipyMinimizePlugin
. This plugin
extends an exisiting QPU by using the “|” operator
from qat.plugins import ScipyMinimizePlugin
from qat.qpus import get_default_qpu
qpu = (
ScipyMinimizePlugin(method="COBYLA", tol=1e-3, options={"maxiter": 150})
| get_default_qpu()
)
This new QPU will optimize the abstract variable parametrizing the submitted job, to minimize the measured average value of the observable attached to the job.
from qat.lang import qrout, RY, RZ
from qat.core import Observable, Term, Variable
# Define the observable
t = Variable("t")
obs = sum((1 - t) * Observable.sigma_x(idx) for idx in range(3))
# Define the Ansatz
@qrout
def ansatz(theta):
" Dummy Ansatz"
for qbit in range(3):
RY(theta)(qbit)
RZ(4 * theta)(qbit)
# Define job and submit it
job = ansatz.to_job(observable=obs)
result = qpu.submit(job)
print('final energy:', result.value)
print('best parameters:', result.parameter_map)
print('trace:', result.meta_data['optimization_trace'])
final energy: -10.916735368356278
best parameters: {'t': -4.006962399326393, 'theta': 0.8456745564489095}
trace: [-0.7238644499442355, 1.4424404200558907, 0.3605977037868817, -0.16028846853297635, -1.1847076160553212, 0.40345962397413293, -1.3427834209599792, -2.2788640264032134, -3.3156597676213817, -2.9785207834713097, -2.090428376482937, -3.034619932166386, -3.170463199956326, -3.4199232704708526, -3.2334698332899143, -3.488909452870865, -3.5563883242732883, -3.6111268229943763, -3.681914461024951, -3.7474922768348855, -3.815604647926592, -3.883801579324434, -3.952068712299663, -4.020385246489566, -4.088691279342445, -4.156925766353516, -4.225100899126921, -4.293203119532166, -4.361374632539239, -4.429473423953059, -4.497627112843779, -4.565765579694931, -4.6339219208632665, -4.702068870877859, -4.770221044353228, -4.838373707674069, -4.906525957816083, -4.974677715751644, -5.042829770204554, -5.110981770818085, -5.179125912715975, -5.247280403139576, -5.315429761375151, -5.383582064565826, -5.451734477764558, -5.519886562240716, -5.588038529447911, -5.656190480193986, -5.724342350574416, -5.792494381768353, -5.860646380892876, -5.928797926541394, -5.996950074231608, -6.0651019358178315, -6.133253949388598, -6.20140597195046, -6.2695579751655295, -6.337709970856862, -6.40586196374644, -6.474013958267795, -6.542165957000476, -6.610317954928897, -6.678469951352948, -6.746621949526811, -6.814773945320668, -6.882925942616414, -6.951077938407315, -7.019229931410483, -7.087381928012338, -7.155533924428369, -7.223685919835009, -7.291837903153706, -7.359989696028966, -7.428141757632886, -7.496293751590622, -7.564445723864852, -7.632597716774863, -7.700749685268594, -7.76890149788181, -7.837053536715411, -7.905205568399482, -7.973357531173214, -8.041509541950228, -8.10966150459685, -8.177813492506882, -8.245965476440377, -8.314117452642769, -8.382269443312468, -8.450421414644433, -8.51857303202806, -8.586724727449496, -8.654876168432054, -8.72302427197884, -8.791167766830522, -8.859317011745567, -8.927465477868992, -8.99560875379649, -9.063535221405399, -9.13155315486273, -9.19934405717236, -9.263988288812522, -9.327781415005706, -9.39149224901892, -9.440168313810272, -9.501549015225983, -9.520982325956979, -9.308316901747638, -9.603723072176555, -9.587132656702524, -9.607778993509587, -9.631906264797987, -9.667221986005604, -9.694545358940491, -9.730161814444518, -9.762201094970573, -9.796703854360494, -9.830942221352139, -9.864888145341723, -9.898994424887968, -9.933074310676991, -9.96714514434107, -10.001222407126232, -10.035297763089677, -10.06929644955695, -10.1033961713893, -10.13746021313116, -10.171531252351404, -10.205593662298664, -10.23953702166662, -10.27362098084407, -10.307565878334174, -10.341603157589953, -10.37559394255587, -10.409124415104426, -10.44300935537938, -10.476557404161882, -10.506804106748643, -10.540796275178042, -10.571280266366706, -10.60477008542901, -10.636292429332785, -10.669926827815338, -10.701830180251884, -10.734756423245393, -10.767045044250578, -10.791618306035009, -10.827193300589169, -10.851817132255785, -10.88739753945245, -10.916735368356278]
This plugin also supports a nice feature: it can read optimization parameters directly from the job’s meta data or directly from the result. This allows you to build a stack with no particular choice of optimization parameters and attach these parameters directly to the job when submitting it. In this setting, the previous example becomes:
import json
from qat.plugins import ScipyMinimizePlugin
from qat.qpus import get_default_qpu
qpu = (
ScipyMinimizePlugin()
| get_default_qpu()
)
from qat.lang import qrout, RY, RZ
from qat.core import Observable, Term, Variable
# Define the observable
t = Variable("t")
obs = sum((1 - t) * Observable.sigma_x(idx) for idx in range(3))
# Define the Ansatz
@qrout
def ansatz(theta):
" Dummy Ansatz"
for qbit in range(3):
RY(theta)(qbit)
RZ(4 * theta)(qbit)
# Define job and submit it
job = ansatz.to_job(observable=obs)
optimizer_args = {
"method": "COBYLA",
"tol": 1e-3,
"options": {"maxiter": 150}
}
result = qpu.submit(job, meta_data={"ScipyMinimizePlugin": json.dumps(optimizer_args)})
print('final energy:', result.value)
print('best parameters:', result.parameter_map)
print('trace:', result.meta_data['optimization_trace'])
final energy: -11.741890076597265
best parameters: {'t': 6.384182271068701, 'theta': -0.8420575265599467}
trace: [0.11188378850969406, -0.2563064618485502, 0.22317694411627614, -1.9877952367911216, 4.369965004151404, 0.09799343735690907, -0.7451812500708982, -2.798800415053689, -1.9942113418026945, -2.3175395637312723, -2.810697148986073, -2.948329672698289, -3.09483657434794, -3.164575355834647, -2.9049189976772007, -3.30747532431854, -3.3969117808450244, -3.1293131004638712, -3.5139960947603197, -3.603845256364666, -3.4349929412365423, -3.719202239759416, -3.783841016964653, -3.448024506654489, -3.924451387695758, -3.954317191130725, -3.620480633638869, -4.127634182926933, -4.160921716691587, -4.336397913852055, -4.399182019240352, -4.564913251411358, -4.646406060874543, -4.805700813644624, -4.892662539674824, -5.048866311236385, -5.127260769971701, -5.283128754132125, -5.331829832603108, -5.496381701788584, -5.4832752200943595, -5.5127435930738065, -5.600082342564688, -5.648078200819214, -5.719880226579707, -5.790365290725034, -5.858418872325783, -5.926596181341914, -5.99061227217427, -6.0601274024474865, -6.1265991137146685, -6.195172223258634, -6.262773185568237, -6.330767852274681, -6.3985460402504675, -6.464504120723472, -6.516774208031645, -6.587286789895529, -6.658267429511921, -6.726366152774516, -6.794445499368543, -6.860573198123154, -6.9291440276536225, -6.996424367850681, -7.064906614324585, -7.132106212743862, -7.200536061234072, -7.268061944265737, -7.336441114787923, -7.403935807116948, -7.4722852205262305, -7.539934871532686, -7.608258075228692, -7.675867807088178, -7.744156405914537, -7.811845065289795, -7.88011598444586, -7.947755321689877, -8.015944700666246, -8.083639567710708, -8.151778392812824, -8.219438727948251, -8.287317717733382, -8.355107933907565, -8.422766074043466, -8.49063762720205, -8.556887918666854, -8.625527662853415, -8.691129601744446, -8.760159503654648, -8.828370856602406, -8.896311243574312, -8.964116699108054, -9.032324486128486, -9.100453264454025, -9.167482306715902, -9.232221472466673, -9.300299981114637, -9.369370869511558, -9.43814936323697, -9.505476028159343, -9.57365190398248, -9.641163203568034, -9.698325399456019, -9.771454331435885, -9.832494608530485, -9.903870338834297, -9.967624595245514, -10.037753594493001, -10.10362907562963, -10.172711707105874, -10.240409183927941, -10.308522077835699, -10.376533286548867, -10.44392424949426, -10.50823074061111, -10.57711561726082, -10.64651833853478, -10.71366537406745, -10.782269997637133, -10.848966579258388, -10.915553618372266, -10.982456618285148, -11.046231085538466, -10.941234567244415, -11.044388889917707, -11.05733928745824, -11.051259134430348, -11.02216552930954, -11.102310586037776, -11.12016931064947, -11.158194216865791, -11.1918269808267, -11.225662709998591, -11.259468024005118, -11.293501385687462, -11.325857511795414, -11.358969875667245, -11.391470112630122, -11.416797670270471, -11.451831884578324, -11.476151950795549, -11.511297046533972, -11.53896304493953, -11.574902151651113, -11.605172695566242, -11.64048672057029, -11.673658399528177, -11.707733462692389, -11.741890076597265]
An alternative is the SeqOptim
Plugin, which only works for a certain class of circuits but stands out for its
shot-noise resilience.
Differentiating jobs
Many variational algorithms require computing the gradient of the cost function \(E(\vec{\theta}) = \langle \psi(\vec{\theta}) | H | \psi(\vec{\theta})\rangle\).
The gradient can be used in gradient-based optimization methods.
Qaptiva jobs come with methods to compute the derivative of \(E(\vec{\theta})\) automically: differentiate()
and gradient()
.
Examples of use of this feature are given in the "differentiating jobs" notebook.
Testing for several initializations of the parameters
Variational optimization tends to be sensitive to the initial parameters it started from. You can insert the
MultipleLaunchesAnalyzer
Plugin before a VQE optimizer to automatically perform several VQE
runs and keep the lowest-energy result. This is illustrated in the notebook
Making several VQE runs and keeping the best result with the MultipleLaunchesAnalyzer plugin.