Module:Harmonic entropy

Revision as of 13:54, 10 October 2022 by Plumtree (talk | contribs) (harmonic_entropy() implemented)
Module documentation[view] [edit] [history] [purge]
This module primarily serves as a library for other modules and has no corresponding template.

This module provides a means to calculate harmonic Shannon entropy of a particular interval.


Introspection summary for Module:Harmonic entropy 
Functions provided (3)
Line Function Params Description
7 to_cents (invokable) (frame)
12 _to_cents (ratio, prec)
29 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.
Lua modules required (3)
Variable Module Functions used
getArgs Module:Arguments getArgs
rat Module:Rational beneditti_height
cents
u Module:Utils eval_num_arg
_log
_round

local getArgs = require('Module:Arguments').getArgs
local u = require('Module:Utils')
local rat = require('Module:Rational')
local p = {}

-- return measure in cents of an interval ratio, rounded to prec decimal places
function p.to_cents(frame)
	local args = getArgs(frame)
	return p._to_cents(args[1], args[2])
end	

function p._to_cents(ratio, prec)
	-- ratio defaults to 1
	ratio = u.eval_num_arg(ratio, 1)
	-- prec defaults to nil
	prec = u.eval_num_arg(prec)
	local result = 1200*u._log(ratio), prec
	if prec == nil then
		return result
	else
		return u._round(result, prec)
	end
end

-- compute Shannon harmonic 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)
	deviation = deviation or 17
	norm = norm or function(ratio)
		return math.sqrt(rat.beneditti_height(ratio))
	end
	
	local function S(x)
		return math.exp(-x*x / (2*deviation*deviation)) / (deviation * math.sqrt(2*math.pi))
	end
	local function Q(ratio)
		return S(rat.cents(ratio) - c) / norm(ratio)
	end
	
	local Q_norm = 0
	for i, ratio in ipairs(ratios) do
		Q_norm = Q_norm + Q(ratio)
	end
	
	local function P(ratio)
		return Q(ratio) / Q_norm
	end
	
	local entropy = 0
	for i, ratio in ipairs(ratios) do
		local P_i = P(ratio)
		if P_i > 1e-5 then
			entropy = entropy - P_i * math.log(P_i) / math.log(2)
		end
	end
	return entropy
end

return p