C and Python API
Implement a C and Python API for LibKet.
-
A good documentation for writing C wrappers around C++ objects and methods is given here https://nachtimwald.com/2017/08/18/wrapping-c-objects-in-c/
The C API should be inspired by the CUDA Runtime API, e.g.
qError_t qStreamCreate(qStream_t* pStream)qError_t qStreamDestroy(qStream_t* stream)qError_t qStreamQuery(qStream_t stream)qError_t qStreamSynchronize(qStream_t stream)
Since exceptions are not available in C all functions will return their status via
qError_t, which likecudaError_tis implemented as enumeratorenum qError { qSuccess = 0, qErrorInvalidValue = 1, qErrorNotYetImplemented = 31, qErrorNotReady = 300 }; typedef enum qError qError_t;For compatibility reasons, we try to use the same return codes if there exists a counterpart in CUDA.
A first version of a possible C API is implemented in the directory
c_apifor theQJoband theQStreamclasses for demonstration purposes. Once we agreed on a stable API for filters, gates, and circuits, the corresponding C functions will be implemented. The overall idea is to let the C functions generate a string representation of the C++ expressions, which gets just-in-time compiled upon execution.Suggestions for the C API
Consider the following C++ code snippet
auto expr = cnot( range<3,5>(), sel<0,1,2>( init() ) ); QData<6, QBackend::cQASMv1> data_cQASMv1; utils::json result = data_cQASMv1.execute(); std::cout << result["histogram"] << std::endl;A possible C API could look as follows
// Create a generic quantum expression object that will store the string representation internally and provides factory functions for all supported quantum gates and circuits qExpression_t* expr; assert (qExpressionCreate(expr) == qSuccess); // Create a generic quantum filter object qFilter_t* filter; assert (qFilterCreate(filter) == qSuccess); // Compose quantum expression expr.init(); // apply init() to all qubits (default behavior); // also possible expr.init(filter.all()); expr.cnot(filter.range(3,5), // apply cnot() to selected qubits filter.sel(0,1,2) ); // Create quantum backend object qCQASMv1Backend_t* data; assert (qCQASMv1BackendCreate(data, 6) == qSuccess); // Create JSON result object qJSON_t* result; assert (qJSONCreate(result) == qSuccess); // Execute quantum expression on quantum backend assert (qCQASMv1BackendExecute(data, expr, result /*, possible JSON configuration */) // Destroy quantum expression object assert (qExpressionDestroy(expr) == qSuccess); // Destroy quantum backend object assert (qCQASMv1BackendDestroy(data) == qSuccess); // Destroy JSON result object assert (qJSONDestroy(result) == qSuccess); -
Based on the C API write a Python API using one of the following approaches
- Cython (https://cython.readthedocs.io/en/latest/). A good documentation for integrating Cython into a Cake-based project is here
- pybind11 (https://github.com/pybind/pybind11). See the nn_ode demo from Denis Demidov
Building on the C API the above C++ code snippet could be implemented as follows
>>> try: ... expr = Expression() ... filter = Filter() ... ... expr.init() ... expr.cnot(filter.range(3,5), ... filter.sel(0,1,2)) ... ... data = Backend(6, "cQASMv1") ... except Exception as e:As in the C++ API, the Python methods throw exceptions of an error occurs.