예제 #1
0
파일: Parsing.py 프로젝트: sa-/LOTlib
def list2FunctionNode(l, style="atis"):
    """
            Takes a list *l* of lambda arguments and maps it to a function node.

            The *style* of lambda arguments could be "atis", "scheme", etc.
    """

    if isinstance(l, list):
        if len(l) == 0: return None
        elif style is 'atis':
            rec = lambda x: list2FunctionNode(
                x, style=style)  # a wrapper to my recursive self
            if l[0] == 'lambda':
                return FunctionNode('FUNCTION',
                                    'lambda', [rec(l[3])],
                                    generation_probability=0.0,
                                    bv_type=l[1],
                                    bv_args=None)  # TOOD: HMM WHAT IS THE BV?
            else:
                return FunctionNode(l[0],
                                    l[0],
                                    map(rec, l[1:]),
                                    generation_probability=0.0)
        elif style is 'scheme':
            raise NotImplementedError

    else:  # for non-list
        return l
예제 #2
0
def compose_and_reduce(*args):
    """
            ((args[0] args[1]) args[2]) ..

            This copies each arg, so you don't have to
    """
    assert len(args) > 1

    fn = FunctionNode(None, 'EXPR', 'apply_', [copy(args[0]), copy(args[1])])
    for i in xrange(2, len(args)):
        fn = FunctionNode(fn, 'EXPR', 'apply_', [fn, copy(args[i])])

    try:
        return lambda_reduce(fn)
    except RuntimeError:
        return None
예제 #3
0
def compose_and_reduce(*args):
    """
            ((args[0] args[1]) args[2]) ..

            This copies each arg, so you don't have to
    """

    ## TODO: UGH THIS CIRCULAR IMPORT
    from LOTlib.FunctionNode import FunctionNode
    assert len(args) > 1

    fn = FunctionNode('EXPR', 'apply_', [copy(args[0]), copy(args[1])])
    for i in xrange(2,len(args)):
        fn = FunctionNode('EXPR', 'apply_', [fn, copy(args[i])])

    try:
        return lambda_reduce(fn)
    except RuntimeError:
        return None
예제 #4
0
    def generate(self, x='*USE_START*', d=0):
        """
              RealValueGrammar.generate may create gaussians or uniforms when given "*gaussian*" and "*uniform*" as the nonterminal type.
              Otherwise, this is identical to LOTlib.Grammar
        """
            if x == '*USE_START*':
                x = self.start

            if x=='*gaussian*':
                # TODO: HIGHLY EXPERIMENTAL!!
                # Wow this is really terrible for mixing...
                v = np.random.normal()
                gp = normlogpdf(v, 0.0, 1.0)
                return FunctionNode(returntype=x, name=str(v), args=None, generation_probability=gp, ruleid=0, resample_p=CONSTANT_RESAMPLE_P ) ##TODO: FIX THE ruleid

            elif x=='*uniform*':
                v = np.random.rand()
                gp = 0.0
                return FunctionNode(returntype=x, name=str(v), args=None, generation_probability=gp, ruleid=0, resample_p=CONSTANT_RESAMPLE_P ) ##TODO: FIX THE ruleid
            else:
                # Else call normal generation
                Grammar.generate(self,x,d=d)
예제 #5
0
    def make(cls, make_h0, data, grammar, **args):
        """ This is the initializer we use to create this from a grammar, creating children for each way grammar.start can expand """
        h0 = make_h0(value=None)

        ## For each nonterminal, find out how much (in the prior) we pay for a hole that size
        hole_penalty = dict()
        dct = defaultdict(list)  # make a lit of the log_probabilities below
        for _ in xrange(1000):  # generate this many trees
            t = grammar.generate()
            for fn in t:
                dct[fn.returntype].append(grammar.log_probability(fn))
        hole_penalty = {nt: sum(dct[nt]) / len(dct[nt]) for nt in dct}

        #We must modify the grammar to include one more nonterminal here
        mynt = "<hsmake>"
        myr = GrammarRule(mynt, '', [grammar.start], p=1.0)
        grammar.rules[mynt].append(myr)
        return cls(make_h0(
            value=FunctionNode(None, mynt, '', [grammar.start], rule=myr)),
                   data,
                   grammar,
                   hole_penalty=hole_penalty,
                   parent=None,
                   **args)  # the top state
예제 #6
0
    def propose_tree(self, t):
        """
			Delete:
				- find an apply
				- take the interior of the lambdathunk and sub it in for the lambdaarg everywhere, remove the apply
			Insert:
				- Find a node
				- Find a subnode s
				- Remove all repetitions of s, create a lambda thunk
				- and add an apply with the appropriate machinery
		"""

        newt = copy(t)
        f, b = 0.0, 0.0
        success = False  #acts to tell us if we found and replaced anything

        def is_extractable(n):
            # We must check that this doesn't contain any bound variables of outer lambdas
            introduced_bvs = set(
            )  # the bvs that are introduced below n (and are thus okay)
            for ni in n:
                if ni.ruleid < 0 and ni.name not in introduced_bvs:  # If it's a bv
                    return False
                elif ni.islambda() and ni.bv_name is not None:
                    introduced_bvs.add(ni.bv_name)
            return True

        def is_apply(x):
            return (x.name == 'apply_') and (
                len(x.args)
                == 2) and x.args[0].islambda() and not x.args[1].islambda()

        # ------------------
        if random() < 0.5:  #INSERT MOVE

            # sample a node
            for ni, di, resample_p, Z in self.grammar.sample_node_via_iterate(
                    newt):

                # Sample a subnode -- NOTE: we must use copy(ni) here since we modify this tree, and so all hell breaks loose otherwise
                for s, sdi, sresample_p, sZ in self.grammar.sample_node_via_iterate(
                        copy(ni), predicate=is_extractable):
                    success = True

                    below = copy(ni)
                    varname = 'Y' + str(di + 1)

                    # replace with the variables
                    # TODO: FIX THE RID HERE -- HOW DO WE TREAT IT?
                    below.replace_subnodes(
                        s,
                        FunctionNode(s.returntype, varname, None, ruleid=-999))

                    # create a new node, the lambda abstraction
                    fn = FunctionNode(below.returntype, 'apply_', [ \
                     FunctionNode('LAMBDAARG', 'lambda', [ below ], bv_prefix='Y', bv_name=varname, bv_type=s.returntype, bv_args=[] ),\
                     s
                      ] )

                    # Now convert into a lambda abstraction
                    ni.setto(fn)

                    f += (log(resample_p) - log(Z)) + (log(sresample_p) -
                                                       log(sZ))

        else:  # DELETE MOVE

            resample_p = None
            for ni, di, resample_p, Z in self.grammar.sample_node_via_iterate(
                    newt, predicate=is_apply):
                success = True

                ## what does the variable look like? Here a thunk with bv_name
                var = FunctionNode(ni.args[0].bv_type, ni.args[0].bv_name,
                                   None)

                assert len(ni.args) == 2
                assert len(ni.args[0].args) == 1

                newni = ni.args[0].args[0]  # may be able to optimize away?

                ## and remove
                newni.replace_subnodes(var, ni.args[1])

                ##print ":", newni
                ni.setto(newni)
                f += (log(resample_p) - log(Z))

            if resample_p is None: return [newt, 0.0]

            #newZ = self.grammar.resample_normalizer(newt, predicate=is_replacetype)
            ##to go back, must choose the
            #b += log(resample_p) - log(newZ)

    #	newt.fix_bound_variables() ## TODO: I think these are just from old versions
    #	newt.reset_function() # make sure we update the function
        if not success:
            return [copy(t), 0.0]
        else:
            return [newt, f - b]