Module:Harmonic entropy: Difference between revisions
m harmonic_entropy() improvements |
ArrowHead294 (talk | contribs) Remove already finished Todo |
||
| (13 intermediate revisions by 4 users not shown) | |||
| Line 1: | Line 1: | ||
local | local limits = require("Module:Limits") | ||
local rat = require("Module:Rational") | |||
local rat = require( | |||
local p = {} | local p = {} | ||
-- | -- Compute Harmonic Shannon entropy for an interval of `c` cents | ||
-- `c`, `deviation`: in cents | -- `c`, `deviation`: in cents | ||
-- `ratios`: an array of rational numbers | -- `ratios`: an array of rational numbers | ||
| Line 30: | Line 9: | ||
function p.harmonic_entropy(c, ratios, deviation, norm) | function p.harmonic_entropy(c, ratios, deviation, norm) | ||
norm = norm or function(ratio) | norm = norm or function(ratio) | ||
return math.sqrt(rat. | return math.sqrt(rat.benedetti_height(ratio)) | ||
end | end | ||
deviation = deviation or | deviation = deviation or 1200 * math.log(1.01, 2) | ||
ratios = ratios or | ratios = ratios | ||
or limits.integer_limit(200, function(ratio) | |||
if math.abs(rat.cents(ratio) - c) > 3 * deviation then | if math.abs(rat.cents(ratio) - c) > 3 * deviation then | ||
return 1/0 | return 1 / 0 | ||
end | end | ||
return norm(ratio) | return norm(ratio) | ||
end, | end, 100) | ||
local function gaussian(x) | |||
return math.exp(-x * x / (2 * deviation * deviation)) / (deviation * math.sqrt(2 * math.pi)) | |||
local function | |||
return math.exp(-x*x / (2*deviation*deviation)) / (deviation * math.sqrt(2*math.pi)) | |||
end | end | ||
local function | |||
return | local function weighted_gaussian(ratio) | ||
return gaussian(rat.cents(ratio) - c) / norm(ratio) | |||
end | end | ||
local | local q_norm = 0 | ||
for | for _, ratio in pairs(ratios) do | ||
q_norm = q_norm + weighted_gaussian(ratio) | |||
end | end | ||
local function | local function probability(ratio) | ||
return | return weighted_gaussian(ratio) / q_norm | ||
end | end | ||
local entropy = 0 | local entropy = 0 | ||
for | for _, ratio in pairs(ratios) do | ||
local | local p_i = probability(ratio) | ||
if | if p_i > 1e-5 then | ||
entropy = entropy - | entropy = entropy - p_i * math.log(p_i) | ||
end | end | ||
end | end | ||