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: -0.867661435962414
best parameters: {'t': 3.0777169304304124, 'theta': 0.21388438242851276}
trace: [0.1782478542056311, -0.013751440245713255, 0.08129420302617135, 0.0659469997870128, 0.19621686078846184, 0.010964683979888921, -0.015669034696309467, -0.04129658248547298, -0.05715820560588497, 0.007766347533907925, -0.134950868139071, -0.102669339184235, -0.13271267362061978, -0.14622602400408302, -0.16206221378525446, -0.15235646914224418, -0.17727387510384096, -0.1823807031253784, -0.16800743617649558, -0.19567433152088268, -0.20851795296054812, -0.2208418451000293, -0.2309683395481424, -0.24505416826111348, -0.2559712403519038, -0.2693107538207882, -0.28223910478288, -0.29530849302372486, -0.3083662141636717, -0.3214172850493846, -0.3344557213526851, -0.3475077069263882, -0.360538093325531, -0.37355795065946534, -0.3865968949717123, -0.3996259068633419, -0.4125688567718394, -0.42345551150826266, -0.43721593470748654, -0.45006405106127195, -0.46293982520904675, -0.47511337586165747, -0.48696948078634184, -0.49869585141115313, -0.5054143668847706, -0.5200843978500113, -0.5201429760279723, -0.5313547898140634, -0.5386792708370813, -0.5437383885436298, -0.5362960752344558, -0.5496080237213903, -0.5558187378873155, -0.5613292762055495, -0.5574605824216685, -0.5667560823143307, -0.5637880043006789, -0.5697908751017791, -0.5713114668353714, -0.57479717358788, -0.578072529854495, -0.5813056372210984, -0.5845644745021604, -0.5878201494722547, -0.5910668483839963, -0.5941950205325575, -0.5974935851339122, -0.6007402795769712, -0.6039968430160749, -0.6072382596944392, -0.6102706139728663, -0.6135846550851268, -0.6168310801629244, -0.6200830232512888, -0.6233037614082748, -0.626553061081732, -0.6298039798074736, -0.6330175449983988, -0.6362673375414829, -0.639516662721556, -0.6427190308151294, -0.6459695399088738, -0.649216315714096, -0.6524000062292311, -0.6556526151572654, -0.6588957321814017, -0.6621605732409938, -0.665423053824875, -0.6686854328364148, -0.6719479718397987, -0.6752105015550798, -0.678473027464784, -0.6817355483191484, -0.684998027318596, -0.6882605330245284, -0.6915230396720192, -0.6947854858397199, -0.6980479859326665, -0.7013104830902224, -0.7045728800604775, -0.7078353731122022, -0.7110978538450374, -0.7143601572344667, -0.7176226416216765, -0.7208850924331043, -0.7241472063281643, -0.7274096826723256, -0.7306720759199605, -0.7339346160197546, -0.7371971311972516, -0.7404596557221071, -0.7437221794589179, -0.74698470106114, -0.7502472047238258, -0.7535096923131854, -0.7567722047403156, -0.760034699747373, -0.7632970618565369, -0.766559291314231, -0.7698217328420425, -0.7730840903485998, -0.7763459884253061, -0.7796085277155054, -0.7828706711105391, -0.7861330908457446, -0.7893955558299073, -0.7926578529897496, -0.7959137096914237, -0.7991779734726105, -0.8024394474616025, -0.805701691872012, -0.8089635822883413, -0.8122233515781567, -0.815460387539368, -0.818723788942909, -0.8219882657647378, -0.8252525123247726, -0.8285158739139264, -0.831778643661125, -0.83504109022024, -0.8383010609244537, -0.8415624551835196, -0.8448244492927672, -0.8480870506181823, -0.8513495360956018, -0.8546113888699114, -0.8578739996270834, -0.8611363459326344, -0.8643988982776867, -0.867661435962414]

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: -15.36852786145532
best parameters: {'t': 6.12284262048511, 'theta': 1.5707963208691633}
trace: [0.33489663777138934, -0.042434499649867695, -0.11565534320369589, -2.9493603388074687, -5.901048635896789, -8.750629777797355, -12.22964101898102, 2.2518354366777635, 4.9462171945118945, 4.796050624902591, -11.39115046478873, -7.299607044142108, -10.295012178258364, -12.127520159255937, -12.067493434534546, -12.172660996162467, -12.160020359140326, -12.289706319033979, -12.333108431795107, -12.311744755923886, -12.354319426809585, -12.367746733219336, -12.392247432693981, -12.41562357601802, -12.438885585663945, -12.462322550092038, -12.485703822432388, -12.509156123438615, -12.532593833833324, -12.55602868155869, -12.579465924054094, -12.60290293285958, -12.626340464122796, -12.649777991426987, -12.67321550715333, -12.696653013925136, -12.720090516454333, -12.743528017287236, -12.76696551672298, -12.790403009409381, -12.813840494493292, -12.837277992056471, -12.860715487750042, -12.884152977699099, -12.907590361018126, -12.93102788765008, -12.954465385179113, -12.977902880302626, -13.001340378977961, -13.024777878825915, -13.048215362860347, -13.071652865079976, -13.095090365809163, -13.118527865743548, -13.141965365647819, -13.16540286564263, -13.18884036563538, -13.212277865624648, -13.235715365604168, -13.259152865510849, -13.282590365363141, -13.306027865323735, -13.3294653652312, -13.352902864850265, -13.376340363129897, -13.399777863037446, -13.423215362961585, -13.446652862892531, -13.470090362827206, -13.49352786276441, -13.516965362703973, -13.540402862647259, -13.563840362600473, -13.587277862587719, -13.610715362678558, -13.63415286289044, -13.65759036301255, -13.68102786302854, -13.704465363029716, -13.72790286302516, -13.751340361364615, -13.774777861623598, -13.79821536170938, -13.821652861688309, -13.845090361674092, -13.868527861675435, -13.891965361676107, -13.915402861676379, -13.938840361676274, -13.962277861674528, -13.98571536166941, -14.00915286166869, -14.032590361667594, -14.056027861665473, -14.079465361655433, -14.102902861643566, -14.126340361639631, -14.149777861629584, -14.173215361574321, -14.196652861584829, -14.220090361577238, -14.243527861575963, -14.266965361572035, -14.290402861554274, -14.31384036146585, -14.337277861462123, -14.360715361460105, -14.384152861459286, -14.407590361459702, -14.431027861461562, -14.454465361464857, -14.477902861468767, -14.50134036147191, -14.524777861473673, -14.548215361474377, -14.571652861473911, -14.595090361461441, -14.618527861462677, -14.641965361461924, -14.665402861461931, -14.68884036145527, -14.712277861456187, -14.735715361456428, -14.759152861456121, -14.782590361456254, -14.806027861456137, -14.829465361456148, -14.85290286145613, -14.876340361455519, -14.899777861455643, -14.923215361455625, -14.946652861455588, -14.970090361455586, -14.993527861455586, -15.016965361455583, -15.040402861455547, -15.06384036145555, -15.087277861455561, -15.11071536145555, -15.134152861455554, -15.157590361455547, -15.181027861455547, -15.204465361455547, -15.227902861455547, -15.251340361455556, -15.274777861455295, -15.298215361455316, -15.321652861455338, -15.345090361455343, -15.36852786145532]

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.