Module:Limits: Difference between revisions
Distinct consistency limit: bugfix |
merge changes from dev |
||
Line 1: | Line 1: | ||
local rat = require( | local rat = require("Module:Rational") | ||
local ET = require( | local ET = require("Module:ET") | ||
local p = {} | local p = {} | ||
Line 13: | Line 13: | ||
a = rat.modulo_mul(a, equave) | a = rat.modulo_mul(a, equave) | ||
local a_key = rat.as_ratio(a) | local a_key = rat.as_ratio(a) | ||
local b = rat.new(q, n) | local b = rat.new(q, n) | ||
b = rat.modulo_mul(b, equave) | b = rat.modulo_mul(b, equave) | ||
local b_key = rat.as_ratio(b) | local b_key = rat.as_ratio(b) | ||
if previous[a_key] == nil then | if previous[a_key] == nil then | ||
ratios[a_key] = a | ratios[a_key] = a | ||
Line 41: | Line 41: | ||
-- if a function `norm` and a number `max_norm` are provided, the output will be additionally restricted | -- if a function `norm` and a number `max_norm` are provided, the output will be additionally restricted | ||
function p.integer_limit(q, norm, max_norm) | function p.integer_limit(q, norm, max_norm) | ||
local check_norm = type(norm) == | local check_norm = type(norm) == "function" and type(max_norm) == "number" | ||
local ratios = {} | local ratios = {} | ||
for n = 1, q do | for n = 1, q do | ||
Line 68: | Line 68: | ||
if approx_set[a_approx] then | if approx_set[a_approx] then | ||
if not rat.eq(rat.modulo_mul(rat.div(a, approx_set[a_approx]), et.equave), 1) then | if not rat.eq(rat.modulo_mul(rat.div(a, approx_set[a_approx]), et.equave), 1) then | ||
mw.log(a_key .. | mw.log(a_key .. " -> " .. a_approx .. ": conflict!") | ||
return false | return false | ||
end | end | ||
end | end | ||
approx_set[a_approx] = a | approx_set[a_approx] = a | ||
mw.log(a_key .. | mw.log(a_key .. " -> " .. a_approx) | ||
end | end | ||
for a_key, a in pairs(ratios) do | for a_key, a in pairs(ratios) do | ||
Line 79: | Line 79: | ||
if approx_set[a_approx] then | if approx_set[a_approx] then | ||
if not rat.eq(rat.modulo_mul(rat.div(a, approx_set[a_approx]), et.equave), 1) then | if not rat.eq(rat.modulo_mul(rat.div(a, approx_set[a_approx]), et.equave), 1) then | ||
mw.log(a_key .. | mw.log(a_key .. " -> " .. a_approx .. ": conflict!") | ||
return false | return false | ||
end | end | ||
end | end | ||
approx_set[a_approx] = a | approx_set[a_approx] = a | ||
mw.log(a_key .. | mw.log(a_key .. " -> " .. a_approx) | ||
end | end | ||
end | end | ||
if type(distinct) == | if type(distinct) == "number" then | ||
return true | return true | ||
end | end | ||
local previous_ordered = {} | local previous_ordered = {} | ||
for | for _, a in pairs(previous) do | ||
table.insert(previous_ordered, a) | table.insert(previous_ordered, a) | ||
end | end | ||
local ratios_ordered = {} | local ratios_ordered = {} | ||
for | for _, a in pairs(ratios) do | ||
table.insert(ratios_ordered, a) | table.insert(ratios_ordered, a) | ||
end | end | ||
for i, a in ipairs(ratios_ordered) do | for i, a in ipairs(ratios_ordered) do | ||
local a_approx = ET.approximate(et, rat.as_float(a)) | local a_approx = ET.approximate(et, rat.as_float(a)) | ||
for | for _, b in ipairs(previous_ordered) do | ||
local b_approx = ET.approximate(et, rat.as_float(b)) | local b_approx = ET.approximate(et, rat.as_float(b)) | ||
local c = rat.mul(a, b) | local c = rat.mul(a, b) | ||
local c_approx = ET.approximate(et, rat.as_float(c)) | local c_approx = ET.approximate(et, rat.as_float(c)) | ||
c = rat.modulo_mul(c, et.equave) | c = rat.modulo_mul(c, et.equave) | ||
local c_key = rat.as_ratio(c) | local c_key = rat.as_ratio(c) | ||
if previous[c_key] or ratios[c_key] then | if previous[c_key] or ratios[c_key] then | ||
if c_approx ~= a_approx + b_approx then | if c_approx ~= a_approx + b_approx then | ||
mw.log( | mw.log("a = " .. rat.as_ratio(a) .. "; b = " .. rat.as_ratio(b) .. "; ab = " .. c_key) | ||
mw.log(a_approx .. | mw.log(a_approx .. " + " .. b_approx .. " != " .. c_approx) | ||
return false | return false | ||
end | end | ||
Line 119: | Line 119: | ||
if i <= j then | if i <= j then | ||
local b_approx = ET.approximate(et, rat.as_float(b)) | local b_approx = ET.approximate(et, rat.as_float(b)) | ||
local c = rat.mul(a, b) | local c = rat.mul(a, b) | ||
local c_approx = ET.approximate(et, rat.as_float(c)) | local c_approx = ET.approximate(et, rat.as_float(c)) | ||
c = rat.modulo_mul(c, et.equave) | c = rat.modulo_mul(c, et.equave) | ||
local c_key = rat.as_ratio(c) | local c_key = rat.as_ratio(c) | ||
if previous[c_key] or ratios[c_key] then | if previous[c_key] or ratios[c_key] then | ||
if c_approx ~= a_approx + b_approx then | if c_approx ~= a_approx + b_approx then | ||
mw.log( | mw.log("a = " .. rat.as_ratio(a) .. "; b = " .. rat.as_ratio(b) .. "; ab = " .. c_key) | ||
mw.log(a_approx .. | mw.log(a_approx .. " + " .. b_approx .. " != " .. c_approx) | ||
return false | return false | ||
end | end | ||
Line 145: | Line 145: | ||
if et.size == 0 then | if et.size == 0 then | ||
-- the answer is known already | -- the answer is known already | ||
return | return "∞" | ||
end | end | ||
max_n = max_n or 1/0 | max_n = max_n or 1 / 0 | ||
distinct = distinct or false | distinct = distinct or false | ||
local n = 1 | local n = 1 | ||
Line 153: | Line 153: | ||
local previous = {} | local previous = {} | ||
while true do | while true do | ||
if type(distinct) == | if type(distinct) == "number" and n > distinct then | ||
return last_n | return last_n | ||
end | end | ||
local ratios = p.limit_modulo_equave(n, et.equave, previous) | local ratios = p.limit_modulo_equave(n, et.equave, previous) | ||
for key, | for key, _ in pairs(ratios) do | ||
mw.log( | mw.log("step " .. n .. ": " .. key) | ||
end | end | ||
if next(ratios) ~= nil then | if next(ratios) ~= nil then | ||
local consistent = p.additively_consistent(et, ratios, distinct, previous) | local consistent = p.additively_consistent(et, ratios, distinct, previous) | ||
if not consistent then | if not consistent then | ||
mw.log( | mw.log("Not consistent at step " .. n .. ", returning " .. last_n) | ||
return last_n | return last_n | ||
end | end |