ts-quantum
Version:
TypeScript library for quantum mechanics calculations and utilities
349 lines • 13.5 kB
JavaScript
;
/**
* Intertwiner Basis Construction
*
* This module constructs orthonormal basis states for intertwiner spaces using
* Clebsch-Gordan coefficients and the StateVector framework. It handles the
* coupling of angular momentum at spin network nodes.
*/
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.getFourSpinHalfBasis = exports.constructBasisVector = exports.constructBasis = void 0;
const stateVector_1 = require("../states/stateVector");
const composition_1 = require("../angularMomentum/composition");
const matrixOperations_1 = require("../utils/matrixOperations");
const core_1 = require("./core");
const math = __importStar(require("mathjs"));
/**
* Construct complete orthonormal basis for intertwiner space
*
* @param edgeSpins Array of angular momentum quantum numbers for node edges
* @returns Complete intertwiner space with orthonormal basis
* @throws Error if edge spins are invalid or unsupported valence
*/
function constructBasis(edgeSpins) {
validateEdgeSpins(edgeSpins);
const valence = edgeSpins.length;
const dimension = (0, core_1.calculateDimension)(edgeSpins);
if (dimension === 0) {
return {
dimension: 0,
basisStates: [],
edgeSpins: [...edgeSpins],
totalJ: 0
};
}
let basisStates = [];
switch (valence) {
case 2:
basisStates = constructTwoValentBasis(edgeSpins);
break;
case 3:
basisStates = constructThreeValentBasis(edgeSpins);
break;
case 4:
basisStates = constructFourValentBasis(edgeSpins);
break;
default:
throw new Error(`Basis construction for ${valence}-valent nodes not implemented`);
}
// Orthonormalize basis states
const orthonormalBasis = orthonormalizeBasis(basisStates);
return {
dimension: orthonormalBasis.length,
basisStates: orthonormalBasis,
edgeSpins: [...edgeSpins],
totalJ: 0
};
}
exports.constructBasis = constructBasis;
/**
* Construct single basis vector for 4-valent node with given intermediate coupling
*
* @param j1 First edge angular momentum
* @param j2 Second edge angular momentum
* @param j3 Third edge angular momentum
* @param j4 Fourth edge angular momentum
* @param intermediateJ Intermediate angular momentum coupling
* @returns Basis state or null if coupling is invalid
*/
function constructBasisVector(j1, j2, j3, j4, intermediateJ) {
// Validate intermediate coupling is allowed
const j12_values = (0, core_1.allowedIntermediateSpins)(j1, j2);
const j34_values = (0, core_1.allowedIntermediateSpins)(j3, j4);
if (!j12_values.includes(intermediateJ) || !j34_values.includes(intermediateJ)) {
return null;
}
// Calculate dimensions
const dims = [j1, j2, j3, j4].map(j => Math.floor(2 * j + 1));
const totalDim = dims.reduce((prod, dim) => prod * dim, 1);
// Generate m-value arrays for each edge
const mValues = [j1, j2, j3, j4].map(j => generateMValues(j));
// Build coefficient array using CG coefficients
const coefficients = new Array(totalDim).fill(0);
// Iterate over all m-value combinations
for (const m1 of mValues[0]) {
for (const m2 of mValues[1]) {
// First coupling: j1 ⊗ j2 → intermediateJ
const m12 = m1 + m2;
if (Math.abs(m12) > intermediateJ + 1e-10)
continue;
const cg1 = (0, composition_1.clebschGordan)(j1, m1, j2, m2, intermediateJ, m12);
if (math.abs(cg1).re < 1e-10)
continue;
for (const m3 of mValues[2]) {
for (const m4 of mValues[3]) {
// Second coupling: j3 ⊗ j4 → intermediateJ
const m34 = m3 + m4;
if (math.abs(m34) > intermediateJ + 1e-10)
continue;
// For total J=0, need m12 + m34 = 0
if (math.abs(m12 + m34) > 1e-10)
continue;
const cg2 = (0, composition_1.clebschGordan)(j3, m3, j4, m4, intermediateJ, m34);
if (math.abs(cg2).re < 1e-10)
continue;
// Final coupling: intermediateJ ⊗ intermediateJ → 0
const cgFinal = (0, composition_1.clebschGordan)(intermediateJ, m12, intermediateJ, m34, 0, 0);
if (math.abs(cgFinal).re < 1e-10)
continue;
// Calculate tensor product index
const index = calculateTensorIndex([m1, m2, m3, m4], [j1, j2, j3, j4]);
if (index >= 0 && index < totalDim) {
coefficients[index] += cg1.re * cg2.re * cgFinal.re;
}
}
}
}
}
// Check if vector is non-zero
const norm = Math.sqrt(coefficients.reduce((sum, c) => sum + c * c, 0));
if (norm < 1e-10) {
return null;
}
// Create StateVector with normalized coefficients
const complexCoeffs = coefficients.map(c => math.complex(c / norm, 0));
const stateVector = buildStateVector(complexCoeffs, dims);
return {
intermediateJ,
stateVector,
recouplingScheme: createRecouplingScheme(j1, j2, j3, j4),
normalization: norm
};
}
exports.constructBasisVector = constructBasisVector;
/**
* Optimized basis for four spin-1/2 edges (2-dimensional space)
*
* @returns Complete intertwiner space for four spin-1/2 edges
*/
function getFourSpinHalfBasis() {
const edgeSpins = [0.5, 0.5, 0.5, 0.5];
// First basis state: (j12=0) ⊗ (j34=0) → j=0
const basis1 = constructBasisVector(0.5, 0.5, 0.5, 0.5, 0);
// Second basis state: (j12=1) ⊗ (j34=1) → j=0
const basis2 = constructBasisVector(0.5, 0.5, 0.5, 0.5, 1);
const basisStates = [basis1, basis2].filter(state => state !== null);
// Orthonormalize basis
const orthonormalBasis = orthonormalizeBasis(basisStates);
return {
dimension: orthonormalBasis.length,
basisStates: orthonormalBasis,
edgeSpins,
totalJ: 0
};
}
exports.getFourSpinHalfBasis = getFourSpinHalfBasis;
// ==================== Helper Functions ====================
/**
* Build StateVector from coefficient array and dimensions
*/
function buildStateVector(coefficients, dimensions) {
const totalDim = dimensions.reduce((prod, dim) => prod * dim, 1);
if (coefficients.length !== totalDim) {
throw new Error(`Coefficient array length ${coefficients.length} does not match total dimension ${totalDim}`);
}
return new stateVector_1.StateVector(totalDim, coefficients, 'intertwiner', { dimensions, tensorProduct: true });
}
/**
* Generate array of m-values for given angular momentum j
*/
function generateMValues(j) {
const dim = Math.floor(2 * j + 1);
const mValues = [];
for (let i = 0; i < dim; i++) {
mValues.push(j - i);
}
return mValues;
}
/**
* Calculate linear index in tensor product space from m-value tuple
*/
function calculateTensorIndex(mValues, jValues) {
if (mValues.length !== jValues.length) {
throw new Error('mValues and jValues arrays must have same length');
}
let index = 0;
let stride = 1;
// Calculate index in reverse order (rightmost varies fastest)
for (let i = jValues.length - 1; i >= 0; i--) {
const j = jValues[i];
const m = mValues[i];
const mIndex = Math.floor(j - m); // Convert m to array index
index += mIndex * stride;
stride *= Math.floor(2 * j + 1);
}
return index;
}
/**
* Orthonormalize basis states using existing quantum module infrastructure
*/
function orthonormalizeBasis(basisStates) {
if (basisStates.length === 0) {
return [];
}
// Extract StateVectors
const stateVectors = basisStates.map(state => state.stateVector);
// Orthogonalize using validated algorithm
const orthogonalizedVectors = (0, matrixOperations_1.orthogonalizeStateVectors)(stateVectors);
// Reconstruct basis states with orthogonalized vectors
return orthogonalizedVectors.map((vector, i) => ({
...basisStates[i],
stateVector: vector,
normalization: 1.0 // Vectors are now normalized
}));
}
/**
* Validate input edge spins
*/
function validateEdgeSpins(edgeSpins) {
if (!Array.isArray(edgeSpins) || edgeSpins.length < 2) {
throw new Error('Edge spins must be array with at least 2 elements');
}
for (const [i, j] of edgeSpins.entries()) {
if (typeof j !== 'number' || j < 0) {
throw new Error(`Invalid edge spin at index ${i}: ${j}`);
}
// Check if j is integer or half-integer
const doubleJ = 2 * j;
if (Math.abs(doubleJ - Math.round(doubleJ)) > 1e-10) {
throw new Error(`Edge spin at index ${i} must be integer or half-integer: ${j}`);
}
}
}
/**
* Create recoupling scheme string for documentation
*/
function createRecouplingScheme(j1, j2, j3, j4) {
return `(${j1},${j2})⊗(${j3},${j4})→0`;
}
/**
* Construct basis for 2-valent node (identity coupling)
*/
function constructTwoValentBasis(edgeSpins) {
const [j1, j2] = edgeSpins;
if (Math.abs(j1 - j2) > 1e-10) {
return []; // No intertwiner for different spins
}
// Create identity coupling state
const dim = Math.floor(2 * j1 + 1);
const coefficients = Array(dim * dim).fill(math.complex(0, 0));
// Set diagonal elements
for (let i = 0; i < dim; i++) {
coefficients[i * dim + i] = math.complex(1 / Math.sqrt(dim), 0);
}
const stateVector = buildStateVector(coefficients, [dim, dim]);
return [{
intermediateJ: j1,
stateVector,
recouplingScheme: `(${j1},${j2})→0`,
normalization: 1.0
}];
}
/**
* Construct basis for 3-valent node (single coupling)
*/
function constructThreeValentBasis(edgeSpins) {
const [j1, j2, j3] = edgeSpins;
if (!(0, core_1.triangleInequality)(j1, j2, j3)) {
return [];
}
// For 3-valent node, there's exactly one basis state
const dims = [j1, j2, j3].map(j => Math.floor(2 * j + 1));
const totalDim = dims.reduce((prod, dim) => prod * dim, 1);
const coefficients = new Array(totalDim).fill(math.complex(0, 0));
// Generate m-values
const mValues = [j1, j2, j3].map(j => generateMValues(j));
// Build CG coefficient sum
for (const m1 of mValues[0]) {
for (const m2 of mValues[1]) {
for (const m3 of mValues[2]) {
// Check m-conservation
if (math.abs(m1 + m2 + m3) > 1e-10)
continue;
const cg = (0, composition_1.clebschGordan)(j1, m1, j2, m2, j3, m3);
if (math.abs(cg).re < 1e-10)
continue;
const index = calculateTensorIndex([m1, m2, m3], [j1, j2, j3]);
if (index >= 0 && index < totalDim) {
coefficients[index] = math.complex(cg.re, 0);
}
}
}
}
// Normalize
const norm = Math.sqrt(coefficients.reduce((sum, c) => sum + math.abs(c) ** 2, 0));
if (norm < 1e-10) {
return [];
}
const normalizedCoeffs = coefficients.map(c => math.divide(c, math.complex(norm, 0)));
const stateVector = buildStateVector(normalizedCoeffs, dims);
return [{
intermediateJ: 0, // 3-valent always couples to j=0
stateVector,
recouplingScheme: `(${j1},${j2},${j3})→0`,
normalization: norm
}];
}
/**
* Construct basis for 4-valent node (main case)
*/
function constructFourValentBasis(edgeSpins) {
const [j1, j2, j3, j4] = edgeSpins;
// Get allowed intermediate spins
const j12_values = (0, core_1.allowedIntermediateSpins)(j1, j2);
const j34_values = (0, core_1.allowedIntermediateSpins)(j3, j4);
// Find common intermediate values
const commonJs = j12_values.filter(j12 => j34_values.some(j34 => Math.abs(j12 - j34) < 1e-10));
const basisStates = [];
for (const intermediateJ of commonJs) {
const basisState = constructBasisVector(j1, j2, j3, j4, intermediateJ);
if (basisState !== null) {
basisStates.push(basisState);
}
}
return basisStates;
}
//# sourceMappingURL=basis.js.map