Accessing info with qiskit-superstaq
This tutorial will cover the information you can access on your account and related jobs and backends using qiskit-superstaq
.
Imports and API Token
As usual, we’ll begin with importing requirements and setting up access to Superstaq. This tutorial uses qiskit-superstaq
, our Superstaq client for Qiskit. You can install it and relevant dependencies by running pip install qiskit-superstaq[examples]
.
[1]:
# Requirements to use qiskit-superstaq
try:
import qiskit
import qiskit_superstaq as qss
except ImportError:
print("Installing qiskit-superstaq...")
%pip install --quiet 'qiskit-superstaq[examples]'
print("Installed qiskit-superstaq.")
print("You may need to restart the kernel to import newly installed packages.")
import qiskit
import qiskit_superstaq as qss
Now, we instantiate a provider in qiskit-superstaq
with SuperstaqProvider()
. Supply the Superstaq API token by providing the token as an argument of qss.SuperstaqProvider()
or setting it as an environment variable (see this guide).
[2]:
provider = qss.SuperstaqProvider()
Account Information
The provider
class gives you a means to retrieve information regarding your Superstaq account. Currently, you can use provider
to retrieve your Superstaq balance.
[3]:
provider.get_balance()
[3]:
'20 credits'
If are interested in increasing your balance or have more information on your user role, please reach out to us at superstaq@infleqtion.com or join our Slack workspace.
Backend Information
In addition to account information, the SuperstaqProvider
object also gives you a list of all the devices and simulators to which you have access, as well as additional information about those backends.
get_targets()
: Retrieves a list of supported Superstaq targets. This method also accepts the following boolean keyword arguments to filter the backends returned:simulator
,supports_submit
,supports_submit_qubo
,supports_compile
,available
,retired
, andaccessible
.backends()
: Retrieves a list of available backends. This method also accepts the same keyword arguments as mentioned above.get_my_targets()
: Retrieves a filtered list of targets that are accessible to the user based on their user role permissions. This method is equivalent toget_targets(accessible=True)
.get_backend("<backend_name>")
: Select your target backend, where<backend_name>
is the name of the desired backendget_backend("<backend_name>").target_info()
: Retrieve information on your selected backend, such as number of qubits, native gate set
[4]:
provider.get_targets()
[4]:
[Target(target='aqt_keysight_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='aqt_zurich_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='aws_dm1_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='aws_sv1_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='aws_tn1_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='cq_sqale_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='cq_sqale_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='eeroq_wonderlake_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_brisbane_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_fez_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_kyiv_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_marrakesh_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_sherbrooke_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ibmq_torino_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ionq_aria-1_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='ionq_aria-2_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=False, retired=False),
Target(target='ionq_forte-1_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=False, retired=False),
Target(target='ionq_ion_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='iqm_garnet_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=False, retired=False),
Target(target='qscout_peregrine_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='qtm_h1-1_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='qtm_h1-1e_simulator', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='qtm_h2-1_qpu', supports_submit=True, supports_submit_qubo=False, supports_compile=True, available=True, retired=False),
Target(target='rigetti_ankaa-2_qpu', supports_submit=False, supports_submit_qubo=False, supports_compile=True, available=False, retired=False),
Target(target='ss_unconstrained_simulator', supports_submit=True, supports_submit_qubo=True, supports_compile=True, available=True, retired=False)]
[5]:
backend = provider.get_backend("ibmq_brisbane_qpu") # selecting IBM's Brisbane device
backend.target_info()
[5]:
{'num_qubits': 127,
'target': 'ibmq_brisbane_qpu',
'coupling_map': [[0, 1],
[0, 14],
[1, 0],
[1, 2],
[2, 1],
[2, 3],
[3, 2],
[3, 4],
[4, 3],
[4, 5],
[4, 15],
[5, 4],
[5, 6],
[6, 5],
[6, 7],
[7, 6],
[7, 8],
[8, 7],
[8, 9],
[8, 16],
[9, 8],
[9, 10],
[10, 9],
[10, 11],
[11, 10],
[11, 12],
[12, 11],
[12, 13],
[12, 17],
[13, 12],
[14, 0],
[14, 18],
[15, 4],
[15, 22],
[16, 8],
[16, 26],
[17, 12],
[17, 30],
[18, 14],
[18, 19],
[19, 18],
[19, 20],
[20, 19],
[20, 21],
[20, 33],
[21, 20],
[21, 22],
[22, 15],
[22, 21],
[22, 23],
[23, 22],
[23, 24],
[24, 23],
[24, 25],
[24, 34],
[25, 24],
[25, 26],
[26, 16],
[26, 25],
[26, 27],
[27, 26],
[27, 28],
[28, 27],
[28, 29],
[28, 35],
[29, 28],
[29, 30],
[30, 17],
[30, 29],
[30, 31],
[31, 30],
[31, 32],
[32, 31],
[32, 36],
[33, 20],
[33, 39],
[34, 24],
[34, 43],
[35, 28],
[35, 47],
[36, 32],
[36, 51],
[37, 38],
[37, 52],
[38, 37],
[38, 39],
[39, 33],
[39, 38],
[39, 40],
[40, 39],
[40, 41],
[41, 40],
[41, 42],
[41, 53],
[42, 41],
[42, 43],
[43, 34],
[43, 42],
[43, 44],
[44, 43],
[44, 45],
[45, 44],
[45, 46],
[45, 54],
[46, 45],
[46, 47],
[47, 35],
[47, 46],
[47, 48],
[48, 47],
[48, 49],
[49, 48],
[49, 50],
[49, 55],
[50, 49],
[50, 51],
[51, 36],
[51, 50],
[52, 37],
[52, 56],
[53, 41],
[53, 60],
[54, 45],
[54, 64],
[55, 49],
[55, 68],
[56, 52],
[56, 57],
[57, 56],
[57, 58],
[58, 57],
[58, 59],
[58, 71],
[59, 58],
[59, 60],
[60, 53],
[60, 59],
[60, 61],
[61, 60],
[61, 62],
[62, 61],
[62, 63],
[62, 72],
[63, 62],
[63, 64],
[64, 54],
[64, 63],
[64, 65],
[65, 64],
[65, 66],
[66, 65],
[66, 67],
[66, 73],
[67, 66],
[67, 68],
[68, 55],
[68, 67],
[68, 69],
[69, 68],
[69, 70],
[70, 69],
[70, 74],
[71, 58],
[71, 77],
[72, 62],
[72, 81],
[73, 66],
[73, 85],
[74, 70],
[74, 89],
[75, 76],
[75, 90],
[76, 75],
[76, 77],
[77, 71],
[77, 76],
[77, 78],
[78, 77],
[78, 79],
[79, 78],
[79, 80],
[79, 91],
[80, 79],
[80, 81],
[81, 72],
[81, 80],
[81, 82],
[82, 81],
[82, 83],
[83, 82],
[83, 84],
[83, 92],
[84, 83],
[84, 85],
[85, 73],
[85, 84],
[85, 86],
[86, 85],
[86, 87],
[87, 86],
[87, 88],
[87, 93],
[88, 87],
[88, 89],
[89, 74],
[89, 88],
[90, 75],
[90, 94],
[91, 79],
[91, 98],
[92, 83],
[92, 102],
[93, 87],
[93, 106],
[94, 90],
[94, 95],
[95, 94],
[95, 96],
[96, 95],
[96, 97],
[96, 109],
[97, 96],
[97, 98],
[98, 91],
[98, 97],
[98, 99],
[99, 98],
[99, 100],
[100, 99],
[100, 101],
[100, 110],
[101, 100],
[101, 102],
[102, 92],
[102, 101],
[102, 103],
[103, 102],
[103, 104],
[104, 103],
[104, 105],
[104, 111],
[105, 104],
[105, 106],
[106, 93],
[106, 105],
[106, 107],
[107, 106],
[107, 108],
[108, 107],
[108, 112],
[109, 96],
[109, 114],
[110, 100],
[110, 118],
[111, 104],
[111, 122],
[112, 108],
[112, 126],
[113, 114],
[114, 109],
[114, 113],
[114, 115],
[115, 114],
[115, 116],
[116, 115],
[116, 117],
[117, 116],
[117, 118],
[118, 110],
[118, 117],
[118, 119],
[119, 118],
[119, 120],
[120, 119],
[120, 121],
[121, 120],
[121, 122],
[122, 111],
[122, 121],
[122, 123],
[123, 122],
[123, 124],
[124, 123],
[124, 125],
[125, 124],
[125, 126],
[126, 112],
[126, 125]],
'supports_midcircuit_measurement': True,
'native_gate_set': ['ecr', 'id', 'rz', 'sx', 'x'],
'max_experiments': 300,
'max_shots': 100000,
'processor_type': {'family': 'Eagle', 'revision': 3},
'open_pulse': True,
'supports_dynamic_circuits': True}
Job Information
Jobs submitted through Superstaq contain the following information:
job_id()
: Unique identifier for the job.status()
: Overall status of the job (Submitted, Queued, Running, Failed, Cancelled, or Done). Note that anindex
argument can be passed optionally to retreive the status of a specific job indexed byindex
in a batch job.backend()
: Device the job was run on.result().get_counts()
: Counts from the result of the job run. Note thatresult()
can take anindex
argument to retrieve a specific job result (corresponding to the circuit with the sameindex
). It also optionally accepts a list of qubit indices to retrieve marginal counts on specific qubits via thequbit_indices
argument ofresult()
.input_circuits()
: Retrieves original (i.e., not compiled) circuit(s) for job. Note this returns a list and you must specify anindex
if you want to retrieve a single/specific circuit.compiled_circuits()
: Retrieves compiled circuit(s) from submitted job. Note this returns a list and you must specify anindex
if you want to retrieve a single/specific circuit.
Note that jobs live in our database for a limited amount of time. Typically, they have a lifespan of 1 year.
[6]:
# Creating a circuit using Qiskit
qc = qiskit.QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
# Submitting the circuit to IBM's Brisbane QPU
backend = provider.get_backend("ibmq_brisbane_qpu")
job = backend.run(
[qc], method="dry-run", shots=100
) # Specify "dry-run" as the method to submit & run a Superstaq simulation
[7]:
job.job_id()
[7]:
'128cdcd8-47cf-4d62-a788-c7c672db2150'
[8]:
job.status()
[8]:
<JobStatus.DONE: 'job has successfully run'>
[9]:
job.backend()
[9]:
<SuperstaqBackend('ibmq_brisbane_qpu')>
[10]:
job.result(index=0).get_counts()
[10]:
{'11': 49, '00': 51}
[11]:
job.input_circuits(index=0).draw(output="mpl")
[11]:
Additionally, you may cancel the current job (or, optionally, a sub-job by passing an index
argument) if it is not in a terminal state like so:
[12]:
job.cancel()
SuperstaqWarning: Job '128cdcd8-47cf-4d62-a788-c7c672db2150' cannot be cancelled: it already has status Done
self._backend._provider._client.cancel_jobs(ids_to_cancel, **kwargs)
Lastly, you may also retrieve the information described above on a previously submitted qiskit-superstaq
job:
[ ]:
backend = provider.get_backend("ibmq_brisbane_qpu")
job_id = job.job_id() # Here we use the job ID from above, but this can be any old job ID
job_old = provider.get_job(job_id)
job_old.input_circuits(index=0).draw(output="mpl")