diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d861af..821c84e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ project( MQSS-Client VERSION 0.1 DESCRIPTION "MQSS Client" - LANGUAGES CXX) + LANGUAGES CXX C) # Generate compile_commands.json to make it easier to work with clang based tools set(CMAKE_EXPORT_COMPILE_COMMANDS @@ -33,6 +33,7 @@ option(BUILD_TESTS "Build the tests" OFF) option(BUILD_UNIT_TESTS "Build the unit tests" OFF) option(BUILD_INTEGRATION_TESTS "Build the unit tests" OFF) option(ENABLE_COVERAGE "Enabling coverage" OFF) +option(BUILD_BINDINGS "Build Python Bindings" OFF) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") diff --git a/include/mqss-c/client.h b/include/mqss-c/client.h new file mode 100644 index 0000000..35926f6 --- /dev/null +++ b/include/mqss-c/client.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 - 2026 MQSS Project + * All rights reserved. + * + * Licensed under the Apache License v2.0 with LLVM Exceptions (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifdef __cplusplus +extern "C" { +#endif +#include "job.h" +#include "resource.h" + +#include + +typedef struct MQSSOpaqueClient* MQSSClientRef; + +MQSSClientRef mqssClientCreateClient(char* token, char* urlOrQueue, bool isHpc); + +MQSSResourceRef* mqssClientGetAllResources(MQSSClientRef client, int* size); + +MQSSResourceRef* mqssClientGetResourceInfo(MQSSClientRef client, + char* resourceName); + +int mqssClientSubmitJob(MQSSClientRef client, MQSSJobRef job); + +void mqssClientCancelJob(MQSSClientRef client, MQSSJobRef job); + +MQSSJobResultRef mqssClientGetJobResult(MQSSClientRef client, MQSSJobRef job, bool wait, + unsigned int timeout); + +int mqssClientGetNumberPendingJobs(MQSSClientRef client, char* resourceName, + int pendingJobNumber); +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/mqss-c/job.h b/include/mqss-c/job.h new file mode 100644 index 0000000..eb0d210 --- /dev/null +++ b/include/mqss-c/job.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 - 2026 MQSS Project + * All rights reserved. + * + * Licensed under the Apache License v2.0 with LLVM Exceptions (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + + +#ifdef __cplusplus +extern "C" { +#endif +#include +typedef struct MQSSOpaqueJob *MQSSJobRef; + +typedef struct MQSSOpaqueJobResult *MQSSJobResultRef; + +MQSSJobRef mqssClientCreateCircuitJob(char* circuit, + char* circuitFormat, char* resourceName, + unsigned int shots, bool noModify, bool queued); + +int mqssClientCreateHamiltonianJob(MQSSJobRef job, char* resourceName, + char* interactionStr, char* coefficientsStr); + +int mqssClientGetJobResultCounts(MQSSJobResultRef jobResult, char** bitstreams, int* counts, int size); + +int mqssClientGetJobResultCompletedTimestamp(MQSSJobResultRef jobResult, unsigned int completedTimestamp); + +int mqssClientGetJobResultSubmittedTimestamp(MQSSJobResultRef jobResult, unsigned int submittedTimestamp); + +int mqssClientGetJobResultScheduledTimestamp(MQSSJobResultRef jobResult, unsigned int scheduledTimestamp); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/mqss-c/resource.h b/include/mqss-c/resource.h new file mode 100644 index 0000000..9ae91c6 --- /dev/null +++ b/include/mqss-c/resource.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 - 2026 MQSS Project + * All rights reserved. + * + * Licensed under the Apache License v2.0 with LLVM Exceptions (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://llvm.org/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + * + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifdef __cplusplus +extern "C" { +#endif +#include + +typedef struct MQSSOpaqueResource *MQSSResourceRef; + +typedef struct MQSSOpaqueGate *MQSSGateRef; + +int mqssClientResourceGetInfo(MQSSResourceRef resource, char** name, + unsigned* qubitCount, bool* online, + int** couplingMap, MQSSGateRef** nativeGateset, + unsigned int* gateCount); + +int mqssClientResourceGetGateInfo(MQSSGateRef gate, unsigned int qubitNumber, + unsigned int parameterNumber, + int* supportedQubits); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/mqss/client.h b/include/mqss/client.h index 222c415..ec58d04 100644 --- a/include/mqss/client.h +++ b/include/mqss/client.h @@ -32,6 +32,14 @@ #define MQP_DEFAULT_URL "https://portal.quantum.lrz.de:4000/v1/" +template inline T* unwrap(RefT ref) { + return reinterpret_cast(ref); +} + +template inline RefT wrap(T* ptr) { + return reinterpret_cast(ptr); +} + namespace mqss::client { class MQSSBaseClient { diff --git a/include/mqss/resource.h b/include/mqss/resource.h index ba6bbf8..4d4c8cc 100644 --- a/include/mqss/resource.h +++ b/include/mqss/resource.h @@ -33,6 +33,12 @@ class Gate { mParameterNumber(parameterNumber), mSupportedQubits(std::move(supportedQubits)) {} + Gate(const Gate&) = default; + Gate& operator=(const Gate&) = default; + + Gate(Gate&&) = default; + Gate& operator=(Gate&&) = default; + const std::string& getName() const noexcept { return mName; } const unsigned int& getQubitNumber() const noexcept { return mQubitNumber; } @@ -69,9 +75,7 @@ class Resource { return mCouplingMap; } - const std::vector& getNativeGateset() const noexcept { - return mNativeGateset; - } + std::vector& getNativeGateset() { return mNativeGateset; } private: std::string mName; diff --git a/src/client.cpp b/src/client.cpp index 36eb940..112cb27 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -21,6 +21,7 @@ #include "clients/hpc_client.h" #include "clients/rest_client.h" +#include "mqss-c/client.h" #include #include @@ -139,3 +140,40 @@ int MQSSClient::getNumberPendingJobs(const std::string& resource) const { return parsed.value("num_pending_jobs", -1); } + +MQSSClientRef mqssClientCreateClient(char* token, char* urlOrQueue, + bool isHpc) { + + return wrap(new MQSSClient(token, urlOrQueue, isHpc)); +} +MQSSResourceRef* mqssClientGetAllResources(MQSSClientRef client, int* size) { + auto resources_ = unwrap(client)->getAllResources(); + + auto resources = + (MQSSResourceRef*)malloc(resources_.size() * sizeof(MQSSResourceRef)); + + for (size_t i = 0; i < resources_.size(); ++i) { + resources[i] = wrap(new Resource(resources_[i])); + } + + *size = (int)resources_.size(); + return resources; +} + +int mqssClientSubmitJob(MQSSClientRef client, MQSSJobRef job) { + auto uuid = + unwrap(client)->submitJob(*unwrap(job)); + if (!uuid.has_value()) { + return -1; + } + return std::stoi(*uuid); +} + +MQSSJobResultRef mqssClientGetJobResult(MQSSClientRef client, MQSSJobRef job, + bool wait, unsigned int timeout) { + + std::unique_ptr jobResult = unwrap(client)->getJobResult(*unwrap(job), + wait, timeout); + std::cout << jobResult->getTimestampCompleted() << "\n"; + return wrap(jobResult.get()); +} \ No newline at end of file diff --git a/src/job.cpp b/src/job.cpp index d5b38b0..04dac8e 100644 --- a/src/job.cpp +++ b/src/job.cpp @@ -18,6 +18,8 @@ */ #include "mqss/job.h" +#include "mqss-c/job.h" +#include "mqss/client.h" using namespace mqss::client; @@ -96,3 +98,10 @@ JobResult::JobResult(const nlohmann::json& parsed) { mTimestampSubmitted = parsed.at("timestamp_submitted").get(); mTimestampScheduled = parsed.at("timestamp_scheduled").get(); } + +MQSSJobRef mqssClientCreateCircuitJob(char* circuit, + char* circuitFormat, char* resourceName, + unsigned int shots, bool noModify, bool queued) { + return wrap(new CircuitJobRequest( + circuit, circuitFormat, resourceName, shots, noModify, queued)); +} diff --git a/src/resource.cpp b/src/resource.cpp index e0635f4..d6fa523 100644 --- a/src/resource.cpp +++ b/src/resource.cpp @@ -19,6 +19,8 @@ #include "mqss/resource.h" +#include "mqss-c/resource.h" +#include "mqss/client.h" #include using namespace mqss::client; @@ -170,3 +172,36 @@ Resource::Resource(const nlohmann::json& json) { mCouplingMap = std::move(couplingMap); mNativeGateset = std::move(nativeGateset); } + +int mqssClientResourceGetInfo(MQSSResourceRef resource, char** name, + unsigned* qubitCount, bool* online, + int** couplingMap, MQSSGateRef** nativeGateset, + unsigned int* gateCount) { + auto* resource_ = unwrap(resource); + if (resource_ == nullptr) + return -2; + + // Name + if (asprintf(name, "%s", resource_->getName().c_str()) < 0) + return -3; + + *qubitCount = resource_->getQubitCount(); + *online = resource_->isOnline(); + + *couplingMap = nullptr; + + auto& gates = resource_->getNativeGateset(); + + *gateCount = gates.size(); + + *nativeGateset = (MQSSGateRef*)malloc(sizeof(MQSSGateRef) * gates.size()); + + if (!*nativeGateset) + return -4; + + for (size_t i = 0; i < gates.size(); ++i) { + (*nativeGateset)[i] = wrap(&gates[i]); + } + + return 0; +} \ No newline at end of file