Resources#
This chapter describes supported Solver Application Programming Interface (SAPI) resources and provides example usages.
Examples Setup#
The examples below use the following setup:
>>> import base64
>>> import hashlib
>>> import json
>>> import os
>>> import requests
>>> import struct
>>> from urllib.parse import urlencode
...
>>> SAPI_HOME = "https://na-west-1.cloud.dwavesys.com/sapi/v2"
... # Replace with your API token
>>> SAPI_TOKEN = "ABC-1234567...345678"
...
>>> session = requests.Session()
>>> session.headers = {'X-Auth-Token': SAPI_TOKEN, 'Content-type': 'application/json'}
For some examples of uploading problems to the Leap service’s quantum-classical hybrid solvers, a serialized binary quadratic model (\(\text{E} = -ab\)) is also used. The following code uses Ocean software to serialize the problem to the required format.[1]
>>> import dimod
>>> bqm = dimod.BinaryQuadraticModel({}, {'xy': -1}, 'BINARY')
>>> bqm_ser = bqm.to_file().read()
$ export SAPI_HOME=https://na-west-1.cloud.dwavesys.com/sapi/v2
$ export SAPI_TOKEN=ABC-1234567...345678 # Replace with your API token
For some examples of uploading problems to the Leap service’s quantum-classical hybrid
solvers, a serialized binary quadratic model (\(\text{E} = -ab\)) is also
used. The dimod
to_file()
method is used to serialize the problem,
which is saved to a file.
Example serialized file
The serialized file may look like this:
b'DIMODBQM\x02\x00\xb2\x00\x00\x00{"dtype": "float64", "itype": "int32",
"ntype": "int32", "shape": [2, 1], "type": "BinaryQuadraticModel", "variables": true,
"vartype": "BINARY"}\n \x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xbf
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\xbfVARS8\x00\x00
\x00["x", "y"]
SAPI Resources#
SAPI provides the following resources and methods.
Resource |
Method |
Reference |
---|---|---|
/bqm/multipart |
POST |
|
/bqm/multipart/<problem_data_id>/part/<part> |
PUT |
|
/bqm/multipart/<problem_data_id>/combine |
POST |
|
/bqm/multipart/<problem_data_id>/status |
GET |
|
/problems/ |
POST |
|
/problems/ |
DELETE |
|
/problems/<problem_id> |
DELETE |
|
/problems/ |
GET |
|
/problems/<problem_id>/ |
GET |
|
/problems/<problem_id>/info |
GET |
|
/problems/<problem_id>/answer/ |
GET |
|
/problems/<problem_id>/messages/ |
GET |
|
/solvers/remote/ |
GET |
|
/solvers/remote/<solver_id>/ |
GET |
Initiate Upload of Problem Data#
For quantum-classical hybrid solvers in the Leap service, you must upload your problem
using the $SAPI_HOME/bqm/multipart/*
endpoints before submitting a SAPI request
to run the problem. For large problems (starting from several megabytes and higher),
upload the problem data in multiple parts.
Maximum problem size currently supported is 50 GB.
Size of all parts must be 5M (5242880 bytes), except the last, which may be smaller.
To initiate the uploading of a problem, in a single part for small problems or
multiple parts for problems of several megabytes and higher, send an HTTP POST
request to bqm/multipart
.
The POST request body should contain the number of bytes—size
, as an
integer—required to store the problem.
SAPI returns an identifier, of type UUID, for the uploaded problem.
This example initiates an upload of the serialized BQM, bqm_ser
, created
in the Examples Setup section.
>>> size = len(bqm_ser)
>>> r = session.post(f"{SAPI_HOME}/bqm/multipart",
... json={"size": size})
This example sets the size of the uploaded problem, size
, to the number of
bytes of the serialized BQM of the Examples Setup section.
$ size=312
$ curl -H "X-Auth-Token: $SAPI_TOKEN" -H "Content-type: application/json" \
-X POST $SAPI_HOME/bqm/multipart/ -d '{"size": '"$size"'}'
{"id":"be806ff1-09d3-49d4-bba1-3008790c99d6"}
2xx responses
SAPI returns a 200 OK
response with an identifier for the problem data
that is to be uploaded.
>>> problem_data_id = r.json()["id"]
>>> print(problem_data_id)
be806ff1-09d3-49d4-bba1-3008790c99d6
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
for a failure to initiate upload
Below are some example error responses:
>>> r.status_code
401
>>> r.reason
'Unauthorized'
Upload Problem Data#
To upload a problem, or parts of a large problem, send an HTTP PUT
request to bqm/multipart/<problem_data_id>/part/<part>
(for each part, where
<part>
is an integer beginning at 1).
The POST request body should contain the data for (one part of) the problem,
encoded as described in the dimod
to_file()
method, and the header should contain the
MD5 checksum.
For a multi-part upload, data size for each part should be 5 MB (5242880 bytes), except for the last part, which may be smaller.
Calculating the MD5 Hash
The MD5 checksum can be found, for example, using the Python
hashlib
library. The following code example finds the checksum
for the problem created in the Examples Setup section.
>>> import hashlib
>>> import base64
...
>>> # For small problems:
>>> hash_md5 = hashlib.md5()
>>> hash_md5.update(bqm_ser)
>>> part_hash = base64.b64encode(hash_md5.digest()).decode('utf-8')
>>> print(part_hash)
mkDiHuw5xZD3ocYSikE4nw==
>>> # For large problems:
>>> hash_md5 = hashlib.md5()
>>> with bqm.to_file() as f: # for a saved file: with open("filename", "r")
... for chunk in iter(lambda: f.read(4096), b""):
... hash_md5.update(chunk)
>>> part_hash = (base64.b64encode(hash_md5.digest()).decode('utf-8'))
>>> print(part_hash)
mkDiHuw5xZD3ocYSikE4nw==
This example uses the identifier problem_data_id
returned from the
Initiate Upload of Problem Data example and an MD5 hash calculated above.
>>> r = session.put(f"{SAPI_HOME}/bqm/multipart/{problem_data_id}/part/1",
... headers={"Content-type": "application/octet-stream",
... "Content-MD5": "mkDiHuw5xZD3ocYSikE4nw=="},
... data=bqm_ser)
This example sets the identifier, problem_data_id
, of the problem data to be uploaded
to the value returned from the Initiate Upload of Problem Data example, the MD5
checksum, md5
, to the value calculated above, and the uploaded data to
the BQM of the Examples Setup section saved to file
my_bqm.txt
.
$ problem_data_id="be806ff1-09d3-49d4-bba1-3008790c99d6"
$ md5="mkDiHuw5xZD3ocYSikE4nw=="
$ curl -H "X-Auth-Token: $SAPI_TOKEN" -H "Content-MD5: $md5" -H \
"Content-type: application/octet-stream" -X PUT \
$SAPI_HOME/bqm/multipart/$problem_data_id/part/1 -T my_bqm.txt
2xx responses
SAPI returns a 200 OK
response.
You can check the upload status using the method shown in the Status of a Problem Upload section.
>>> session.get(f"{SAPI_HOME}/bqm/multipart/{problem_data_id}/status").json()
{'status': 'UPLOAD_IN_PROGRESS',
'parts': [{'part_number': 1, 'checksum': '9a40e21eec39c590f7a1c6128a41389f'}]}
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
for a failure to upload or invalid checksum404
for a failure to find the specified upload415
for incorrect media type
Below is and example error response to an incorrect MD5:
>>> r.status_code
401
>>> r.reason
'Bad Request'
Below is and example error response to an incorrect content type:
>>> r.status_code
415
>>> r.reason
'Unsupported Media Type'
Submit a Checksum for a Problem Upload#
To complete an upload of problem data, send an HTTP POST request to
bqm/multipart/<problem_data_id>/combine
.
The POST request body should contain the checksum for the entire problem, as a string.
Calculating the Checksum
The Leap service calculates the checksum of the combined file in a particular way: it concatenates all the checksums of the parts and then calculates the checksum of that concatenation. Your checksum must follow this same format.
The checksum can be found, for example, using the Python
hashlib
library. The examples below find the concatenated checksum
for the problem of the Examples Setup section and for an
artificial problem that reuses that same problem to represent two parts for the
sole purpose of constructing a combined checksum.
>>> # For a problem uploaded in a single part:
>>> hash_md5 = hashlib.md5()
>>> hash_md5.update(bqm_ser)
>>> problem_checksum = (hashlib.md5(bytes.fromhex(hash_md5.hexdigest()))).hexdigest()
>>> print(problem_checksum)
baf79ab99e269f7fda21e927b33345e9
>>> # For large problems:
>>> hash_md5_1 = hashlib.md5()
>>> hash_md5_1.update(bqm_ser) # replace bqm_ser with the part 1 data
>>> hash_md5_2 = hashlib.md5()
>>> hash_md5_2.update(bqm_ser) # replace bqm_ser with the part 2 data
>>> print((hashlib.md5(bytes.fromhex(
... hash_md5_1.hexdigest() +
... hash_md5_2.hexdigest())
... )).hexdigest())
65e5a89d30c855758d71844a927a8133
This example uses the identifier problem_data_id
returned from the
Initiate Upload of Problem Data example and a checksum calculated above.
>>> r = session.post(f"{SAPI_HOME}/bqm/multipart/{problem_data_id}/combine",
... json={"checksum": "baf79ab99e269f7fda21e927b33345e9"})
This example sets the identifier, problem_data_id
, of the problem data to be uploaded to
the value returned from the Initiate Upload of Problem Data example and the checksum,
checksum
, to the value calculated above.
$ problem_data_id="be806ff1-09d3-49d4-bba1-3008790c99d6"
$ checksum="baf79ab99e269f7fda21e927b33345e9"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" -H "Content-type: application/json" \
-X POST $SAPI_HOME/bqm/multipart/$problem_data_id/combine/ -d '{"checksum":'"$checksum"'}'
2xx responses
SAPI returns a 200 OK
response.
You can check the upload status using the method shown in the Status of a Problem Upload section.
>>> session.get(f"{SAPI_HOME}/bqm/multipart/{problem_data_id}/status").json()
{'status': 'UPLOAD_COMPLETED', 'parts': []}
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
for a failure to upload or missing or invalid checksum404
for a failure to find the specified upload
Below are some example error responses:
>>> r.reason
Failed to combine the multipart upload
Status of a Problem Upload#
To query the status of an in-progress problem upload, send an HTTP GET
request to bqm/multipart/<problem_data_id>/status
.
The GET request should contain no body.
SAPI returns the status as a string with parts and checksums.
This example uses the identifier problem_data_id
returned from the
Initiate Upload of Problem Data example.
>>> r = session.get(f"{SAPI_HOME}/bqm/multipart/{problem_data_id}/status")
This example sets the identifier, problem_data_id
, of the problem data being uploaded to
the value returned from the Initiate Upload of Problem Data example.
$ problem_data_id="be806ff1-09d3-49d4-bba1-3008790c99d6"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/bqm/multipart/$problem_data_id/status
2xx responses
SAPI returns a 200 OK
response.
For an ongoing upload, SAPI returns a status similar to the following:
>>> r.json()
{'status': 'UPLOAD_IN_PROGRESS',
'parts': [{'part_number': 1, 'checksum': '9a40e21eec39c590f7a1c6128a41389f'}]}
For a successfully completed upload, SAPI returns a status similar to the following:
>>> r.json()
{'status': 'UPLOAD_COMPLETED', 'parts': []}
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for a failure to find the specified upload
Submit Problems#
To submit problems to a solver in the Leap service, send an HTTP POST request to problems
.
The POST request body should contain the JSON-encoded fields described below. When possible, if you have more than one problem, submit them in a single query.[2]
Fields in Request Body
The JSON data for the submitted problem includes the following key-value pairs:
Key |
Value |
---|---|
data |
Encoded problem data; see below. |
label |
Optional user-defined string to label the problem. |
params |
Solver-specific parameters. |
solver |
Solver to be used. |
type |
One of the supported problem types. |
Key |
Value and Encoding |
---|---|
format |
Format of the problem data as a string. Supported values are:
|
lin |
For Set values for all qubits of the QPU’s working graph in the same order as the qubits solver property.
For example, before encoding, a Not used for |
quad |
For Set one value per active coupler in the same order as the couplers solver property. An active coupler means that both qubits the coupler is incident to are active. NaN values are not permitted. For example, before encoding, a Not used for |
For an example of sumitting a problem to a quantum processing unit (QPU) sampler, see the End-to-End Examples section.
This example uses the identifier problem_data_id
returned from the
Initiate Upload of Problem Data example and hybrid solver
solver_hybrid_bqm
selected as in the Submit a Problem to a Quantum-Classical Hybrid Solver
section.
>>> r = session.post(f"{SAPI_HOME}/problems",
... json=[{"solver": solver_hybrid_bqm,
... "label": "REST Submission to hybrid BQM solver",
... "data": {"format": "ref", "data": problem_data_id},
... "type": "bqm",
... "params": {"time_limit": 5}}])
This example sets the identifier, problem_data_id
, of the problem data
being uploaded to the value returned from the Initiate Upload of Problem Data
example and sets the requested solver to hybrid_binary_quadratic_model_version2p
,
a solver available to the user account that executed this example.
$ problem_data_id="be806ff1-09d3-49d4-bba1-3008790c99d6"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems -X POST \
-d '[{"type":"bqm","label": "REST Submission to hybrid BQM solver", \
"solver":"hybrid_binary_quadratic_model_version2p", \
"data":{"format": "ref", "data": "'"$problem_data_id"'"}, \
"params":{"time_limit":5}}]'
The request body is JSON data enclosed in a list. For submitting multiple
problems in a single query, the list is the comma-separated fields of each
problem: [{"solver": ...},{"solver": ...},...{"solver": ...}]
2xx responses
SAPI returns a 200 OK
response with the problem identifier.
Below are some example 201 responses:
>>> r.json()
{'status': 'IN_PROGRESS',
'id': 'a239c000-10de-4663-b562-af8029c0c470',
'solver': 'hybrid_binary_quadratic_model_version2p',
'type': 'bqm',
'submitted_on': '2022-09-01T16:48:36.052206Z',
'label': 'REST Submission to hybrid BQM solver'}
>>> r.json()
{'status': 'COMPLETED',
'id': '51fa2c98-3f19-4dd9-9f2d-c4295278218f',
'solver': 'Advantage_system4.1',
'type': 'ising',
'submitted_on': '2022-09-01T17:55:00.877038Z',
'label': 'QPU REST submission 1',
'solved_on': '2022-09-01T17:55:01.087126Z',
'answer': {'solutions': 'AMA=',
'energies': 'AAAAAAAA8L8AAAAAAADwvw==',
... # SNIPPED FOR BREVITY
'num_variables': 5760}
}
The following table describes fields in the responses above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
The following table describes the answer
field for a QPU solver.
Key |
Value |
---|---|
format |
String: |
num_variables |
Total number of variables (active or otherwise) that the solver has. JSON integer. |
solutions |
Base-64–encoded string of bit-packed solutions (with 0 = -1
for Ising problems). Bits are in little-endian order. Each
solution is padded to end on a byte boundary and contains values
for active qubits only. Ordered by the values of |
energies |
Base-64–encoded string of energies, each a little-endian 8-byte floating-point number (doubles). Ordered from low to high. |
active_variables |
Base-64–encoded string of the indices of the problem’s active variables. The indices are 4-byte little-endian integers. |
num_occurrences |
Base-64–encoded string of the number of occurrences of each
solution when answer_mode is |
timing |
Solver-specific JSON object reporting the time that the solver took to handle the problem. |
For quantum-classical hybrid solvers, the answer
field differs. For
example, format
might be bq
and fields might include the type of
variables (e.g., INTEGER
), version, etc.
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
for various failures
Below are some example error responses:
>>> r.json()
{'error_code': 400,
'error_msg': 'Problem type (cqm) is not supported by the solver.'}
>>> r.json()
{'error_code': 400,
'error_msg': 'Attempting to run a problem for less than the allowed minimum time_limit 3.0 s'}
>>> r.json()
{'error_code': 400,
'error_msg': 'Solver does not exist or apitoken does not have access'}
Cancel Multiple Problems#
To cancel pending problems (problems with status PENDING
), send an HTTP
DELETE request to problems
.
The request body should be a JSON-encoded list of problem IDs; if the request body is empty, the request has no effect.
When possible, if you have more than one problem to cancel, submit them in a single query.
>>> id_list = ["74d9344c-0160-47bc-b7b1-e245b2ffd955",
... "25f98470-bc55-476c-9042-120bbc0336cf"]
...
>>> r = session.delete(f"{SAPI_HOME}/problems", json=id_list)
$ id_list=[\"74d9344c-0160-47bc-b7b1-e245b2ffd955\",\"25f98470-bc55-476c-9042-120bbc0336cf\"]
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems -X DELETE -d $id_list
2xx responses
SAPI returns a 2xx
response. Below are some example 2xx responses:
200
for cancelled problem202
for cancellation request received for in-progress jobs. The problem is cancelled if the request was received in time; otherwise, it will complete.
>>> r.json()
[{'status': 'CANCELLED',
'id': '74d9344c-0160-47bc-b7b1-e245b2ffd955',
'solver': 'hybrid_binary_quadratic_model_version2p',
'type': 'bqm',
'submitted_on': '2022-09-01T18:20:02.594833Z',
'label': 'REST Submission to hybrid BQM solver',
'solved_on': '2022-09-01T18:20:03.708681Z'}]
>>> r.json()
[{'error_code': 202, 'error_msg': 'Attempting to cancel problem in progress.'},
{'error_code': 202, 'error_msg': 'Attempting to cancel problem in progress.'}]
>>> r = session.get(SAPI_HOME + "/problems/74d9344c-0160-47bc-b7b1-e245b2ffd955/info")
>>> r.json()['metadata']['status']
'CANCELLED'
>>> r.json()
[{'error_code': 202, 'error_msg': 'Attempting to cancel problem in progress.'},
{'error_code': 202, 'error_msg': 'Attempting to cancel problem in progress.'}]
>>> r = session.get(SAPI_HOME + "/problems/7d341c42-0eea-460a-b7d0-82892a4a6726/info")
>>> r.json()['metadata']['status']
'COMPLETED'
The following table describes fields in the responses above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for nonexistent problem ID409
for a poblem that reached a terminal states before the request
Below are some example error responses:
>>> r.json()
[{'error_code': 409, 'error_msg': 'Problem has been finished.'},
{'error_code': 409, 'error_msg': 'Problem has been finished.'}]
Cancel a Problem by ID#
To cancel a previously submitted problem, make an HTTP DELETE request to
problems/<problem_id>
.
The request should contain no body.
>>> problem_id = "74d9344c-0160-47bc-b7b1-e245b2ffd955"
...
>>> r = session.delete(f"{SAPI_HOME}/problems/{problem_id}")
$ problem_id="74d9344c-0160-47bc-b7b1-e245b2ffd955"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems/$problem_id -X DELETE
2xx responses
SAPI returns a 2xx
response. Below are some example 2xx responses:
200
for cancelled problem202
for cancellation request received for in-progress jobs. The problem is cancelled if the request was received in time; otherwise, it will complete.
>>> r.json()
{'status': 'CANCELLED',
'id': 'd92d5b66-330b-4bfd-b26f-a6220b4d2710',
'solver': 'hybrid_binary_quadratic_model_version2p',
'type': 'bqm',
'submitted_on': '2022-09-01T20:09:55.377688Z',
'label': 'REST Submission to hybrid BQM solver',
'solved_on': '2022-09-01T20:09:56.489498Z'}
The following table describes fields in the response above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for nonexistent problem ID409
for a poblem that reached a terminal states before the request
Below are some example error responses:
>>> r.json()
{'error_code': 409,
'error_msg': 'Problem has been finished.'}
List Problems#
To retrieve a list of previously submitted problems, send an HTTP GET request to
problems
.
The request should contain no body.
By default, the request blocks for up to one second unless at least one problem has completed processing.
You can customize polling by adding the optional timeout
parameter to specify
the blocking time, in seconds, for this request. Supported values are integers
between 1 to 30.
You can filter the results using one or more optional filter keys, concatenated with an ampersand (”&”).
Filter Keys
Key |
Value |
---|---|
id |
Comma-separated list of problem IDs |
label |
Labels that contain the given text. |
max_results |
Maximum number of results to return. Returns up to 1000 if not specified. |
status |
Problem state: COMPLETED, IN_PROGRESS, PENDING, FAILED, CANCELLED. |
solver |
Solver name (e.g., |
>>> r = session.get(f"{SAPI_HOME}/problems/?max_results=3")
$ filter="solver=Advantage_system4.1&max_results=3"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" -X GET "$SAPI_HOME/problems/?$filter"
2xx response
SAPI returns a 200 OK
response.
>>> r.json()
[{'id': 'fe863ae1-1d7e-4444-a18e-c1fe7708b8a0',
'solver': 'Advantage_system4.1',
'type': 'ising',
'label': 'QPU REST submission 1',
'submitted_on': '2022-08-29T15:13:11.532127Z',
'solved_on': '2022-08-29T15:13:11.709085Z',
'status': 'COMPLETED'},
{'id': '25f98470-bc55-476c-9042-120bbc0336cf',
'solver': 'Advantage_system4.1',
'type': 'ising',
'label': 'QPU REST submission 1',
'submitted_on': '2022-08-29T15:12:10.461598Z',
'solved_on': '2022-08-29T15:12:10.635163Z',
'status': 'COMPLETED'},
{'id': 'a56da5c5-f8a9-49ad-885b-d7e1b117639e',
'solver': 'Advantage_system4.1',
'type': 'ising',
'label': 'QPU REST submission 1',
'submitted_on': '2022-08-29T15:11:38.897970Z',
'solved_on': '2022-08-29T15:11:39.088480Z',
'status': 'COMPLETED'}]
The following table describes fields in the response above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
iftimeout
is specified as an unsupported value404
for nonexistent or non-accessible problem ID410
for submitted problems that are no longer accessible
Below are some example error responses:
>>> r.text
'Problem does not exist or apitoken does not have access'
Retrieve a Problem#
To retrieve a previously submitted problem, send an HTTP GET request to
problems/<problem_id>
.
The request should contain no body.
By default, the request blocks for up to one second if a submitted problem has not completed processing.
You can customize polling by adding the optional timeout
parameter to specify
the blocking time, in seconds, for this request. Supported values are integers
between 1 to 30.
>>> problem_id = "74d9344c-0160-47bc-b7b1-e245b2ffd955"
...
>>> r = session.get(f"{SAPI_HOME}/problems/{problem_id}?timeout=5")
$ problem_id="74d9344c-0160-47bc-b7b1-e245b2ffd955"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems/$problem_id?timeout=5 -X GET
2xx responses
SAPI returns a 200 OK
response.
>>> r.json()
{'status': 'COMPLETED',
'id': '74d9344c-0160-47bc-b7b1-e245b2ffd955',
'solver': 'hybrid_binary_quadratic_model_version2p',
'type': 'bqm',
'submitted_on': '2022-08-31T14:27:47.822848Z',
'label': 'hybrid BQM solver REST Submission python 2',
'solved_on': '2022-08-31T14:27:55.497511Z',
'answer': {'format': 'bq',
... # SNIPPED FOR BREVITY
'charge_time': 4981622,
'run_time': 4981622}}}}
The following table describes fields in the response above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
The following table describes the answer
field for a QPU solver.
Key |
Value |
---|---|
format |
String: |
num_variables |
Total number of variables (active or otherwise) that the solver has. JSON integer. |
solutions |
Base-64–encoded string of bit-packed solutions (with 0 = -1
for Ising problems). Bits are in little-endian order. Each
solution is padded to end on a byte boundary and contains values
for active qubits only. Ordered by the values of |
energies |
Base-64–encoded string of energies, each a little-endian 8-byte floating-point number (doubles). Ordered from low to high. |
active_variables |
Base-64–encoded string of the indices of the problem’s active variables. The indices are 4-byte little-endian integers. |
num_occurrences |
Base-64–encoded string of the number of occurrences of each
solution when answer_mode is |
timing |
Solver-specific JSON object reporting the time that the solver took to handle the problem. |
For quantum-classical hybrid solvers, the answer
field differs. For
example, format
might be bq
and fields might include the type of
variables (e.g., INTEGER
), version, etc.
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
400
iftimeout
is specified as an unsupported value404
for nonexistent problem ID410
for submitted problems that are no longer accessible
Below are some example error responses:
>>> r.json()
{'error_code': 404,
'error_msg': 'Problem does not exist or apitoken does not have access'}
Retrieve Problem Information#
To retrieve information about a problem, send an HTTP GET request to
problems/<problem_id>/info
:
The request should contain no body.
>>> problem_id = "74d9344c-0160-47bc-b7b1-e245b2ffd955"
...
>>> r = session.get(f"{SAPI_HOME}/problems/{problem_id}/info")
$ problem_id="74d9344c-0160-47bc-b7b1-e245b2ffd955"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems/$problem_id/info -X GET
2xx responses
SAPI returns a 200 OK
response.
>>> r.json()
{'id': '7d341c42-0eea-460a-b7d0-82892a4a6726',
'data': {'format': 'ref', 'data': 'be806ff1-09d3-49d4-bba1-3008790c99d6'},
'params': {'time_limit': 5},
'metadata': {'submitted_by': 'ABC-123456789...',
'solver': 'hybrid_binary_quadratic_model_version2p',
'type': 'bqm',
'submitted_on': '2022-09-01T18:27:30.281252Z',
'solved_on': '2022-09-01T18:27:35.473474Z',
'status': 'COMPLETED',
'messages': [],
'label': 'REST Submission to hybrid BQM solver'},
'answer': {'format': 'bq',
... # SNIPPED FOR BREVITY
'run_time': 4998527}}}}
The following table describes fields in the response above.
Key |
Value |
---|---|
answer |
Content of the answer depends on the solver and parameters used. |
id |
Unique identifier of the problem. Can be used to retrieve problem information, solutions, and messages. |
label |
Optional user-defined string (label) for a problem. |
status |
One of the problem states as defined in SAPI Problem Lifecycle. For
example, |
submitted_on |
Time when problem was submitted. |
solved_on |
If this problem is in terminal state ( |
type |
One of the supported problem types. |
The following table describes the answer
field for a QPU solver.
Key |
Value |
---|---|
format |
String: |
num_variables |
Total number of variables (active or otherwise) that the solver has. JSON integer. |
solutions |
Base-64–encoded string of bit-packed solutions (with 0 = -1
for Ising problems). Bits are in little-endian order. Each
solution is padded to end on a byte boundary and contains values
for active qubits only. Ordered by the values of |
energies |
Base-64–encoded string of energies, each a little-endian 8-byte floating-point number (doubles). Ordered from low to high. |
active_variables |
Base-64–encoded string of the indices of the problem’s active variables. The indices are 4-byte little-endian integers. |
num_occurrences |
Base-64–encoded string of the number of occurrences of each
solution when answer_mode is |
timing |
Solver-specific JSON object reporting the time that the solver took to handle the problem. |
For quantum-classical hybrid solvers, the answer
field differs. For
example, format
might be bq
and fields might include the type of
variables (e.g., INTEGER
), version, etc.
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for nonexistent problem ID410
for submitted problems that are no longer accessible
Below are some example error responses:
>>> r.json()
{'error_code': 404,
'error_msg': 'Problem does not exist or apitoken does not have access'}
Retrieve an Answer#
To retrieve an answer for a problem, send an HTTP GET request to
problems/<problem_id>/answer
. The answer consists of solution data
in binary format or a URL to such solution data as well as additional problem
information.
The request should contain no body.
>>> problem_id = "74d9344c-0160-47bc-b7b1-e245b2ffd955"
...
>>> r = session.get(f"{SAPI_HOME}/problems/{problem_id}/answer")
$ problem_id="74d9344c-0160-47bc-b7b1-e245b2ffd955"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems/$problem_id/answer -X GET
2xx responses
Quadratic models
SAPI returns a 200 OK
response.
>>> r.json()
{'answer': {'solutions': 'AMA=',
'energies': 'AAAAAAAA8L8AAAAAAADwvw==',
'timing': {'qpu_sampling_time': 769.4,
'qpu_anneal_time_per_sample': 20.0,
'qpu_readout_time_per_sample': 36.4,
'qpu_access_time': 15831.76,
'qpu_access_overhead_time': 6535.24,
'qpu_programming_time': 15062.36,
'qpu_delay_time_per_sample': 20.54,
'total_post_processing_time': 1853.0,
'post_processing_overhead_time': 1853.0},
'num_occurrences': 'BgAAAAQAAAA=',
'format': 'qp',
'active_variables': 'HgAAAB8AAAA=',
'num_variables': 5760}}
The following table describes the answer
field for a QPU solver.
Key |
Value |
---|---|
format |
String: |
num_variables |
Total number of variables (active or otherwise) that the solver has. JSON integer. |
solutions |
Base-64–encoded string of bit-packed solutions (with 0 = -1
for Ising problems). Bits are in little-endian order. Each
solution is padded to end on a byte boundary and contains values
for active qubits only. Ordered by the values of |
energies |
Base-64–encoded string of energies, each a little-endian 8-byte floating-point number (doubles). Ordered from low to high. |
active_variables |
Base-64–encoded string of the indices of the problem’s active variables. The indices are 4-byte little-endian integers. |
num_occurrences |
Base-64–encoded string of the number of occurrences of each
solution when answer_mode is |
timing |
Solver-specific JSON object reporting the time that the solver took to handle the problem. |
For quantum-classical hybrid solvers, the answer
field differs. For
example, format
might be bq
and fields might include the type of
variables (e.g., INTEGER
), version, etc.
Nonlinear models
SAPI returns a 200 OK
response.
>>> r.json()
{'answer': {'format': 'binary-ref',
'auth_method': 'sapi-token',
'url': 'https://cloud.dwavesys.com/sapi/v2/problems/74d9344c-0160-47bc-b7b1-e245b2ffd955/answer/data/',
'timing': {'qpu_access_time': 47512, 'warnings': [], 'charge_time': 1000000, 'run_time': 1067327},
'shape': {}}}
Key |
Value |
---|---|
format |
String: |
auth_method |
Authorization method required to download
binary data specified in |
url |
URL to download the solution in binary format. |
timing |
Solver-specific JSON object reporting the time that the solver took to handle the problem. |
shape |
Shape of the nonlinear problem. |
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for nonexistent problem ID410
for submitted problems that are no longer accessible
Below are some example error responses:
>>> r.text
'Problem does not exist or apitoken does not have access'
Retrieve Problem Messages#
To retrieve messages for a problem, send an HTTP GET request to
problems/<problem_id>/messages
.
The request should contain no body.
>>> problem_id = "74d9344c-0160-47bc-b7b1-e245b2ffd955"
...
>>> r = session.get(f"{SAPI_HOME}/problems/{problem_id}/messages")
$ problem_id="74d9344c-0160-47bc-b7b1-e245b2ffd955"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/problems/$problem_id/messages -X GET
2xx responses
SAPI returns a 200 OK
response.
>>> r.json()
[]
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
404
for nonexistent problem ID410
for submitted problems that are no longer accessible
Below are some example error responses:
>>> r.text
'Problem does not exist or apitoken does not have access'
Retrieve Available Solvers#
To retrieve a list of available solvers from the Leap service, send an HTTP GET request to
solvers/remote
.
The request should contain no body.
The request supports the use of the If-None-Match
request header.
If the ETag
(entity tag) value in the request header matches the one
on the server, a 304 (Not Modified)
response is returned;
otherwise, the list of solvers is returned. You can use this feature to manage
downloading and caching of this content.
By default, all solver fields are returned. You can use the filter
parameter to get a subset of solver fields.
Filtering Solver Fields with the filter
Parameter
To retrieve a subset of solver fields, create a list of the subset
of solver fields by specifying the filter
parameter
via the following syntax:
filter={all|none}[,{+|-}field]... [,{+|-}field]
where:
all
Initializes the list with all solver fields. This is the default.
none
Initializes the list with no solver fields.
{+|-}field
Adds (
+
) or removes (-
) a solver field to or from the list. The fields are evaluated left to right; for example, if a field is both added and removed, the last action prevails. To specify the solver properties in a solver’sproperties
dict, use dot notation as follows:properties.property[.property]... [.property]
For example:
properties.problem_timing_data.typical_programming_time
If a field does not exist or a field does not contain a value,
nothing is returned for that field.
The maximum size of the SAPI URL in the request is 8 KB; thus, the specified
filter
parameter must not extend the URL beyond this maximum.
>>> filter = urlencode({"filter": "none,+id,+status,+avg_load,+properties.num_qubits,+properties.category"})
...
>>> r = session.get(f"{SAPI_HOME}/solvers/remote/?{filter}")
$ filter="filter=none%2C%2Bid%2C%2Bstatus"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/solvers/remote/?filter
2xx response
SAPI returns a 200 OK
response.
The Cache-Control
response header is returned with the following directives:
private
max-age
: Specifies the time, in seconds, that the returned solver fields should be cached; the time depends on the expected longevity of the solver field values. Solver fields with values that change more frequently (e.g.,avg_load
) should probably be cached for a shorter time than fields with values that change infrequently (e.g.,description
andid
). The value for this directive is based on the shortest cache-refresh time of the returned fields. (Use thefilter
parameter to return the desired subset of solver fields.)
>>> r = r.json()
>>> for i in range(len(r)):
... print(f"{r[i]['id']} \n\tStatus: {r[i]['status']} Load: {r[i]['avg_load']}")
DW_2000Q_6
Status: ONLINE Load: 0.0
DW_2000Q_VFYC_6
Status: ONLINE Load: 0.0
hybrid_binary_quadratic_model_version2p
Status: ONLINE Load: 0.0
hybrid_discrete_quadratic_model_version1p
Status: ONLINE Load: 0.0
Advantage_system4.1
Status: ONLINE Load: 0.13
hybrid_constrained_quadratic_model_version1p
Status: ONLINE Load: 0.0
Advantage_system6.1
Status: ONLINE Load: 0.01
Advantage2_prototype1.1
Status: ONLINE Load: 0.0
Field |
Description |
---|---|
avg_load |
Average current load for the solver. |
description |
Description of the solver. |
id |
Unique ID (name) of the solver. |
properties |
Solver properties
that reside in the |
status |
Status of the solver; for example, a status of
|
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
304
for unmodified resource
Retrieve Solver Fields#
To retrieve the fields of a solver, send an HTTP GET request
to solvers/remote/<solver_id>
.
The request supports the If-None-Match
request header.
If the ETag
(entity tag) value in the request header matches the one
on the server, a 304 (Not Modified)
response is returned;
otherwise, the solver fields and values are returned. You can use this feature
to manage downloading and caching of this content.
By default, all solver fields are returned.
You can use the filter
parameter to get a subset of solver fields.
Filtering Solver Fields with the filter
Parameter
To retrieve a subset of solver fields, create a list of the subset
of solver fields by specifying the filter
parameter
via the following syntax:
filter={all|none}[,{+|-}field]... [,{+|-}field]
where:
all
Initializes the list with all solver fields. This is the default.
none
Initializes the list with no solver fields.
{+|-}field
Adds (
+
) or removes (-
) a solver field to or from the list. The fields are evaluated left to right; for example, if a field is both added and removed, the last action prevails. To specify the solver properties in a solver’sproperties
dict, use dot notation as follows:properties.property[.property]... [.property]
For example:
properties.problem_timing_data.typical_programming_time
If a field does not exist or a field does not contain a value,
nothing is returned for that field.
The maximum size of the SAPI URL in the request is 8 KB; thus, the specified
filter
parameter must not extend the URL beyond this maximum.
>>> solver_name = "Advantage_system4.1"
>>> r = session.get(f"{SAPI_HOME}/solvers/remote/{solver_name}")
$ solver_name="Advantage_system4.1"
$ filter="none%2C%2Bstatus%2C%2Bavg_load%2C%2Bproperties.num_qubits"
$ curl -H "X-Auth-Token: $SAPI_TOKEN" $SAPI_HOME/solvers/remote/$solver_name/?filter
2xx response
SAPI returns a 200 OK
response.
The Cache-Control
response header is returned with the following directives:
private
max-age
: Specifies the time, in seconds, that the returned solver fields should be cached; the time depends on the expected longevity of the solver field values. Solver fields with values that change more frequently (e.g.,avg_load
) should probably be cached for a shorter time than fields with values that change infrequently (e.g.,description
andid
). The value for this directive is based on the shortest cache-refresh time of the returned fields. (Use thefilter
parameter to return the desired subset of solver fields.)
>>> r.json()['description']
'Advantage performance update'
Field |
Description |
---|---|
avg_load |
Average current load for the solver. |
description |
Description of the solver. |
id |
Unique ID (name) of the solver. |
properties |
Solver properties
that reside in the |
status |
Status of the solver; for example, a status of
|
Error responses
In addition to generic client and server error responses, SAPI may return particular error codes.
304
for unmodified resource