The file is part of the BURN project (learing multi-objective rules).
Because learning is not the filling a pail, but the lighting of a fire.
Burn=require "burn"
local lib= {
E = 2.7182818285,
PI = 3.1415926536,
abs = math.abs,
int = math.floor,
printf = function(s, ...) return io.write(s:format(...)) end,
sprintf= function(s, ...) return s:format(...) end,
match = function(s,p) return string.match(s,p) ~= nil end}
Returns m
rounded to the nearest n
. E.g.
round(32.7812, 0.1)
returns 32.8.
function lib.round(exact, quantum)
local quant,frac = math.modf(exact/quantum)
return quantum * (quant + (frac > 0.5 and 1 or 0))
end
Return true are m
and n
are within e
% of each other
(default value for e = 1).
function lib.close(m,n,e)
e = e and e or 1
return lib.abs(m-n)/n <= e/100
end
function lib.max(a,b) return a > b and a or b end
function lib.min(a,b) return a < b and a or b end
do
local seed0 = 10013
local seed = seed0
local modulus = 2147483647
local multipler = 16807
function lib.rseed(n) seed = n or seed0 end
function lib.rand() -- park miller
seed = (multipler * seed) % modulus
return seed / modulus end
end
Return a y
value for x
by interpolating across the points in xs,ys
.
E.g.
interpolate(3,{1,2,4},{10,20,40})
returns 30,
This function assumes that y
changes linearly between the
points records in xs,ys
. Also, anything less or more than
the first and last values in xs
are capped to the ys[1]
or ys[#ys]
values, respectively.
function lib.interpolate(x,xs,ys, x1,y1)
local x0, y0 = xs[1], ys[1]
if x <= x0 then return y0 end
if x > xs[ #xs ] then return ys[ #ys ] end
for i = 1, #xs do
x1,y1 = xs[i],ys[i]
if x0 <= x and x < x1 then break end
x0, y0 = x1, y1 end
return y0 + (x - x0)/(x1 - x0) * (y1 - y0)
end
function lib.weibull(x,l,k)
return x < 0 and 0 or k/l*(x/l)^(k-1)*E^(-1*(x/l)^k)
end
function lib.weibullCdf(x,l,k)
return x < 0 and 0 or 1 - E^(-(x/l)^k)
end
function lib.normal(x, mu, sigma)
return E^(-.5 * (x-mu)*(x-mu)/(sigma*sigma)) /
math.sqrt(2.0*math.pi*sigma*sigma)
end
function lib.normCdf(x, mu, sigma)
return 0.5 * (1.0 + E^((x-mu)/math.sqrt(2*sigma*sigma)))
end
function lib.ordered(t)
local i,tmp = 0,{}
for key,_ in pairs(t) do tmp[#tmp+1] = key end
table.sort(tmp)
return function ()
if i < #tmp then
i=i+1; return tmp[i], t[tmp[i]] end end
end
function lib.eras(src,era)
local era = era or 32
local e,tmp,out,one = 0,{},{},src()
return function()
while one do
tmp[ #tmp+1 ] = one
one = src()
if #tmp >= era then
out = lib.shuffle(lib.copy(tmp))
tmp,e = {},e+1
return out,e end
end
if #tmp > 0 then
out = lib.shuffle(lib.copy(tmp))
tmp,e = {},e+1
return out,e end end
end
function lib.sorted(t, f)
f = f or function (x,y) return x<y end
table.sort(t,f)
return t
end
function lib.member(x,t)
for _,y in pairs(t) do if x==y then return true end end
return false
end
function lib.slice(t, i,j)
local out={}
for k=i,j do out[#out+1] = t[k] end
return out
end
function lib.push(x,t)
t[ #t+1 ] = x; return x
end
function lib.join(t, sep)
local u ={}
for i,x in pairs(t) do u[i] = tostring(x) end
return table.concat(u, sep or ", ")
end
function lib.any(t)
local pos = math.floor(0.5 + lib.rand() * #t)
return t[ lib.min(#t,lib.max(1,pos)) ]
end
function lib.anys(t,n)
t = lib.shuffle(t)
a,b = {},{}
for i=1,n do a[#a+1] = t[i] end
for i=n+1,#t do b[#b+1] = t[i] end
return a,b
end
function lib.merge(t1,t2)
for _,x in pairs(t2) do t1[#t1+1] = x end
return t1
end
function lib.shuffle( t )
for i= 1,#t do
local j = i + math.floor((#t - i) * lib.rand() + 0.5)
t[i],t[j] = t[j], t[i] end
return t
end
function lib.shallowCopy(t)
return lib.collect(t,lib.same)
end
function lib.copy(t) --recursive
return type(t) ~= 'table' and t or lib.collect(t,lib.copy)
end
Reading from updates
(or, if missing, arg
),
ignoring any flags listed in ignore
, update settings
with command-line settings such as -k a=1 b=2
(which sets k
to true and a,b
to 1,2).
function lib.args(settings,ignore, updates)
updates = updates or arg
ignore = ignore or {}
local i = 1
while updates[i] ~= nil do
local flag = updates[i]
local b4 = #flag
flag = flag:gsub("^[-]+","")
if not lib.member(flag,ignore) then
if settings[flag] == nil then
error("unknown flag '" .. flag .. "'")
else
if b4 - #flag == 2 then settings[flag] = true
elseif b4 - #flag == 1 then
local a1 = updates[i+1]
local a2 = tonumber(a1)
settings[flag] = a2 or a1
i = i + 1 end end end
i = i + 1 end
return settings
end
function lib.say(x) io.write(tostring(x)); io.flush() end
function lib.scan(s) return tonumber(s) or s end
function lib.rep(s, n) return n > 0 and s .. lib.rep(s, n-1) or "" end
Return a table of cells generated by spliting s
on sep
.
function lib.split(s, sep)
local t, sep = {}, sep or ","
local notsep = "([^" ..sep.. "]+)"
for y in string.gmatch(s, notsep) do t[#t+1] = y end
return t
end
Extract substrings. Allow Python style negative indexes
function lib.sub(s,lo,hi)
if lo and lo < 0 then
return lib.sub(s, string.len(s) + lo +1)
else
return string.sub(s,lo and lo or 1,hi) end
end
Print anything, including nested things
If you want the string, without printing it,
use ooo(x)
.
function lib.oo(data) print(lib.ooo(data)) end
function lib.ooo(data)
local seen={}
local function go(x, str,sep)
if type(x) ~= "table" then return tostring(x) end
if seen[x] then return "..." end
seen[x] = true
for k,v in lib.ordered(x) do
str = str .. sep .. k .. ": " .. go(v, "{","")
sep = ", " end
return str .. '}'
end
return go(data,"{","")
end
Pretty print the list of lists in t
.
If numfmt
suppied, use it to format numbers.
If noline
then suppress the underlines beneath row1.
function lib.cols(t, numfmt, noline)
local w={}
for i,_ in pairs(t[1]) do w[i] = 0 end
for i,line in pairs(t) do
for j,cell in pairs(line) do
if type(cell)=="number" and numfmt then
cell = lib.sprintf(numfmt, cell)
t[i][j] = cell end
w[j] = lib.max( w[j], #tostring(cell) ) end end
for n,line in pairs(t) do
local txt,sep="",""
for j,cell in pairs(line) do
local fmt = "%" .. (w[j]+1) .. "s"
txt = txt .. sep .. lib.sprintf(fmt, cell)
sep = ","
end
print(txt)
if (n==1 and not noline) then
local sep="#"
for _,w1 in pairs(w) do
io.write(sep .. string.rep("-",w1) )
sep=", " end
print("") end end
end
function lib.same(x) return x end
function lib.map(t,f)
if t then for i,v in pairs(t) do f(v) end end
end
function lib.map2(t,i,f)
if t then for _,v in pairs(t) do f(i,v) end end
return i
end
function lib.collect(t,f)
local out={}
if t then for i,v in pairs(t) do out[i] = f(v) end end
return out
end
function lib.select(t,f)
local out={}
if t then for i,v in pairs(t) do
if f(v) then out[#out + 1]=v end end end
return out
end
Reject all results that do not satisfy f(v) for each item v
in t
.
function lib.reject(t,f)
return lib.select(t, function(v) return not f(v) end)
end
function lib.when(f, r)
r= r or 1
local t1=os.clock()
for _=1,r do f() end
return (os.clock() - t1)/ r
end
return lib