Using quantum circuits as reservoirs in reservoir computing is fairly new. The current examples in the literature rely heavily on quantum circuits of a very periodic nature. This package is meant to simplify the creation and simulation of such periodic circuits.
See the documentation for this package.
QuantumReservoirPy is available as a pip-installable package on PyPI.
pip install quantumreservoirpy
This will install QuantumReservoirPy along with its dependent packages.
Alternatively, you may clone the repository from GitHub
git clone https://github.com/OpenQuantumComputing/quantumreservoirpy.git
navigate to the repository
cd quantumreservoirpy
and install it from here.
pip install .
This is functionally equivalent to installing from PyPI.
The interface of this package is somewhat inspired by ReservoirPy. Consider checking out their tutorials to better understand this package.
A reservoir is in this package defined as a class implementing the abstract class QReservoir
. To create a completely custom reservoir, you need to implement 5 functions as shown.
class CustomRes(QReservoir):
def before(self, circuit):
pass
def during(self, circuit, timestep):
pass
def after(self, circuit):
pass
def run(self, timeseries, **kwargs):
pass
def predict(self, num_pred, model, from_series, **kwargs):
pass
QuantumReservoirPy has some partially implemented reservoirs already, which have easier interfaces.
These reservoirs have implemented the run
and predict
methods, so you only need to implement before
, during
, and after
.
All the reservoirs created with Static
and Ìncremental
have the same three layered circuit structure; they begin with an initialization, which is defined by before
. Then, a small circuit is created for every timestep in the timeseries, which is defined by during
. The third and last layer is defined by after
.
from quantumreservoirpy.reservoirs import Static
class CustomRes(Static):
def before(self, circuit):
circuit.h(circuit.qubits)
circuit.barrier()
def during(self, circuit, timestep):
circuit.initialize(str(timestep), [0])
circuit.h(0)
circuit.cx(0, 1)
def after(self, circuit):
circuit.barrier()
circuit.measure_all()
res = CustomRes(n_qubits=2)
res.circuit([0, 1]).draw('mpl')
The three functions before
, during
, and after
do the same thing for both Static
and Incremental
reservoirs. The difference between them is what happens when the reservoirs are run.
Having created a reservoir, you can simply call reservoir.run
.
states = res.run(timeseries)
This will return a np.ndarray
of the same length as the timeseries, corresponding to the reservoir state at each timestep.
Static
reservoirs run once and all measurements are reshaped to a (len(timeseries), -1)
shape.
Incremental
reservoirs run incrementally. For every state, only the last M
steps of the timeseries is built at a time (M
being a parameter of Incremental.__init__
).
Some tests have been implemented using pytest. To run them, ensure pytest is installed (not installed as runtime dependency) and run
pytest
You can find out more about QuantumReservoirPy and contact the authors here.
This project is supported by SINTEF Digital.
Teknologi for et bedre samfunn