132 lines
3.6 KiB
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 } ) |