Module:JI ratios: Difference between revisions
save running changes to subgroup search |
Finalized main algorithm for subgroup search |
||
| Line 96: | Line 96: | ||
-------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ||
-- | -- WARNING: searching by nonprime subgroup may lead to redundant ratios being | ||
function p.search_by_subgroup(subgroup, int_limit, | -- added, so checking for duplicates is necessary, but not implemented yet. | ||
-- Rational subgroup isn't supported yet either. | |||
-- Prime limits should be converted to subgroup (eg, 7-limit -> 2.3.5.7) so as | |||
-- to avoid brute-force searching incurred by first searching by int limit. | |||
function p.search_by_subgroup(subgroup, int_limit, equave) | |||
local subgroup = subgroup or { 2, 3, 7, 11 } | local subgroup = subgroup or { 2, 3, 7, 11 } | ||
local int_limit = int_limit or 50 | local int_limit = int_limit or 50 | ||
local | local equave = equave or rat.new(2,1) | ||
local equave_as_float = rat.as_float(equave) | |||
-- For each factor in the subgroup, calculate the largest exponent (power) | |||
-- that factor can be raised to that is just less than the int limit. | |||
-- Use this to create a running vector of powers. | |||
-- | |||
-- | |||
-- | |||
local max_powers = {} | local max_powers = {} | ||
local curr_powers = {} | local curr_powers = {} -- Running vector of powers | ||
for i = 1, # | for i = 1, #subgroup do | ||
local curr_max_multiplier = math.floor(int_limit/subgroup[i]) | |||
local curr_max_multiplier = math.floor( | local max_power = math.log(int_limit) / math.log(subgroup[i]) | ||
local max_power = math.log( | table.insert(max_powers, math.floor(max_power)) | ||
table.insert(max_powers, math. | |||
table.insert(curr_powers, -max_powers[i]) | table.insert(curr_powers, -max_powers[i]) | ||
end | end | ||
-- Increment current powers one by one, and | -- Increment current powers one by one, and use those powers to create the | ||
-- | -- required ratios. | ||
local | local ratios = {} | ||
while curr_powers[#curr_powers] < max_powers[#max_powers] do | while curr_powers[#curr_powers] <= max_powers[#max_powers] do | ||
-- Calculate new ratio | |||
local new_ratio = { 1, 1 } | |||
for i = 1, #curr_powers do | |||
if curr_powers[i] >= 1 then | |||
new_ratio[1] = new_ratio[1] * math.pow(subgroup[i], curr_powers[i]) | |||
else | |||
new_ratio[2] = new_ratio[2] * math.pow(subgroup[i], -curr_powers[i]) | |||
end | |||
end | |||
-- Check whether new ratio as a float is within the range of 1 and the | |||
-- equave as a float, and whether its num and den are within the int | |||
-- limit. If so, add it to the running list of ratios. | |||
local curr_product = new_ratio[1] / new_ratio[2] | |||
if new_ratio[1] <= int_limit and new_ratio[2] <= int_limit and curr_product >= 1 and curr_product <= equave_as_float then | |||
table.insert(ratios, new_ratio) | |||
end | |||
-- Increment powers | |||
curr_powers[1] = curr_powers[1] + 1 | curr_powers[1] = curr_powers[1] + 1 | ||
for i = 1, #curr_powers - 1 do | for i = 1, #curr_powers - 1 do | ||
if curr_powers[i] > | if curr_powers[i] > max_powers[i] then | ||
curr_powers[i] = -max_powers[i] | curr_powers[i] = -max_powers[i] | ||
curr_powers[i+1] = curr_powers[i+1] + 1 | curr_powers[i+1] = curr_powers[i+1] + 1 | ||
end | end | ||
end | end | ||
end | end | ||
-- Convert to ratios that Module:Rational can work with | |||
for i = 1, #ratios do | |||
ratios[i] = rat.new(ratios[i][1], ratios[i][2]) | |||
-- | |||
for i = 1, # | |||
end | end | ||
return | return ratios | ||
end | end | ||
| Line 387: | Line 351: | ||
--return p.ratios_as_text(ratios) .. " " .. #ratios | --return p.ratios_as_text(ratios) .. " " .. #ratios | ||
-- Using these params with the naive search algorithm | -- Using these params with the naive search algorithm (iterating through | ||
-- to return only 1563 results: factors 2, 3, 7, 11; max product: 10 million | -- every number from to to the int limit and checking whether its factors | ||
local factors = { 2, | -- are present in the subgroup) takes several seconds to return only 1563 | ||
local max_product = | -- results using these params: factors 2, 3, 7, 11; max product: 10 million. | ||
local factors = { 2, 15, 17, 22 } | |||
local max_product = 100 | |||
return p. | return p.ratios_as_text(p.search_by_subgroup(factors, max_product)) | ||
end | end | ||
return p | return p | ||