Module:Interval

From Xenharmonic Wiki
Jump to navigation Jump to search

This module provides several functions to work with interval-related math. Currently, it only exists to calculate the harmonic entropy.

Namely, the functions in this module can be called from other modules by using require('Module:Interval') and calling the _-prefixed functions.

Functions

  • harmonic_entropy(c, ratios, deviation, norm) computes harmonic Shannon entropy of an interval of c cents across ratios with a Gaussian with standard deviation (also in cents) and a norm associated with the ratios.

Documentation transcluded from /doc
-- TODO: this module should just be called harmonic entropy!
local limits = require("Module:Limits")
local rat = require("Module:Rational")
local p = {}

-- compute harmonic Shannon entropy for an interval of `c` cents
-- `c`, `deviation`: in cents
-- `ratios`: an array of rational numbers
-- `norm`: a function of rational numbers
function p.harmonic_entropy(c, ratios, deviation, norm)
	norm = norm or function(ratio)
		return math.sqrt(rat.benedetti_height(ratio))
	end
	deviation = deviation or 17
	ratios = ratios
		or limits.integer_limit(200, function(ratio)
			if math.abs(rat.cents(ratio) - c) > 3 * deviation then
				return 1 / 0
			end
			return norm(ratio)
		end, 100)

	local function gaussian(x)
		return math.exp(-x * x / (2 * deviation * deviation)) / (deviation * math.sqrt(2 * math.pi))
	end

	local function weighted_gaussian(ratio)
		return gaussian(rat.cents(ratio) - c) / norm(ratio)
	end

	local q_norm = 0
	for _, ratio in pairs(ratios) do
		q_norm = q_norm + weighted_gaussian(ratio)
	end

	local function probability(ratio)
		return weighted_gaussian(ratio) / q_norm
	end

	local entropy = 0
	for _, ratio in pairs(ratios) do
		local p_i = probability(ratio)
		if p_i > 1e-5 then
			entropy = entropy - p_i * math.log(p_i)
		end
	end
	return entropy
end

return p