JION QPU¶
JION is the 30 qubit Trapped Ion device hosted in the JUNIQ facility. There exists a digital twin of the JION QPU called EmuJION that allows for simulation and testing of quantum circuits before they are run on the actual hardware.
Getting Access¶
Access to the EmuJION 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 EmuJION when signing up on the JuDoor portal.
Submitting first job¶
Submitting the job to EmuJION is similar to the test job on the Qaptiva device. The only difference is that you need to import the JionQPU class (EmuJionQPU in the case of the digital twin) instead of the LinAlg QPU.
Note: At the moment the legacy name EmuEleqtronQPU is still used for the digital twin of JION, but it will be renamed to EmuJionQPU in the near future.
from qlmaas.qpus import EmuEleqtronQPU # Note that we are importing EmuEleqtron 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 = EmuEleqtronQPU()
# 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: SJob18004 State |00> probability 0.43359375 State |11> probability 0.494140625 State |01> probability 0.046875 State |10> probability 0.025390625
result.display()
Result(raw_data=[Sample(_state=b'\x00', probability=0.43359375, _amplitude=None, intermediate_measurements=None, err=0.02192275221095228, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)]), Sample(_state=b'\x03', probability=0.494140625, _amplitude=None, intermediate_measurements=None, err=0.022117178937598445, qregs=[DefaultRegister(length=2, start=0, msb=None, _subtype_metadata=None, key=None)]), Sample(_state=b'\x01', probability=0.046875, _amplitude=None, intermediate_measurements=None, err=0.00935050616324091, 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={'job_id': '982b1273-2fcd-4474-9c54-ba929102ef50', 'status': 'finished_success', 'executed_shots': 'None', 'compilation_metadata': "{'ion_bit_map': [0, 1, -1, -1, -1, -1, -1, -1, -1, -1]}", 'backend': 'ParityOS Ions Digital Twin', 'received_at': '2025-09-01 07:07:09.473983+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
{'job_id': '982b1273-2fcd-4474-9c54-ba929102ef50',
'status': 'finished_success',
'executed_shots': 'None',
'compilation_metadata': "{'ion_bit_map': [0, 1, -1, -1, -1, -1, -1, -1, -1, -1]}",
'backend': 'ParityOS Ions Digital Twin',
'received_at': '2025-09-01 07:07:09.473983+00:00',
'nbshots': '512',
'single_job': 'True'}
Visualising the QPU topology¶
graph = qpu.get_specs().as_graph()
nx.draw(graph, with_labels=True, pos=nx.circular_layout(graph))
Further reading¶
More details on writing and submitting circuits can be seen via mainly two resources:
Here are some useful topics: