This post is part of my 21-day quantum computing learning journey, focusing on practical quantum programming with Qiskit - IBM’s powerful quantum development framework. Today we’re exploring how to transform theoretical quantum concepts into executable code and simulate real quantum circuits.

Progress: 14/21 days completed. Qiskit Setup: ✓. Quantum Gates: ✓. Circuit Simulation: mastered.

Qiskit: From Theory to Practice

Quantum computing concepts fascinate in theory — but the real magic happens when we implement them! Qiskit (Quantum Information Science Kit) is IBM’s open-source quantum SDK that makes quantum computing accessible to developers worldwide. Whether you’re curious about superposition, entanglement, or quantum gates, Qiskit transforms abstract quantum mechanics into tangible, executable code.

Unlike classical programming where bits are deterministic, quantum programming deals with probabilistic quantum states, complex amplitudes, and the mysterious world of superposition and entanglement.

The Foundation: Understanding Qiskit Components

Quantum Circuit - The Blueprint

The quantum circuit is Qiskit’s core structure, serving as the blueprint for quantum operations. Think of it as a recipe that tells quantum hardware exactly what operations to perform:

from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister

# Create a quantum circuit with 3 qubits and 3 classical bits
qc = QuantumCircuit(3, 3)

Qubits vs Classical Bits

  • Qubits: The quantum information carriers that can exist in superposition
  • Classical Bits: Storage for measurement results, converting quantum to classical information

Registers: Organizing Quantum Information

python# Quantum register for qubits
qreg = QuantumRegister(3, 'q')
# Classical register for measurement results
creg = ClassicalRegister(3, 'c')
# Create circuit with named registers
qc = QuantumCircuit(qreg, creg)

Essential Quantum Gates in Qiskit

Single-Qubit Gates: The Building Blocks

Hadamard Gate (H): Creates superposition

# Put qubit in equal superposition of |0⟩ and |1⟩
qc.h(0)  # |0⟩ → (|0⟩ + |1⟩)/√2

Pauli Gates: Fundamental quantum rotations

qc.x(0)  # Bit flip: |0⟩ ↔ |1⟩
qc.y(0)  # Bit and phase flip
qc.z(0)  # Phase flip: |1⟩ → -|1⟩

Phase Gates: Precision phase control

qc.s(0)   # S gate: |1⟩ → i|1⟩
qc.t(0)   # T gate: |1⟩ → e^(iπ/4)|1⟩

Practical Implementation: Building Your First Quantum Circuit

import numpy as np
from qiskit import QuantumCircuit, execute, Aer
from qiskit.visualization import plot_histogram
import matplotlib.pyplot as plt

def create_bell_state():
    """Create and simulate a Bell state (maximally entangled state)"""
    print("Creating Bell State |Φ⁺⟩ = (|00⟩ + |11⟩)/√2")
    print("=" * 50)
    
    # Create quantum circuit
    qc = QuantumCircuit(2, 2)
    
    # Create Bell state
    qc.h(0)      # Put qubit 0 in superposition
    qc.cx(0, 1)  # Entangle qubit 1 with qubit 0
    
    # Add measurements
    qc.measure(0, 0)
    qc.measure(1, 1)
    
    # Print circuit
    print("Quantum Circuit:")
    print(qc.draw())
    
    # Simulate
    backend = Aer.get_backend('qasm_simulator')
    job = execute(qc, backend, shots=1024)
    result = job.result()
    counts = result.get_counts(qc)
    
    print(f"\nMeasurement results (1024 shots):")
    for state, count in counts.items():
        print(f"|{state}⟩: {count} times ({count/1024:.1%})")
    
    return qc, counts

def demonstrate_superposition():
    """Show quantum superposition with Hadamard gate"""
    print("\nDemonstrating Quantum Superposition")
    print("=" * 40)
    
    qc = QuantumCircuit(1, 1)
    
    # Start with |0⟩
    print("Initial state: |0⟩")
    
    # Apply Hadamard
    qc.h(0)
    print("After Hadamard: (|0⟩ + |1⟩)/√2")
    
    # Measure
    qc.measure(0, 0)
    
    # Simulate
    backend = Aer.get_backend('qasm_simulator')
    job = execute(qc, backend, shots=1000)
    result = job.result()
    counts = result.get_counts(qc)
    
    print("Measurement results:")
    for state, count in counts.items():
        print(f"|{state}⟩: {count}/1000 = {count/1000:.1%}")
    
    return qc, counts

def quantum_teleportation_circuit():
    """Implement quantum teleportation protocol"""
    print("\nQuantum Teleportation Protocol")
    print("=" * 40)
    
    # Create circuit with 3 qubits and 3 classical bits
    qc = QuantumCircuit(3, 3)
    
    # Step 1: Prepare unknown state |ψ⟩ = α|0⟩ + β|1⟩
    # For demo, let's prepare |ψ⟩ = (|0⟩ + |1⟩)/√2
    qc.h(0)
    qc.barrier()  # Visual separator
    
    # Step 2: Create Bell pair between qubits 1 and 2
    qc.h(1)
    qc.cx(1, 2)
    qc.barrier()
    
    # Step 3: Bell measurement on qubits 0 and 1
    qc.cx(0, 1)
    qc.h(0)
    qc.measure(0, 0)
    qc.measure(1, 1)
    qc.barrier()
    
    # Step 4: Conditional operations on qubit 2
    qc.cx(1, 2)  # Conditional X
    qc.cz(0, 2)  # Conditional Z
    
    # Step 5: Measure final state
    qc.measure(2, 2)
    
    print("Teleportation Circuit:")
    print(qc.draw())
    
    # Simulate
    backend = Aer.get_backend('qasm_simulator')
    job = execute(qc, backend, shots=1024)
    result = job.result()
    counts = result.get_counts(qc)
    
    print("Teleportation Results:")
    for state, count in counts.items():
        print(f"|{state}⟩: {count} times")
    
    return qc, counts

def grover_search_2qubits():
    """Implement Grover's search algorithm for 2 qubits"""
    print("\nGrover's Search Algorithm (2 qubits)")
    print("=" * 40)
    print("Searching for |11⟩ state")
    
    qc = QuantumCircuit(2, 2)
    
    # Step 1: Initialize superposition
    qc.h([0, 1])
    qc.barrier()
    
    # Step 2: Oracle (mark |11⟩)
    qc.cz(0, 1)  # Flips phase of |11⟩
    qc.barrier()
    
    # Step 3: Diffusion operator (amplitude amplification)
    qc.h([0, 1])
    qc.z([0, 1])
    qc.cz(0, 1)
    qc.h([0, 1])
    qc.barrier()
    
    # Step 4: Measure
    qc.measure([0, 1], [0, 1])
    
    print("Grover Circuit:")
    print(qc.draw())
    
    # Simulate
    backend = Aer.get_backend('qasm_simulator')
    job = execute(qc, backend, shots=1024)
    result = job.result()
    counts = result.get_counts(qc)
    
    print("Search Results:")
    for state, count in sorted(counts.items()):
        print(f"|{state}⟩: {count} times ({count/1024:.1%})")
    
    return qc, counts

if __name__ == "__main__":
    # Run demonstrations
    bell_circuit, bell_counts = create_bell_state()
    super_circuit, super_counts = demonstrate_superposition()
    teleport_circuit, teleport_counts = quantum_teleportation_circuit()
    grover_circuit, grover_counts = grover_search_2qubits()

Simulation and Execution: From Code to Results

Understanding Backends Qiskit provides multiple execution environments:

pythonfrom qiskit import Aer, IBMQ

# Local simulators
qasm_sim = Aer.get_backend('qasm_simulator')      # Classical simulation
statevector_sim = Aer.get_backend('statevector_simulator')  # Quantum state

# Real quantum hardware (requires IBMQ account)
# IBMQ.load_account()
# provider = IBMQ.get_provider()
# quantum_computer = provider.get_backend('ibmq_qasm_simulator')

Key Concepts for Execution

Shots: Number of circuit repetitions

pythonjob = execute(circuit, backend, shots=1024)

Job Management: Tracking quantum computations

result = job.result()
counts = result.get_counts()

Circuit Visualization

pythonfrom qiskit.visualization import plot_circuit_layout, plot_histogram

# Visualize circuit
print(qc.draw())
print(qc.draw(output='mpl'))  # Matplotlib version

# Plot results
plot_histogram(counts)

Common Qiskit Functions Reference

Function Purpose Example
qc.h(qubit) Hadamard gate (superposition) qc.h(0)
qc.x(qubit) Pauli-X gate (bit flip) qc.x(1)
qc.y(qubit) Pauli-Y gate qc.y(0)
qc.z(qubit) Pauli-Z gate (phase flip) qc.z(1)
qc.cx(control, target) CNOT gate (entanglement) qc.cx(0, 1)
qc.ccx(c1, c2, target) Toffoli gate qc.ccx(0, 1, 2)
qc.measure(q, c) Measure qubit to classical bit qc.measure(0, 0)
qc.barrier() Visual circuit separator qc.barrier()
qc.draw() Display circuit diagram print(qc.draw())

Conclusion

Qiskit transforms quantum computing from abstract theory into practical reality. By mastering these core components - circuits, gates, measurements, and simulation - you’re building the foundation for quantum algorithm development. The journey from classical to quantum programming requires new thinking about information, probability, and computation itself.

Start with simple circuits, gradually building complexity as you develop intuition for quantum behavior. Remember: quantum programming is fundamentally different from classical programming - embrace the probabilistic nature and the strange beauty of quantum mechanics.

My site is free of ads and trackers. Was this post helpful to you? Why not BuyMeACoffee


Reference:

  1. Nielsen, M. A., & Chuang, I. L. (2024). Quantum Computation and Quantum Information: 10th Anniversary Edition. Cambridge University Press