qml.metric_tensor

metric_tensor(qnode, diag_approx=False, only_construct=False)[source]

Returns a function that returns the value of the metric tensor of a given QNode.

Note

Currently, only the RX, RY, RZ, and PhaseShift parametrized gates are supported. All other parametrized gates will be decomposed if possible.

Parameters
  • qnode (QNode or ExpvalCost) – QNode(s) to compute the metric tensor of

  • diag_approx (bool) – iff True, use the diagonal approximation

  • only_construct (bool) – Iff True, construct the circuits used for computing the metric tensor but do not execute them, and return the tapes.

Returns

Function which accepts the same arguments as the QNode. When called, this function will return the metric tensor.

Return type

func

Example

Consider the following QNode:

dev = qml.device("default.qubit", wires=3)

@qml.qnode(dev, interface="autograd")
def circuit(weights):
    # layer 1
    qml.RX(weights[0, 0], wires=0)
    qml.RX(weights[0, 1], wires=1)

    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[1, 2])

    # layer 2
    qml.RZ(weights[1, 0], wires=0)
    qml.RZ(weights[1, 1], wires=2)

    qml.CNOT(wires=[0, 1])
    qml.CNOT(wires=[1, 2])
    return qml.expval(qml.PauliZ(0) @ qml.PauliZ(1)), qml.expval(qml.PauliY(2))

We can use the metric_tensor function to generate a new function, that returns the metric tensor of this QNode:

>>> met_fn = qml.metric_tensor(circuit)
>>> weights = np.array([[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]], requires_grad=True)
>>> met_fn(weights)
tensor([[0.25  , 0.    , 0.    , 0.    ],
        [0.    , 0.25  , 0.    , 0.    ],
        [0.    , 0.    , 0.0025, 0.0024],
        [0.    , 0.    , 0.0024, 0.0123]], requires_grad=True)

The returned metric tensor is also fully differentiable, in all interfaces. For example, differentiating the (3, 2) element:

>>> grad_fn = qml.grad(lambda x: met_fn(x)[3, 2])
>>> grad_fn(weights)
array([[ 0.04867729, -0.00049502,  0.        ],
       [ 0.        ,  0.        ,  0.        ]])