Quantum Fisher information
The Fisher information is a key metric widely used in physics and optimization. It has recently gathered great interest due to its applications in Machine Learning (ML), as it provides information about the local curvature of the Loss function, which can be leveraged to enhance vanilla gradient descent algorithms to perform natural gradient.
Its quantum version, the quantum Fisher information (QFI), plays a fundamental role in multiple fields of quantum physics such as quantum metrology, quantum information processing and quantum many-body physics. Furthermore, it lies at the core of recent quantum algorithms, such as the quantum natural gradient, variational quantum imaginary time evolution or quantum Boltzmann machines.
However, the QFI is not directly related to any physical observable, which makes it very hard to measure. While fileds like quantum sensing or quantum machine learning would greatly benefit from it, its elevetaed cost makes it impractical to use in actual applications.
A central element in the calculation of the QFI is the notion of distance between quantum states, which corresponds to their overlaps. In this hackathon we have developed a toolbox to compute the overlap between quantum states implementing various methods that do not require the explicit calculation of the state-vectors. Even more, they allow the computation of overlaps between mixed states and states in different devices.
In this example we show how to use this library to compute the QFI through different methods.
Quantum Overlaps
The overlap between two states $\rho_0, \rho_1$ is defined as the trace of their product $\text{Tr}\left[\rho_0\rho_1\right]$ and measures the similarity between the two states. For pure states, the overlap coincides with the fidelity and can be expressed as $|\langle\psi|\phi\rangle|^2$ for two pure states $|\psi\rangle, |\phi\rangle$. This quantity also defines the purity, which is the overlap of a state with itself and it is one for pure states.
When dealing with large systems, the direct calculation of the overlap is impractical as it requires either full knowledge of the density matrices or the state vectors. Here, we provide three methods to compute the overlap between quantum states that do not require the explicit calculation of such quantities:
- Compute-uncompute: this method relies on the prepartion of a state through a unitary evolution of the zero state, followed by the "un-preparation" of another state to then measure the initial zero state. Then, the value of the overlap is the probability of measuring zero at the end.
- Swap test: this method builds a circuit containing the two states to be compared and an additional qubit. The extra qubit serves as control for a set of controled swap gates between the states. The fidelity is obtained as a function of the probability to measure the zero state in the additional qubit.
- Random measurements: this method performs a series of random measurements implmenting a series of random unitary gates. It then infers the value of the overlap from the resulting statistics from the random measurements. We extend the method compute the overlap across different quantum devices.
In this example we show how to use this library to compute state overlaps and purities with the described methods. Furthermore, we show how to use the method based on random measurements to compute the overlap between states in different devices.
Basic usage
The package is designed to be very straightforward with a simple API. It is prepared to import all the key functionalities at once as follows
from fisherman.overlap.all import *
Then we need to import some qiskit functions in order to create our circuits.
from qiskit import QuantumCircuit
from qiskit.opflow import CircuitStateFn
from qiskit.circuit import Parameter
First, we need to create the states from which we want to compute the overlap. In this case, we take a very simple single-qubit circuit with a parameterized rotation around the $x$ axis.
qc = QuantumCircuit(1)
theta = Parameter('theta')
qc.rx(theta, 0)
qc.draw('mpl')
Now, we convert the circuit into a StateFn
so that it eases the parameter assignment and operations. The three main methods corresponding to each of the briefly introduced algorithms are:
Let us start by computing the overlap between two states with the three methods.
state = CircuitStateFn(qc)
state_0 = state.assign_parameters({theta: 0.})
state_1 = state.assign_parameters({theta: 1.})
cu_overlap = compute_uncompute_overlap(state_0, state_1)
swap_overlap = swap_test_overlap(state_0, state_1)
rnd_overlap = randomized_measurement_overlap(state_0, state_1)
print(f"Overlap with comp-uncomp: {cu_overlap:.3f}")
print(f"Overlap with swap test: {swap_overlap:.3f}")
print(f"Overlap with random_measurements: {rnd_overlap:.3f}")
All the three methods, while executing different algorithms, share the same functionalities. Thus, the main functionalities, while showcased with a single method at once, are applicable to all of them.
The most basic functionality is the calculation of the purity of a single state. This is achieved by providing a single input state and no additional state or value to the parameters.
purity = swap_test_overlap(state_0)
purity
Just as shown before, the next step is the computation of the overlap between two defined states.
overlap = randomized_measurement_overlap(state_0, state_1)
overlap
We can compute the overlap between a reference state state_0
and a series of states at once. We will create these states by providing a list of values into the dictionary that contains the parameters and binding them into the state.
param_dict = {theta: [0., 2.5, 5.3]} # arbitrary parameter values
states = state.bind_parameters(param_dict)
overlaps = compute_uncompute_overlap(state_0, states)
overlaps
Finally, the last possibility is to provide a single parameterized state with a parameter dictionary contianing several values (or a single-element list). In this case, the method computes the overlap between all possible combinations of parameters returning a matrix.
overlaps = randomized_measurement_overlap(state, param_dict=param_dict)
overlaps
In the resulting matrix, the $i,j$ position is the overlap between parameter sets $i,j$. Therefore, in each row we find the overlap of each state with respect to the rest and the purities at the diagonal.
overlaps.diagonal()
Finally, we have the device_independent_overlap
method, which computes the overlap between quantum states across devices. The behaviour si similar to that of the previous methods but with backends.
The most straightforward functionality is the evaluation of two states each running on a backend.
from qiskit.providers.aer import QasmSimulator
from qiskit.test.mock import FakeVigo
backends = [QasmSimulator(), QasmSimulator.from_backend(FakeVigo())]
device_independent_overlap(state_0, backends, state1=state_1)
This returns the overlap between state_0
executed on the first backend and state_1
on the second one. Notice that we also obtain the purites. If we only provide a backend, the reference state state0
is simulated with StatevectorSimulator
.
Just like in the previous methods, can input a list of states to compare to a reference state. In this case, we may provide:
- A single backend:
state0
is simulated and all statesstate1
run in the backend. - Two backends:
state0
runs on the first, allstate1
run on the second - As many backends as
state1
:state0
is simulated andstate1
run each on the backends state0
+state1
backends:state0
runs on the first,state1
states run on the rest.
For further details about the underlying mechanisms of each method and their arguments, refer to the docs :)