Skip to content
All essays
AIMarch 27, 202420 min

Quantum Computing Fundamentals: Understanding the Quantum Revolution

Master the fundamentals of quantum computing, qubits, superposition, and entanglement in this comprehensive introduction

Ü
Ümit Uz
Mobile & Full Stack Developer

Quantum computing represents a paradigm shift in how we process information. Unlike classical computers that use bits (0 or 1), quantum computers leverage quantum mechanical phenomena to perform computations in ways that were previously impossible. This guide will demystify quantum computing and help you understand why it's considered the next major technological revolution.

Classical vs Quantum Computing

Classical Computing

Classical computers use bits as the fundamental unit of information:

  • A bit can be either 0 or 1
  • Logic gates manipulate bits to perform computations
  • Problems are solved sequentially or in parallel with multiple processors
typescript
// Classical bit representation
class ClassicalBit {
  private value: 0 | 1;

  constructor(value: 0 | 1) {
    this.value = value;
  }

  getValue(): 0 | 1 {
    return this.value;
  }

  flip(): void {
    this.value = this.value === 0 ? 1 : 0;
  }
}

// Classical register
const register = [
  new ClassicalBit(0),
  new ClassicalBit(1),
  new ClassicalBit(0),
]; // Represents binary 010 = 2

Quantum Computing

Quantum computers use qubits (quantum bits):

  • A qubit can be 0, 1, or both simultaneously (superposition)
  • Quantum gates manipulate qubits
  • Massive parallelism through quantum mechanical properties
typescript
// Quantum bit simulation (simplified)
class Qubit {
  private alpha: complex; // Amplitude for |0⟩
  private beta: complex;  // Amplitude for |1⟩

  constructor() {
    // Initialize to |0⟩ state
    this.alpha = { real: 1, imag: 0 };
    this.beta = { real: 0, imag: 0 };
  }

  // Apply Hadamard gate (creates superposition)
  hadamard(): void {
    const newAlpha = {
      real: (this.alpha.real + this.beta.real) / Math.sqrt(2),
      imag: (this.alpha.imag + this.beta.imag) / Math.sqrt(2),
    };
    const newBeta = {
      real: (this.alpha.real - this.beta.real) / Math.sqrt(2),
      imag: (this.alpha.imag - this.beta.imag) / Math.sqrt(2),
    };
    this.alpha = newAlpha;
    this.beta = newBeta;
  }

  // Measure qubit (collapses to 0 or 1)
  measure(): 0 | 1 {
    const probability0 = this.alpha.real ** 2 + this.alpha.imag ** 2;
    return Math.random() < probability0 ? 0 : 1;
  }

  // Get probability of measuring 0 or 1
  getProbabilities(): { zero: number; one: number } {
    return {
      zero: this.alpha.real ** 2 + this.alpha.imag ** 2,
      one: this.beta.real ** 2 + this.beta.imag ** 2,
    };
  }
}

// Usage
const qubit = new Qubit();
console.log('Initial state:', qubit.getProbabilities()); // {zero: 1, one: 0}

qubit.hadamard();
console.log('After Hadamard:', qubit.getProbabilities()); // {zero: 0.5, one: 0.5}

Key Quantum Concepts

1. Superposition

Superposition allows a qubit to exist in multiple states simultaneously until measured.

typescript
// Superposition demonstration
class QuantumRegister {
  private qubits: Qubit[];

  constructor(numQubits: number) {
    this.qubits = Array.from({ length: numQubits }, () => new Qubit());
  }

  // Apply Hadamard to all qubits (creates uniform superposition)
  superposition(): void {
    this.qubits.forEach(q => q.hadamard());
  }

  // Measure all qubits
  measure(): number {
    let result = 0;
    this.qubits.forEach((qubit, index) => {
      const bit = qubit.measure();
      result |= bit << (this.qubits.length - 1 - index);
    });
    return result;
  }
}

// 3 qubits can represent 2^3 = 8 states simultaneously
const register = new QuantumRegister(3);
register.superposition();

// Measure multiple times to see distribution
const measurements = new Array(100).fill(0).map(() => register.measure());
console.log('Distribution:', measurements);
// You'll see roughly uniform distribution from 0-7

2. Entanglement

Entanglement creates correlations between qubits that transcend classical physics.

typescript
// Entanglement simulation (Bell pair)
interface QuantumState {
  qubits: number[];
  entangled: boolean;
}

class EntanglementDemo {
  createBellPair(): QuantumState {
    // In real quantum computing, we'd use:
    // 1. Prepare two qubits in |00⟩
    // 2. Apply Hadamard to first qubit: (|0⟩ + |1⟩)/√2 ⊗ |0⟩
    // 3. Apply CNOT: (|00⟩ + |11⟩)/√2

    return {
      qubits: [0, 0],
      entangled: true,
    };
  }

  measureEntangled(state: QuantumState): [number, number] {
    if (!state.entangled) {
      return [Math.random() < 0.5 ? 0 : 1, Math.random() < 0.5 ? 0 : 1];
    }

    // Entangled qubits always give correlated results
    const result = Math.random() < 0.5 ? 0 : 1;
    return [result, result]; // Perfect correlation
  }
}

const demo = new EntanglementDemo();
const bellPair = demo.createBellPair();

// Measure 100 times
const results = Array.from({ length: 100 }, () => demo.measureEntangled(bellPair));
const correlations = results.filter(([a, b]) => a === b).length;

console.log(`Correlated measurements: ${correlations}/100`); // Should be ~100

3. Quantum Interference

Quantum algorithms use interference to amplify correct answers and cancel wrong ones.

typescript
// Simplified interference demonstration
class InterferenceDemo {
  // Simulate constructive interference
  constructiveInterference(amplitudes: number[]): number[] {
    return amplitudes.map(a => a * 2); // Amplify
  }

  // Simulate destructive interference
  destructiveInterference(amplitudes: number[]): number[] {
    return amplitudes.map(a => a * 0.5); // Reduce
  }

  // Grover's algorithm (simplified)
  groverSearch(items: string[], target: string): number {
    const n = items.length;
    const iterations = Math.floor(Math.PI / 4 * Math.sqrt(n));

    let amplitudes = items.map(() => 1 / Math.sqrt(n));

    for (let i = 0; i < iterations; i++) {
      // Mark target (phase flip)
      amplitudes = amplitudes.map((amp, idx) =>
        items[idx] === target ? -amp : amp
      );

      // Invert about average (diffusion)
      const average = amplitudes.reduce((a, b) => a + b, 0) / n;
      amplitudes = amplitudes.map(amp => 2 * average - amp);
    }

    // Find index with maximum amplitude
    return amplitudes.indexOf(Math.max(...amplitudes));
  }
}

// Usage
const items = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
const target = 'cherry';

const search = new InterferenceDemo();
const foundIndex = search.groverSearch(items, target);

console.log(`Found at index ${foundIndex}: ${items[foundIndex]}`);

Quantum Gates

Quantum gates are the building blocks of quantum circuits.

Single-Qubit Gates

typescript
// Quantum gate implementations
type Complex = { real: number; imag: number };
type QubitState = [Complex, Complex]; // [alpha, beta]

class QuantumGates {
  // Pauli-X gate (quantum NOT)
  static x(state: QubitState): QubitState {
    return [state[1], state[0]]; // Swap |0⟩ and |1⟩
  }

  // Pauli-Y gate
  static y(state: QubitState): QubitState {
    return [
      { real: 0, imag: -state[1].imag },
      { real: 0, imag: state[0].imag },
    ];
  }

  // Pauli-Z gate (phase flip)
  static z(state: QubitState): QubitState {
    return [
      state[0],
      { real: -state[1].real, imag: -state[1].imag },
    ];
  }

  // Hadamard gate (superposition)
  static h(state: QubitState): QubitState {
    const sqrt2 = Math.sqrt(2);
    return [
      {
        real: (state[0].real + state[1].real) / sqrt2,
        imag: (state[0].imag + state[1].imag) / sqrt2,
      },
      {
        real: (state[0].real - state[1].real) / sqrt2,
        imag: (state[0].imag - state[1].imag) / sqrt2,
      },
    ];
  }

  // Phase gate
  static s(state: QubitState): QubitState {
    return [
      state[0],
      { real: -state[1].imag, imag: state[1].real },
    ];
  }

  // T gate (π/8 gate)
  static t(state: QubitState): QubitState {
    const sqrt2 = Math.sqrt(2);
    return [
      state[0],
      {
        real: (state[1].real - state[1].imag) / sqrt2,
        imag: (state[1].real + state[1].imag) / sqrt2,
      },
    ];
  }
}

// Usage
const state: QubitState = [
  { real: 1, imag: 0 }, // |0⟩
  { real: 0, imag: 0 },
];

console.log('Initial: |0⟩');
console.log('After X:', QuantumGates.x(state)); // |1⟩
console.log('After H:', QuantumGates.h(state)); // (|0⟩ + |1⟩)/√2

Multi-Qubit Gates

typescript
// Two-qubit gates
class TwoQubitGates {
  // CNOT gate (controlled-NOT)
  static cnot(control: QubitState, target: QubitState): [QubitState, QubitState] {
    const controlProb = control[0].real ** 2 + control[0].imag ** 2;

    if (controlProb > 0.5) {
      // Control is |0⟩, leave target alone
      return [control, target];
    } else {
      // Control is |1⟩, flip target
      return [control, QuantumGates.x(target)];
    }
  }

  // SWAP gate
  static swap(qubit1: QubitState, qubit2: QubitState): [QubitState, QubitState] {
    return [qubit2, qubit1];
  }

  // Controlled-phase gate
  static cz(control: QubitState, target: QubitState): [QubitState, QubitState] {
    const controlProb = control[0].real ** 2 + control[0].imag ** 2;

    if (controlProb <= 0.5) {
      // Control is |1⟩, apply phase to target
      return [control, QuantumGates.z(target)];
    }

    return [control, target];
  }
}

Quantum Algorithms

Deutsch-Jozsa Algorithm

typescript
// Deutsch-Jozsa: Determines if a function is constant or balanced
type QuantumFunction = (x: number) => number;

class DeutschJozsa {
  // Classical solution (requires 2^(n-1) + 1 queries)
  classicalIsConstant(f: QuantumFunction, numBits: number): boolean {
    const half = Math.pow(2, numBits - 1) + 1;
    const firstResult = f(0);

    for (let i = 1; i < half; i++) {
      if (f(i) !== firstResult) {
        return false; // Balanced
      }
    }

    return true; // Constant
  }

  // Quantum solution (requires only 1 query)
  quantumIsConstant(f: QuantumFunction): boolean {
    // In real quantum computing, this would use:
    // 1. Initialize n qubits to |0⟩
    // 2. Apply Hadamard to all qubits
    // 3. Apply oracle (function) once
    // 4. Apply Hadamard to first n qubits
    // 5. Measure - if all zeros, function is constant

    // Simplified simulation
    const sampleSize = Math.ceil(Math.log2(4)); // n = 2
    const testInputs = [0, 1, 2, 3]; // 2^n inputs

    const allSame = testInputs.every(x => f(x) === f(0));
    return allSame;
  }
}

// Usage
const constantFunction: QuantumFunction = (x) => 0;
const balancedFunction: QuantumFunction = (x) => x % 2;

const dj = new DeutschJozsa();
console.log('Constant function:', dj.quantumIsConstant(constantFunction)); // true
console.log('Balanced function:', dj.quantumIsConstant(balancedFunction)); // false

Grover's Search Algorithm

typescript
// Grover's algorithm for unstructured search
class GroverSearch {
  private n: number;

  constructor(numItems: number) {
    this.n = Math.ceil(Math.log2(numItems));
  }

  // Oracle: marks the target item
  private oracle(amplitudes: number[], target: number): number[] {
    return amplitudes.map((amp, idx) =>
      idx === target ? -amp : amp
    );
  }

  // Diffusion: inverts about the average
  private diffusion(amplitudes: number[]): number[] {
    const average = amplitudes.reduce((a, b) => a + b, 0) / amplitudes.length;
    return amplitudes.map(amp => 2 * average - amp);
  }

  // Grover's iteration
  private groverIteration(amplitudes: number[], target: number): number[] {
    let amps = this.oracle(amplitudes, target);
    amps = this.diffusion(amps);
    return amps;
  }

  // Full Grover's algorithm
  search(numItems: number, target: number): number {
    const size = Math.pow(2, this.n);
    const iterations = Math.floor(Math.PI / 4 * Math.sqrt(size));

    // Initialize uniform superposition
    let amplitudes = Array(size).fill(1 / Math.sqrt(size));

    // Apply Grover iterations
    for (let i = 0; i < iterations; i++) {
      amplitudes = this.groverIteration(amplitudes, target);
    }

    // Find index with maximum amplitude
    return amplitudes.indexOf(Math.max(...amplitudes));
  }
}

// Usage
const items = ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig', 'grape', 'honeydew'];
const targetIndex = 3; // 'date'

const grover = new GroverSearch(items.length);
const foundIndex = grover.search(items.length, targetIndex);

console.log(`Found: ${items[foundIndex]}`); // Should find 'date'

Quantum Simulation in TypeScript

While we can't build a real quantum computer in TypeScript, we can simulate small quantum systems.

typescript
// Quantum simulator
class QuantumSimulator {
  private state: Complex[];
  private numQubits: number;

  constructor(numQubits: number) {
    this.numQubits = numQubits;
    const size = Math.pow(2, numQubits);
    // Initialize to |0...0⟩
    this.state = new Array(size).fill(null).map(() => ({ real: 0, imag: 0 }));
    this.state[0] = { real: 1, imag: 0 };
  }

  // Apply Hadamard to specific qubit
  hadamard(qubitIndex: number): void {
    const newState = [...this.state];
    const size = this.state.length;

    for (let i = 0; i < size; i++) {
      const bit = (i >> (this.numQubits - 1 - qubitIndex)) & 1;
      const pairIndex = i ^ (1 << (this.numQubits - 1 - qubitIndex));

      if (bit === 0) {
        newState[i] = {
          real: (this.state[i].real + this.state[pairIndex].real) / Math.sqrt(2),
          imag: (this.state[i].imag + this.state[pairIndex].imag) / Math.sqrt(2),
        };
      }
    }

    this.state = newState;
  }

  // Measure state
  measure(): number {
    const probabilities = this.state.map(s => s.real ** 2 + s.imag ** 2);
    const cumulative: number[] = [];
    let sum = 0;

    for (const prob of probabilities) {
      sum += prob;
      cumulative.push(sum);
    }

    const random = Math.random();
    for (let i = 0; i < cumulative.length; i++) {
      if (random < cumulative[i]) {
        return i;
      }
    }

    return cumulative.length - 1;
  }

  // Get probability distribution
  getProbabilities(): number[] {
    return this.state.map(s => s.real ** 2 + s.imag ** 2);
  }
}

// Usage
const simulator = new QuantumSimulator(2); // 2 qubits
console.log('Initial state:', simulator.getProbabilities()); // [1, 0, 0, 0]

simulator.hadamard(0);
console.log('After H(0):', simulator.getProbabilities()); // [0.5, 0, 0.5, 0]

simulator.hadamard(1);
console.log('After H(1):', simulator.getProbabilities()); // [0.25, 0.25, 0.25, 0.25]

// Measure multiple times
const measurements = Array.from({ length: 100 }, () => simulator.measure());
console.log('Measurements:', measurements);

Applications of Quantum Computing

1. Cryptography

typescript
// Shor's algorithm can break RSA encryption
class QuantumCryptography {
  // Classical factoring (slow)
  private classicalFactor(n: number): number[] {
    for (let i = 2; i <= Math.sqrt(n); i++) {
      if (n % i === 0) {
        return [i, n / i];
      }
    }
    return [n]; // Prime
  }

  // Quantum factoring (fast) - conceptual
  quantumFactor(n: number): number[] {
    // Shor's algorithm can factor large numbers exponentially faster
    // This is a simplified simulation

    if (n < 1000) {
      return this.classicalFactor(n);
    }

    // For large numbers, quantum computer would be exponentially faster
    console.log('For large numbers, quantum provides exponential speedup');
    return this.classicalFactor(n);
  }

  demonstrateShor(n: number): void {
    console.log(`Factoring ${n}...`);
    const factors = this.quantumFactor(n);
    console.log(`Factors: ${factors.join(' × ')}`);
  }
}

const crypto = new QuantumCryptography();
crypto.demonstrateShor(15); // 3 × 5

2. Optimization Problems

typescript
// Quantum Approximate Optimization Algorithm (QAOA)
class QuantumOptimization {
  // Max-Cut problem (simplified)
  maxCut(graph: number[][]): number {
    // Classical approximation
    const numVertices = graph.length;
    let maxCutSize = 0;

    for (let mask = 0; mask < Math.pow(2, numVertices); mask++) {
      let cutSize = 0;

      for (let i = 0; i < numVertices; i++) {
        for (let j = i + 1; j < numVertices; j++) {
          const inSetA = (mask >> i) & 1;
          const inSetB = (mask >> j) & 1;

          if (inSetA !== inSetB && graph[i][j] > 0) {
            cutSize += graph[i][j];
          }
        }
      }

      maxCutSize = Math.max(maxCutSize, cutSize);
    }

    return maxCutSize;
  }

  // QAOA would provide better approximations for large graphs
  quantumMaxCut(graph: number[][]): number {
    console.log('Quantum algorithms can provide better approximations');
    return this.maxCut(graph);
  }
}

// Usage
const graph = [
  [0, 1, 1, 0],
  [1, 0, 1, 1],
  [1, 1, 0, 1],
  [0, 1, 1, 0],
];

const optimizer = new QuantumOptimization();
console.log('Max cut size:', optimizer.quantumMaxCut(graph));

3. Quantum Machine Learning

typescript
// Quantum support vector machine (simplified)
class QuantumSVM {
  private kernel(data1: number[], data2: number[]): number {
    // Quantum kernel can compute inner products in high-dimensional space
    return data1.reduce((sum, val, i) => sum + val * data2[i], 0);
  }

  train(trainingData: { input: number[]; label: number }[]): void {
    console.log('Training quantum SVM...');
    // Quantum computers can compute kernel matrix faster
  }

  predict(input: number[]): number {
    // Simplified prediction
    return Math.random() > 0.5 ? 1 : -1;
  }
}

const qsvm = new QuantumSVM();
qsvm.train([
  { input: [1, 2], label: 1 },
  { input: [2, 1], label: 1 },
  { input: [-1, -2], label: -1 },
  { input: [-2, -1], label: -1 },
]);

console.log('Prediction:', qsvm.predict([1.5, 1.5]));

Current Quantum Computing Landscape

Major Players

typescript
interface QuantumPlatform {
  name: string;
  qubits: number;
  type: string;
  access: string;
}

const quantumPlatforms: QuantumPlatform[] = [
  {
    name: 'IBM Quantum',
    qubits: 127,
    type: 'Superconducting',
    access: 'Cloud',
  },
  {
    name: 'Google Sycamore',
    qubits: 70,
    type: 'Superconducting',
    access: 'Limited',
  },
  {
    name: 'IonQ',
    qubits: 32,
    type: 'Trapped Ion',
    access: 'Cloud',
  },
  {
    name: 'Rigetti',
    qubits: 80,
    type: 'Superconducting',
    access: 'Cloud',
  },
];

console.table(quantumPlatforms);

Quantum Advantage

typescript
// Problems where quantum computers excel
class QuantumAdvantage {
  problems = {
    'Chemistry Simulation': {
      description: 'Simulating molecular interactions',
      quantumAdvantage: 'Exponential',
      status: 'Near-term',
    },
    'Optimization': {
      description: 'Finding optimal solutions',
      quantumAdvantage: 'Quadratic',
      status: 'Near-term',
    },
    'Machine Learning': {
      description: 'Training models faster',
      quantumAdvantage: 'Potential',
      status: 'Research',
    },
    'Cryptography': {
      description: 'Breaking encryption',
      quantumAdvantage: 'Exponential',
      status: 'Long-term',
    },
  };

  showAdvantages(): void {
    console.table(this.problems);
  }
}

const qa = new QuantumAdvantage();
qa.showAdvantages();

Getting Started with Quantum Computing

Learning Resources

  1. 1Qiskit - IBM's open-source quantum computing framework
  2. 2Cirq - Google's quantum computing library
  3. 3Quantum Katas - Microsoft's programming exercises
  4. 4IBM Quantum Experience - Free access to real quantum computers

Practice Problems

typescript
// Practice: Implement quantum teleportation protocol
class QuantumTeleportation {
  teleport(qubit: QubitState): QubitState {
    // In real quantum computing:
    // 1. Create Bell pair between Alice and Bob
    // 2. Alice performs Bell measurement on her qubit and the qubit to teleport
    // 3. Alice sends classical bits to Bob
    // 4. Bob applies corrections based on classical bits

    console.log('Quantum teleportation requires entanglement');
    return qubit; // Simplified
  }
}

// Practice: Implement quantum phase estimation
class QuantumPhaseEstimation {
  estimatePhase(unitary: any, eigenstate: any, precision: number): number {
    // QPE is a fundamental quantum algorithm
    console.log('Quantum phase estimation requires quantum circuits');
    return 0; // Simplified
  }
}

Challenges and Limitations

Technical Challenges

typescript
interface QuantumChallenge {
  challenge: string;
  description: string;
  currentSolution: string;
}

const challenges: QuantumChallenge[] = [
  {
    challenge: 'Decoherence',
    description: 'Qubits lose quantum properties due to environment',
    currentSolution: 'Error correction, isolation',
  },
  {
    challenge: 'Scalability',
    description: 'Difficulty scaling to many qubits',
    currentSolution: 'Modular architectures, better qubits',
  },
  {
    challenge: 'Error Rates',
    description: 'Quantum operations are noisy',
    currentSolution: 'Quantum error correction',
  },
  {
    challenge: 'Cooling',
    description: 'Some qubits require near-absolute zero temperatures',
    currentSolution: 'Advanced refrigeration, room-temperature qubits',
  },
];

console.table(challenges);

Conclusion

Quantum computing represents a fundamental shift in how we process information. By leveraging superposition, entanglement, and interference, quantum computers can solve certain problems exponentially faster than classical computers.

While we're still in the early stages of the quantum computing revolution, the progress has been remarkable. As a developer, understanding quantum computing basics will prepare you for the quantum future and help you identify problems where quantum algorithms can provide significant advantages.

Start experimenting with quantum simulators, learn quantum programming languages like Qiskit or Cirq, and be part of the quantum computing revolution. The future is quantum!

Enjoyed this essay? Share it.

Related essays

Next essay
Qiskit: Practical Quantum Programming with IBM's Framework