Skip to content

Instantly share code, notes, and snippets.

@vznvzn
Created December 25, 2020 01:29
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save vznvzn/0dccfc632b7e96a566b24f9ec75e57a4 to your computer and use it in GitHub Desktop.
require 'statsample'
def f2(n)
return n.odd? ? (n * 3 + 1) / 2 : n / 2
end
def dot(x, z)
t = z['c']
(z.keys - ['c']).each { |v| t += z[v] * x[v] }
return t
end
def predict(l, vy, z)
l.each { |x| x["#{vy}_y"] = dot(x, z) }
end
def sum(l)
t = 0.0
l.each { |x| t += x }
return t
end
def av(l)
return nil if (l.empty?)
return sum(l) / l.size
end
def corr(l, y1, yp = "#{y1}_y")
ye = "#{y1}_e"
xav = av(l.map { |x| x[y1] })
yav = av(l.map { |x| x[yp] })
tx = ty = txy = e = 0.0
m = nil
l.each \
{
|z|
x = z[y1]
y = z[yp]
txy += (x - xav) * (y - yav)
tx += (x - xav) ** 2
ty += (y - yav) ** 2
z[ye] = (x - y)
e1 = z[ye]
e += e1.abs
}
d = Math.sqrt(tx) * Math.sqrt(ty)
r = txy / (d.abs < $z ? $z : d)
e /= l.size
return r
end
def fit(l, vx, vy)
a = {}
(vx + [vy]).each { |v| a[v] = l.map { |x| x[v] }.to_vector() }
begin
r = Statsample::Regression.multiple(a.to_dataset(), vy)
# rescue Statsample::Regression::LinearDependency
# return nil
end
# $stderr.puts(r.summary)
z = r.coeffs.merge({'c' => r.constant})
predict(l, vy, z)
r = corr(l, vy)
return r, z
end
def read(fn)
l = (f = File.open(fn)).readlines.map { |x| Kernel.eval(x) }
f.close
$stderr.puts(['read', fn, l.size].inspect)
return l
end
def stat(k, l)
t = l.inject { |a, x| a + x }
t2 = l.inject(0) { |a, x| a + (x ** 2) }
c = l.size
a = t.to_f / c
z = t2.to_f / c - a ** 2
sd = Math.sqrt(z < 0 ? 0 : z)
raise [k, l].inspect if (sd.nan?)
return {"#{k}_a" => a, "#{k}_s" => sd,
"#{k}_mn" => l.min, "#{k}_mx" => l.max}
end
def outd(f, l)
f.puts('$dat << eof')
k = l[0].keys
f.puts(k.join("\t"))
l.each { |x| f.puts(x.values.join("\t")) }
f.puts('eof')
return k
end
def hide(a, x)
return (a.member?(x) && a[x].nil?)
end
def plot(f, d, k, a, t = nil)
f.puts("# #{t}") if (!t.nil?)
f.puts("set colors classic; set title '#{t}'; ")
# f.puts("set key top right opaque; ")
f.puts("set ytics nomirror; set y2tics;")
f.puts("plot \\")
k.each \
{
|x|
next if (hide(a, x))
opt = a.fetch(x, '')
opt = ' with line ' + opt if (!opt.include?('with') && !opt.include?('pt'))
opt += ' lw 2 ' if (!opt.include?('lw') && !opt.include?('pt'))
f.puts("#{d} using (column('#{x}')) #{opt} title '#{x}',\\")
}
f.puts
# f.puts("reset; pause -1;")
end
def outa(f, l, a = {}, t = nil)
k = outd(f, l)
plot(f, '$dat', k, a, t)
end
def outafn(l, a = {}, fno = nil, t = '')
outa(f = File.open(fn = "gnuplot#{fno}.cmd", 'w'), l, a, t)
f.close
$stderr.puts([fn, l.size, t, l[0].keys].inspect)
end
def streamafn(a = nil, a1 = {}, fno = nil, t = nil)
$f, $n = [{}, 1] if ($f.nil?)
fno = $n if (fno.nil?)
if (a.nil?) then
$f[$f.keys.last]['f'].close
$n += 1
return
end
if (!$f.member?(fno)) then
$f[fno] = {'fn' => (fn2 = "out#{fno}.txt"),
'f' => File.open(fn2, 'w')}
$f[fno]['f'].puts(a.keys.join("\t"))
plot(f = File.open(fn = "gnuplot#{fno}.cmd", 'w'), "'#{fn2}'", a.keys, a1, t)
f.close
$stderr.puts([fn, fn2, t, a.keys].inspect)
end
$f[fno]['f'].puts(a.values.join("\t"))
$f[fno]['f'].flush
end
def keys(l, ks)
return l.map { |x| Hash[[ks, x.values_at(*ks)].transpose] }
end
def seq(n)
l = [n]
while (n != 1)
n = f2(n)
l << n
end
return l
end
def sum(l)
return l.inject(0) { |t, x| t + x }
end
def avg(l)
return sum(l).to_f / l.size
end
def runavg(l, k, c, ka = "#{k}_a")
l1 = l.map { |x| x[k] }
t = sum(l1[0...c])
l2 = (['-'] * (c - 1)) + [t.to_f / c]
while (l1.size > c)
t -= l1.shift
t += l1[c - 1]
l2 << (t.to_f / c)
end
l.each_with_index { |x, i| x[ka] = l2[i] }
end
def len(ns, p)
l = ns.split(p)
l = [] if (l.nil?)
l.shift if (l[0] == '')
return l.map { |x| x.length }
end
def len1(ns)
return len(ns, /0+/)
end
def len0(ns)
return len(ns, /1+/)
end
def len01(ns)
return len1(ns), len0(ns)
end
def e(ns)
return 0 if (ns.empty?)
return len01(ns).flatten.size.to_f / ns.length
end
def d(s)
return 0 if (s.empty?)
c = s.split('').select { |x| x == '1' }.size
d = c.to_f / s.length
return d
end
def midpt(ns)
w2 = ns.length / 4
l = ns.split('')
i = j = 0
while (i < w2 && j < l.size)
i += l[j].to_i
j += 1
end
return j.to_f / ns.length
end
def d1(s)
c = s.split('').select { |x| x == '1' }.size
return c
end
def midpt2(ns)
w2 = d1(ns) / 2
l = ns.split('')
i = j = 0
while (i < w2 && j < l.size)
i += l[j].to_i
j += 1
end
return j.to_f / ns.length
end
def log2(x)
return Math.log(x) / Math.log(2.0)
end
def features(ns)
d = d(ns) - 0.5
e = e(ns) - 0.5
nw = ns.length
nw2 = nw / 2
nshi = ns[0...nw2]
nslo = ns[nw2..-1]
dlo = d(nslo) - 0.5
dhi = d(nshi) - 0.5
elo = e(nslo) - 0.5
ehi = e(nshi) - 0.5
mp1 = midpt(ns) - 0.5
mp2 = midpt2(ns) - 0.5
l0 = len0(ns)
mx0 = l0.empty? ? 0 : l0.max
mx1 = len1(ns).max
mx01 = [mx0, mx1].max
mx = log2(log2(ns.to_i(2).to_f))
a0 = l0.empty? ? 0 : avg(l0)
a1 = avg(len1(ns))
a01 = avg(len01(ns).flatten)
return {
"d" => d,
"e" => e,
"ea" => e.abs,
"da" => d.abs,
"dlo" => dlo,
"dhi" => dhi,
"elo" => elo,
"ehi" => ehi,
'mp1' => mp1,
"mp2" => mp2,
'mx0' => mx0.to_f / ns.length,
'mx1' => mx1.to_f / ns.length,
'mx01' => mx01.to_f / ns.length,
'a0' => a0 / ns.length,
'a1' => a1 / ns.length,
'a01' => a01 / ns.length,
'a1m' => a1 / (mx == 0 ? 1 : mx),
# 'c0' => l0.size,
# 'c1' => l1.size,
"nw" => ns.length
}
end
def smooth(l2)
l = l2.map { |x| features(x.to_s(2)) }
c = 50
(ks = l[0].keys).each { |k| runavg(l, k, c) }
return (c...l.size).map { |x| Hash[[ks + ['nw1'], l[x].values_at(*(ks.map { |x1| "#{x1}_a" } + ['nw']))].transpose] }
end
def dataset(l)
return l.map { |x| smooth(x) }
end
def adj(l, z, ks, wt)
ks.each \
{
|k|
l.each { |x| x[k] = (x[k] - z["#{k}_a"]) * wt[k] }
}
end
def model(l1, ks, k, wt, s)
ks.each \
{
|k|
s.merge!(stat(k, l1.map { |x| x[k] }))
wt[k] = 1.0 / s["#{k}_s"]
}
adj(l1, s, ks, wt)
r, z = fit(l1, ks, k)
$stderr.puts([r, z].inspect)
return z
end
def cg(l2)
cg = l2.index { |x| x < l2[0] }
return cg
end
def sample2(l, n)
d = (l.size - 1).to_f / (n - 1)
l2 = []
n.times \
{
|i|
j = (i * d).to_i
l2 << l[j]
}
return l2
end
def apply(n1, k, ky, n, s, ks, wt, z)
l2 = smooth(l = seq(n1))
l2.each_with_index { |x, j| x['hc'] = (l2.size - j - 1).to_f / x['nw1']; x['j'] = (l2.size - j - 1); x['nw2'] = 1.0 / x['nw1']; }
l2.pop
adj(l2, s, ks, wt)
predict(l2, k, z)
outafn(keys(l2, [k, ky, 'nw1']), {'nw1' => 'axes x1y2'}, n)
end
def linear(fn, n)
l1 = read(fn)
k = 'hc'
l1.each \
{
|x|
c = (l = seq(x['ns'].to_i(2))).size
x[k] = c.to_f / x['ns'].length
x['c'] = c
x['cg'] = cg(l)
}
ks = [
'a0', 'a1', 'a01',
'a1m',
# 'd',
# 'e',
'da', 'ea',
# 'dlo',
'dhi', 'elo', 'ehi', 'mp1', 'mp2', 'mx0', 'mx1', 'mx01',
# 'c0', 'c1'
]
z = model(l1, ks, k, wt = {}, s = {})
ky = "#{k}_y"
l1.sort_by! { |x| x[k] }
outafn(keys(l1, [k, ky]), {})
x = l1.max_by { |x| x['cg'] }
$stderr.puts(keys([x], ['cg', 'c', 'nw'])[0].inspect)
apply(x['ns'].to_i(2), k, ky, 1, s, ks, wt, z)
apply(n, k, ky, 2, s, ks, wt, z)
end
$z = 1e-4
n = 20678096139828932684255824799921978289932242905629473048320332
linear('outline2.txt', n)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment