]> hydra-www.ietfng.org Git - dyna2/commitdiff
added `mean=` aggregator.
authorTim Vieira <tim.f.vieira@gmail.com>
Mon, 1 Jul 2013 21:12:53 +0000 (17:12 -0400)
committerTim Vieira <tim.f.vieira@gmail.com>
Mon, 1 Jul 2013 21:12:53 +0000 (17:12 -0400)
`set=` and `bag=` aggregators return dyna lists. So we can use the results in
other rules.

make sure we show changes when we `retract_rule`

when we show changes we print a header

    > a += 1.

    Changes
    =======
    a = 1.

Also, pycall translates python and dyna lists.

Fixed formatting of lists, strings are double quoted.

Fixed `query [A|_] is [1,2,3]` -- we weren't substituting `A`.

src/Dyna/Backend/Python/Backend.hs
src/Dyna/Backend/Python/defn.py
src/Dyna/Backend/Python/repl.py
src/Dyna/Backend/Python/stdlib.py
src/Dyna/Backend/Python/term.py
src/Dyna/Backend/Python/utils.py
test/repl/aggregator-conflict.expect
test/repl/late-aggregator-assignment.expect
test/repl/retract-rule.expect

index 8645c6b0aa4f5a21e2d4921a49549210030d2c49..d5e2f9be69fd4732c0304b0280774c4230d1e0c5 100644 (file)
@@ -54,7 +54,8 @@ aggrs = S.fromList
   , "and=" , "or=" , "&=" , "|="
   , ":-"
   , "="
-  , "majority=" , "set=" , "bag="
+  , "majority=" , "mean="
+  , "set=" , "bag="
   , ":="
   , "dict="
   ]
index a67c4d2c638967906280ee116755ab4c1efbbc34..6a6bd893d0f4f0cdd51fbb7a791238b9f4aa1161 100644 (file)
@@ -120,8 +120,17 @@ class DictEquals(BAggregator):
 
 class majority_equals(BAggregator):
     def fold(self):
-        [(k,_)] = self.most_common(1)
-        return k
+        [(k,c)] = self.most_common(1)
+        if c > 0:
+            return k
+
+class mean_equals(BAggregator):
+    def fold(self):
+        # TODO: support negative multiplicity or throw an error
+        s = [k*m for k, m in self.iteritems() if m > 0]
+        if len(s):
+            n = sum(m for _, m in self.iteritems() if m > 0)
+            return reduce(operator.add, s) / n
 
 class max_equals(BAggregator):
     def fold(self):
@@ -173,13 +182,15 @@ class b_or_equals(BAggregator):
 
 class set_equals(BAggregator):
     def fold(self):
+        from stdlib import todynalist
         s = {x for x, m in self.iteritems() if m > 0}
         if len(s):
-            return s
+            return todynalist(s)
 
 class bag_equals(BAggregator):
     def fold(self):
-        return Counter(self)
+        from stdlib import todynalist
+        return todynalist(Counter(self).elements())
 
 
 # map names to functions
@@ -196,6 +207,7 @@ defs = {
     'majority=': majority_equals,
     'set=': set_equals,
     'bag=': bag_equals,
+    'mean=': mean_equals,
 }
 
 def aggregator(name):
index fccbf9e3c4a2b667c8ebaa45fa76e233712a20d6..d88525f86d33c160dc06c1b3273b026e786b49c6 100644 (file)
@@ -87,9 +87,12 @@ class REPL(cmd.Cmd, object):
         except ValueError:
             print 'Please specify an integer. Type `help retract_rule` to read more.'
         else:
-            if self.interp.retract_rule(idx) is None:
+            changes = self.interp.retract_rule(idx)
+            if changes is None:
                 print 'List available by typing `rules`'
                 print
+            else:
+                self._changed(changes)
 
     def do_exit(self, _):
         """
@@ -201,9 +204,7 @@ class REPL(cmd.Cmd, object):
             print 'No results.'
             return
         for val, bindings in results:
-            #if not bindings:
-            #    print '   ', _repr(val)
-            print '  ', _repr(val), 'where', drepr(dict(bindings))
+            print _repr(val), 'where', drepr(dict(bindings))
         print
 
     def do_query(self, q):
@@ -269,9 +270,13 @@ class REPL(cmd.Cmd, object):
     def _changed(self, changed):
         if not changed:
             return
-        print '============='
+
+        print
+        print 'Changes'
+        print '======='
         for x, v in sorted(changed.items()):
             print '%s = %s.' % (x, _repr(v))
+        print
 
 #    def _changed_subscriptions(self, changed):
 #
index a96ffd548481ba4696ffcd0b366dd44329c372e7..7b1d8da4d7716e7d47dc9fcd210fc9ccd370bbfc 100644 (file)
@@ -11,17 +11,29 @@ except ImportError:                       # XXX: should probably issue a warning
         return _random() * (b - a) + a
 
 def split(s, delim='\s+'):
-    return _todynalist(re.split(delim, s))
+    return todynalist(re.split(delim, s))
 
 def pycall(name, *args):
     """
     Temporary foreign function interface - call Python functions from dyna!
     """
+    args = tuple(topython(x) for x in args)
     x = eval(name)(*args)
-    if isinstance(x, list):
-        return _todynalist(x)
+    return todyna(x)
+
+def todyna(x):
+    if isinstance(x, (list, tuple)):
+        return todynalist(x)
+    return x
+
+def topython(x):
+    if isinstance(x, (Cons, Nil)):
+        return x.aslist
     return x
 
+def todynalist(x):
+    return _todynalist(list(x))
+
 def _todynalist(x):
     if not x:
         return Nil
index c0bf6da329304646ea176a49758104791dc58964..9d093dc56de9757a44b497af042964507adc08bb 100644 (file)
@@ -47,43 +47,39 @@ class Term(object):
 
     __add__ = __sub__ = __mul__ = notimplemented
 
-from term import Term
 
 class Cons(Term):
+
     def __init__(self, head, tail):
         self.head = head
         self.tail = tail
         assert isinstance(tail, (Cons, _Nil)), tail
         Term.__init__(self, 'cons/2', (head, tail))
         self.aggregator = Aggregator()
-    def tolist(self):
-        return [self.head] + self.tail.tolist()
-    def __repr__(self):
-        return repr(self.tolist())
-
-    def __iter__(self):
-#        return iter([(x,(x,),x) for x in self.tolist()])
-        for a in self.tolist():
+        self.aslist = [self.head] + self.tail.aslist
 
-            if not isinstance(a, Term):
-                yield a, (None,), a
+    def __repr__(self):
+        return '[%s]' % (', '.join(map(_repr, self.aslist)))
 
-            else:
-                yield a, (None,), a
+#    def __iter__(self):
+#        for a in self.aslist:
+#            if not isinstance(a, Term):
+#                yield a, (None,), a
+#            else:
+#                yield a, (None,), a
 
     def __eq__(self, other):
         try:
-            return self.tolist() == other.tolist()
+            return self.aslist == other.aslist
         except AttributeError:
             return False
 
+
 class _Nil(Term):
     def __init__(self):
         Term.__init__(self, 'nil/0', ())
         self.aggregator = Aggregator()
-
-    def tolist(self):
-        return []
+        self.aslist = []
     def __repr__(self):
         return '[]'
 
index ccf50bddd901e0608aec113cda9236c656c569f1..d66b00700b101da135e46a5729e9b6377d844dc3 100644 (file)
@@ -81,12 +81,12 @@ def dynac(f, out, anf=None, compiler_args=()):
 def lexer(term):
     return re.findall('"[^"]*"'               # string
                       '|[a-z][a-zA-Z_0-9]*'   # functor
-                      '|[A-Z][a-zA-Z0-9_]*'   # variable
-                      '|[(), ]+'              # parens and comma
+                      '|[A-Z_][a-zA-Z0-9_]*'   # variable
+                      '|[(), \[\]|]+'         # parens and comma
                       '|[^(), ]+', term)      # everything else
 
 
-def subst(term, v, show_vars=False):
+def subst(term, v):
     """
     >>> subst('f("asdf",*g(1,X, Y), X+1)', {'X': 1234})
     'f("asdf",*g(1,1234, Y), 1234+1)'
@@ -99,10 +99,6 @@ def subst(term, v, show_vars=False):
 
     """
     assert isinstance(v, dict)
-
-    if show_vars:
-        return ''.join((x + (red % ('=' + _repr(v[x]))) if x in v else x) for x in lexer(term))
-
     return ''.join((_repr(v[x]) if x in v else x) for x in lexer(term))
 
 
index cebfc6e95c4390251d6270ab23c6cf4a62435d44..1bc2e60938d7614bb17ad7f2c857a5b5fd12c702 100644 (file)
@@ -1,5 +1,8 @@
-> > =============
+> > 
+Changes
+=======
 a = 1.
+
 > DynaCompilerError:
 Encountered error in input program:
  Conflicting aggregators; rule <repl>
index 7f69603dc5662d198220d9e74749ff59a5550a6c..6321d06b1980bb537ec31855670eeefaee070cfe 100644 (file)
@@ -3,17 +3,23 @@ Rules
 =====
   0: a += b * c.
 
-> =============
+> 
+Changes
+=======
 b = 2.
+
 > 
 Rules
 =====
   0: a += b * c.
   1: b := 2.
 
-> =============
+> 
+Changes
+=======
 a = 6.
 c = 3.
+
 > 
 Rules
 =====
index abb16d119f4924ec0beb5d85ccdc3d39e7f156c7..2e477bac0aedc89c36b1e3f9976ac33b06b85fc5 100644 (file)
@@ -1,9 +1,18 @@
-> > =============
+> > 
+Changes
+=======
 a = 1.
-> =============
+
+> 
+Changes
+=======
 b = 1.
-> =============
+
+> 
+Changes
+=======
 a = 2.
+
 > 
 Rules
 =====
@@ -17,7 +26,17 @@ Solution
 a = 2.
 b = 1.
 
-> > > 
+> 
+Changes
+=======
+a = 1.
+
+> 
+Changes
+=======
+b = null.
+
+> 
 Solution
 ========
 a = 1.