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")"