qml.ExpvalCost¶
-
class
ExpvalCost
(ansatz, hamiltonian, device, interface='autograd', diff_method='best', optimize=False, **kwargs)[source]¶ Bases:
object
Create a cost function that gives the expectation value of an input Hamiltonian.
This cost function is useful for a range of problems including VQE and QAOA.
Warning
ExpvalCost
is deprecated. Instead, it is recommended to simply pass Hamiltonians to theexpval()
function inside QNodes.@qml.qnode(dev) def ansatz(params): some_qfunc(params) return qml.expval(Hamiltonian)
In order to optimize the Hamiltonian evaluation taking into account commuting terms, use the
grouping_type
keyword inHamiltonian
.- Parameters
ansatz (callable) –
The ansatz for the circuit before the final measurement step. Note that the ansatz must have the following signature:
ansatz(params, wires, **kwargs)
where
params
are the trainable weights of the variational circuit,wires
is the wires the circuit acts on, andkwargs
are any additional keyword arguments that need to be passed to the template.hamiltonian (Hamiltonian) – Hamiltonian operator whose expectation value should be measured
device (Device, Sequence[Device]) – Corresponding device(s) where the resulting cost function should be executed. This can either be a single device, or a list of devices of length matching the number of terms in the Hamiltonian.
interface (str, None) – Which interface to use. This affects the types of objects that can be passed to/returned to the cost function. Supports all interfaces supported by the
qnode()
decorator.diff_method (str, None) – The method of differentiation to use with the created cost function. Supports all differentiation methods supported by the
qnode()
decorator.optimize (bool) – Whether to optimize the observables composing the Hamiltonian by separating them into qubit-wise commuting groups. Each group can then be executed within a single QNode, resulting in fewer QNodes to evaluate.
- Returns
a cost function with signature
cost_fn(params, **kwargs)
that evaluates the expectation of the Hamiltonian on the provided device(s)- Return type
callable
See also
Hamiltonian
,molecular_hamiltonian()
,map()
,dot()
Example:
To construct an
ExpvalCost
cost function, we require a Hamiltonian to measure, and an ansatz for our variational circuit.We can construct a Hamiltonian manually,
coeffs = [0.2, -0.543] obs = [ qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliY(3), qml.PauliZ(0) @ qml.Hadamard(2) ] H = qml.Hamiltonian(coeffs, obs)
Alternatively, the
molecular_hamiltonian()
function from the Quantum Chemistry module can be used to generate a molecular Hamiltonian.Once we have our Hamiltonian, we can select an ansatz and construct the cost function.
>>> ansatz = qml.templates.StronglyEntanglingLayers >>> dev = qml.device("default.qubit", wires=4) >>> cost = qml.ExpvalCost(ansatz, H, dev, interface="torch") >>> params = torch.rand([2, 4, 3]) >>> cost(params) tensor(-0.2316, dtype=torch.float64)
The cost function can then be minimized using any gradient descent-based optimizer.
Usage Details
Optimizing observables:
Setting
optimize=True
can be used to decrease the number of device executions. The observables composing the Hamiltonian can be separated into groups that are qubit-wise commuting using thegrouping
module. These groups can be executed together on a single qnode, resulting in a lower device overhead:commuting_obs = [qml.PauliX(0), qml.PauliX(0) @ qml.PauliZ(1)] H = qml.Hamiltonian([1, 1], commuting_obs) dev = qml.device("default.qubit", wires=2) ansatz = qml.templates.StronglyEntanglingLayers cost_opt = qml.ExpvalCost(ansatz, H, dev, optimize=True) cost_no_opt = qml.ExpvalCost(ansatz, H, dev, optimize=False) shape = qml.templates.StronglyEntanglingLayers.shape(n_layers=3, n_wires=2) params = np.random.random(shape)
Grouping these commuting observables leads to fewer device executions:
>>> with qml.Tracker(dev) as tracker: ... cost_opt(params) >>> ex_opt = tracker.totals["executions"] >>> with tracker: ... cost_no_opt(params) >>> ex_no_opt = tracker.totals["executions"] >>> print("Number of executions:", ex_no_opt) Number of executions: 2 >>> print("Number of executions (optimized):", ex_opt) Number of executions (optimized): 1
Methods