Custom Backend¶
The custom backend feature allows a user to use the Intel® Quantum Compiler and Quantum Runtime (QRT) with their own simulator.
Users will need to include the <quantum_custom_backend.h>
header file to use the Custom Backend.
In the header file there is a CustomInterface
class and a CustomSimulator
class. The CustomInterface
class
is an abstract base class where the user can implement their own simulator. The CustomSimulator
class
is similar to FullStateSimulator
, TensorNetworkSimulator
, or CliffordSimulator
classes in that this is the
class representing the quantum device.
CustomInterface
¶
The CustomInterface
has the following abstract methods that must be implemented by the user
in any derived class:
RXY()
void RXY(qbit q, double theta, double phi) = 0;
The function called by the QRT to apply a Rotation-in-the-XY-plane (
RXY
, RXY Matrix Representation) gate.RZ()
void RZ(qbit q, double angle) = 0;
The function called by the QRT to apply a Rotation-around-Z-axis (
RZ
) gate.CPhase()
void CPhase(qbit ctrl, qbit target, double angle) = 0;
The function called by the QRT to apply a Controlled-Phase (
CPhase
) gate.SwapA()
void SwapA(qbit q1, qbit q2, double angle) = 0;
The function called by the QRT to apply a Swap-Alpha (
SwapA
) gate.PrepZ()
void PrepZ(qbit q) = 0;
The function called by the QRT to prepare the specified qubit in the Z basis (
PrepZ
).MeasZ()
cbit MeasZ(qbit q) = 0;
The function called by the runtime to measure the qubit in the Z basis (
MeasZ
). The return value is the result of the measurement. The QRT will map the measurement into the appropriate bool (orcbit
) variable.
The user is free to implement any other functions that they may wish to call in this class as well. In addition, they can implement a constructor that takes in any number of arguments. Also, the base class does not include utilities to manage a state vector or other representation of the quantum state. The user will also need to manage this information if it is needed.
CustomSimulator
¶
The user needs to register their simulator with the QRT. The following example assumes that the user made a class
called MyCustomBackend
that is publicly derived from CustomInterface
.
class MyCustomBackend : public iqsdk::CustomInterface
The user will then need to create a device_id
which is a string that will refer to the device type, which must not be
an identifier for an already defined backend. Existing reserved identifiers include "IQS"
, "Tensor_Network"
, "QD_SIM"
, and "Clifford"
.
Then they will need to call iqsdk::CustomSimulator::registerCustomInterface<MyCustomBackend> (device_id, args...)
The template parameter to registerCustomInterface()
is the class for the simulator, the first parameter is the device_id
,
and the rest of the parameters get passed into the constructor for MyCustomBackend
(can be zero parameters).
As an example, if MyCustomBackend
has a constructor taking in a single integer, the following is possible:
std::string device_id = "my_custom_device";
iqsdk::QRT_ERROR_T status = iqsdk::CustomSimulator::registerCustomInterface<MyCustomBackend>(device_id, 3);
Then, the user can use iqsdk::DeviceConfig
to make an instance of the device.
iqsdk::DeviceConfig new_device_config(device_id);
iqsdk::CustomSimulator generic_simulator(new_device_config);
As usual, you call ready()
to indicate the next quantum kernel gets run on the custom backend.
status = generic_simulator.ready();
To get access to the custom simulator class, you can call getCustomBackend()
.
iqsdk::CustomInterface *custom_interface = generic_simulator.getCustomBackend();
Then you can dynamic cast it to your class.
MyCustomBackend *custom_simulator_instance = dynamic_cast<MyCustomBackend *>(custom_interface);
Here, after running a quantum kernel, you can call any function you have implemented for the class.
Alternatively, for single use purposes, it is possible to register and get a generic simulator in a single call.
iqsdk::CustomSimulator *generic_simulator = iqsdk::CustomSimulator::createSimulator<MyCustomBackend>("my_custom_device", 3);
Methods¶
getCustomBackend()
iqsdk::CustomInterface *getCustomBackend();
Gets the custom backend stored in the
CustomSimulator
object.registerCustomInterface()
template <typename T, typename... Ts> static QRT_ERROR_T registerCustomInterface(std::string device_id, Ts... args);
Registers the custom backend with the QRT.
createSimulator()
template <typename T, typename... Ts> static CustomSimulator *createSimulator(std::string device_id, Ts... args);
Registers and creates a custom backend.