UNPKG

ts-quantum

Version:

TypeScript library for quantum mechanics calculations and utilities

436 lines 16.7 kB
"use strict"; /** * Density matrix implementation for mixed quantum states and operations */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.negativity = exports.concurrence = exports.traceFidelity = exports.createPhaseFlipChannel = exports.createBitFlipChannel = exports.createPhaseDampingChannel = exports.createAmplitudeDampingChannel = exports.createDepolarizingChannel = exports.KrausChannel = exports.DensityMatrixOperator = void 0; const operator_1 = require("../operators/operator"); const matrixOperations_1 = require("../utils/matrixOperations"); const math = __importStar(require("mathjs")); const matrixOperations_2 = require("../utils/matrixOperations"); /** * Implementation of density matrix operations */ class DensityMatrixOperator { constructor(matrix) { this.objectType = 'operator'; // Inherits from IOperator this.type = 'hermitian'; // Validate matrix dimensions if (!matrix || matrix.length === 0) { throw new Error('Empty matrix provided'); } const dim = matrix.length; if (!matrix.every(row => row.length === dim)) { throw new Error('Matrix must be square'); } // Normalize matrix and create operator const normalizedMatrix = (0, matrixOperations_2.normalizeMatrix)(matrix); this.operator = new operator_1.MatrixOperator(normalizedMatrix, 'hermitian'); this.dimension = dim; // Validate trace = 1 const tr = this.trace(); // console.log("Trace: ", tr); // console.log("Trace real part: ", tr.re); // console.log("Trace imaginary part: ", tr.im); if (Math.abs(tr.re - 1) > 1e-10 || Math.abs(tr.im) > 1e-10) { throw new Error('Density matrix must have trace 1'); } // Validate positive semidefinite (simplified check via purity ≤ 1) if (this.purity() > 1 + 1e-10) { throw new Error('Density matrix must be positive semidefinite'); } } /** * Applies density matrix to state vector */ apply(state) { return this.operator.apply(state); } /** * Composes with another operator */ compose(other) { return this.operator.compose(other); } /** * Returns adjoint (same as original for density matrix) */ adjoint() { return this; // Density matrices are Hermitian } /** * Returns matrix representation */ toMatrix() { return this.operator.toMatrix(); } /** * Calculates trace of density matrix */ trace() { const matrix = this.toMatrix(); return matrix.reduce((sum, row, i) => math.add(sum, row[i]), math.complex(0, 0)); } /** * Calculates purity Tr(ρ²) */ purity() { // Calculate Tr(ρ²) by squaring the matrix and taking trace const matrix = this.toMatrix(); const matSquared = (0, matrixOperations_1.multiplyMatrices)(matrix, matrix); // Sum diagonal elements let trace = math.complex(0, 0); for (let i = 0; i < this.dimension; i++) { trace = math.add(trace, matSquared[i][i]); } // The purity should be real for a valid density matrix return trace.re; } /** * Calculates von Neumann entropy -Tr(ρ ln ρ) */ vonNeumannEntropy() { const { values } = this.eigenDecompose(); let entropy = 0; for (const value of values) { if (value.re > 1e-10) { // Only consider non-zero eigenvalues entropy -= value.re * Math.log(value.re); } } return entropy; } /** * Performs partial trace over specified subsystems */ partialTrace(dims, traceOutIndices) { return this.operator.partialTrace(dims, traceOutIndices); } /** * Scales density matrix by a complex number */ scale(scalar) { return this.operator.scale(scalar); } /** * Adds this density matrix with another operator */ add(other) { return this.operator.add(other); } /** * Returns eigenvalues and eigenvectors */ eigenDecompose() { return this.operator.eigenDecompose(); } /** * Creates density matrix from pure state */ static fromPureState(state) { const dim = state.dimension; const matrix = Array(dim).fill(null).map(() => Array(dim).fill(null).map(() => math.complex(0, 0))); // Compute |ψ⟩⟨ψ| for (let i = 0; i < dim; i++) { for (let j = 0; j < dim; j++) { matrix[i][j] = math.multiply(state.amplitudes[i], math.conj(state.amplitudes[j])); } } return new DensityMatrixOperator(matrix); } /** * Creates density matrix from mixed state */ static mixedState(states, probabilities) { if (states.length !== probabilities.length) { throw new Error('Number of states must match number of probabilities'); } if (Math.abs(probabilities.reduce((a, b) => a + b, 0) - 1) > 1e-10) { throw new Error('Probabilities must sum to 1'); } const dim = states[0].dimension; if (!states.every(s => s.dimension === dim)) { throw new Error('All states must have same dimension'); } // Compute Σᵢ pᵢ|ψᵢ⟩⟨ψᵢ| const matrix = Array(dim).fill(null).map(() => Array(dim).fill(null).map(() => math.complex(0, 0))); for (let k = 0; k < states.length; k++) { const state = states[k]; const prob = probabilities[k]; for (let i = 0; i < dim; i++) { for (let j = 0; j < dim; j++) { const term = math.multiply(math.multiply(state.amplitudes[i], math.conj(state.amplitudes[j])), math.complex(prob, 0)); matrix[i][j] = math.add(matrix[i][j], term); } } } return new DensityMatrixOperator(matrix); } /** * Returns tensor product with another operator */ tensorProduct(other) { return this.operator.tensorProduct(other); } /** * Calculates the operator norm */ norm() { return this.operator.norm(); } /** * Tests whether the density matrix is identically zero */ isZero(tolerance) { return this.operator.isZero(tolerance); } } exports.DensityMatrixOperator = DensityMatrixOperator; /** * Implementation of quantum channels using Kraus operators */ class KrausChannel { constructor(krausOperators) { this.krausOperators = krausOperators; // Validate non-empty array of operators if (!krausOperators || krausOperators.length === 0) { throw new Error('At least one Kraus operator is required'); } // Validate completeness relation Σᵢ Eᵢ†Eᵢ = I const dim = krausOperators[0].dimension; if (!krausOperators.every(op => op.dimension === dim)) { throw new Error('All Kraus operators must have same dimension'); } // Check completeness relation const sum = krausOperators.reduce((sum, Ei) => { const EiDagger = Ei.adjoint(); return addOperators(sum, EiDagger.compose(Ei)); }, createZeroOperator(dim)); const identity = createIdentityOperator(dim); const diff = subtractOperators(sum, identity); if (!diff.isZero()) { throw new Error('Kraus operators must satisfy completeness relation'); } } getOperators() { return [...this.krausOperators]; } apply(state) { const dim = this.krausOperators[0].dimension; const result = Array(dim).fill(null).map(() => Array(dim).fill(null).map(() => math.complex(0, 0))); // Apply channel: ρ' = Σᵢ EᵢρEᵢ† for (const Ei of this.krausOperators) { const EiDagger = Ei.adjoint(); const term = Ei.compose(state).compose(EiDagger); const termMatrix = term.toMatrix(); for (let i = 0; i < dim; i++) { for (let j = 0; j < dim; j++) { result[i][j] = math.add(result[i][j], termMatrix[i][j]); } } } return new DensityMatrixOperator(result); } } exports.KrausChannel = KrausChannel; // Helper functions for quantum channel creation /** * Creates a depolarizing channel * For qubits: ρ → (1-p)ρ + p/3(XρX + YρY + ZρZ) */ function createDepolarizingChannel(dimension, p) { if (p < 0 || p > 1) { throw new Error('Probability must be between 0 and 1'); } if (dimension !== 2) { throw new Error('Depolarizing channel currently only implemented for qubits (dimension=2)'); } // Kraus operators for depolarizing channel const krausOperators = []; // E0 = √(1-p) * I const E0Matrix = [ [math.complex(Math.sqrt(1 - p), 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(1 - p), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E0Matrix)); // E1 = √(p/3) * X const sqrt_p_3 = Math.sqrt(p / 3); const E1Matrix = [ [math.complex(0, 0), math.complex(sqrt_p_3, 0)], [math.complex(sqrt_p_3, 0), math.complex(0, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E1Matrix)); // E2 = √(p/3) * Y const E2Matrix = [ [math.complex(0, 0), math.complex(0, -sqrt_p_3)], [math.complex(0, sqrt_p_3), math.complex(0, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E2Matrix)); // E3 = √(p/3) * Z const E3Matrix = [ [math.complex(sqrt_p_3, 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(-sqrt_p_3, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E3Matrix)); return new KrausChannel(krausOperators); } exports.createDepolarizingChannel = createDepolarizingChannel; /** * Creates an amplitude damping channel * Models energy decay: |1⟩ → |0⟩ with probability γ */ function createAmplitudeDampingChannel(gamma) { if (gamma < 0 || gamma > 1) { throw new Error('Damping parameter must be between 0 and 1'); } // Kraus operators for amplitude damping const krausOperators = []; // E0 = |0⟩⟨0| + √(1-γ)|1⟩⟨1| const E0Matrix = [ [math.complex(1, 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(1 - gamma), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E0Matrix)); // E1 = √γ|0⟩⟨1| const E1Matrix = [ [math.complex(0, 0), math.complex(Math.sqrt(gamma), 0)], [math.complex(0, 0), math.complex(0, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E1Matrix)); return new KrausChannel(krausOperators); } exports.createAmplitudeDampingChannel = createAmplitudeDampingChannel; /** * Creates a phase damping channel * Models pure dephasing without energy loss */ function createPhaseDampingChannel(gamma) { if (gamma < 0 || gamma > 1) { throw new Error('Damping parameter must be between 0 and 1'); } // Kraus operators for phase damping const krausOperators = []; // E0 = |0⟩⟨0| + √(1-γ)|1⟩⟨1| const E0Matrix = [ [math.complex(1, 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(1 - gamma), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E0Matrix)); // E1 = √γ|1⟩⟨1| const E1Matrix = [ [math.complex(0, 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(gamma), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E1Matrix)); return new KrausChannel(krausOperators); } exports.createPhaseDampingChannel = createPhaseDampingChannel; /** * Creates a bit flip channel * Applies X gate with probability p: ρ → (1-p)ρ + pXρX */ function createBitFlipChannel(p) { if (p < 0 || p > 1) { throw new Error('Probability must be between 0 and 1'); } // Kraus operators for bit flip channel const krausOperators = []; // E0 = √(1-p) * I const E0Matrix = [ [math.complex(Math.sqrt(1 - p), 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(1 - p), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E0Matrix)); // E1 = √p * X const sqrtP = Math.sqrt(p); const E1Matrix = [ [math.complex(0, 0), math.complex(sqrtP, 0)], [math.complex(sqrtP, 0), math.complex(0, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E1Matrix)); return new KrausChannel(krausOperators); } exports.createBitFlipChannel = createBitFlipChannel; /** * Creates a phase flip channel * Applies Z gate with probability p: ρ → (1-p)ρ + pZρZ */ function createPhaseFlipChannel(p) { if (p < 0 || p > 1) { throw new Error('Probability must be between 0 and 1'); } // Kraus operators for phase flip channel const krausOperators = []; // E0 = √(1-p) * I const E0Matrix = [ [math.complex(Math.sqrt(1 - p), 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(Math.sqrt(1 - p), 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E0Matrix)); // E1 = √p * Z const sqrtP = Math.sqrt(p); const E1Matrix = [ [math.complex(sqrtP, 0), math.complex(0, 0)], [math.complex(0, 0), math.complex(-sqrtP, 0)] ]; krausOperators.push(new operator_1.MatrixOperator(E1Matrix)); return new KrausChannel(krausOperators); } exports.createPhaseFlipChannel = createPhaseFlipChannel; // Helper functions for quantum operations function addOperators(a, b) { if (a.dimension !== b.dimension) { throw new Error('Operator dimensions do not match'); } const matrixA = a.toMatrix(); const matrixB = b.toMatrix(); const sumMatrix = matrixA.map((row, i) => row.map((elem, j) => math.add(elem, matrixB[i][j]))); return new operator_1.MatrixOperator(sumMatrix); } function subtractOperators(a, b) { if (a.dimension !== b.dimension) { throw new Error('Operator dimensions do not match'); } const matrixA = a.toMatrix(); const matrixB = b.toMatrix(); const diffMatrix = matrixA.map((row, i) => row.map((elem, j) => math.subtract(elem, matrixB[i][j]))); return new operator_1.MatrixOperator(diffMatrix); } function createIdentityOperator(dimension) { const matrix = Array(dimension).fill(null).map((_, i) => Array(dimension).fill(null).map((_, j) => i === j ? math.complex(1, 0) : math.complex(0, 0))); return new operator_1.MatrixOperator(matrix, 'unitary'); } function createZeroOperator(dimension) { const matrix = Array(dimension).fill(null).map(() => Array(dimension).fill(null).map(() => math.complex(0, 0))); return new operator_1.MatrixOperator(matrix); } // Note: Entanglement measures have been moved to information.ts // This allows better organization of quantum information metrics // Re-export entanglement measures from information.ts var information_1 = require("../utils/information"); Object.defineProperty(exports, "traceFidelity", { enumerable: true, get: function () { return information_1.traceFidelity; } }); Object.defineProperty(exports, "concurrence", { enumerable: true, get: function () { return information_1.concurrence; } }); Object.defineProperty(exports, "negativity", { enumerable: true, get: function () { return information_1.negativity; } }); //# sourceMappingURL=densityMatrix.js.map