Skip to content

Your First Quantum Program

Welcome to your first quantum program with SuperQuantX! This comprehensive guide will walk you through building quantum applications from the ground up, explaining each concept along the way.

๐ŸŽฏ What You'll Learn

By the end of this tutorial, you'll understand:

  • Quantum Basics: Qubits, superposition, and entanglement
  • Circuit Building: Creating and manipulating quantum circuits
  • Quantum Algorithms: Implementing basic quantum algorithms
  • Backend Integration: Using different quantum computing frameworks
  • Result Analysis: Interpreting quantum measurement results

๐Ÿงช Prerequisites

Make sure you have SuperQuantX installed:

pip install superquantx[pennylane]

๐Ÿš€ Hello Quantum World

Let's start with the quantum equivalent of "Hello, World!" - creating a superposition state:

Step 1: Setting Up Your Environment

import superquantx as sqx
import numpy as np
import matplotlib.pyplot as plt

# Verify your installation
print(f"SuperQuantX version: {sqx.__version__}")
print(f"Available backends: {sqx.list_available_backends()}")

Step 2: Understanding Qubits

Unlike classical bits that can only be 0 or 1, qubits can exist in a superposition of both states simultaneously.

# Get a quantum backend
backend = sqx.get_backend('simulator')

# Create a circuit with one qubit
circuit = backend.create_circuit(n_qubits=1)

# Initially, the qubit is in state |0โŸฉ
print("Initial state: |0โŸฉ")

# Apply a Hadamard gate to create superposition
circuit = backend.add_gate(circuit, 'H', 0)  # Now the qubit is in state (|0โŸฉ + |1โŸฉ)/โˆš2

# Measure the qubit
circuit = backend.add_measurement(circuit)

# Run the circuit multiple times
result = backend.execute_circuit(circuit, shots=1000)
counts = result['counts']

print(f"Measurement results: {counts}")
print("๐ŸŽ‰ You've created quantum superposition!")

Expected output:

Measurement results: {'0': 503, '1': 497}

Notice how we get roughly equal counts of 0 and 1! This is quantum superposition in action.

Step 3: Understanding the Results

The Hadamard gate (H) puts a qubit in an equal superposition:

  • Before H gate: Qubit is definitely in state |0โŸฉ
  • After H gate: Qubit is in state (|0โŸฉ + |1โŸฉ)/โˆš2
  • After measurement: We get 0 or 1 with equal probability

๐Ÿ”— Quantum Entanglement

Now let's create something more exotic - quantum entanglement between two qubits:

Creating the Bell State

The Bell state is a famous quantum entangled state where two qubits are perfectly correlated:

# Create a circuit with 2 qubits
circuit = backend.create_circuit(n_qubits=2)

# Step 1: Put first qubit in superposition
circuit = backend.add_gate(circuit, 'H', 0)

# Step 2: Entangle the qubits with CNOT gate
circuit = backend.add_gate(circuit, 'CNOT', [0, 1])  # Controlled-X gate (CNOT)

# Step 3: Measure both qubits
circuit = backend.add_measurement(circuit)

# Run the circuit
result = backend.execute_circuit(circuit, shots=1000)
counts = result['counts']

print(f"Bell state results: {counts}")

# Circuit information (visualization to be implemented)
print(f"\nCircuit created successfully!")
print(f"Circuit has {circuit.n_qubits} qubits")
print(f"Current state vector shape: {circuit.state.shape}")

Expected output:

Bell state results: {'00': 496, '11': 504}

๐Ÿค” Notice something interesting? We only get 00 and 11 - never 01 or 10! This is quantum entanglement - the qubits are perfectly correlated.

Understanding Entanglement

# Let's verify the entanglement property
print("\n๐Ÿ” Analyzing entanglement:")
total_shots = sum(counts.values())

prob_00 = counts.get('00', 0) / total_shots
prob_11 = counts.get('11', 0) / total_shots
prob_01 = counts.get('01', 0) / total_shots
prob_10 = counts.get('10', 0) / total_shots

print(f"P(00) = {prob_00:.3f}")
print(f"P(11) = {prob_11:.3f}")
print(f"P(01) = {prob_01:.3f}")
print(f"P(10) = {prob_10:.3f}")

if prob_01 + prob_10 < 0.1:  # Less than 10% due to statistical noise
    print("โœ… Qubits are entangled!")
else:
    print("โŒ Something went wrong...")

๐ŸŽฒ Random Number Generator

Let's build a quantum random number generator:

def quantum_random_number(num_bits=8):
    """Generate a random number using quantum superposition."""

    # Create circuit with specified number of qubits
    circuit = backend.create_circuit(n_qubits=num_bits)

    # Put all qubits in superposition
    for i in range(num_bits):
        circuit = backend.add_gate(circuit, 'H', i)

    # Measure all qubits
    circuit = backend.add_measurement(circuit)

    # Run the circuit once
    result = backend.execute_circuit(circuit, shots=1)

    # Convert result to integer
    binary_result = list(result['counts'].keys())[0]
    random_number = int(binary_result, 2)

    return random_number, binary_result

# Generate some quantum random numbers
print("๐ŸŽฒ Quantum Random Numbers:")
for i in range(5):
    number, binary = quantum_random_number(8)  # 8-bit numbers (0-255)
    print(f"  {number:3d} (binary: {binary})")

๐Ÿงฎ Quantum Interference

Let's explore quantum interference with a more complex example:

def quantum_interference_demo():
    """Demonstrate quantum interference patterns."""

    circuit = backend.create_circuit(n_qubits=1)

    # Create superposition
    circuit = backend.add_gate(circuit, 'H', 0)

    # Add a phase (rotation around Z-axis)
    circuit = backend.add_gate(circuit, 'RZ', 0, [np.pi/4])  # 45-degree phase

    # Apply another Hadamard - this creates interference
    circuit = backend.add_gate(circuit, 'H', 0)

    circuit = backend.add_measurement(circuit)

    # Run multiple times to see the pattern
    result = backend.execute_circuit(circuit, shots=1000)
    counts = result['counts']

    return counts

# Test different phases
phases = [0, np.pi/4, np.pi/2, 3*np.pi/4, np.pi]
results = []

print("๐ŸŒŠ Quantum Interference Patterns:")
print("Phase\t|0โŸฉ Count\t|1โŸฉ Count")
print("-" * 35)

for phase in phases:
    circuit = backend.create_circuit(n_qubits=1)
    circuit = backend.add_gate(circuit, 'H', 0)
    circuit = backend.add_gate(circuit, 'RZ', 0, [phase])
    circuit = backend.add_gate(circuit, 'H', 0)
    circuit = backend.add_measurement(circuit)

    result = backend.execute_circuit(circuit, shots=1000)
    counts = result['counts']

    count_0 = counts.get('0', 0)
    count_1 = counts.get('1', 0)

    print(f"{phase:.2f}\t{count_0}\t\t{count_1}")
    results.append((phase, count_0, count_1))

๐ŸŽฏ Building a Quantum Coin Flipper

Let's create a biased quantum coin that we can control:

class QuantumCoin:
    """A quantum coin flipper with controllable bias."""

    def __init__(self, backend_name='simulator'):
        self.backend = sqx.get_backend(backend_name)

    def flip(self, bias=0.5, shots=1000):
        """
        Flip the quantum coin.

        Args:
            bias (float): Probability of getting 'heads' (0.0 to 1.0)
            shots (int): Number of measurements

        Returns:
            dict: Results with counts for heads and tails
        """
        # Calculate rotation angle for desired bias
        theta = 2 * np.arcsin(np.sqrt(bias))

        circuit = self.backend.create_circuit(n_qubits=1)

        # Start in |0โŸฉ (tails)
        # Rotate to achieve desired bias
        circuit = self.backend.add_gate(circuit, 'RY', 0, [theta])

        circuit = self.backend.add_measurement(circuit)

        result = self.backend.execute_circuit(circuit, shots=shots)
        counts = result['counts']

        # Map 0->tails, 1->heads
        heads = counts.get('1', 0)
        tails = counts.get('0', 0)

        return {
            'heads': heads,
            'tails': tails,
            'bias': heads / (heads + tails) if (heads + tails) > 0 else 0
        }

# Test the quantum coin
coin = QuantumCoin()

print("๐Ÿช™ Quantum Coin Flipper Test:")
biases = [0.1, 0.3, 0.5, 0.7, 0.9]

for target_bias in biases:
    result = coin.flip(bias=target_bias, shots=1000)
    print(f"Target: {target_bias:.1f}, Actual: {result['bias']:.3f}, "
          f"Heads: {result['heads']}, Tails: {result['tails']}")

๐Ÿ“Š Visualizing Your Results

Let's add some visualization to better understand our quantum programs:

def plot_quantum_results(counts, title="Quantum Measurement Results"):
    """Plot quantum measurement results."""

    states = list(counts.keys())
    values = list(counts.values())

    plt.figure(figsize=(10, 6))
    bars = plt.bar(states, values, alpha=0.7)

    # Color bars differently for different states
    colors = ['skyblue', 'lightcoral', 'lightgreen', 'gold']
    for i, bar in enumerate(bars):
        bar.set_color(colors[i % len(colors)])

    plt.title(title, fontsize=16, fontweight='bold')
    plt.xlabel('Quantum State', fontsize=12)
    plt.ylabel('Count', fontsize=12)
    plt.grid(axis='y', alpha=0.3)

    # Add value labels on bars
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height,
                f'{int(height)}',
                ha='center', va='bottom')

    plt.tight_layout()
    # Save instead of showing to avoid timeout in automated tests
    plt.savefig('/tmp/quantum_results.png', dpi=150, bbox_inches='tight')
    plt.close()  # Close to free memory
    print(f"โœ… Plot saved successfully with data: {dict(zip(states, values))}")

# Example: Visualize Bell state results
circuit = backend.create_circuit(n_qubits=2)
circuit = backend.add_gate(circuit, 'H', 0)
circuit = backend.add_gate(circuit, 'CNOT', [0, 1])
circuit = backend.add_measurement(circuit)

result = backend.execute_circuit(circuit, shots=1000)
counts = result['counts']

plot_quantum_results(counts, "Bell State |ฮฆโบโŸฉ = (|00โŸฉ + |11โŸฉ)/โˆš2")

๐Ÿ”ง Working with Different Backends

SuperQuantX's power lies in backend flexibility. Let's compare the same algorithm across different backends:

def compare_backends(algorithm_func, *args, **kwargs):
    """Run the same algorithm on different backends."""

    available_backends = sqx.list_available_backends()
    results = {}

    # Only test backends that are actually available and support gate-model circuits
    for backend_name in available_backends:
        # Skip quantum annealing backends (they use a different programming model)
        if backend_name in {'ocean', 'dwave'}:
            print(f"โญ๏ธ  Skipping {backend_name}: Quantum annealing backend (not compatible with gate circuits)")
            continue

        if available_backends[backend_name].get('available', False):
            try:
                print(f"๐Ÿ”„ Testing {backend_name}...")
                result = algorithm_func(backend_name, *args, **kwargs)
                results[backend_name] = result
                print(f"โœ… {backend_name} completed successfully")

            except Exception as e:
                print(f"โŒ {backend_name} failed: {e}")
                results[backend_name] = None
        else:
            reason = available_backends[backend_name].get('reason', 'Not available')
            print(f"โญ๏ธ  Skipping {backend_name}: {reason}")

    return results

def bell_state_test(backend_name):
    """Create Bell state on specified backend."""
    backend = sqx.get_backend(backend_name)
    circuit = backend.create_circuit(n_qubits=2)

    circuit = backend.add_gate(circuit, 'H', 0)
    circuit = backend.add_gate(circuit, 'CNOT', [0, 1])
    circuit = backend.add_measurement(circuit)

    result = backend.execute_circuit(circuit, shots=1000)
    return result['counts']

# Compare Bell state across backends
print("๐Ÿ” Cross-Backend Comparison:")
backend_results = compare_backends(bell_state_test)

print("\n๐Ÿ“Š Results Summary:")
for backend_name, counts in backend_results.items():
    if counts:
        prob_entangled = (counts.get('00', 0) + counts.get('11', 0)) / 1000
        print(f"{backend_name}: Entanglement fidelity = {prob_entangled:.3f}")
        print(f"  Results: {counts}")

print("\n๐Ÿ’ก Note: This example uses gate-model quantum computing.")
print("   Ocean/D-Wave backends are quantum annealers for optimization problems")
print("   and use a completely different programming model (QUBO/Ising).")

๐ŸŽ“ Algorithm: Quantum Phase Kickback

Let's implement a more advanced concept - quantum phase kickback:

def phase_kickback_demo():
    """Demonstrate quantum phase kickback."""

    print("๐Ÿ”„ Quantum Phase Kickback Demonstration")
    print("This shows how a controlled operation can affect the control qubit")

    circuit = backend.create_circuit(n_qubits=2)

    # Put control qubit in superposition
    circuit = backend.add_gate(circuit, 'H', 0)

    # Put target qubit in |1โŸฉ state (important for kickback!)
    circuit = backend.add_gate(circuit, 'X', 1)

    # Apply controlled-Z gate
    circuit = backend.add_gate(circuit, 'CZ', [0, 1])

    # Measure in X-basis to see phase difference
    circuit = backend.add_gate(circuit, 'H', 0)  # Hโ€ |ยฑโŸฉ = |0โŸฉ/|1โŸฉ
    circuit = backend.add_measurement(circuit)

    result = backend.execute_circuit(circuit, shots=1000)
    counts = result['counts']

    print(f"Results: {counts}")

    # Compare with reference (no kickback)
    circuit_ref = backend.create_circuit(n_qubits=2)
    circuit_ref = backend.add_gate(circuit_ref, 'H', 0)
    circuit_ref = backend.add_gate(circuit_ref, 'X', 1)
    # Skip the CZ gate
    circuit_ref = backend.add_gate(circuit_ref, 'H', 0)
    circuit_ref = backend.add_measurement(circuit_ref)

    result_ref = backend.execute_circuit(circuit_ref, shots=1000)
    counts_ref = result_ref['counts']

    print(f"Reference (no CZ): {counts_ref}")
    print("The difference shows the phase kickback effect!")

    return counts, counts_ref

phase_kickback_demo()

๐ŸŽฏ Next Steps: Your Learning Path

Congratulations! You've built your first quantum programs. Here's what to explore next:

Immediate Next Steps

  1. Configuration Guide: Customize SuperQuantX for your needs
  2. Basic Quantum Tutorial: Deep dive into quantum concepts
  3. Quantum Algorithms: Explore built-in algorithms

Intermediate Topics

  1. Quantum Machine Learning: Apply QML algorithms
  2. Multi-Backend Usage: Compare frameworks
  3. Circuit Optimization: Efficient circuit design

Advanced Projects

  1. Build a Quantum Game: Create quantum versions of classical games
  2. Quantum Cryptography: Implement quantum key distribution
  3. Variational Algorithms: Explore VQE and QAOA

๐Ÿงช Practice Challenges

Try these challenges to reinforce your learning:

Challenge 1: Quantum Dice

Create a quantum 6-sided die that's perfectly fair:

# Hint: Use multiple qubits and post-process results
def quantum_dice():
    # Your code here
    pass

Challenge 2: Quantum Walk

Implement a simple quantum random walk:

def quantum_walk(steps=10):
    # Use superposition to move left and right simultaneously
    pass

Challenge 3: Grover's Algorithm

Try implementing a simple version of Grover's search:

def mini_grover_search(target_item):
    # Search for an item in a small database
    pass

๐Ÿ“ž Getting Help

If you get stuck or have questions:

๐Ÿ“š Additional Resources


Congratulations! ๐ŸŽ‰

You've successfully created your first quantum programs with SuperQuantX! You now understand superposition, entanglement, and quantum measurement. Keep experimenting and exploring the quantum world!

Pro Tip

The best way to learn quantum computing is through hands-on experimentation. Try modifying the examples above and see what happens!