rapport/rapport.lua

132 lines
3.6 KiB
Lua

local function Gap(t, i)
if not t[i] then return i else return Gap(t, i + 1) end
end
local function Gaps(t, i)
return Gap, t, i
end
--Data structure supporting fast ordered insertion and search.
local function Order()
local o = {}
local list = { val = nil, prev = nil, next = nil }
o.Get = function( x )
end
o.GetAdjacent = function( node )
return node.prev.val, node.next.val
end
o.Insert = function( x )
if not list.val then
list.val = x
return list
end
local node = list
while node and node.val < x do node = node.next end
end
return o
end
--Construct an isomorphism between two countable dense total orders
--these orders are specified by functions which return the next element in some enumeration
--these elements must be comparable with comparison operators <, >, &c.
local function Isomorphism( Enumeration, InverseEnumeration, inv )
--Exported table.
local t = {}
local enum, order, mapping, inverse
--Another Isomorphism structure,
--which contains the image of this isomorphism and the inverse
--isomorphism mapping back to our dense countable linear order.
inverse = inv or Isomorphism( InverseEnumeration, nil, t )
--Array for caching and lazily evaluating the supplied Enumeration,
--an iterator that enumerates the elements of a dense countable linear order.
enum = { Enumeration() }
setmetatable(enum, {__index = function(_, i)
for j = #enum + 1, i do
enum[j] = Enumeration()
end
return rawget( enum, i )
end})
t.enum = enum --Expose as field
--Structure supporting fast ordered insertion and search.
--Values are i such that mapping[order[i]] is not nil,
--sorted according to getmetatable( enum[i] ).__lt
order = { 1 }
--Find the indices i and k such that
--enum[i] is the greatest lower bound on enum[j] in the mapping's support
--enum[k] is the least upper bound on enum[j] in the mapping's support
local function GetBounds( leaf )
end
--Array defining isomorphism mapping this dense countable order to the one in inverse.
--If mapping[i] = j, then f(enum[i]) = inverse.enum[j]
mapping = { 1 }
setmetatable( mapping, {__newindex = function(map, k, v)
rawset(mapping, k, v)
end})
--Iterates over the natural numbers outside the isomorphism's support,
--so returns the least n such that n >= i and mapping[n] == nil.
--(Warning, infinite loop! Make sure to break out of this.)
local function NextGap(i)
if not mapping[i] then return i else return NextGap(i + 1) end --tail-recursive
end
--Include another point in the mapping's support.
--Infinite loop: ))<<>>((
function t.ExpandMap()
local gapIdx = NextGap(1)
local pred, succ = GetBounds( OrderedInsertion( gapIdx ) )
mapping[gapIdx] = inverse.AddNextBetween( i, mapping[pred], mapping[succ] )
return inverse.ExpandMap()
end
--Find the first j such that mapping[j] == nil,
--enum[lower] < enum[j] < enum[upper]
--Then map j to i, and add j to the order.
function t.AddNextBetween( i, lower, upper )
local p, q, r, j = enum[lower], nil, enum[upper], nil
for k in Gaps( 1 ) do
q = enum[k]
if ((not p) or (p < q))
and ((not r) or (q < r)) then
j = k
break
end
end
mapping[j] = i
OrderedInsertion(j)
return j
end
--Get the isomorphism as a dictionary, for plotting.
function t.GetMapping( )
local map = {}
for idx, imageIdx in pairs( mapping ) do
map[ enum[ idx ] ] = inverse.enum[ imageIdx ]
end
return map
end
return t
end
return setmetatable( { Isomorphism = Isomorphism }, {__call = Isomorphism } )