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. QLM jobs come with methods to compute the derivative of $E(\vec{\theta})$ automatically: differentiate
and gradient
.
differentiate
returns the jobs allowing to compute the derivative of $E(\vec{\theta})$ with respect to a given variable.
gradient
returns the jobs allowing to compute the derivative of $E(\vec{\theta})$ with respect to all variables (in the form of a dictionary whose keys are the variable names).
Two methods for computing these derivatives are proposed: the shift-rule method and the Hadamard test method. The latter requires an ancilla qubit.
Simple, one-parameter example¶
from qat.lang.AQASM import CNOT, RX, H, Program
prog = Program()
qbits = prog.qalloc(2)
theta = prog.new_var(float, r"\theta")
H(qbits[0])
CNOT(qbits)
RX(theta)(qbits[1])
CNOT(qbits)
circ = prog.to_circ()
circ.display()
Let us now define a job corresponding to computing $E(\theta) = \langle \psi(\theta) | Z_0 | \psi(\theta)\rangle$ and its derivative:
from qat.core import Observable, Term
obs = Observable(2, pauli_terms=[Term(1, "Z", [0])])
job = circ.to_job(observable=obs)
jobs = job.differentiate(r"\theta")
for job_ in jobs:
circ = job_.circuit
circ.display()
With no additional arguments, differentiate
uses the shift-rule method. To use the Hadamard test method:
jobs = job.differentiate(r"\theta", method="h-test")
for job_ in jobs:
circ = job_.circuit
circ.display()
More variables¶
Let us look at a slightly more involved example, with two variables:
prog = Program()
qbits = prog.qalloc(2)
theta = prog.new_var(float, r"\theta")
phi = prog.new_var(float, r"\phi")
H(qbits[0])
CNOT(qbits)
RX(theta)(qbits[1])
RX(phi)(qbits[0])
CNOT(qbits)
circ = prog.to_circ()
circ.display()
job = circ.to_job(observable=obs)
jobs = job.gradient()
for var in jobs.keys():
print(var)
for job_ in jobs[var]:
circ = job_.circuit
circ.display()
\phi
\theta