Hands-On Lab: Simulating a 2-Qubit Circuit in Python and Interpreting the Results
Build and analyze a 2-qubit Python circuit, from state vectors to Bell-state measurements, in a reproducible hands-on lab.
Hands-On Lab: Simulating a 2-Qubit Circuit in Python and Interpreting the Results
If you want to move from quantum theory to actual intuition, a 2-qubit simulation is the fastest place to start. In this lab, we’ll build a reproducible quantum-safe migration-style mindset for quantum learning: small, inspectable, and grounded in math you can verify by hand. We’ll use Python to simulate a simple circuit, track the state vector, apply gate operations, and interpret measurement outcomes with the same discipline you’d use in production engineering. If you’re also evaluating how quantum fits into broader stack decisions, it helps to think in terms of platform risk and compatibility the way you would when reading a vendor evaluation checklist or a safe orchestration pattern guide for AI systems.
This guide is written for developers and IT practitioners who want a reproducible starter lab rather than a conceptual overview. You’ll see the linear algebra behind each gate, a practical Python implementation, and a repeatable way to compare ideal state evolution versus sampled measurement statistics. For teams building internal enablement materials, this is similar in spirit to the structure used in a bite-size authority content model: concise enough to follow, but deep enough to serve as a reference. By the end, you should be able to explain what the circuit is doing, why the results look the way they do, and how to extend the lab into entanglement experiments or SDK-specific workflows.
1) What a 2-Qubit Simulation Teaches You
Why start with two qubits instead of one?
A single qubit is great for learning superposition, but it does not fully expose the combinatorial jump that makes quantum programming feel different from classical programming. With two qubits, the state lives in a 4-dimensional complex vector space, which means you can observe basis states like |00⟩, |01⟩, |10⟩, and |11⟩ as amplitudes in a single vector. That is the first point where linear algebra becomes operational rather than abstract. It also creates the perfect setup for entanglement, which is the key phenomenon that pushes quantum computing beyond simple probabilistic analogies.
In practical terms, two qubits are enough to show how gates transform amplitudes, how tensor products expand state space, and how measurement collapses a probability distribution into a classical result. This is one reason introductory labs remain so effective: they are small enough to inspect manually, but rich enough to reflect the core mechanics of quantum algorithms. The math may feel unusual at first, but it becomes intuitive once you see how a Hadamard gate spreads amplitude and a CNOT gate correlates the qubits. That intuition is much more valuable than memorizing symbols in isolation.
For broader context on why this matters, see our explainer on quantum computing fundamentals and our practical notes on quantum-safe migration. Even if you are not deploying quantum workloads tomorrow, understanding the mechanics now helps you evaluate vendor claims and SDK tradeoffs later. That same architectural caution shows up in enterprise planning around internal AI news pulses and infrastructure readiness. The pattern is consistent: learn the primitives first, then assess tooling and integration paths.
What you will build in this lab
We will create a tiny simulator in Python that initializes a 2-qubit state, applies gates, computes the resulting state vector, and samples measurements to approximate shot-based outcomes. We’ll start with the |00⟩ state, apply a Hadamard gate to the first qubit, then a CNOT to entangle the pair. That sequence should produce a Bell state, which is ideal for seeing how deterministic amplitude evolution translates into probabilistic measurement output. Once the circuit is working, we’ll run repeated measurements and compare the results against the expected 50/50 distribution.
This approach is deliberately simple because the goal is reproducibility, not raw performance. If you later move to real SDKs, you can port the logic to frameworks such as Qiskit, Cirq, or PennyLane, but the intuition remains the same. The simulator here makes the matrix math visible, which is useful for developers who want to understand what the SDK is abstracting away. It also mirrors the evaluation discipline you might use in a real-project prioritization framework: keep the first test case small, measurable, and easy to validate.
Why reproducibility matters in quantum labs
Quantum tutorials often fail when they skip the most important part: showing how to verify that the code is actually doing what the theory says it should do. A reproducible lab should include fixed gate order, explicit matrix definitions, and a clear measurement strategy. If you do not control these details, the output becomes a mystery rather than a learning tool. Reproducibility is also how you separate genuine quantum behavior from accidental implementation mistakes.
For tech teams, this is exactly the same reason benchmarks and lab notes matter in other areas of the stack. If you compare serverless and managed infrastructure, for example, you would not trust a cost claim without a clear workload model, as explained in our guide on serverless cost modeling. The same standard applies here: define the input state, apply known gates, and inspect the resulting amplitudes before you measure. That discipline turns quantum programming from folklore into engineering practice.
2) Linear Algebra Primer for the Lab
State vectors and basis states
A 2-qubit system is represented by a normalized complex vector with four components. In the computational basis, the state is often written as |ψ⟩ = α|00⟩ + β|01⟩ + γ|10⟩ + δ|11⟩, where the squared magnitudes of the amplitudes sum to 1. That normalization is what makes measurement probabilities well-defined. If you can read a 4-element vector, you can already reason about many beginner quantum circuits.
For developers, the easiest mental model is to think of each basis state as a slot in an array. Unlike classical bits, these slots can hold complex numbers, and the gate operations are unitary matrices that preserve total probability. Once you see the state vector as the source of truth, the rest of the lab becomes an exercise in matrix multiplication. This is also why quantum programming feels so natural to people with a strong math or signal-processing background.
Gate matrices you need for this lab
We will use three building blocks: the identity gate, the Hadamard gate, and the controlled-NOT gate. The Hadamard gate creates equal superposition, transforming |0⟩ into (|0⟩ + |1⟩)/√2. The CNOT gate flips the target qubit only when the control qubit is |1⟩, making it the standard tool for building entanglement in introductory examples. These are not arbitrary choices; they are the minimum set needed to show both superposition and correlation.
Mathematically, the single-qubit Hadamard matrix is H = 1/√2 [[1, 1], [1, -1]]. To apply it to a specific qubit in a multi-qubit system, you tensor it with the identity matrix on the other qubit. That tensor-product step is where many beginners lose confidence, but it is just a systematic way of expanding a small gate into a larger Hilbert space. Once you work through it once, it becomes much less intimidating.
Measurement probabilities
Measurement converts a quantum state into a classical outcome based on amplitude squared. If your state vector contains amplitudes [α, β, γ, δ], then the measurement probabilities are [|α|², |β|², |γ|², |δ|²]. In practice, a simulator samples these probabilities using a pseudo-random number generator, while a real quantum device samples them through physical noise and hardware constraints. The lab output will therefore be probabilistic even when the pre-measurement state is mathematically exact.
This distinction is critical because quantum programming is not about predicting a single deterministic result. Instead, it is about shaping the probability distribution so that the useful answers become more likely. That pattern is described well in foundational discussions of qubit superposition and measurement, and it is why repeated shots are central to quantum experiments. If you remember only one lesson from this section, make it this: the state vector is deterministic until measurement, and the measurement is where randomness appears.
3) Build the Python Simulator
Environment setup
You do not need a heavy quantum SDK to learn the basics. A minimal setup with Python and NumPy is enough to implement the full lab, inspect each matrix step, and verify the results manually. That makes this exercise ideal for reproducible notebooks, onboarding workshops, and internal training sessions. You can later move the same ideas into larger frameworks once the concepts feel natural.
Install NumPy if you do not already have it: pip install numpy. Then create a Python file or notebook and define the state vectors and gate matrices explicitly. Keeping the code plain and readable is important, because the goal is to understand the math rather than hide it behind abstractions. If your team is evaluating quantum tooling, this same “minimal viable lab” mindset is useful when comparing SDKs against the kind of practical checklists we use for technical vendor selection.
Code for the 2-qubit circuit
Below is a complete starter implementation. It initializes |00⟩, applies H to qubit 0, then CNOT with qubit 0 as control and qubit 1 as target, and finally samples measurements from the resulting distribution.
import numpy as np
# Basis states for two qubits
zero = np.array([1, 0], dtype=complex)
one = np.array([0, 1], dtype=complex)
# 2-qubit initial state |00>
psi0 = np.kron(zero, zero)
# Single-qubit gates
I = np.array([[1, 0], [0, 1]], dtype=complex)
H = (1/np.sqrt(2)) * np.array([[1, 1], [1, -1]], dtype=complex)
# Two-qubit operators
H_on_q0 = np.kron(H, I)
# CNOT with q0 as control and q1 as target
CNOT = np.array([
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0]
], dtype=complex)
# Apply gates
psi1 = H_on_q0 @ psi0
psi2 = CNOT @ psi1
print('Initial state:', psi0)
print('After H on q0:', psi1)
print('After CNOT:', psi2)
# Measurement probabilities
probs = np.abs(psi2)**2
print('Probabilities:', probs)
# Sample measurements
shots = 1000
outcomes = np.random.choice(4, size=shots, p=probs)
counts = {format(i, '02b'): int(np.sum(outcomes == i)) for i in range(4)}
print('Counts:', counts)This code is intentionally compact enough to read in one pass, but complete enough to be used as a lab artifact. The key thing to notice is that the two-qubit Hadamard operator is built using a tensor product, not by writing a custom 4x4 superposition matrix from scratch. That is how most real quantum libraries think about multi-qubit gate composition under the hood. Understanding this now will save you confusion later when SDKs appear to “magically” place gates on individual qubits.
Walkthrough of each line
The first two vectors define the single-qubit computational basis states |0⟩ and |1⟩. The initial 2-qubit state is computed with a Kronecker product, which produces |00⟩ = [1, 0, 0, 0]. The Hadamard is then expanded to act on the first qubit only, meaning the second qubit remains unchanged. Finally, the CNOT gate flips the second qubit only when the first qubit is 1, which is exactly what transforms a simple superposition into a Bell state.
When the gates are applied in this order, the final state should be (|00⟩ + |11⟩)/√2, represented in vector form as [1/√2, 0, 0, 1/√2]. That result means the circuit has put the two qubits into perfect correlation: measure one as 0, and the other will also be 0; measure one as 1, and the other will also be 1. This is the essence of entanglement in the lab setting. The elegance of this example is that the outcome is simple enough to recognize but subtle enough to reveal the difference between amplitudes and probabilities.
4) Interpret the State Vector Step by Step
Before the first gate
The state |00⟩ is the clean starting point for almost every introductory circuit because it provides an unambiguous baseline. In vector form, only the first amplitude is 1, and every other basis component is 0. This means the probability of measuring 00 is 100% before any gates are applied. If your simulator does not reproduce this trivial case correctly, nothing else in the lab can be trusted.
Because this baseline is so simple, it is worth checking manually rather than assuming the code is correct. This habit is especially helpful for teams learning quantum alongside other emerging tech stacks, where foundational confidence matters more than speed. Similar review discipline is recommended in our guide to turning AI press hype into real projects, because a clean baseline prevents overclaiming later. The same principle applies here: verify the smallest unit first.
After the Hadamard gate
Applying H to the first qubit transforms the system into (|00⟩ + |10⟩)/√2. In vector form, the amplitudes become [1/√2, 0, 1/√2, 0]. This is superposition, but importantly, it is not yet entanglement. The first qubit is now in a mixed possibility state, while the second qubit is still definitely 0.
What matters conceptually is that the state is now distributed across two basis states. If you were to measure immediately after the Hadamard, you would expect 00 and 10 each to appear about 50% of the time. That is a great moment to emphasize the difference between amplitude and outcome: the circuit is not “half 0 and half 1” in a classical sense, but rather represented by complex amplitudes whose magnitudes determine probabilities. This is the part of quantum computing that feels strange until you compute it directly.
After the CNOT gate
The CNOT maps |10⟩ to |11⟩ while leaving |00⟩ unchanged, so the final state becomes (|00⟩ + |11⟩)/√2. That is a Bell state, one of the standard examples of entanglement. In the state vector, the amplitudes for |01⟩ and |10⟩ collapse to zero while |00⟩ and |11⟩ each retain magnitude 1/√2. The resulting measurement probabilities are 50% for 00 and 50% for 11, with 01 and 10 absent in the ideal noiseless model.
This is where simulation becomes genuinely useful. You can inspect the amplitudes before measurement and see the exact mathematical source of correlation, then sample many times and watch the observed counts converge toward the expected distribution. If you want to understand why quantum algorithms rely so heavily on interference, this is the toy model that makes it obvious. It also sets up more advanced experiments where you compare different circuits using the same reproducible measurement workflow.
5) Run and Validate the Experiment
Expected results and how to read them
When you run the script with 1,000 shots, you should see counts roughly split between 00 and 11. Due to randomness, the split will not be exact, but it should remain close to 50/50 in repeated runs. If you get a substantial number of 01 or 10 outcomes in a noiseless simulator, that suggests a bug in the gate matrices, qubit ordering, or measurement logic. Those are the first places to debug.
A useful validation strategy is to print the intermediate state vector after each gate and compare it against the hand-calculated result. This “trace the amplitudes” habit is one of the best ways to build intuition. You can even set up assertions in code to check that the vector matches expected values within a tolerance. That is a very practical engineering habit, not just a teaching technique.
Common debugging pitfalls
The most common beginner error is mixing up qubit order in the tensor product. Some frameworks treat the leftmost qubit as the most significant bit; others use the opposite convention in display or indexing. If the circuit appears to be “wrong,” the issue is often not the math but the ordering convention. Be explicit about your basis order and keep it documented in the notebook or script.
Another common mistake is applying the gate to the wrong qubit by constructing the tensor product in the wrong order. For example, H ⊗ I acts on the first qubit in the basis used here, while I ⊗ H would act on the second. Finally, do not forget that measurement probabilities come from squared magnitudes, not raw amplitudes. Negative amplitudes are valid, and complex phases matter in larger circuits even when they do not change simple probability counts.
How to verify correctness like an engineer
One of the most valuable habits in quantum programming is to validate the circuit at three levels: matrix correctness, state vector correctness, and sampled outcome correctness. At the matrix level, confirm that H and CNOT are unitary and that their dimensions match the system size. At the state level, confirm that each intermediate vector matches expectation after every gate application. At the sampled level, run enough shots that the frequency distribution approaches the theoretical probabilities.
If you need a mental analogy, think of it the way infrastructure teams validate a new service rollout: first the configuration, then the runtime state, then the user-facing metrics. This layered approach resembles the practical thinking behind web resilience planning and capacity forecasting, where you don’t trust a system until every layer is behaving as expected. Quantum labs deserve the same rigor. That rigor is what makes a tutorial reproducible rather than merely illustrative.
6) Extend the Lab for Better Intuition
Try alternative starting states
Once the Bell-state circuit works, change the initial state to |01⟩, |10⟩, or |11⟩ and observe how the same gates behave. This helps you understand that gates are not magic one-off tricks; they are linear operators that transform whatever state you feed them. The output may become less symmetric, but the principles remain identical. This is a good way to confirm that your simulator is really computing the evolution rather than hardcoding an answer.
You can also prepare a superposition on both qubits and see how the CNOT reshapes the distribution. That exercise highlights the difference between independent superpositions and correlated states. If you later move into multi-gate circuits, this intuition will help you reason about interference patterns more confidently. The habit of changing one variable at a time is the same habit used in performance experiments and capacity decision workflows.
Measure multiple times and compare counts
Increase the number of shots to 10,000 and compare the empirical counts to the theoretical probabilities. As shots increase, the relative frequencies should move closer to the expected 50/50 split. This is a practical demonstration of the law of large numbers in the context of quantum sampling. It also reinforces the idea that a single measurement is not very informative; the distribution is what matters.
You can store results in a simple table or plot them using Matplotlib to visualize convergence. Doing so makes the difference between ideal and sampled behavior clearer for learners who are new to probabilistic systems. In enterprise settings, this same practice of comparing expected and observed outputs is essential for any experimental technology evaluation. That mindset is also why teams adopt structured content and enablement models like brief, authoritative technical briefs for internal training.
Add a phase gate and observe what changes
One of the best next steps is to add a phase gate, such as Z or S, and observe whether the measurement counts change. In some cases, the distribution will remain the same even though the state has changed, because phase can influence future interference without affecting immediate probabilities. That distinction is one of the most important conceptual leaps in quantum computing. It is also one of the reasons simple measurement counts do not tell the whole story.
If you want to go deeper, try inserting phase gates before a second Hadamard and see how the interference pattern changes. This is where state-vector analysis becomes indispensable, because two states with identical measurement outcomes after one gate can behave very differently after the next gate. That is the kind of subtlety that separates casual exposure from real quantum programming competence. Once you see it in code, it tends to stick.
7) What This Lab Means in Real Quantum Development
From toy example to SDK fluency
Although this lab uses plain NumPy, the concepts transfer directly into production-oriented quantum SDKs. The workflow is always the same: define a basis state, apply gates, inspect the state vector or simulator output, and sample measurements. The abstraction layer changes, but the underlying math does not. That means a developer who understands this lab will adapt much faster to Qiskit, Cirq, or other tooling.
SDK choice matters because vendor ecosystems differ in how they express circuits, manage qubit order, optimize compilation, and expose simulation or backend options. Before you commit to one stack, it helps to compare those tradeoffs the same way you would compare a cloud partner using a CTO vendor checklist. For broader industry reading on how engineers separate signal from noise, see our guide to tools that actually move the needle in competitive analysis. The lesson is universal: know what problem you are solving before choosing the tool.
How teams should use this lab internally
This 2-qubit exercise works well as a training artifact for platform teams, developer advocates, and AI/ML engineers who are quantum-curious but not yet expert. It can be run as a 30-minute workshop, a notebook exercise, or a code review session where participants explain each line of the circuit. Because the result is a Bell state, it naturally leads into discussions about entanglement, error, decoherence, and why real devices are harder than simulators. That progression makes the lab both educational and practical.
If your organization is exploring future-ready architecture, consider pairing this lab with a quantum risk and roadmap discussion. Our guide to auditing crypto for quantum-safe migration is a good companion piece because it connects quantum progress with today’s security decisions. You can also feed the insights into broader strategic planning, such as the type of signal monitoring described in building an internal AI news pulse. The result is a more mature view of where quantum belongs in your roadmap, and where it does not.
Why simulation still matters when hardware is noisy
Real quantum hardware introduces decoherence, calibration errors, readout noise, and device-specific constraints that the ideal simulator ignores. That does not make the simulator irrelevant; it makes it the baseline against which noisy experiments are compared. In practice, a simulator tells you what should happen before the hardware distorts the result. This baseline is crucial for debugging and for understanding whether a discrepancy is due to your circuit or the machine.
That is exactly why early quantum labs remain centered on state vectors and ideal measurements. The simpler the model, the easier it is to diagnose where things diverge once you move to a noisy backend. If you later explore hardware-aware workflows, you’ll appreciate the distinction between ideal simulation and physical execution just as infrastructure teams appreciate the difference between synthetic testing and real production traffic. The analogy is familiar because the discipline is the same.
8) Practical Takeaways for Developers
Key lessons to remember
First, a 2-qubit circuit already contains the essential ingredients of quantum programming: vector spaces, tensor products, unitary gates, superposition, and probabilistic measurement. Second, the final measurement distribution is only part of the story; the state vector before measurement contains the deeper structure. Third, reproducibility is non-negotiable if you want to trust your lab results. These principles remain true whether you are writing your own simulator or using a commercial SDK.
If you remember one engineering heuristic from this article, it should be this: always inspect the intermediate state, not just the final counts. That habit dramatically improves your ability to reason about bugs, qubit order, and gate placement. It also helps you recognize when phase information is changing the computation even if the immediate probabilities do not. In quantum computing, that hidden state information is often the whole point.
Suggested next experiments
From here, try building a 3-qubit GHZ state, adding a Pauli-Z to study phase effects, or replacing the ideal CNOT with a noisy approximation. You can also compare a hand-rolled NumPy simulator against a real SDK to see how circuit syntax changes while the linear algebra remains constant. Those exercises will give you a much stronger intuition for how quantum APIs are organized. They also create a natural bridge into benchmarking and platform evaluation content later on.
For practitioners who want a broader ecosystem view, pair this lab with a look at how teams make technical choices in adjacent domains such as agentic AI orchestration, launch resilience, and memory forecasting. The reason is simple: quantum readiness is not just about qubits, but about disciplined engineering, experimentation, and validation. The best teams transfer those habits across every emerging technology they evaluate.
9) Quick Reference Table
The table below summarizes the most important elements of the lab and how to interpret them. Use it as a checkpoint while you code or teach the exercise. If a result differs from the expected behavior, the row descriptions tell you where to start debugging. This is the kind of compact reference that helps a reproducible lab stay useful after the first run.
| Component | Role in the circuit | Expected result | What to verify |
|---|---|---|---|
| |00⟩ initial state | Baseline two-qubit input | 100% probability on 00 | State vector should be [1, 0, 0, 0] |
| Hadamard on q0 | Creates superposition | (|00⟩ + |10⟩)/√2 | Amplitudes on 00 and 10 should each be 1/√2 |
| CNOT q0→q1 | Entangles the qubits | (|00⟩ + |11⟩)/√2 | Only 00 and 11 should remain nonzero |
| Measurement | Samples the quantum state | Approx. 50/50 between 00 and 11 | Counts should converge with more shots |
| Phase changes | Affects interference, not always counts | May not change immediate probabilities | Inspect state vector, not only sampled results |
10) FAQ
What does a 2-qubit state vector actually represent?
A 2-qubit state vector represents all possible basis states of the system at once, each with a complex amplitude. In the computational basis, those states are |00⟩, |01⟩, |10⟩, and |11⟩. The amplitudes determine the probabilities you will observe after measurement, but the amplitudes themselves can also carry phase information that affects future gates.
Why do we use a simulator instead of jumping straight to hardware?
A simulator gives you a clean, noiseless baseline that makes the math easier to understand and debug. Real hardware introduces decoherence, noise, and device-specific limitations that can obscure the basic circuit behavior. Starting with simulation helps you distinguish between a conceptual error in your code and an execution issue on a backend.
Why does the Bell state only produce 00 and 11?
Because the Hadamard followed by CNOT creates the entangled state (|00⟩ + |11⟩)/√2 in the ideal model. The amplitudes for |01⟩ and |10⟩ become zero, so those outcomes should not appear in a noiseless simulation. In a real device, noise can introduce small deviations, but the ideal distribution remains the reference point.
What is the difference between amplitude and probability?
Amplitude is a complex number associated with a basis state, while probability is the squared magnitude of that amplitude. Amplitudes can be positive, negative, or complex, and these signs and phases matter because they can interfere constructively or destructively. Probabilities are always real numbers between 0 and 1 and are what you observe after measurement.
How do I know if my qubit ordering is correct?
Print the intermediate vectors after each gate and compare them to hand-calculated expectations. If the circuit output appears to affect the wrong basis states, your tensor-product order is likely reversed. Document your basis convention clearly in the notebook so future readers do not have to guess.
Related Reading
- Audit Your Crypto: A Practical Roadmap for Quantum‑Safe Migration - Learn how quantum progress changes real-world security planning.
- Agentic AI in Production: Safe Orchestration Patterns for Multi-Agent Workflows - Useful context for thinking about control, validation, and orchestration.
- RTD Launches and Web Resilience - A practical analogy for validating systems under stress.
- Forecasting Memory Demand - Good reading on measurement, baselines, and capacity planning discipline.
- How Engineering Leaders Turn AI Press Hype into Real Projects - A framework for separating novelty from actionable engineering.
Related Topics
Maya Thornton
Senior Quantum Content Strategist
Senior editor and content strategist. Writing about technology, design, and the future of digital media. Follow along for deep dives into the industry's moving parts.
Up Next
More stories handpicked for you
How to Build a Quantum Technology Watchlist Using Search Signals and Analyst Research
Quantum Market Intelligence Dashboards: Turning Hardware News Into Executive Decisions
Why Google Is Betting on Two Qubit Modalities: Superconducting and Neutral Atom Architectures Explained
Quantum Talent Gap: What IT Leaders Can Do Before the Skills Shortage Becomes a Blocker
The Quantum Developer Stack in 2026: SDKs, Orchestration Layers, and What’s Missing
From Our Network
Trending stories across our publication group