From: Tim Vieira Date: Wed, 19 Jun 2013 04:05:35 +0000 (-0400) Subject: ground backward chaining! X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=882df6b3f8b1a0ff4aac78b72e262e445539e425;p=dyna2 ground backward chaining! --- diff --git a/examples/ptb.dyna b/examples/ptb.dyna index 918bd6d..4a9cbd7 100644 --- a/examples/ptb.dyna +++ b/examples/ptb.dyna @@ -115,17 +115,25 @@ sym(&t(A,B,C)) := needs(&t(A,B,C)), A. rules(&t(X,Y)) := needs(&t(X,Y)), &r(X, sym(Y)). rules(&t(X,Y,Z)) := needs(&t(X,Y,Z)), needs(Z), &r(X, sym(Y), sym(Z)). +:- dispos &t(&). +:- dispos &t(&,&). +:- dispos &t(&,&,&). + % count the number of words in a subtree +:- backchain numwords/1. numwords(X) := 1. numwords(t(X,Y)) := numwords(Y). numwords(t(X,Y,Z)) := numwords(Y) + numwords(Z). % extract word and it's position in tree +:- backchain word/2. word(0, X) := X. word(I, t(X,Y)) := word(I, Y). word(I, t(X,Y,Z)) := I < numwords(Y), word(I, Y). word(I, t(X,Y,Z)) := I >= numwords(Y), word(I-numwords(Y), Z). +%senword(S, I) := word(I, sentence(S)), between(0,I,numwords(S)). + % unnormalized c(X,Y) += r(X,Y) is rules(&t(X1,Y1)), 1. c(X,Y,Z) += r(X,Y,Z) is rules(&t(X1,Y1,Z1)), 1. diff --git a/src/Dyna/Backend/Python/Backend.hs b/src/Dyna/Backend/Python/Backend.hs index 63cbe8f..033315b 100644 --- a/src/Dyna/Backend/Python/Backend.hs +++ b/src/Dyna/Backend/Python/Backend.hs @@ -260,12 +260,12 @@ pdope_ bc (OPIter o m f DetSemi Nothing) | (f,length m) `S.member` bc = vcat [ pretty (o^.mv_var) <+> equals - <+> "gbc" <> brackets (pfas f m) - <> tupled (map (pretty . _mv_var) m) + <+> "gbc" + <> tupled (pfas f m : map (pretty . _mv_var) m) , "if" <+> pretty (o^.mv_var) <+> "is not None" <> colon ] -pdope_ bc (OPIter o m f _ Nothing) = +pdope_ bc (OPIter o m f _ Nothing) = assert (not $ (f,length m) `S.member` bc) $ do i <- incState return $ let mo = m ++ [o] in @@ -383,6 +383,7 @@ driver am um is bc qp pr fh = do hPutStrLn fh "\"\"\"" hPutStrLn fh "" + hPutStrLn fh $ "queries = []" hPutStrLn fh $ "agg_decl = {}" hPutStrLn fh $ "updaters = []" hPutStrLn fh $ "initializers = []" diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index 061ff75..6d5d665 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -234,12 +234,13 @@ class Rule(object): self.idx = idx self.init = None self.updaters = [] + self.query = None @property def span(self): - return parse_attrs(self.init)['Span'] + return parse_attrs(self.init or self.query)['Span'] @property def src(self): - return parse_attrs(self.init)['rule'] + return parse_attrs(self.init or self.query)['rule'] def __repr__(self): return 'Rule(%s, %r)' % (self.idx, self.src) @@ -266,6 +267,8 @@ class Interpreter(object): # declarations self.agg_name = defaultdict(none) self.updaters = defaultdict(list) + self._gbc = defaultdict(list) + # data structures self.agenda = prioritydict() self.parser_state = '' @@ -488,6 +491,34 @@ class Interpreter(object): rule.updaters.append(handler) handler.rule = rule + + def gbc(self, fn, *args): + # TODO: need to distinguish `unknown` from `null` + + head = self.build(fn, *args) + + if head.value is not None: + return head.value + + head.aggregator.clear() + + def _emit(item, val, ruleix, variables): + assert item is head, [item, head] + head.aggregator.inc(val, ruleix, variables) + + for h in self._gbc[fn]: + h(*args, emit=_emit) + + head.value = head.aggregator.fold() + return head.value + + def new_query(self, fn, ruleix, handler): + self._gbc[fn].append(handler) + rule = self.rules[ruleix] + assert rule.query is None + rule.query = handler + handler.rule = rule + def new_initializer(self, ruleix, init): rule = self.rules[ruleix] assert rule.init is None @@ -525,6 +556,7 @@ class Interpreter(object): for k,v in [('chart', self.chart), ('build', self.build), + ('gbc', self.gbc), ('peel', peel), ('uniform', uniform), ('log', log), ('exp', exp), ('sqrt', sqrt), ('pycall', pycall)]: @@ -538,6 +570,9 @@ class Interpreter(object): for k, v in env.agg_decl.items(): self.new_fn(k, v) + for fn, r, h in env.queries: + self.new_query(fn, r, h) + try: if initialize: # only run new initializers @@ -555,12 +590,11 @@ class Interpreter(object): # - maybe transaction isn't want I mean. Maybe all I want (for now # is to avoid ^C. - # add new updaters for fn, r, h in env.updaters: self.new_updater(fn, r, h) - # add new initializers for r, h in env.initializers: self.new_initializer(r, h) + # accept the new parser state self.parser_state = env.parser_state # process emits @@ -646,7 +680,8 @@ def main(): if args.plan: plan = args.source else: - plan = dotdynadir / 'tmp' / args.source.read_hexhash('sha1') + '.plan.py' +# plan = dotdynadir / 'tmp' / args.source.read_hexhash('sha1') + '.plan.py' + plan = args.source + '.plan.py' dynac(args.source, plan) if args.profile: