From: timv Date: Mon, 10 Jun 2013 17:49:27 +0000 (-0400) Subject: tweaks, fixes. X-Git-Url: https://hydra-www.ietfng.org/gitweb/?a=commitdiff_plain;h=60f6a7d6949aad7b60153ac73211c7c84d8477d5;p=dyna2 tweaks, fixes. --- diff --git a/README.md b/README.md index e605139..ebd6027 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ You'll want to have the following programs installed: The python modules required - $ easy_install path.py ipython pygments + $ easy_install numpy ipython pygments path.py You should probably run diff --git a/examples/force.dyna b/examples/force.dyna index bc31d7c..fb9885b 100644 --- a/examples/force.dyna +++ b/examples/force.dyna @@ -15,7 +15,7 @@ shortestpath(U,U) min= 0 for node(U). shortestpath(U,V) min= shortestpath(U,W) + edge(W,V). % "the unit edge length" -edgelen := 5.0. +edgelen := 4.0. f(U,V,T) := (U != V), dist(U,V,T) / (shortestpath(U,V) * edgelen) - 1. diff --git a/src/Dyna/Backend/Python/Backend.hs b/src/Dyna/Backend/Python/Backend.hs index 85103c8..85d599a 100644 --- a/src/Dyna/Backend/Python/Backend.hs +++ b/src/Dyna/Backend/Python/Backend.hs @@ -189,8 +189,11 @@ pslice vs = brackets $ sepBy "," (map (\x -> if nGround (x^.mv_mi) then pretty (x^.mv_var) else ":") vs) <> "," -- add a comma to ensure getitem is always passed a tuple. -piterate vs = parens $ - sepBy "," (map (\x -> if nGround (x^.mv_mi) then "_" else pretty (x^.mv_var)) vs) +ground2underscore x = if nGround (x^.mv_mi) then "_" else pretty (x^.mv_var) + +piterate vs = if length vs == 0 then "_" + else parens $ + sepBy "," (map ground2underscore vs) <> "," -- add a comma to ensure tuple. @@ -205,13 +208,13 @@ pdope_ (OPCheq v val) = return $ "if" <+> pretty v <+> "!=" pdope_ (OPCkne v val) = return $ "if" <+> pretty v <+> "==" <+> pretty val <> ": continue" pdope_ (OPPeel vs i f _) = return $ - --"try:" `above` (indent 4 $ + "try:" `above` (indent 4 $ tupledOrUnderscore vs <+> equals <+> "peel" <> (parens $ pfas f vs <> comma <> pretty i) - --) + ) -- you'll get a "TypeError: 'NoneType' is not iterable." - --`above` "except (TypeError, AssertionError): continue" + `above` "except (TypeError, AssertionError): continue" pdope_ (OPWrap v vs f) = return $ pretty v <+> equals <+> "build" @@ -225,7 +228,7 @@ pdope_ (OPIter v vs f Det (Just (PDBS c))) = return $ pretty (v^.mv_var) pdope_ (OPIter o m f _ Nothing) = do i <- incState return $ let mo = m ++ [o] in - "for" <+> "d" <> pretty i <> "," <> piterate mo + "for" <+> "d" <> pretty i <> "," <> piterate m <> comma <> (ground2underscore o) <+> "in" <+> functorIndirect "chart" f m <> pslice mo <> colon -- XXX Ought to make i and vs conditional on... doing debugging or the diff --git a/src/Dyna/Backend/Python/chart.py b/src/Dyna/Backend/Python/chart.py index a5cb9d4..a9a8b0c 100644 --- a/src/Dyna/Backend/Python/chart.py +++ b/src/Dyna/Backend/Python/chart.py @@ -16,6 +16,8 @@ class Term(object): def __cmp__(self, other): if other is None: return 1 + if not isinstance(other, Term): + return 1 return cmp((self.fn, self.args), (other.fn, other.args)) # default hash and eq suffice because we intern @@ -95,11 +97,11 @@ class Chart(object): if isinstance(val, slice): for term in candidates: if term.value is not None: - yield term, term.args + (term.value,) + yield term, term.args, term.value else: for term in candidates: if term.value == val: - yield term, term.args + (term.value,) # TODO: change codegen to avoid addition.. + yield term, term.args, term.value def insert(self, args): # TODO: rename try: diff --git a/src/Dyna/Backend/Python/debug.py b/src/Dyna/Backend/Python/debug.py index 96f816a..a71e16b 100644 --- a/src/Dyna/Backend/Python/debug.py +++ b/src/Dyna/Backend/Python/debug.py @@ -82,22 +82,21 @@ class Hypergraph(object): id=id(e), label=e.label) - # connect body variables to edge + # connect body variables to edge crux for b in e.body: +# print >> f, '"%s" -> "%s" [arrowhead=none];' % (b, id(e)) print >> f, '"%s" -> "%s";' % (b, id(e)) # connect head variables to edge - print >> f, '"%s" -> "%s";' % (id(e), e.head) +# print >> f, ' "%s" [label="",shape=point];' % (id(e)) + print >> f, ' "%s" -> "%s";' % (id(e), e.head) # node styles for x in self.nodes: -# sty[x].update({'shape': 'circle'}) - sty[e].update({'shape': 'rectangle'}) print >> f, '"%s" [%s]' % (x, ','.join('%s="%s"' % (k,v) for k,v in sty[x].items())) # edge styles for e in self.edges: - sty[e].update({'shape': 'rectangle'}) print >> f, '"%s" [%s]' % (id(e), ','.join('%s="%s"' % (k,v) for k,v in sty[e].items())) print >> f, '}' diff --git a/src/Dyna/Backend/Python/graph.py b/src/Dyna/Backend/Python/graph.py index c6d01de..aa0f213 100644 --- a/src/Dyna/Backend/Python/graph.py +++ b/src/Dyna/Backend/Python/graph.py @@ -9,7 +9,7 @@ def g(nodes, edges, t, ax, interp): ax.set_ylim(-2,2) pos = defaultdict(lambda: (0,0)) - pos.update({node: p for _, (node, _, p) in interp.chart['pos/2'][:,t,:]}) + pos.update({node: p for _, (node, _), p in interp.chart['pos/2'][:,t,:]}) for u,v in edges: if u < v: @@ -21,10 +21,10 @@ def g(nodes, edges, t, ax, interp): ax.text(x,y,s) def animate(interp): - [(_, (niter,))] = interp.chart['niter/0'][:,] + [(_, _, niter)] = interp.chart['niter/0'][:,] - nodes = [name for _, (name, _) in interp.chart['node/1'][:,:]] - edges = [(u,v) for _, (u,v,_) in interp.chart['edge/2'][:,:,:]] + nodes = [name for _, [name], _ in interp.chart['node/1'][:,:]] + edges = [(u,v) for _, [u,v] ,_ in interp.chart['edge/2'][:,:,:]] fig = pl.figure() ax = pl.axes() diff --git a/src/Dyna/Backend/Python/interpreter.py b/src/Dyna/Backend/Python/interpreter.py index ffd2298..70c9185 100644 --- a/src/Dyna/Backend/Python/interpreter.py +++ b/src/Dyna/Backend/Python/interpreter.py @@ -17,12 +17,21 @@ TODO - let Dyna do some of the work for you. think about using Dyna to maintain rules and update handlers. + - magic templates transform for backward chaining, for example: + + :- sigmoid(X) := needs(X), 1 / (1 + exp(-X)). + :- needs(0.5). + BIGGER (new features) ===================== - - TODO: operator for getattr (this will generate slightly different code becase - we don't want to look up by string -- i.e. call the getattr builtin). + - TODO: operator for getattr (this will generate slightly different code + because we don't want to look up by string -- i.e. call the getattr builtin). + + - hook for python imports? + + :- python: from numpy import exp, sqrt, log FASTER @@ -38,7 +47,7 @@ FASTER indexed. - TODO: dynac should provide routines for building terms. We can hack something - together with anf output. + together with anf output, but this will be prety kludgy and inefficient. - TODO: prioritization @@ -81,7 +90,7 @@ USERS DEVELOPERS ========== - - TODO: visualize execution of algorithm on hypergraph -- recreate nwf's + - TODO: visualize execution of solver on hypergraph -- recreate nwf's animations from his ICLP talk. @@ -183,7 +192,8 @@ from utils import ip, red, green, blue, magenta, yellow, \ DynaCompilerError, DynaInitializerException, AggregatorConflict from prioritydict import prioritydict from config import dotdynadir, dynahome - +from numpy import log, exp, sqrt +from numpy.random import uniform from time import time @@ -213,6 +223,8 @@ class Interpreter(object): self.agenda = prioritydict() self.parser_state = '' + self.tape = [] + def newchart(fn): arity = int(fn.split('/')[-1]) return Chart(fn, arity, lambda: aggregator(self.agg_name[fn])) @@ -220,8 +232,6 @@ class Interpreter(object): self.chart = ddict(newchart) self.rules = ddict(Rule) self.errors = {} - # misc - self.trace = file(dotdynadir / 'trace', 'wb') def new_fn(self, fn, agg): # check for aggregator conflict. @@ -343,11 +353,17 @@ class Interpreter(object): def _go(self): "the main loop" + + tape = self.tape + changed = {} agenda = self.agenda errors = self.errors while agenda: item = agenda.pop_smallest() + + tape.append(item) + was = item.value try: now = item.aggregator.fold() @@ -441,16 +457,16 @@ class Interpreter(object): """ assert os.path.exists(filename) + # TODO: need a new tracing tool # for debuggging - with file(filename) as h: - print >> self.trace, magenta % 'Loading new code' - print >> self.trace, yellow % h.read() - - from numpy.random import uniform +# with file(filename) as h: +# print >> self.trace, magenta % 'Loading new code' +# print >> self.trace, yellow % h.read() env = {'_initializers': [], '_updaters': [], '_agg_decl': {}, 'chart': self.chart, 'build': self.build, 'peel': peel, - 'parser_state': None, 'uniform': uniform} + 'parser_state': None, 'uniform': uniform, + 'log': log, 'exp': exp, 'sqrt': sqrt} # load generated code. execfile(filename, env) @@ -541,7 +557,6 @@ def main(): parser.add_argument('source', help='Path to Dyna source file (or plan if --plan=true).', nargs='?') parser.add_argument('--plan', action='store_true', default=False, help='`source` specifies output of the compiler instead of dyna source code.') - parser.add_argument('--trace', default='/tmp/dyna.log') parser.add_argument('-i', dest='interactive', action='store_true', help='Fire-up an IPython shell.') parser.add_argument('-o', dest='output', help='Output chart.') parser.add_argument('--draw', action='store_true', @@ -553,14 +568,6 @@ def main(): interp = Interpreter() - if argv.trace == 'stderr': - interp.trace = sys.stderr - elif argv.trace == 'stdout': - interp.trace = sys.stdout - else: - interp.trace = file(argv.trace, 'wb') - - if argv.source: if not os.path.exists(argv.source): diff --git a/src/Dyna/Backend/Python/repl.py b/src/Dyna/Backend/Python/repl.py index 3893b3c..89ed971 100644 --- a/src/Dyna/Backend/Python/repl.py +++ b/src/Dyna/Backend/Python/repl.py @@ -89,7 +89,7 @@ class REPL(cmd.Cmd, object): self.default(query) try: - [(_, (_, results))] = self.interp.chart['out/1'][self.lineno,:] + [(_, _, results)] = self.interp.chart['out/1'][self.lineno,:] except ValueError: print 'No results.' return diff --git a/src/Dyna/Backend/Python/utils.py b/src/Dyna/Backend/Python/utils.py index a32ef64..fcaadd2 100644 --- a/src/Dyna/Backend/Python/utils.py +++ b/src/Dyna/Backend/Python/utils.py @@ -147,4 +147,15 @@ def rule_source(span, src=None): if __name__ == '__main__': - rule_source('examples/papa.dyna:4:1-examples/papa.dyna:4:47') + #rule_source('examples/papa.dyna:4:1-examples/papa.dyna:4:47') + import sys + + def t(xs): + if isinstance(xs, basestring): + return '"%s"' % xs + else: + return '&t(%s)' % ','.join(t(x) for x in xs) + + for i, [x] in enumerate(parse_sexpr(sys.stdin.read())): + print 'sentence(%s) := %s.' % (i, t(x)) + print