UNPKG

ts-quantum

Version:

TypeScript library for quantum mechanics calculations and utilities

349 lines 14 kB
/** * Quantum Hamiltonian Implementation * * This module provides a comprehensive implementation of quantum Hamiltonians, * which are the fundamental operators representing the total energy of quantum * systems. The Hamiltonian determines: * - System energy levels (eigenvalues) * - Stationary states (eigenvectors) * - Time evolution (through Schrödinger equation) * * Key features: * - Custom and predefined Hamiltonian types * - Time evolution generation * - Energy expectation calculation * - Support for common physical systems: * * Spin-1/2 in magnetic field * * Heisenberg spin chains * * Harmonic oscillators * * Custom interactions * * Mathematical form: * H = Σᵢ cᵢOᵢ where: * - cᵢ are complex coefficients * - Oᵢ are quantum operators * * @module quantum/hamiltonian */ import { MatrixOperator } from './operator'; import { validatePosDim } from '../utils/validation'; import { matrixExponential, scaleMatrix } from '../utils/matrixOperations'; import { PauliX, PauliY, PauliZ } from './gates'; import { composeOperators } from '../states/composite'; import { isHermitian } from '../utils/matrixOperations'; import * as math from 'mathjs'; /** * Core Hamiltonian class representing quantum system energy operators * * The Hamiltonian is the fundamental operator in quantum mechanics that: * 1. Determines the total energy of the system * 2. Generates time evolution through Schrödinger's equation * 3. Defines the system's energy eigenstates * * Features: * - Constructs Hamiltonians from operator terms * - Validates Hermiticity (optional) * - Generates time evolution operators * - Computes energy expectations * - Supports both time-dependent and time-independent cases * * Physical Significance: * - Eigenvalues represent possible energy measurements * - Eigenvectors represent stationary states * - Expectation values give average energy * - Time evolution U(t) = exp(-iHt/ħ) describes dynamics * * @extends MatrixOperator */ export class Hamiltonian extends MatrixOperator { hamiltonianType; terms; _timeDependent; constructor(dimension, terms, hamiltonianType = 'custom', timeDependent = false, requireHermitian = false) { validatePosDim(dimension); // Validate Hermiticity of individual terms and result if required if (requireHermitian) { for (const term of terms) { if (!term || !term.operator) { throw new Error('Invalid term in Hamiltonian'); } const termMatrix = term.operator.toMatrix(); try { if (!isHermitian(termMatrix)) { throw new Error('All terms must be Hermitian when requireHermitian is true'); } } catch (e) { if (e instanceof Error) { throw new Error(`Hermiticity check failed: ${e.message}`); } else { throw new Error('Hermiticity check failed: Unknown error'); } } if (term.coefficient && Math.abs(term.coefficient.im) > 1e-10) { throw new Error('All coefficients must be real when requireHermitian is true'); } } // Also check the final matrix try { const matrix = terms.reduce((acc, term) => { const termMatrix = term.operator.toMatrix(); const scaledTerm = scaleMatrix(termMatrix, term.coefficient); return acc.map((row, i) => row.map((elem, j) => math.add(elem, scaledTerm[i][j]))); }, Array(dimension).fill(null).map(() => Array(dimension).fill(null).map(() => math.complex(0, 0)))); if (!isHermitian(matrix)) { throw new Error('Combined Hamiltonian must be Hermitian when requireHermitian is true'); } } catch (e) { if (e instanceof Error) { throw new Error(`Hermiticity validation failed: ${e.message}`); } else { throw new Error('Hermiticity validation failed: Unknown error'); } } } // Initialize operator with sum of terms const matrix = terms.reduce((acc, term) => { const termMatrix = term.operator.toMatrix(); const scaledTerm = scaleMatrix(termMatrix, term.coefficient); return acc.map((row, i) => row.map((elem, j) => math.add(elem, scaledTerm[i][j]))); }, Array(dimension).fill(null).map(() => Array(dimension).fill(null).map(() => math.complex(0, 0)))); // Always use 'general' as the operator type, store Hamiltonian type separately super(matrix, 'general'); this.hamiltonianType = hamiltonianType; this.terms = [...terms]; this._timeDependent = timeDependent; } /** * Generates the quantum time evolution operator U(t) = exp(-iHt/ħ) * * The time evolution operator is fundamental in quantum mechanics: * - Transforms states from time t₀ to t: |ψ(t)⟩ = U(t-t₀)|ψ(t₀)⟩ * - Preserves probability (unitary) * - Satisfies group properties (U(t₁)U(t₂) = U(t₁+t₂)) * * Implementation: * 1. Validates time-independence * 2. Computes -iHt (using ħ = 1 units) * 3. Calculates matrix exponential * 4. Ensures unitarity * * @param time - Evolution time (in natural units) * @returns Unitary evolution operator U(t) * @throws Error for time-dependent Hamiltonians * @throws Error for invalid matrix structure */ getEvolutionOperator(time) { if (this._timeDependent) { throw new Error('Time-dependent Hamiltonians require numerical integration'); } // For a Hermitian matrix H, exp(-iHt) should be unitary // Create -iHt matrix const matrix = this.toMatrix(); // Explicitly verify matrix if (!matrix || matrix.length === 0 || !matrix[0] || matrix[0].length === 0) { throw new Error('Invalid Hamiltonian matrix'); } // Scale by -i*t (ħ = 1 units) const scaledMatrix = matrix.map(row => row.map(element => { // Multiply by -i*t return math.multiply(element, math.complex(0, -time)); })); // Compute matrix exponential const evolutionMatrix = matrixExponential(scaledMatrix); // Explicitly ensure it's properly formed const dim = this.dimension; for (let i = 0; i < dim; i++) { for (let j = 0; j < dim; j++) { if (!evolutionMatrix[i][j] || typeof evolutionMatrix[i][j].re !== 'number' || typeof evolutionMatrix[i][j].im !== 'number') { evolutionMatrix[i][j] = math.complex(i === j ? 1 : 0, 0); } } } // Return as unitary operator return new MatrixOperator(evolutionMatrix, 'unitary', false); } /** * Evolves a quantum state under this Hamiltonian for time t * * Implements Schrödinger equation evolution: * |ψ(t)⟩ = exp(-iHt/ħ)|ψ(0)⟩ * * Process: * 1. Validates state dimension * 2. Computes evolution operator U(t) * 3. Applies U(t) to initial state * 4. Ensures normalization (corrects numerical errors) * * Physical meaning: * - Describes how quantum state changes with time * - Preserves total probability (norm = 1) * - Maintains quantum superposition * * @param state - Initial quantum state |ψ(0)⟩ * @param time - Evolution time t * @returns Evolved state |ψ(t)⟩ * @throws Error if dimensions don't match */ evolveState(state, time) { if (state.dimension !== this.dimension) { throw new Error('State dimension does not match Hamiltonian dimension'); } const U = this.getEvolutionOperator(time); // Apply evolution operator to state const evolvedState = U.apply(state); // Ensure the state is properly normalized // This step is important to correct for any numerical errors try { const norm = evolvedState.norm(); if (norm > 1e-10 && Math.abs(norm - 1) > 1e-10) { return evolvedState.normalize(); } return evolvedState; } catch (e) { // If normalization fails, ensure we still return a valid state console.error("Normalization error in evolveState:", e instanceof Error ? e.message : "Unknown error"); return state; // Return original state if evolution fails } } /** * Computes the expectation value of energy for a given state * * The energy expectation value is: * ⟨E⟩ = ⟨ψ|H|ψ⟩ * * Physical significance: * - Average energy in state |ψ⟩ * - Real for physical (Hermitian) Hamiltonians * - Bounded by energy eigenvalues * - Constant for energy eigenstates * * @param state - Quantum state |ψ⟩ * @returns Complex energy expectation value * @throws Error if dimensions don't match */ expectationValue(state) { if (state.dimension !== this.dimension) { throw new Error('State dimension does not match Hamiltonian dimension'); } const Hpsi = this.apply(state); return state.innerProduct(Hpsi); } /** * Creates a spin-1/2 Hamiltonian in a magnetic field * * Implements the Zeeman Hamiltonian: * H = B·σ = Bxσx + Byσy + Bzσz * where: * - B = (Bx, By, Bz) is the magnetic field vector * - σ = (σx, σy, σz) are the Pauli matrices * * Physical significance: * - Describes magnetic dipole in field * - Energy splitting ΔE = 2|B| * - Precession frequency ω = 2|B| * - Eigenstates align/anti-align with B * * @param magneticField - [Bx, By, Bz] field components * @returns Spin Hamiltonian operator * * @example * // Create Hamiltonian for field along z-axis * const H = Hamiltonian.createSpinHamiltonian([0, 0, 1]); */ static createSpinHamiltonian(magneticField) { const [Bx, By, Bz] = magneticField; const terms = [ { coefficient: math.complex(Bx, 0), operator: PauliX }, { coefficient: math.complex(By, 0), operator: PauliY }, { coefficient: math.complex(Bz, 0), operator: PauliZ } ]; return new Hamiltonian(2, terms, 'spin'); } /** * Creates a Heisenberg interaction Hamiltonian for a spin chain * * Implements the Heisenberg model: * H = J Σᵢ Sᵢ·Sᵢ₊₁ * where: * - J is the exchange coupling constant * - Sᵢ are spin operators at site i * - Sum runs over nearest neighbors * * The interaction term Sᵢ·Sᵢ₊₁ expands as: * Sᵢ·Sᵢ₊₁ = SxᵢSxᵢ₊₁ + SyᵢSyᵢ₊₁ + SzᵢSzᵢ₊₁ * * Physical significance: * - Models magnetic interactions in materials * - J > 0: Ferromagnetic coupling (parallel spins favored) * - J < 0: Antiferromagnetic coupling (anti-parallel spins favored) * - Conserves total spin * - Supports quantum entanglement * * @param numSpins - Number of spins in the chain * @param coupling - Exchange coupling strength J * @returns Heisenberg Hamiltonian operator * @throws Error if numSpins < 2 * * @example * // Create antiferromagnetic chain of 3 spins * const H = Hamiltonian.createHeisenbergHamiltonian(3, -1.0); */ static createHeisenbergHamiltonian(numSpins, coupling) { if (numSpins < 2) { throw new Error('Heisenberg model requires at least 2 spins'); } const terms = []; const coeff = math.complex(coupling, 0); const dimension = Math.pow(2, numSpins); // For each pair of neighboring spins for (let i = 0; i < numSpins - 1; i++) { // Create terms for σx⊗σx + σy⊗σy + σz⊗σz for (const pauli of [PauliX, PauliY, PauliZ]) { // Create array of operators for tensor product const ops = Array(numSpins).fill(null).map(() => MatrixOperator.identity(2)); ops[i] = pauli; ops[i + 1] = pauli; try { const op = composeOperators(ops); // Verify operator dimension if (op.dimension !== dimension) { throw new Error(`Operator dimension mismatch: expected ${dimension}, got ${op.dimension}`); } terms.push({ coefficient: coeff, operator: op }); } catch (e) { console.error(`Error creating Heisenberg term: ${e instanceof Error ? e.message : "Unknown error"}`); // Create fallback identity term as placeholder terms.push({ coefficient: math.complex(0, 0), // Zero coefficient operator: MatrixOperator.identity(dimension) }); } } } // Validate we have terms before creating Hamiltonian if (terms.length === 0) { throw new Error('Failed to create any valid terms for Heisenberg Hamiltonian'); } return new Hamiltonian(dimension, terms, 'interaction'); } } //# sourceMappingURL=hamiltonian.js.map