Juspark QPU¶
Juspark is the 5 qubit IQM Spark device hosted in the JUNIQ facility.
Getting Access¶
Access to the Juspark QPU is available via the Qaptiva device which accepts jobs written using myqlm framework. If you haven't set up the access to Qaptiva yet, please follow the instructions in the Qaptiva access documentation to get started. Use the project name relevant to Juspark when signing up on the JuDoor portal.
Submitting first job¶
Submitting the job to Juspark is similar to the test job on the Qaptiva device. The only difference is that you need to import the JusparkQPU class instead of the LinAlg QPU.
from qlmaas.qpus import JusparkQPU # Note that we are importing Juspark QPU from qlmaas
from qat.lang import qrout, H, CNOT
import networkx as nx
# Define the circuit
@qrout
def bell_pair():
H(0)
CNOT(0, 1)
bell_pair.display()
# Convert the circuit into a myqlm Job
job = bell_pair.to_job(nbshots=512)
# Instantiate the qpu
qpu = JusparkQPU()
# Submit the job to the QPU
result = qpu.submit(job)
# Visualise the result
for sample in result:
print("State %s probability %s" % (sample.state, sample.probability))
Submitted a new batch: SJob16720 State |00> probability 0.5 State |11> probability 0.458984375 State |01> probability 0.015625 State |10> probability 0.025390625
result.display()
Result(raw_data=[Sample(_state=b'\x00', probability=0.5, _amplitude=None, intermediate_measurements=None, err=0.02211869776019044, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)]), Sample(_state=b'\x03', probability=0.458984375, _amplitude=None, intermediate_measurements=None, err=0.02204415239037991, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)]), Sample(_state=b'\x01', probability=0.015625, _amplitude=None, intermediate_measurements=None, err=0.00548630377481862, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)]), Sample(_state=b'\x02', probability=0.025390625, _amplitude=None, intermediate_measurements=None, err=0.006958915097827096, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)])], _value=None, error=None, value_data=None, error_data=None, meta_data={'backend_name': 'None', 'backend_version': 'None', 'date': '2025-08-26', 'header': 'None', 'qobj_id': 'None', 'job_id': '937b93ca-bae8-4da2-81ac-6e385386f6f3', 'status': 'None', 'success': 'True', 'timestamps': "{'job_start': '2025-08-26T07:29:58.349498+00:00', 'compile_start': '2025-08-26T07:29:58.349760+00:00', 'compile_end': '2025-08-26T07:29:58.363178+00:00', 'submit_start': '2025-08-26T07:29:58.363382+00:00', 'submit_end': '2025-08-26T07:29:58.526674+00:00', 'execution_start': '2025-08-26T07:29:58.474246+00:00', 'execution_end': '2025-08-26T07:29:59.218049+00:00', 'job_end': '2025-08-26T07:29:59.807694+00:00'}", 'nbshots': '512', 'single_job': 'True'}, in_memory=None, data=None, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)], _parameter_map=None, _values=None, values_data=None, need_flip=False, nbqbits=None, lsb_first=False, has_statevector=False, statevector=None)# Display the metadata of the result including the date and the timestamps
result.meta_data
{'backend_name': 'None',
'backend_version': 'None',
'date': '2025-08-26',
'header': 'None',
'qobj_id': 'None',
'job_id': '937b93ca-bae8-4da2-81ac-6e385386f6f3',
'status': 'None',
'success': 'True',
'timestamps': "{'job_start': '2025-08-26T07:29:58.349498+00:00', 'compile_start': '2025-08-26T07:29:58.349760+00:00', 'compile_end': '2025-08-26T07:29:58.363178+00:00', 'submit_start': '2025-08-26T07:29:58.363382+00:00', 'submit_end': '2025-08-26T07:29:58.526674+00:00', 'execution_start': '2025-08-26T07:29:58.474246+00:00', 'execution_end': '2025-08-26T07:29:59.218049+00:00', 'job_end': '2025-08-26T07:29:59.807694+00:00'}",
'nbshots': '512',
'single_job': 'True'}
Getting each samples for a circuit¶
In case you want to have the measured sample for each shot, set aggregate_data to False in the job options.
job_with_samples = bell_pair.to_job(nbshots=10, aggregate_data=False)
result_with_samples = qpu.submit(job_with_samples)
Submitted a new batch: SJob16722
from collections import Counter
history = [s.state for s in result_with_samples]
print(Counter(history))
print(f"Shot order: {history}")
Counter({|11>: 7, |00>: 3})
Shot order: [|11>, |11>, |11>, |00>, |00>, |11>, |11>, |11>, |11>, |00>]
Visualising the qpu tolopogy¶
graph = qpu.get_specs().as_graph()
nx.draw(graph, with_labels=True)
Further reading¶
More details on writing and submitting circuits can be seen via mainly two resources:
Here are some useful topics: