Accessing info with cirq-superstaq

This tutorial will cover the information you can access on your account and related jobs and targets using cirq-superstaq.

Open in Colab Launch Binder

Imports and API Token

As usual, we’ll begin with importing requirements and setting up access to Superstaq. This tutorial uses cirq-superstaq, our Superstaq client for Cirq. You can install it and relevant dependencies by running pip install cirq-superstaq.

[1]:
# Requirements to use cirq-superstaq
try:
    import cirq
    import cirq_superstaq as css
except ImportError:
    print("Installing cirq-superstaq...")
    %pip install --quiet 'cirq-superstaq[examples]'
    print("Installed cirq-superstaq.")
    print("You may need to restart the kernel to import newly installed packages.")
    import cirq
    import cirq_superstaq as css

Now, we instantiate a service provider in cirq-superstaq with Service(). Supply the Superstaq API token by providing the token as an argument of css.Service() or setting it as an environment variable (see this guide).

[2]:
service = css.Service()

Account Information

The service class gives you a means to retrieve information regarding your Superstaq account. Currently, you can use service to retrieve your Superstaq balance.

[3]:
service.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 Service object also gives you a list of all the devices and simulators to which you have access, as well as additional information about those targets.

  • get_targets(): Retrieves a list of available targets. This method also accepts the following boolean keyword arguments to filter the targets returned: simulator, supports_submit, supports_submit_qubo, supports_compile, available, retired, and accessible.

  • 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 to get_targets(accessible=True).

  • target_info("<target_name>"): Retrieve information on your selected backend, such as number of qubits, native gate set, where <target_name> is the name of the desired backend

[4]:
service.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)]
[ ]:
service.target_info("ibmq_brisbane_qpu")  # retrieving information about IBM's Brisbane device
{'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, Canceled, or Done). Note that an index argument can be passed optionally to retreive the status of a specific job indexed by index in a batch job.

  • target(): Device the job was run on.

  • counts(): Counts from the result of the job run. Note this can return a list, so you must specify an index if you want to retrieve a specific counts dictionary (corresponding to the circuit with the same index).

  • num_qubits(): Number of qubits for the job. Note this can return a list, so you must specify an index if you want to retrieve the corresponding number of qubits to a particular circuit.

  • repetitions(): Number of repetitions for the job.

  • input_circuits(): Retrieves original (i.e., not compiled) circuit(s) for job. Note this returns a list and you must specify an index 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 an index 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 Cirq
qubits = cirq.LineQubit.range(2)
circuit = cirq.Circuit(
    cirq.H(qubits[0]),
    cirq.CNOT(qubits[0], qubits[1]),
    cirq.measure(qubits[0]),
    cirq.measure(qubits[1]),
)

# Submitting the circuit to IBM's Brisbane QPU
job = service.create_job(
    circuit, repetitions=100, method="dry-run", target="ibmq_brisbane_qpu"
)  # Specify "dry-run" as the method to submit & run a Superstaq simulation
[7]:
job.job_id()
[7]:
'933729a9-db61-4c94-b994-26e2941a7fd1'
[8]:
job.status()
[8]:
'Done'
[9]:
job.target()
[9]:
'ibmq_brisbane_qpu'
[10]:
job.counts(index=0)
[10]:
{'11': 63, '00': 37}
[11]:
job.num_qubits(index=0)
[11]:
2
[12]:
job.repetitions()
[12]:
100
[13]:
job.input_circuits(index=0)
[13]:
0: ───H───@───M───
          │
1: ───────X───M───
[14]:
job.compiled_circuits(index=0)
[14]:
41: ───Rz(1.5π)───X^0.5───AceCR+-(Z side)───│───M('q(0)')───
                          │                 │
53: ───X^0.5──────────────AceCR+-(X side)───│───M('q(1)')───

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:

[15]:
job.cancel()
SuperstaqWarning: Job '933729a9-db61-4c94-b994-26e2941a7fd1' cannot be cancelled: it already has status Done
  self._client.cancel_jobs(ids_to_cancel, **kwargs)

Lastly, you may also retrieve the information described above on a previously submitted cirq-superstaq job with service.get_job('<job_id>'):

[16]:
job_id = job.job_id()  # Here we use the job ID from above, but this can be any old job ID
job_old = service.get_job(job_id)
job_old.input_circuits(index=0)
[16]:
0: ───H───@───M───
          │
1: ───────X───M───