LibKet: Kwantum Expression Template Library
The open-source expression template library LibKet makes it possible to develop quantum-accelerated scientific applications and test them on different gate-based quantum computing platforms like QuTech's Quantum Inspire, IBM's Quantum Experience and Rigetti's Quantum Cloud Services without the need to reimplement quantum algorithms in vendor-specific SDKs like Qiskit and PyQuil. LibKet is designed as C++14 expression template library that allows to formulate quantum algorithms as generic expressions, which are synthesized to backend-optimized quantum kernels that can be executed in quantum simulators and cloud-based quantum computers. Next to the basic quantum gates, LibKet comes with a growing collection of customizable quantum algorithms and building blocks like the Quantum Fourier transformation (QFT) that simplify the development of quantum-accelerated applications.
The following code snippet shows how to generate the quantum kernel for an n-qubit QFT and execute it first on the Quantum Inspire simulator platform using 6-qubits and then on IBM's Quantum Experience cloud service using one of the 5-qubit quantum processors:
#include <LibKet.hpp>
using namespace LibKet;
using namespace LibKet::circuits;
using namespace LibKet::filters;
using namespace LibKet::gates;
// Create generic quantum expression
auto expr = qft(init());
// Execute QFT<6> on Quantum-Inspire platform
try {
QDevice<QDeviceType::qi_26_simulator, 6> qi; qi(expr);
utils::json result = qi.execute();
QInfo << result << std::endl;
QInfo << "job ID : " << qi.get<QResultType::id>(result) << std::endl;
QInfo << "time stamp : " << qi.get<QResultType::timestamp>(result) << std::endl;
QInfo << "duration : " << qi.get<QResultType::duration>(result).count() << std::endl;
QInfo << "best : " << qi.get<QResultType::best>(result) << std::endl;
QInfo << "histogram : " << qi.get<QResultType::histogram>(result) << std::endl;
} catch(const std::exception &e) {
QWarn << e.what() << std::endl;
}
// Execute QFT<5> on IBM Quantum Experience platform
try {
QDevice<QDeviceType::ibmq_5_london, 5> ibmq; ibmq(expr);
utils::json result = ibmq.execute();
QInfo << result << std::endl;
QInfo << "job ID : " << qi.get<QResultType::id>(result) << std::endl;
QInfo << "time stamp : " << qi.get<QResultType::timestamp>(result) << std::endl;
QInfo << "duration : " << qi.get<QResultType::duration>(result).count() << std::endl;
QInfo << "best : " << qi.get<QResultType::best>(result) << std::endl;
QInfo << "histogram : " << qi.get<QResultType::histogram>(result) << std::endl;
} catch(const std::exception &e) {
QWarn << e.what() << std::endl;
}
The result JSON object holds the raw data
received from the quantum backend, whose format differs from
one backend to the other making it difficult to write
portable code. The result from executing the 6-qubit QFT on
the Quantum Inspire platform reads:
{"calibration":null,"created_at":"2020-04-24T07:56:51.811632Z","execution_time_in_seconds":24.595468044281,"histogram":{"0":0.0126953125,"1":0.0205078125,"10":0.01953125,"11":0.0146484375,"12":0.013671875,"13":0.01953125,"14":0.0068359375,"15":0.0126953125,"16":0.0185546875,"17":0.0146484375,"18":0.0166015625,"19":0.025390625,"2":0.0205078125,"20":0.0166015625,"21":0.0107421875,"22":0.015625,"23":0.0146484375,"24":0.013671875,"25":0.0185546875,"26":0.0126953125,"27":0.021484375,"28":0.017578125,"29":0.01953125,"3":0.015625,"30":0.017578125,"31":0.0087890625,"32":0.0126953125,"33":0.017578125,"34":0.0126953125,"35":0.013671875,"36":0.01953125,"37":0.013671875,"38":0.0146484375,"39":0.0166015625,"4":0.01171875,"40":0.017578125,"41":0.0185546875,"42":0.0166015625,"43":0.017578125,"44":0.0166015625,"45":0.0166015625,"46":0.017578125,"47":0.0126953125,"48":0.0166015625,"49":0.0078125,"5":0.0107421875,"50":0.009765625,"51":0.0185546875,"52":0.0185546875,"53":0.0205078125,"54":0.01171875,"55":0.0126953125,"56":0.01953125,"57":0.0166015625,"58":0.0126953125,"59":0.01171875,"6":0.0166015625,"60":0.0205078125,"61":0.0087890625,"62":0.013671875,"63":0.0166015625,"7":0.013671875,"8":0.0185546875,"9":0.0185546875},"histogram_url":"https://api.quantum-inspire.com/results/6778649/histogram/c1ae5d30ca07c579d24c01cdd3e367ff74089e075544c500ca0ebc815e67f86d/","id":6778649,"job":"https://api.quantum-inspire.com/jobs/6781372/","measurement_mask":0,"measurement_register_url":"https://api.quantum-inspire.com/results/6778649/measurement-register/c1ae5d30ca07c579d24c01cdd3e367ff74089e075544c500ca0ebc815e67f86d/","number_of_qubits":6,"quantum_states_url":"https://api.quantum-inspire.com/results/6778649/quantum-states/c1ae5d30ca07c579d24c01cdd3e367ff74089e075544c500ca0ebc815e67f86d/","raw_data_url":"https://api.quantum-inspire.com/results/6778649/raw-data/c1ae5d30ca07c579d24c01cdd3e367ff74089e075544c500ca0ebc815e67f86d/","raw_text":"","url":"https://api.quantum-inspire.com/results/6778649/"}
With the aid of LibKet's commodity functions, relevant data fields
such as the state with highest probability
(QResultType::best) or the duration of the
quantum kernel execution
(QResultType::duraction) as reported by the
backend can be accessed in a unified way and in terms of C++
data types that can be processed further:
job ID : 6778649
time stamp : 1587707811
duration : 24.5955
best : 19
histogram : 0.012695312500000000,0.020507812500000000,0.020507812500000000,0.015625000000000000,0.011718750000000000,0.010742187500000000,0.016601562500000000,0.013671875000000000,0.018554687500000000,0.018554687500000000,0.019531250000000000,0.014648437500000000,0.013671875000000000,0.019531250000000000,0.006835937500000000,0.012695312500000000,0.018554687500000000,0.014648437500000000,0.016601562500000000,0.025390625000000000,0.016601562500000000,0.010742187500000000,0.015625000000000000,0.014648437500000000,0.013671875000000000,0.018554687500000000,0.012695312500000000,0.021484375000000000,0.017578125000000000,0.019531250000000000,0.017578125000000000,0.008789062500000000,0.012695312500000000,0.017578125000000000,0.012695312500000000,0.013671875000000000,0.019531250000000000,0.013671875000000000,0.014648437500000000,0.016601562500000000,0.017578125000000000,0.018554687500000000,0.016601562500000000,0.017578125000000000,0.016601562500000000,0.016601562500000000,0.017578125000000000,0.012695312500000000,0.016601562500000000,0.007812500000000000,0.009765625000000000,0.018554687500000000,0.018554687500000000,0.020507812500000000,0.011718750000000000,0.012695312500000000,0.019531250000000000,0.016601562500000000,0.012695312500000000,0.011718750000000000,0.020507812500000000,0.008789062500000000,0.013671875000000000,0.016601562500000000
Further features of LibKet are demonstrated in a forthcoming
paper
Contributors
Tim Driebergen (TU Delft), Mike van der Lans (TU Delft), Kelvin Loh (TNO Delft), Menno Looman (TU Delft), Merel Schalkers (TU Delft), Otmar Ubbens (TU Delft), Richard Versluis (TNO Delft)