Permalink
Browse files

2013 March 17

  • Loading branch information...
1 parent 6a1f519 commit 1ae683fcb3ff8b31189ca2aaed8021600a115ce1 @piantado committed Mar 17, 2013
Showing with 503 additions and 104 deletions.
  1. +214 −35 LOTlib/BasicPrimitives.py
  2. +7 −4 LOTlib/FiniteBestSet.py
  3. +6 −6 LOTlib/FunctionNode.py
  4. +62 −0 LOTlib/Grammars.py
  5. +26 −6 LOTlib/Hypothesis.py
  6. +30 −0 LOTlib/HypothesisSet.py
  7. +2 −1 LOTlib/MPI.py
  8. +62 −46 LOTlib/Miscellaneous.py
  9. +94 −6 LOTlib/PCFG.py
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -33,7 +33,7 @@ class FiniteBestSet:
It works by storing a priority queue (in the opposite order), and popping off the worst as we need to add more
"""
- def __init__(self, N=float("inf"), max=True, unique=True):
+ def __init__(self, N=Infinity, max=True, unique=True):
self.__dict__.update(locals())
self.max_multiplier = ifelse(self.max, 1, -1) # invert sign
@@ -42,8 +42,11 @@ def __init__(self, N=float("inf"), max=True, unique=True):
self.unique_set = set()
- def __contains__(self, x):
- return (x in self.Q)
+ def __contains__(self, y):
+ for r in self.Q:
+ if r.x == y: return True
+ return False
+ #return (x in self.Q)
def __iter__(self):
for x in self.get_all(): yield x
@@ -68,7 +71,7 @@ def push(self, x, p):
def get_all(self, **kwargs):
""" Return all elements (arbitrary order). Does NOT return a copy. This uses kwargs so that we can call one 'sorted' """
if kwargs.get('sorted', False):
- return [ c.x for c in sorted(self.Q, reverse = not kwargs.get('decreasing',False))]
+ return [ c.x for c in sorted(self.Q, reverse = kwargs.get('decreasing',False))]
else:
return [ c.x for c in self.Q]
View
@@ -93,7 +93,6 @@ def pystring(self):
return str(self.args[0])
elif self.name is not None and self.name.lower() == 'lambda':
#print len(self.bv)
- #print "HERE !!"
return '(lambda '+commalist( [ str(x.name) for x in self.bv])+': '+str(self.args[0])+' )'
else:
if len(self.args) == 1 and self.args[0] is None: # handle weird case with None as single terminal below
@@ -114,8 +113,6 @@ def fullprint(self, d=0):
#return str(self.name)
#else: return '('+self.name + ' '+commalist( [ str(x) for x in self.args], sep1=' ', sep2=' ')+' )'
-
-
# NOTE: in the future we may want to change this to do fancy things
def __str__(self): return self.pystring()
def __repr__(self): return self.pystring()
@@ -166,8 +163,6 @@ def all_leaves(self):
def string_below(self, sep=" "):
return sep.join(map(str, self.all_leaves()))
-
-
def fix_bound_variables(self, d=0, rename=None):
"""
@@ -248,4 +243,9 @@ def is_replicating(self):
A function node is replicating (by definition) if one of its children is of the same type
"""
return any([isFunctionNode(x) and x.returntype == self.returntype for x in self.args])
-
+
+
+
+
+
+
View
@@ -0,0 +1,62 @@
+"""
+ A bunch of standard grammars.
+
+ NOTE: These do not have terminal expansions, since those will vary by program...
+"""
+
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+## Now define the grammars:
+# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Grammar_SimpleBoolean = PCFG()
+Grammar_SimpleBoolean.add_rule('START', 'False', [], 1.0)
+Grammar_SimpleBoolean.add_rule('START', 'True', [], 1.0)
+Grammar_SimpleBoolean.add_rule('START', '', ['BOOL'], 1.0)
+
+Grammar_SimpleBoolean.add_rule('BOOL', 'and_', ['BOOL', 'BOOL'], 1.0)
+Grammar_SimpleBoolean.add_rule('BOOL', 'or_', ['BOOL', 'BOOL'], 1.0)
+Grammar_SimpleBoolean.add_rule('BOOL', 'not_', ['BOOL'], 1.0)
+
+## ~ ~ ~ ~ ~ ~ ~
+
+Grammar_TF = PCFG()
+Grammar_TF.add_rule('START', 'False', [], 1.0)
+Grammar_TF.add_rule('START', 'True', [], 1.0)
+
+## ~ ~ ~ ~ ~ ~ ~
+
+Grammar_NAND = PCFG()
+Grammar_NAND.add_rule('START', '', ['BOOL'], 1.0)
+Grammar_NAND.add_rule('BOOL', 'nand_', ['BOOL', 'BOOL'], 1.0)
+Grammar_NAND.add_rule('BOOL', 'True', [], 1.0)
+Grammar_NAND.add_rule('BOOL', 'False', [], 1.0)
+
+## ~ ~ ~ ~ ~ ~ ~
+
+Grammar_CNF = PCFG()
+Grammar_CNF.add_rule('START', '', ['CONJ'], 1.0)
+Grammar_CNF.add_rule('START', 'True', [], 1.0)
+Grammar_CNF.add_rule('START', 'False', [], 1.0)
+Grammar_CNF.add_rule('CONJ', '', ['DISJ'], 1.0)
+Grammar_CNF.add_rule('CONJ', '', ['PREDICATE'], 1.0)
+Grammar_CNF.add_rule('CONJ', 'not_', ['PREDICATE'], 1.0)
+Grammar_CNF.add_rule('CONJ', 'and_', ['PREDICATE', 'CONJ'], 1.0)
+
+Grammar_CNF.add_rule('DISJ', '', ['PREDICATE'], 1.0)
+Grammar_CNF.add_rule('DISJ', 'not_', ['PREDICATE'], 1.0)
+Grammar_CNF.add_rule('DISJ', 'or_', ['PREDICATE', 'DISJ'], 1.0)
+
+## ~ ~ ~ ~ ~ ~ ~
+
+Grammar_DNF = PCFG()
+Grammar_DNF.add_rule('START', '', ['DISJ'], 1.0)
+Grammar_DNF.add_rule('START', 'True', [], 1.0)
+Grammar_DNF.add_rule('START', 'False', [], 1.0)
+Grammar_DNF.add_rule('DISJ', '', ['CONJ'], 1.0)
+Grammar_DNF.add_rule('DISJ', '', ['PREDICATE'], 1.0)
+Grammar_DNF.add_rule('DISJ', 'not_', ['PREDICATE'], 1.0)
+Grammar_DNF.add_rule('DISJ', 'or_', ['PREDICATE', 'DISJ'], 1.0)
+
+Grammar_DNF.add_rule('CONJ', '', ['PREDICATE'], 1.0)
+Grammar_DNF.add_rule('CONJ', 'not_', ['PREDICATE'], 1.0)
+Grammar_DNF.add_rule('CONJ', 'and_', ['PREDICATE', 'CONJ'], 1.0)
View
@@ -14,13 +14,11 @@
And then you can just copy this over with the copy constructor
"""
from LOTlib.Miscellaneous import *
-from LOTlib.BasicPrimitives import * # needed to eval __call__ here, since that's where they are bound
+import LOTlib.BasicPrimitives # needed to eval __call__ here, since that's where they are bound
from LOTlib.DataAndObjects import FunctionData,UtteranceData
from copy import copy
import numpy
-POSTERIOR_CALL_COUNTER = 0
-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Hypothesis:
@@ -34,6 +32,7 @@ def __init__(self, v=None):
self.set_value(v) # to zero out prior, likelhood, lp
self.prior, self.likelihood, self.lp = [-Infinity, -Infinity, -Infinity] # this should live here in case we overwrite self_value
self.stored_likelihood = None
+ POSTERIOR_CALL_COUNTER = 0
def set_value(self, v):
""" Sets the (self.)value of this hypothesis to v"""
@@ -111,10 +110,10 @@ def propose(self):
# this updates last_prior and last_likelihood
def compute_posterior(self, d):
- global POSTERIOR_CALL_COUNTER
- POSTERIOR_CALL_COUNTER += 1
+ LOTlib.BasicPrimitives.LOCAL_PRIMITIVE_OPS = 0 # Reset this
p = self.compute_prior()
l = self.compute_likelihood(d)
+ self.lp = p+l
return [p,l]
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
@@ -142,6 +141,27 @@ def __ne__(self, other): return (self.value.__ne__(other.value))
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class VectorHypothesis(Hypothesis):
+ """
+ Store N-dimensional vectors (defaultly with Gaussian proposals)
+ """
+
+ def __init__(self, v=None, N=1, proposal=numpy.eye(1)):
+ #print numpy.array([0.0]*N), [prposal
+ if v is None: v = numpy.random.multivariate_normal(numpy.array([0.0]*N), proposal)
+ Hypothesis.__init__(self, v=v)
+
+ self.__dict__.update(locals())
+
+ def propose(self):
+ ## NOTE: Does not copy proposal
+ newv = numpy.random.multivariate_normal(self.v, self.proposal)
+
+ return VectorHypothesis(v=newv, N=self.N, proposal=self.proposal), 0.0 # symmetric proposals
+
+ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
class FunctionHypothesis(Hypothesis):
"""
A special type of hypothesis whose value is a function.
@@ -165,6 +185,7 @@ def copy(self):
def __call__(self, *vals):
""" Make this callable just like a function. Yay python! """
+ #print ">>", vals
return self.fvalue(*vals)
def value2function(self, v):
@@ -291,7 +312,6 @@ def compute_likelihood(self, data):
# the pointsiwe undecayed likelihood for this data point
self.stored_likelihood[i] = log( self.ALPHA*(r==di.output) + (1.0-self.ALPHA)/2.0 )
- #print self.stored_likelihood[i], di, r, di.output, "\n\n"
# the total culmulative decayed likeliood
self.likelihood += self.stored_likelihood[i] * self.likelihood_decay_function(i, N, self.ll_decay)
View
@@ -0,0 +1,30 @@
+"""
+
+ A class for representing sets of hypotheses. This extends list and gives us functions like
+ computing posteriors, normalizing, posterior predictives, etc. We use list instead of set so
+ we can iterate in order
+
+ This uses each hypothesis' .lp slot to store and update things
+"""
+
+#from LOTlib.FiniteBestSet import FiniteBestSet
+#from LOTlib.Miscellaneous import *
+
+#class HypothesisSet(list):
+
+ #def __init__(hyps):
+ #for h in hyps: self.add(h, h.lp)
+
+ #def add(*h): self.extend(h)
+
+ #def normalize():
+ #self.Z = logsumexp([x.lp for x in self])
+
+ ## change in the Q -- should be okay since we alter everything
+ #for h in self: h = h.lp - self.Z
+
+ #def compute_posterior(data):
+ #for h in self: h.compute_posterior(data)
+
+ #def posterior_predictive(data):
+ #pass
View
@@ -36,7 +36,8 @@ def myexit():
MPI.Finalize()
atexit.register(myexit)
-
+def is_master_process():
+ return rank == MASTER_PROCESS
Oops, something went wrong.

0 comments on commit 1ae683f

Please sign in to comment.