Sitemap
Harshhak chancchawt

Harshhak chancchawt

IT Solution Architect & Cloud Evangelist at IBM.

Press enter or click to view image in full size
The compiler transforms a logical quantum circuit into a hardware-ready circuit by mapping qubits, routing interactions, and rewriting operations into native gates.

From Simulator to Real Hardware: Your 10 Gates Become 163

5 min readSep 5, 2026

--

Quantum for Developers — Part 9 of 10. Eight weeks of theory and simulators. This week, the machine.

A five-qubit quantum program is ten instructions long. On a simulator it runs perfectly, instantly.

Sent to a real 127-qubit quantum computer, that same program arrives as 163 instructions. Nobody edited the code. The compiler rewrote it for the machine because the program, as written, is not something any real quantum computer can run directly.

That gap between the code you write and the code that actually executes is the biggest surprise for anyone moving from simulators to hardware. This article closes it, using real device models that run on an ordinary laptop for free.

Press enter or click to view image in full size
Heavy-hex topology: limited qubit connectivity forces the compiler to add extra operations so distant qubits can interact.

Four words, decoded:

Circuit — a quantum program: a list of operations applied to qubits, ending in a measurement.

Depth — how many steps run one after another. Like the length of a queue: longer means more time for things to go wrong. One of the most important numbers in practical quantum computing.

Transpilation — the compiler step that rewrites a circuit for one specific chip. The same idea as a compiler targeting Intel versus Apple silicon.

Topology — the wiring map of a chip: which qubits can talk to which. Not everyone talks to everyone.

Reality #1: The Qubits Barely Know Each Other

On a simulator, any qubit can interact with any other. Real hardware is nothing like that. The 127-qubit device model used in this article follows a sparse heavy-hex topology: 127 qubits, 144 connections, and no qubit with more than three neighbours.That limited connectivity is exactly why a 10-instruction circuit can expand into dozens or even hundreds of instructions during transpilation.

Press enter or click to view image in full size
Real quantum hardware returns a distribution of outcomes, not a single answer. The signal stands above a background of noise.

That is the problem with a textbook circuit where one qubit must interact with four others. It isn’t impossible, but it isn’t directly executable either. The compiler solves it the only way it can: by inserting extra operations that shuffle quantum states across the chip until the required qubits sit side by side.

Those extra operations are not free, and two-qubit operations are the noisiest things a quantum computer does (Part 3).

Distance on the chip gets paid for in errors.In today’s quantum computers, moving information is often more expensive than computing on it.

Reality #2: The Compiler Setting Is the Biggest Win

The whole story fits in one experiment, and it needs no hardware account. Qiskit ships fake backends: local models carrying the real wiring and real error data of actual quantum devices.

from qiskit import QuantumCircuit, transpile
from qiskit_ibm_runtime.fake_provider import FakeSherbrooke

qc = QuantumCircuit(5, 5)
qc.h(0)

for i in range(1, 5):
qc.cx(0, i) # entangle qubit 0 with all four others

qc.measure(range(5), range(5))

print(qc.depth(), sum(qc.count_ops().values()))
# 6 steps, 10 instructions

backend = FakeSherbrooke()

for lvl in [0, 1, 2, 3]:
t = transpile(
qc,
backend,
optimization_level=lvl,
seed_transpiler=42,
)
print(lvl, t.depth(), sum(t.count_ops().values()))

# level 0 → depth 86, 163 instructions
# level 1 → depth 38, 76
# level 2 → depth 28, 57
# level 3 → depth 27, 57

The same program, the same result, one keyword argument, and level 3 comes out three times shallower than level 0.

On noisy hardware, shallower means fewer chances to fail, and that is often the difference between a usable answer and noise.

So the headline number cuts both ways. 163 instructions is what an unoptimised translation produces. At level 3, the same program lands at 57.

Something else changed quietly in that translation: the original instructions are gone. The chip understands only its own small set of native operations, so everything was rewritten into that set, exactly as a compiler turns a loop into machine instructions nobody ever reads.

The habit that matters: compile at optimization_level=3 against the specific machine being targeted, then check the depth before submitting.

For many near-term workloads, that single practice delivers larger gains than most beginner-level algorithm tuning.

Reality #3: The Output Is a Distribution, Not an Answer

The same program, run through that device’s error model:

from qiskit_aer import AerSimulator

sim = AerSimulator.from_backend(backend)

counts = sim.run(
transpile(qc, backend, optimization_level=3),
shots=4000
).result().get_counts()

A perfect simulator returns a clean split:

{'00000': 2016, '11111': 1984}

Those are the only two outcomes this program should ever produce.

Get Harshhak chancchawt’s stories in your inbox

Join Medium for free to get updates from this writer.

The hardware model returns something else:

{
'00000': 1819,
'11111': 1800,
'11011': 54,
'11101': 50,
'00100': 45,
...
}

correct outcomes: 3619 / 4000 = 90.5%
distinct wrong answers: 24

Exact numbers vary with backend calibration data and software versions, but the overall pattern remains the same: the correct answers dominate while a long tail of error states appears.

Press enter or click to view image in full size
The path from ideal simulation to transpiled circuits, noisy execution, and real hardware results.

Reality #4: Going Live

Moving to the real machine barely changes the code. The fake backend is swapped for a real one:

# Pattern sketch — requires a free quantum account

from qiskit_ibm_runtime import (
QiskitRuntimeService,
SamplerV2
)

service = QiskitRuntimeService()

backend = service.least_busy(
operational=True
)

job = SamplerV2(backend).run(
[transpile(qc, backend, optimization_level=3)],
shots=4000
)

print(job.job_id())

Results arrive asynchronously while the job waits its turn in the queue.

Everything learned on the fake backend transfers unchanged.

Four habits make shared machines bearable:

  • Debug on simulators, never on paid hardware time.
  • Batch circuits together to reduce queue waits.
  • Check machine status before submitting jobs.
  • Start with the smallest circuit that could prove the idea wrong.

The Twenty-Minute Path

Everything above runs locally after a single:

pip install qiskit-ibm-runtime

A real 127-qubit machine’s wiring can reshape a program on your laptop, with no account and no queue.

A free quantum account adds enough runtime to send the same circuit to real hardware and compare the results yourself.

Twenty minutes separates reading about quantum computing from having used one.

The simulator teaches you quantum computing. The hardware teaches you quantum engineering.

Coming Next Week: The Series Finale

Part 10 closes the loop with the quantum readiness roadmap:

  • How to judge which use cases are worth exploring.
  • Which skills compound now versus later.
  • What the 2029–2033 fault-tolerance window means for planning.
  • An honest answer to: “So what do I actually do on Monday?”

Nine weeks, assembled into a plan.

Follow the series — one article, every week, developer-first. Questions? Comments are open.

--

--

Harshhak chancchawt
Harshhak chancchawt

IT Solution Architect & Cloud Evangelist at IBM.