Backends in quask#
In this tutorial, we show how to use quask with different backends. These APIs have been designed to allow us to work with quantum kernels at a high level, hiding all the hardware (or simulator) details. The current APIs are categorized as follows:
The
core
package contains the high-level APIs, with theOperation
class representing a gate, theAnsatz
class that represents a parametric quantum circuit, and theKernel
abstract class representing the quantum kernel.The
core_implementation
package contains the low-level implementation of theKernel
class on some quantum programming framework.The
core.KernelFactory
class is used to instantiateKernel
objects on the chosen, pre-configured backend.
We have seen in the first tutorial on quantum kernels how to work with the Pennylane Backend in a noiseless simulation setting. Here we explore further ptions.
Warning
During the installation of _quask_, not all the dependencies are installed: there is no need, for most users, to have all the possible backend available on the machine. For this reason, no backend library is installed and the user have to do it manually.
Working with the Qiskit backend#
We support Qiskit SDK. It can be installed via pip using the following command:
# !pip install qiskit
# !pip install qiskit_ibm_runtime
Once configured, the class core_implementation.QiskitKernel
can be
used. The objects of this class need a few configurations: * platform,
“BasicAer” or “QiskitRuntimeService” for simulation and access to IBM
cloud * backend, the default ones for “BasicAer” platform, or one of
the available in your account for “QiskitRuntimeService” platform * the
number of samples * optimization_level, the optimization
configuration
* resilience_level, the error mitigation
configuration
* the tokenn, if platform “QiskitRuntimeService” is used and the token
has not been configured yet on the device, None otherwise
from quask.core import Ansatz, Kernel, KernelFactory, KernelType
from quask.core_implementation import QiskitKernel
def create_qiskit_noiseless(ansatz: Ansatz, measurement: str, type: KernelType):
return QiskitKernel(ansatz, measurement, type, device_name="default.qubit", n_shots=None)
KernelFactory.add_implementation('qiskit_noiseless', create_qiskit_noiseless)
Working with the Pennylane backend#
We support Pennylane SDK. It can be installed via pip using the following command:
# !pip install pennylane
Once configured, the class core_implementation.PennylaneKernel
can
be used. The objects of this class need a few configurations: * the
name of the device to be used (‘default.qubit’ being the noiseless
simulator); * the number of shots (‘None’ being infinite shots).
from quask.core import Ansatz, Kernel, KernelFactory, KernelType
from quask.core_implementation import PennylaneKernel
def create_pennylane_noiseless(ansatz: Ansatz, measurement: str, type: KernelType):
return PennylaneKernel(ansatz, measurement, type, device_name="default.qubit", n_shots=None)
KernelFactory.add_implementation('pennylane_noiseless', create_pennylane_noiseless)
Note
The PennylaneKernel class supports the basic functionalities of Pennylane, but not the most advanced ones. In particular, if you want to work with JAX you should copy this class and modify the creation of the device to use JAX instead of the standard libraries.
Working with the Amazon Braket backend#
We support Amazon Braket via the PennyLane plugins. It can be installed via pip using the following command:
# !pip install amazon-braket-sdk
# !pip install amazon-braket-pennylane-plugin
The Amazon SDK has to be configured via the Amazon CLI, whose procedure
is detailed in the
documentation.
Basically, you have to run aws configure
command and follow the
instruction to insert the access key, secret access key, and region of
your account.
Once configured, the class core_implementation.BraketKernel
can be
used. The objects of this class need a few configurations: * the name
of the device to be used; * the Amazon S3 bucket and prefix to save the
results; * the number of shots.
For more detailed explaination on the setup of Amazon Braket objects, you can follow the Amazon Braket documentation. Here’s an example on how to configure the backend in quask:
import numpy as np
from quask.core import Ansatz, Kernel, KernelFactory, KernelType
from quask.core_implementation import BraketKernel
def create_braket(ansatz: Ansatz, measurement: str, type: KernelType):
return BraketKernel(ansatz, measurement, type,
device_name="arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-3",
s3_bucket="my_s3_bucket",
s3_prefix="my_s3_prefix",
n_shots=1024)
KernelFactory.add_implementation('braket_example', create_braket)
KernelFactory.set_current_implementation('braket_example')
Note
If you need to extend _quask_ to support a certain hardware, the easiest way to implement it is by checking if there exists a plugin to make it work with PennyLane. In that case, you can copy the BraketKernel and change the setup of Braket with the setup of the hardware you want to support.
Working with the Qibo backend#
Add your own backend#
Do you want to extend the list of quask backends? Do you need a particular feature that is not supported built-in by our classes? If so, you should consider writing your own backend.
We have designed quask in a modular fashion so that users can modify
it to suit their every need with minimal effort. To start the creation
of a brand new backend, you need to create a class that extends
Kernel
and implements the abstract methods. These are:
kappa
: calculates the inner product between a pair of data points.phi
: calculates the feature map corresponding to a single data point if thekernel_type
field is observable, throws an error otherwise.
Furthermore, the initialization method should set up the backend’s environment properly. For example, if the backend is meant to work on some quantum hardware accessed via the cloud, it should set up all the necessary configurations.
Once you have set this up, you can make it available via the
KernelFactory
. Here follows an example of a mock backend:
import numpy as np
from quask.core import Ansatz, Kernel, KernelFactory, KernelType
class MockKernel(Kernel):
def __init__(self, ansatz: Ansatz, measurement: str, type: KernelType):
super().__init__(ansatz, measurement, type)
def kappa(self, x1, x2) -> float:
if self.type == KernelType.OBSERVABLE:
return 1.0 if np.isclose(x1, x2) else 0.0
elif self.type == KernelType.FIDELITY:
return 1.0 if np.isclose(x1, x2) else 0.0
elif self.type == KernelType.SWAP_TEST:
return 1.0 if np.isclose(x1, x2) else 0.0
def phi(self, x) -> float:
if self.type == KernelType.OBSERVABLE:
return np.array([1.0])
elif self.type in [KernelType.FIDELITY, KernelType.SWAP_TEST]:
raise ValueError("phi not available for fidelity kernels")
else:
raise ValueError("Unknown type, possible erroneous loading from a numpy array")
def create_mock(ansatz: Ansatz, measurement: str, type: KernelType):
return MockKernel(ansatz, measurement, type)
KernelFactory.add_implementation('mock', create_mock)
KernelFactory.set_current_implementation('mock')
Note
If you have added a particular functionality to _quask_, consider reaching out to us if you want if included in a future version of our software.