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 the expval() 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 in Hamiltonian.

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, and kwargs 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

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.

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 the grouping 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

__call__(*args, **kwargs)

Call self as a function.

__call__(*args, **kwargs)[source]

Call self as a function.

Contents

Using PennyLane

Development

API

Internals