Module:JI ratios: Difference between revisions

ArrowHead294 (talk | contribs)
mNo edit summary
Ganaram inukshuk (talk | contribs)
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.
-- Note that mediant search returns sorted ratios, so remove them from the
-- Because the ratios are already sorted by cent value, remove ratios from
-- end until there's no more to remove.
-- 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
-- Filter out ratios that exceed the int limit.
-- Then filter out ratios if their equave complement would be filtered out.
--ratios = p.filter_ratios_by_tenney_height(ratios, equave, fine_search_args)
--ratios = p.filter_ratios_by_complements(ratios, equave, fine_search_args)
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
-- Search for ratios within int limit within subgroup by multiplication.
-- Find all possible ways to multiply subgroup elements with one another
local products = p.multiply_ratios_using_bfs(rat.new(1), subgroup, int_limit)
-- 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 found, have it be the denominator and have the numerator
-- For each ratio in the table of products, create a set of new ratios by
-- be all successive ratios after it. For each new ratio found this way, add
-- having that ratio be the numerator and all successive ratios be possible
-- it to the table of ratios, excluding ratios that exceed the equave or int
-- denominators. Store these new ratios in a table, and repeat with all
-- limit, and excluding duplicates. This is way faster than performing BFS
-- successive products, omitting duplicats. From earlier testing, this is
-- on each ratio and yields the same results.
-- 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 ratio = rat.div(products[j], products[i])
local new_ratio = rat.div(products[j], products[i])
if rat.as_float(ratio) > rat.as_float(equave) then break end
if rat.as_float(new_ratio) > rat.as_float(equave) then break end
if not p.find_ratio_in_table(new_ratios, ratio) and rat.int_limit(ratio) <= int_limit then
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, ratio)
table.insert(new_ratios, new_ratio)
end
end
end
end
p.merge_ratio_tables_without_duplicates(ratios, new_ratios)
-- Merge new ratios with the table of ratios, omitting duplicates.
p.merge_tables(ratios, new_ratios)
end
end
-- Sort, then filter out ratios that exceed the int limit.
-- Sort
-- Then filter out ratios if their equave complement would be filtered out.
table.sort(ratios, rat.lt)
table.sort(ratios, rat.lt)
Line 180: Line 206:
end
end


-- Helper function for subgroup search; implementation of BFS
-- Heleper function; merges elements from source table with destination table
function p.multiply_ratios_using_bfs(init_ratio, subgroup, int_limit)
-- while disallowing duplicates.
local ratios = { init_ratio }
function p.merge_tables(dest_table, source_table)
local i = 1
while i <= #ratios do
local new_ratios = p.multiply_ratio_by_subgroup_elements(ratios[i], subgroup, int_limit)
p.merge_ratio_tables_without_duplicates(ratios, new_ratios)
i = i + 1
end
table.sort(ratios, rat.lt)
return ratios
end
 
-- Helper function for BFS search; returns { ratio } X subgroup
function p.multiply_ratio_by_subgroup_elements(ratio, subgroup, int_limit)
local ratios = {}
for i = 1, #subgroup do
local new_ratio = rat.mul(ratio, subgroup[i])
if rat.int_limit(new_ratio) <= int_limit and not p.find_ratio_in_table(ratios, new_ratio) then
table.insert(ratios, new_ratio)
end
end
return ratios
end
 
-- Heleper function; merges tables while disallowing duplicates
function p.merge_ratio_tables_without_duplicates(dest_table, source_table)
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 table merge function
-- 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