Skip to content

Instantly share code, notes, and snippets.

@HyperCrowd
Created February 21, 2025 19:51
Show Gist options
  • Save HyperCrowd/fb511785cf1c3454948518be65363645 to your computer and use it in GitHub Desktop.
Save HyperCrowd/fb511785cf1c3454948518be65363645 to your computer and use it in GitHub Desktop.
Gibbs-Shannon Entropy
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