Encoding binary sequences - solved lab#
The lab this week consists of implementing all together the grammar from this week’s reading and fitting some fake data to it. This notebook is a report of what we wrote together!
try:
# in colab
import google.colab
print('In colab, downloading LOTlib3')
!git clone https://github.com/thelogicalgrammar/LOTlib3
except:
# not in colab
print('Not in colab!')
Not in colab!
Imports#
First we need to import a bunch of stuff:
from LOTlib3.Grammar import Grammar
from LOTlib3.DataAndObjects import FunctionData
from LOTlib3.Hypotheses.LOTHypothesis import LOTHypothesis
from LOTlib3.Hypotheses.Likelihoods.BinaryLikelihood import BinaryLikelihood
from LOTlib3.Eval import primitive
from LOTlib3.Miscellaneous import qq
from LOTlib3.TopN import TopN
from LOTlib3.Samplers.MetropolisHastings import MetropolisHastingsSampler
Define the grammar#
grammar = Grammar(start='S')
# repeat the expression
grammar.add_rule('S', 'rep_', ['S', 'N', 'BOOL'], 1)
# basic symbols
grammar.add_rule('S', '"0"', None, 1)
grammar.add_rule('S', '"1"', None, 1)
# N
grammar.add_rule('N', '1', None, 1)
grammar.add_rule('N', '%s+1', ['N'], 1)
# BOOL
grammar.add_rule('BOOL', '"+0"', None, 1)
grammar.add_rule('BOOL', '"b"', None, 1)
# concatenation
grammar.add_rule('S', 'concat_', ['S', 'S'], 1)
S -> concat_['S', 'S'] w/ p=1.0
formula = grammar.generate()
formula.fullprint()
S rep_ None
. S concat_ None
. . S rep_ None
. . . S concat_ None
. . . . S "1" None
. . . . S "1" None
. . . N %s+1 None
. . . . N 1 None
. . . BOOL "b" None
. . S rep_ None
. . . S concat_ None
. . . . S "0" None
. . . . S rep_ None
. . . . . S "1" None
. . . . . N 1 None
. . . . . BOOL "+0" None
. . . N %s+1 None
. . . . N 1 None
. . . BOOL "+0" None
. N 1 None
. BOOL "+0" None
Define the semantics#
def swap(c):
assert c in '01', 'UNknown character!'
return '0' if c=='1' else '1'
@primitive
def rep_(S, N, BOOL):
if BOOL == '+0':
return S * N
else:
swapped = ''
for i in range(N):
sw = i%2
if sw:
swapped += ''.join([
swap(c)
for c in S
])
else:
swapped += S
return swapped
@primitive
def concat_(S1, S2):
return S1 + S2
eval(str(formula))
'11000101'
Hypothesis and inference#
class CoolHypothesis(BinaryLikelihood, LOTHypothesis):
def __init__(self, **kwargs):
LOTHypothesis.__init__(
self,
grammar=grammar,
display='lambda: %s',
**kwargs
)
h = CoolHypothesis()
h
lambda: concat_("1", "0")
data = [
FunctionData(input=[], output='0011', alpha=0.95)
]*10
topn = TopN(6)
for h_new in MetropolisHastingsSampler(h, data, steps=100000):
topn.add(h_new)
for h in topn:
print(h.posterior_score, h.prior, h.likelihood, qq(h))
-9.957238607682132 -9.704060527839234 -0.253178079842899 "lambda: concat_(concat_("0", concat_("0", "1")), "1")"
-9.957238607682132 -9.704060527839234 -0.253178079842899 "lambda: concat_(concat_("0", "0"), concat_("1", "1"))"
-9.957238607682132 -9.704060527839234 -0.253178079842899 "lambda: concat_("0", concat_("0", concat_("1", "1")))"
-9.957238607682132 -9.704060527839234 -0.253178079842899 "lambda: concat_("0", concat_(concat_("0", "1"), "1"))"
-8.570944246562242 -8.317766166719343 -0.253178079842899 "lambda: rep_(rep_("0", 1+1, "+0"), 1+1, "b")"
-7.877797066002297 -7.6246189861593985 -0.253178079842899 "lambda: rep_(concat_("0", "0"), 1+1, "b")"