# Calculating the metric_tensor mid-circuit

Hello,

I’m trying to calculate the metric_tensor of a subset of my total circuit before measurement takes place. In particular, in my code below, I want to calculate it after `U1(params)`. My code is as follows:

``````def get_observables(N):
observables = []

# Coupling operators
for i in range(N-1):
observables.append(qml.PauliZ(i) @ qml.PauliZ(i+1))

# Identity operator
for i in range(N):
observables.append(qml.Identity(i))

return observables

def get_coeffs(params, N):
coeffs = []

# Coupling coeffs
for i in range(N-1):
coeffs.append((params[0])**2/params[1])

# Constant coeffs
for i in range(N):
coeffs.append(params[1])

return coeffs

def create_Hamiltonian(params):

coeffs = get_coeffs(params, nqubits)
obs = get_observables(nqubits)

H = qml.Hamiltonian(coeffs, obs, id='QP')

return H

def create_params(L, scale = 0.1):

for i in range(L):
J = scale*np.random.uniform()
O = 1.0
theta = scale*np.random.uniform()

params = np.append(params, [J, O, theta], requires_grad=True)

return params

dev = qml.device("default.qubit", wires=nqubits, shots=None)

def U1(params):
start_index = 0
num_trotter_steps = 10

for i in range(L):
new_params = params[start_index:start_index + 3]
H = create_Hamiltonian(new_params[0:2])
qml.evolve(H, num_steps = num_trotter_steps)
for j in range(nqubits):
qml.RX(new_params[2], wires=j)
start_index += 3 # Put state_index in again

@qml.qnode(dev)
def circuit(params, phi):

U1(params)

for z in range(nqubits): # Perturbation
qml.RY(phi[0], wires = z)

expectation_values = [qml.expval(qml.PauliY(wires=i)) for i in range(nqubits)]

return expectation_values # List of expected values of every input qubit
``````

This is the output of my `qml.about()`

``````Name: PennyLane
Version: 0.33.1
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/PennyLaneAI/pennylane
Author:
Author-email:
Location: /.../python3.11/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, rustworkx, scipy, semantic-version, toml, typing-extensions
Required-by: PennyLane-Lightning

Platform info:           macOS-13.4.1-x86_64-i386-64bit
Python version:          3.11.5
Numpy version:           1.26.2
Scipy version:           1.11.4
Installed devices:
- default.gaussian (PennyLane-0.33.1)
- default.mixed (PennyLane-0.33.1)
- default.qubit (PennyLane-0.33.1)
- default.qubit.jax (PennyLane-0.33.1)
- default.qubit.legacy (PennyLane-0.33.1)
- default.qubit.tf (PennyLane-0.33.1)
- default.qubit.torch (PennyLane-0.33.1)
- default.qutrit (PennyLane-0.33.1)
- null.qubit (PennyLane-0.33.1)
- lightning.qubit (PennyLane-Lightning-0.33.1)
``````

Any help would be appreciated. Thanks in advance!

Hey @NickGut0711! Welcome to the forum

You can use `qml.metric_tensor`: qml.metric_tensor — PennyLane 0.33.0 documentation. However, it’ll need a QNode as input, so you can do something like this:

``````@qml.qnode(dev)
def U1_for_metric_tensor(params):
U1(params)
return # return some measurement

metric_tensor = qml.metric_tensor(U1_for_metric_tensor)(params)
``````

Let me know if this helps!

Thank you for the response and the warm welcome!

The code I put above will be run as follows:

1. Evaluate the circuit for each “U1 layer”, L
2. Optimize the parameters of the L layer
3. Calculate the metric_tensor (with the fully optimized parameters) after every U1(params)

How do I go about this? After my optimization should I just find the optimal parameters, construct a “new U1” QNode based on those params, and calculate the metric tensor of that? Is this the most efficient way to do this? Thanks!

I don’t think you need to create a “new U1” QNode every time the parameters change. You can have a predefined QNode that takes the parameters in as an argument