Module:JI ratios: Difference between revisions
ArrowHead294 (talk | contribs) mNo edit summary |
merge some helper functions; adopt is_within_int_limit function; comments |
||
| Line 84: | Line 84: | ||
local int_limit = int_limit or 50 -- Default is 50 | local int_limit = int_limit or 50 -- Default is 50 | ||
-- Find all ratios from 1/1 to the equave by finding mediants between 1/1 | |||
-- and 1/0. Mediants module has a function for this built-in, but includes | |||
-- ratios that exceed the equave (for example, if the equave is 2/1, then | |||
-- the mediants function will include 3/1 and 4/1), which must be removed | |||
-- afterwards. | |||
local init_ratios = {{1,1}, {1,0}} | local init_ratios = {{1,1}, {1,0}} | ||
local ratios = med.find_only_mediants_by_int_limit(init_ratios, int_limit) | local ratios = med.find_only_mediants_by_int_limit(init_ratios, int_limit) | ||
| Line 93: | Line 98: | ||
-- Remove ratios that exceed the equave. | -- Remove ratios that exceed the equave. | ||
-- | -- Because the ratios are already sorted by cent value, remove ratios from | ||
-- end until there | -- the end of the table until there are no more ratios to remove. | ||
while rat.gt(ratios[#ratios], equave) do | while rat.gt(ratios[#ratios], equave) do | ||
table.remove(ratios, #ratios) | table.remove(ratios, #ratios) | ||
end | end | ||
return ratios | return ratios | ||
| Line 138: | Line 138: | ||
end | end | ||
-- Perform subgroup search. | |||
return p.search_by_subgroup(equave, int_limit, primes) | return p.search_by_subgroup(equave, int_limit, primes) | ||
end | end | ||
| Line 150: | Line 151: | ||
local subgroup = subgroup or {rat.new(2), rat.new(3), rat.new(7)} -- Default is 2.3.7 subgroup | local subgroup = subgroup or {rat.new(2), rat.new(3), rat.new(7)} -- Default is 2.3.7 subgroup | ||
-- | -- Find all possible ways to multiply subgroup elements with one another | ||
local products = | -- using breadth-first-search. Products found this way should not exceed the | ||
-- int limit, and if a subgroup element is rational, neither its numerator | |||
-- nor denominator should exceed the int limit. | |||
local products = { rat.new(1) } | |||
local i = 1 | |||
while i <= #products do | |||
-- Multiply each subgroup element by the current ratio. The table of | |||
-- product ratios created this way is merged with the running table of | |||
-- ratios. This is the Cartesian product of the single ratio as a set, | |||
-- with the subgroup elements as a set, or {p/q} X subgroup. | |||
local new_products = {} | |||
for j = 1, #subgroup do | |||
local new_ratio = rat.mul(products[i], subgroup[j]) | |||
if rat.is_within_int_limit(new_ratio, int_limit) and not p.find_ratio_in_table(new_products, new_ratio) then | |||
table.insert(new_products, new_ratio) | |||
end | |||
end | |||
-- Merge new products with the table of products, omitting duplicates. | |||
p.merge_tables(products, new_products) | |||
i = i + 1 | |||
end | |||
-- Sort for next step | |||
table.sort(products, rat.lt) | |||
-- Use the products found to find all ratios between 1 and the equave. | -- Use the products found to find all ratios between 1 and the equave. | ||
-- For each ratio | -- For each ratio in the table of products, create a set of new ratios by | ||
-- be all successive ratios | -- having that ratio be the numerator and all successive ratios be possible | ||
-- | -- denominators. Store these new ratios in a table, and repeat with all | ||
-- | -- successive products, omitting duplicats. From earlier testing, this is | ||
-- faster than performing BFS on each ratio, and yields the same results. | |||
local ratios = {} | local ratios = {} | ||
for i = 1, #products do | for i = 1, #products do | ||
local new_ratios = {} | local new_ratios = {} | ||
for j = i, #products do | for j = i, #products do | ||
local | local new_ratio = rat.div(products[j], products[i]) | ||
if rat.as_float( | if rat.as_float(new_ratio) > rat.as_float(equave) then break end | ||
if not p.find_ratio_in_table(new_ratios, | if not p.find_ratio_in_table(new_ratios, new_ratio) and rat.is_within_int_limit(new_ratio, int_limit) then | ||
table.insert(new_ratios, | table.insert(new_ratios, new_ratio) | ||
end | end | ||
end | end | ||
p. | |||
-- Merge new ratios with the table of ratios, omitting duplicates. | |||
p.merge_tables(ratios, new_ratios) | |||
end | end | ||
-- Sort | -- Sort | ||
table.sort(ratios, rat.lt) | table.sort(ratios, rat.lt) | ||
| Line 180: | Line 206: | ||
end | end | ||
-- | -- Heleper function; merges elements from source table with destination table | ||
-- while disallowing duplicates. | |||
function p.merge_tables(dest_table, source_table) | |||
-- | |||
function p. | |||
for i = 1, #source_table do | for i = 1, #source_table do | ||
if not p.find_ratio_in_table(dest_table, source_table[i]) then | if not p.find_ratio_in_table(dest_table, source_table[i]) then | ||
| Line 214: | Line 216: | ||
end | end | ||
-- Helper function for | -- Helper function for merge function. | ||
function p.find_ratio_in_table(table_, ratio) | function p.find_ratio_in_table(table_, ratio) | ||
local found = false | local found = false | ||
| Line 325: | Line 327: | ||
ratios = p._ji_ratios(args) | ratios = p._ji_ratios(args) | ||
return p.ratios_as_string(ratios) | return p.ratios_as_string(ratios) | ||
end | |||
function p.tester() | |||
return p.ratios_as_string(p.search_by_subgroup()) | |||
end | end | ||