Unverified Commit 58e84c95 authored by Mccaskey, Alex's avatar Mccaskey, Alex Committed by GitHub
Browse files

Merge pull request #451 from flatslm/ibmq_accelerator_elect_lowest_queue_backend

Ibmq accelerator select lowest queue backend: resolve #441
parents 7428a31e 55ccdbad
Pipeline #149915 passed with stage
in 12 minutes and 34 seconds
import xacc
qpu = xacc.getAccelerator(
'ibm', {'shots': 256, 'backend': 'lowest-queue-count', 'n-qubits': 5, 'check-jobs-limit': True})
print(qpu.getProperties()["total-json"])
xacc.qasm('''.compiler xasm
.circuit bell
.qbit q
H(q[0]);
CX(q[0],q[1]);
Measure(q[0]);
Measure(q[1]);
''')
bell = xacc.getCompiled('bell')
q = xacc.qalloc(2)
qpu.execute(q, bell)
print(q)
......@@ -16,6 +16,9 @@ target_link_libraries(bell_quil_ibm_local PRIVATE xacc)
add_executable(bell_xasm_ibm_local bell_xasm_ibm_local.cpp)
target_link_libraries(bell_xasm_ibm_local PRIVATE xacc)
add_executable(bell_xasm_ibm_select_backend bell_xasm_ibm_select_backend.cpp)
target_link_libraries(bell_xasm_ibm_select_backend PRIVATE xacc)
add_executable(deuteron_2qbit_xasm_X0X1 deuteron_2qbit_xasm_X0X1.cpp)
target_link_libraries(deuteron_2qbit_xasm_X0X1 PRIVATE xacc)
......@@ -29,4 +32,4 @@ add_executable(circuit_with_classical_control circuit_with_classical_control.cpp
target_link_libraries(circuit_with_classical_control PRIVATE xacc)
add_executable(optimal_control_goat optimal_control_goat.cpp)
target_link_libraries(optimal_control_goat PRIVATE xacc)
\ No newline at end of file
target_link_libraries(optimal_control_goat PRIVATE xacc)
#include "xacc.hpp"
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
xacc::external::load_external_language_plugins();
xacc::set_verbose(true);
auto accelerator = xacc::getAccelerator(
"ibm", {std::make_pair("backend", "lowest-queue-count"),
std::make_pair("n-qubits", 5),
std::make_pair("check-jobs-limit", true)}
);
xacc::qasm(R"(
.compiler xasm
.circuit bell
.qbit q
H(q[0]);
CX(q[0],q[1]);
Measure(q[0]);
Measure(q[1]);
)");
auto bell = xacc::getCompiled("bell");
// Allocate some qubits and execute
auto buffer = xacc::qalloc(2);
accelerator->execute(buffer, bell);
buffer->print();
xacc::external::unload_external_language_plugins();
xacc::Finalize();
return 0;
}
......@@ -184,6 +184,92 @@ bool hasMidCircuitMeasurement(
return false;
}
bool IBMAccelerator::verifyJobsLimit(std::string& curr_backend) {
// Get backend jobs limit
std::string getJobsLimitPath = "/api/Network/" + hub + "/Groups/" + group +
"/Projects/" + project + "/devices/" + curr_backend +
"/jobsLimit";
auto backend_jobslimit_response = get(IBM_API_URL, getJobsLimitPath, {},
{std::make_pair("version", "1"),
std::make_pair("access_token", currentApiToken)});
auto backend_jobslimit_response_json = json::parse(backend_jobslimit_response);
auto maximumJobs = backend_jobslimit_response_json["maximumJobs"].get<int>();
auto runningJobs = backend_jobslimit_response_json["runningJobs"].get<int>();
return maximumJobs < 0 || runningJobs < maximumJobs;
}
void IBMAccelerator::processBackendCandidate(nlohmann::json& backend_json) {
// First of all filter by count fo qubits
if (requested_n_qubits > 0) {
if( backend_json.count("n_qubits") ) {
int nqubits = backend_json["n_qubits"].get<int>();
if(nqubits < requested_n_qubits) {
return;
}
} else {
return;
}
}
std::string curr_backend = backend_json["backend_name"].get<std::string>();
std::string getStatusPath = "/api/Network/" + hub + "/Groups/" + group +
"/Projects/" + project + "/devices/" + curr_backend +
"/queue/status";
// Get current backend status
auto status_response = get(IBM_API_URL, getStatusPath, {},
{std::make_pair("version", "1"),
std::make_pair("access_token", currentApiToken)});
auto status_response_json = json::parse(status_response);
auto queue_length = status_response_json["lengthQueue"].get<int>();
auto state = status_response_json["state"].get<bool>();
if (state && (backendQueueLength < 0 || backendQueueLength > queue_length)) {
if (filterByJobsLimit && !verifyJobsLimit(curr_backend)) {
return;
}
backendQueueLength = queue_length;
auto old_backend = backend;
backend = curr_backend;
availableBackends.clear();
availableBackends.insert(std::make_pair(backend, backend_json));
}
}
void IBMAccelerator::selectBackend(std::vector<std::string>& all_available_backends) {
bool lowest_queue_backend = false;
if (backend == "lowest-queue-count") {
lowest_queue_backend = true;
}
for (auto &b : backends_root["backends"]) {
if (!b.count("backend_name")) {
continue;
}
if (b.count("simulator")) {
// We don't need simulators at all
if (b["simulator"].get<bool>()) {
continue;
}
}
// Simple case: select by backend_name
if (!lowest_queue_backend) {
if (b["backend_name"].get<std::string>() == backend) {
availableBackends.insert(std::make_pair(backend, b));
}
} else {
// Select backend by job queue size and by parameters (optional)
processBackendCandidate(b);
}
all_available_backends.push_back(b["backend_name"].get<std::string>());
}
if (lowest_queue_backend) {
xacc::info("Backend with lowest queue count: " + backend);
}
}
void IBMAccelerator::initialize(const HeterogeneousMap &params) {
if (!initialized) {
std::string apiKey = "";
......@@ -208,9 +294,6 @@ void IBMAccelerator::initialize(const HeterogeneousMap &params) {
IBM_CREDENTIALS_PATH =
"/api/Network/" + hub + "/Groups/" + group + "/Projects/" + project;
getBackendPath = IBM_CREDENTIALS_PATH + "/devices?access_token=";
getBackendPropertiesPath = "/api/Network/" + hub + "/Groups/" + group +
"/Projects/" + project + "/devices/" + backend +
"/properties";
// Post apiKey to get temp api key
tokenParam += apiKey + "\"}";
......@@ -229,6 +312,11 @@ void IBMAccelerator::initialize(const HeterogeneousMap &params) {
backends_root = json::parse("{\"backends\":" + response + "}");
getBackendPropsResponse = "{\"backends\":" + response + "}";
std::vector<std::string> your_available_backends;
selectBackend(your_available_backends);
getBackendPropertiesPath = "/api/Network/" + hub + "/Groups/" + group +
"/Projects/" + project + "/devices/" + backend +
"/properties";
// Get current backend properties
auto backend_props_response =
get(IBM_API_URL, getBackendPropertiesPath, {},
......@@ -237,16 +325,6 @@ void IBMAccelerator::initialize(const HeterogeneousMap &params) {
xacc::info("Backend property:\n" + backend_props_response);
auto props = json::parse(backend_props_response);
backendProperties.insert({backend, props});
std::vector<std::string> your_available_backends;
for (auto &b : backends_root["backends"]) {
if (b.count("backend_name") &&
b["backend_name"].get<std::string>() == backend) {
availableBackends.insert(std::make_pair(backend, b));
}
if (b.count("backend_name")) {
your_available_backends.push_back(b["backend_name"].get<std::string>());
}
}
if (!xacc::container::contains(your_available_backends, backend)) {
std::stringstream error_ss;
......
......@@ -101,6 +101,12 @@ public:
if (config.stringExists("backend")) {
backend = config.getString("backend");
}
if (config.keyExists<int>("n-qubits")) {
requested_n_qubits = config.get<int>("n-qubits");
}
if (config.keyExists<bool>("check-jobs-limit")) {
filterByJobsLimit = config.get<bool>("check-jobs-limit");
}
if (config.keyExists<bool>("http-verbose")) {
restClient->setVerbose(config.get<bool>("http-verbose"));
}
......@@ -111,7 +117,7 @@ public:
}
const std::vector<std::string> configurationKeys() override {
return {"shots", "backend"};
return {"shots", "backend", "n-qubits", "check-jobs-limit", "http-verbose", "mode"};
}
HeterogeneousMap getProperties() override;
......@@ -156,6 +162,10 @@ private:
std::string &project);
void findApiKeyInFile(std::string &key, std::string &hub, std::string &group,
std::string &project, const std::string &p);
void selectBackend(std::vector<std::string>& all_available_backends);
void processBackendCandidate(nlohmann::json& b);
bool verifyJobsLimit(std::string& curr_backend);
std::shared_ptr<RestClient> restClient;
static const std::string IBM_AUTH_URL;
......@@ -172,6 +182,7 @@ private:
int shots = 1024;
std::string backend = DEFAULT_IBM_BACKEND;
int backendQueueLength = -1;
bool jobIsRunning = false;
std::string currentJobId = "";
......@@ -185,6 +196,8 @@ private:
std::string getBackendPropsResponse = "{}";
std::string defaults_response = "{}";
std::string mode = "qasm";
int requested_n_qubits = 0;
bool filterByJobsLimit = false;
std::string post(const std::string &_url, const std::string &path,
const std::string &postStr,
std::map<std::string, std::string> headers = {});
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment