]> hydra-www.ietfng.org Git - dyna2/commitdiff
ground backward chaining!
authorTim Vieira <tim.f.vieira@gmail.com>
Wed, 19 Jun 2013 04:05:35 +0000 (00:05 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Wed, 19 Jun 2013 04:05:35 +0000 (00:05 -0400)
examples/ptb.dyna
src/Dyna/Backend/Python/Backend.hs
src/Dyna/Backend/Python/interpreter.py

index 918bd6dcbbca85988f5745c2f7813bd89eda18b6..4a9cbd7a4ce479ded5515cf242ed3af7e09757af 100644 (file)
@@ -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.
index 63cbe8fe7072dee1a2c605dab0e22e68607d86ff..033315b8fb573ded98bca31f7c029662a405cff6 100644 (file)
@@ -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 = []"
index 061ff758efcbffe86035c3e15969954a30de776f..6d5d6652a51cc8b4e49b1b904f79d5975d9245bd 100644 (file)
@@ -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: