Created
February 21, 2025 19:51
-
-
Save HyperCrowd/fb511785cf1c3454948518be65363645 to your computer and use it in GitHub Desktop.
Gibbs-Shannon Entropy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PhaseSpace { | |
/** | |
* Represents phase space and allows calculating its volume, area, and defining distributions | |
* @param {number} positionMinimum Minimum position | |
* @param {number} positionMaximum Maximum position | |
* @param {number} momentumMinimum Minimum momentum | |
* @param {number} momentumMaximum Maximum momentum | |
* @param {number} positionSpacing Distance between positions | |
* @param {number} momentumSpacing Distance between momentums | |
*/ | |
constructor(positionMinimum, positionMaximum, momentumMinimum, momentumMaximum, positionSpacing, momentumSpacing) { | |
this.positionMinimum = positionMinimum | |
this.positionMaximum = positionMaximum | |
this.momentumMinimum = momentumMinimum | |
this.momentumMaximum = momentumMaximum | |
this.positionSpacing = positionSpacing | |
this.momentumSpacing = momentumSpacing | |
// Volume corresponds to the number of microstates given current parameters | |
this.microstates = 0 | |
// Generate the phase space grid (q, p pairs) | |
this.pairs = [] | |
for (let q = positionMinimum; q <= positionMaximum; q += positionSpacing) { | |
let row = [] | |
for (let p = momentumMinimum; p <= momentumMaximum; p += momentumSpacing) { | |
this.microstates += positionSpacing * momentumSpacing | |
row.push([q, p]) // Represent each (q, p) pair in the grid | |
} | |
this.pairs.push(row) | |
} | |
this.count = this.pairs.length | |
} | |
/** | |
* Calculate the volume of phase space | |
* @param {number} positionSpacing Distance between positions | |
* @param {number} momentumSpacing Distance between momentums | |
* @returns {number} (max q - min q) * (max p - min p) | |
*/ | |
getVolume(positionSpacing = this.positionMaximum - this.positionMinimum, momentumSpacing = this.momentumMaximum - this.momentumMinimum) { | |
return positionSpacing * momentumSpacing | |
} | |
/** | |
* Generate a uniform probability distribution | |
* @returns {number[][]} Uniform distribution (same probability for each grid point) | |
*/ | |
getUniformDistribution () { | |
const result = []; | |
for (let i = 0; i < this.pairs.length; i++) { | |
let row = [] | |
let pairLength = this.pairs[i].length | |
for (let j = 0; j < pairLength; j++) { | |
row.push(1 / (this.pairs.length * pairLength)) | |
} | |
result.push(row) | |
} | |
return result | |
} | |
/** | |
* Function to calculate phase space volume using variations of the symplectic form | |
* @param {number} positionSpacing Distance between positions | |
* @param {number} momentumSpacing Distance between momentums | |
* @returns {number} The sum of the areas of all small regions | |
*/ | |
getMicrostateCount(positionSpacing = this.positionSpacing, momentumSpacing = this.momentumSpacing) { | |
let volume = 0 | |
for (let q = this.positionMinimum; q <= this.positionMaximum; q += positionSpacing) { | |
for (let p = this.momentumMinimum; p <= this.momentumMaximum; p += momentumSpacing) { | |
volume += positionSpacing * momentumSpacing | |
} | |
} | |
return volume | |
} | |
/** | |
* Calculate Gibbs-Shannon entropy for a general probability distribution | |
* @param {number[][]} probabilityDistribution Distribution of each grid point | |
* @returns {number} Gibbs-Shannon Entropy | |
*/ | |
calculateGibbsShannonEntropy(probabilityDistribution = this.getUniformDistribution()) { | |
let entropy = 0; | |
// Loop over all points in the phase space grid | |
for (let i = 0; i < this.pairs.length; i++) { | |
for (let j = 0; j < this.pairs[i].length; j++) { | |
// Get the probability density at (q, p) | |
let rho = probabilityDistribution[i][j] | |
// Avoid log(0) since the log of zero is undefined | |
if (rho > 0) { | |
// Add the contribution to entropy | |
entropy -= rho * Math.log(rho) | |
} | |
} | |
} | |
// Multiply by the grid cell area (positionSpacing * momentumSpacing) to account for phase space volume | |
entropy *= this.positionSpacing * this.momentumSpacing | |
return entropy | |
} | |
/** | |
* Calculate Gibbs-Shannon entropy for a uniform distribution | |
* @returns {number} Gibbs-Shannon Entropy | |
*/ | |
calculateGibbsShannonEntropyUniform() { | |
// Calculate the volume of phase space (product of ranges of q and p) | |
let volume = (this.positionMaximum - this.positionMinimum) * (this.momentumMaximum - this.momentumMinimum) | |
// Calculate the number of grid cells in the q and p directions | |
let numCellsQ = Math.floor((this.positionMaximum - this.positionMinimum) / this.positionSpacing) | |
let numCellsP = Math.floor((this.momentumMaximum - this.momentumMinimum) / this.momentumSpacing) | |
// Phase space volume (or number of states) is the area of the grid | |
let phaseSpaceVolume = numCellsQ * numCellsP * this.positionSpacing * this.momentumSpacing | |
// For a uniform distribution, the entropy is simply log(phaseSpaceVolume) | |
let entropy = Math.log(phaseSpaceVolume) | |
return entropy | |
} | |
/** | |
* Reconstruct the measure μ(U) using the supremum of the entropy functional | |
* @returns {number} μ(U) | |
*/ | |
reconstructMeasureFromEntropy() { | |
// Step 1: Calculate the volume of phase space (this is the region U) | |
let volume = (this.positionMaximum - this.positionMinimum) * (this.momentumMaximum - this.momentumMinimum) | |
// Step 2: Calculate the number of grid cells in the q and p directions | |
let numCellsQ = Math.floor((this.positionMaximum - this.positionMinimum) / this.positionSpacing) | |
let numCellsP = Math.floor((this.momentumMaximum - this.momentumMinimum) / this.momentumSpacing) | |
// Step 3: Calculate the phase space volume (number of states) | |
let phaseSpaceVolume = numCellsQ * numCellsP * this.positionSpacing * this.momentumSpacing | |
// Step 4: The supremum of the entropy functional is reached when the distribution is uniform | |
// For a uniform distribution, the measure μ(U) is simply the phase space volume | |
let measure = phaseSpaceVolume | |
return measure | |
} | |
/** | |
* Normalize the probability distribution to make sure it sums to 1 | |
* @param {number[][]} probabilityDistribution Distribution of each grid point | |
* @returns {number[][]} Normalized probability distribution | |
*/ | |
normalizeProbabilityDistribution(probabilityDistribution = this.getUniformDistribution()) { | |
let sum = 0; | |
// Calculate the total sum of all probability values | |
for (let i = 0; i < probabilityDistribution.length; i++) { | |
for (let j = 0; j < probabilityDistribution[i].length; j++) { | |
sum += probabilityDistribution[i][j] | |
} | |
} | |
// Normalize each probability value | |
for (let i = 0; i < probabilityDistribution.length; i++) { | |
for (let j = 0; j < probabilityDistribution[i].length; j++) { | |
probabilityDistribution[i][j] /= sum | |
} | |
} | |
} | |
/** | |
* Function to calculate the supremum of the entropy functional (S) for the uniform distribution | |
* @param {number} positionSpacing Distance between positions | |
* @param {number} momentumSpacing Distance between momentums | |
* @returns {number} μ(U) | |
*/ | |
calculateSupremumEntropy(positionSpacing = this.positionSpacing, momentumSpacing = this.momentumSpacing) { | |
// Step 1: Calculate the volume of the phase space region (U) | |
let volume = this.getVolume(positionSpacing, momentumSpacing) | |
// Step 2: The entropy for a uniform distribution is log(volume) | |
let entropy = Math.log(volume) | |
// Step 3: Exponentiate the entropy to obtain the measure μ(U) | |
let measure = Math.exp(entropy) // This is e^(sup S), which is the measure μ(U) | |
return measure | |
} | |
} | |
/*********** | |
* EXAMPLE * | |
***********/ | |
// Define the phase space boundaries and grid spacing | |
let positionMinimum = 0 | |
let positionMaximum = 5 | |
let momentumMinimum = -5 | |
let momentumMaximum = 5 | |
let positionSpacing = 0.1 | |
let momentumSpacing = 0.1 | |
// Define the phase space boundaries | |
const phaseSpace = new PhaseSpace( | |
positionMinimum, | |
positionMaximum, | |
momentumMinimum, | |
momentumMaximum, | |
positionSpacing, | |
momentumSpacing | |
) | |
// Generate report about the phase space | |
const report = { | |
microstatesAt: { | |
default: phaseSpace.microstates, | |
'0.25x0.25': phaseSpace.getMicrostateCount(0.25, 0.25), | |
'0.5x0.5': phaseSpace.getMicrostateCount(0.5, 0.5), | |
'1x1': phaseSpace.getMicrostateCount(1, 1), | |
'2x2': phaseSpace.getMicrostateCount(2, 2), | |
'3x3': phaseSpace.getMicrostateCount(3, 3), | |
'4x4': phaseSpace.getMicrostateCount(4, 4), | |
'5x5': phaseSpace.getMicrostateCount(5, 5) | |
}, | |
volume: phaseSpace.getVolume(), | |
gibbsShannonEntropy: { | |
general: phaseSpace.calculateGibbsShannonEntropy(), | |
uniform: phaseSpace.calculateGibbsShannonEntropyUniform() | |
}, | |
measures: { | |
reconstructed: phaseSpace.reconstructMeasureFromEntropy(), | |
supremum: { | |
default: phaseSpace.calculateSupremumEntropy(), | |
'0.25x0.25': phaseSpace.calculateSupremumEntropy(0.25, 0.25), | |
'0.5x0.5': phaseSpace.calculateSupremumEntropy(0.5, 0.5), | |
'1x1': phaseSpace.calculateSupremumEntropy(1, 1), | |
'2x2': phaseSpace.calculateSupremumEntropy(2, 2), | |
'3x3': phaseSpace.calculateSupremumEntropy(3, 3), | |
'4x4': phaseSpace.calculateSupremumEntropy(4, 4), | |
'5x5': phaseSpace.calculateSupremumEntropy(5, 5) | |
} | |
} | |
} | |
console.log(report) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment