Quick start¶
This page takes you from an empty file to a running distributed quantum program.
1. Write the program¶
A NetQMPI application is a plain Python file that defines a main(env)
function. The same file runs on every rank — this is the SPMD model — and each
rank tells itself apart by its rank number.
1from netqmpi.sdk.environment import Environment
2
3
4def main(env: Environment = None):
5 comm = env.comm
6 rank = comm.rank
7
8 next_rank = comm.get_next_rank(rank)
9 previous_rank = comm.get_prev_rank(rank)
10
11 # Only what is inside the block takes part in the distributed program.
12 with comm:
13 circuit = env.create_circuit(num_qubits=1, num_clbits=1)
14
15 if rank == 0:
16 circuit.h(0) # prepare |+>
17 comm.qsend(circuit, [0], next_rank) # and give it away
18 else:
19 comm.qrecv(circuit, [0], previous_rank)
20 circuit.measure(0, 0)
21
22 # The circuits of all ranks are submitted together when the last rank
23 # leaves the block, so only that rank sees results here — and it sees
24 # every rank's counts, keyed by rank.
25 if comm.results:
26 for other, counts in comm.results.items():
27 print(f"rank_{other}: {counts}")
Three things are worth noticing:
main(env)is the entry pointNetQMPI loads your script and calls this function once per rank, injecting an
Environment. A script withoutmain()is rejected before anything runs.- Nothing mentions entanglement
qsend()andqrecv()are all you write. The EPR-pair generation, the Bell measurement and the classical corrections that make up the teleportation protocol are filled in by the backend adapter.- The program is backend-agnostic
It imports only from
netqmpi.sdk. No backend package appears anywhere, which is what lets the same file run on all four backends.
2. Run it¶
The launcher is MPI-like: pick the number of nodes with -n and the backend
with a flag.
netqmpi -n 2 app.py --aer --shots 1024 # circuit simulation
netqmpi -n 2 app.py --netqasm # quantum-network simulation
netqmpi -n 2 app.py --cunqa --shots 1024 # HPC vQPU emulation
netqmpi -n 2 app.py --qoala --shots 100 # node execution environment
Start with --aer if you just want to see it work: it is the only backend with
no special installation requirements.
3. Read the results¶
Output is a histogram of measurement outcomes per rank, gathered after all
ranks have left the with comm: block:
rank_0: {'0': 1024}
rank_1: {'0': 517, '1': 507}
Rank 1 measures the |+⟩ it received in the computational basis, so it reads 0
and 1 about equally often. Rank 0 reads 0 because handing a qubit over
moves it: a quantum state cannot be copied, so once qsend returns, rank 0’s
qubit is back in |0⟩.
Only some ranks see comm.results
Circuits are submitted jointly when the last rank leaves its with comm:
block, so comm.results is populated on that rank and — depending on the
backend — possibly not on the others. The if comm.results: guard above is the
idiomatic way to print once. See Reading results.
What to read next¶
Core concepts — ranks, the communicator block, and the execution model.
Communication primitives — moving qubits with
qscatter/qgather, sharing a control withexpose/unexpose.Backends — which one to use, and what each supports.
Shipped examples¶
The repository ships runnable programs under
examples/:
Example |
What it shows |
|---|---|
|
Distributed superposition, teleported between two ranks |
|
A qubit passed around a ring of ranks |
|
|
|
|
|
A full 3-rank QFT built out of telegates |
There is also
examples/frequent_errors/,
a corpus of programs that are meant to fail — one failure mode each — with a
run_all.py that reports what NetQMPI says about every one of them without
needing any vQPU. It is documented in Troubleshooting.