use FIFO priorities added argument for runing post-processing scripts.
--- /dev/null
+% Try to use the force to lay out a few nodes
+
+% Kamada-Kawai force directed layout
+% http://graphael.cs.arizona.edu/papers/graphael_final.pdf
+
+% distance between U and V at time T.
+dist(U,V,T) := (x(U,T) - x(V,T))**2 + (y(U,T) - y(V,T))**2
+ for true is (T < niter). % restrict to niter iterations.
+
+% all pairs shortest path.
+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.
+
+f(U,V,T) := true is (U != V), dist(U,V,T) / (shortestpath(U,V) * edgelen) - 1.
+
+forceX(V,T) += f(U,V,T) * (x(U,T) - x(V,T)).
+forceY(V,T) += f(U,V,T) * (y(U,T) - y(V,T)).
+
+a := 0.15.
+niter := 100.
+
+% should `a` be negative?
+x(U,T) += a * forceX(U,T-1).
+y(U,T) += a * forceY(U,T-1).
+
+edge("a", "b") := 1.
+edge("a", "c") := 1.
+edge("a", "d") := 1.
+edge("a", "e") := 1.
+edge("b", "h") := 1.
+edge("b", "i") := 1.
+edge("b", "j") := 1.
+edge("e", "f") := 1.
+edge("e", "g") := 1.
+edge("a", "i") := 1.
+
+edge(A,B) := 1 for edge(B,A). % make graph symmetric.
+
+% collect nodes.
+node(U) := true for edge(U,_).
+node(U) := true for edge(_,U).
+
+% randomly initialize node positions.
+x("a",0) += uniform(0,1). y("a",0) += uniform(0,1).
+x("b",0) += uniform(0,1). y("b",0) += uniform(0,1).
+x("c",0) += uniform(0,1). y("c",0) += uniform(0,1).
+x("d",0) += uniform(0,1). y("d",0) += uniform(0,1).
+x("e",0) += uniform(0,1). y("e",0) += uniform(0,1).
+x("f",0) += uniform(0,1). y("f",0) += uniform(0,1).
+x("g",0) += uniform(0,1). y("g",0) += uniform(0,1).
+x("h",0) += uniform(0,1). y("h",0) += uniform(0,1).
+x("i",0) += uniform(0,1). y("i",0) += uniform(0,1).
+x("j",0) += uniform(0,1). y("j",0) += uniform(0,1).
+
+pos(U,T) := tuple(x(U, T), y(U, T)).
+
+% import pylab aspl
+% for U,V,_ in edge:
+% pl.plot([x[U], x[V]],
+% [y[U], y[V]])
go ("%",2) = Just $ PDBS $ infixOp "%"
go ("+",2) = Just $ PDBS $ infixOp "+"
- go ("mod",2) = Just $ PDBS $ call "mod"
+ go ("mod",2) = Just $ PDBS $ infixOp "%"
go ("abs",1) = Just $ PDBS $ call "abs"
go ("log",1) = Just $ PDBS $ call "log"
go ("exp",1) = Just $ PDBS $ call "exp"
+ go ("uniform", _) = Just $ PDBS $ call "uniform"
+
go ("<=",2) = Just $ PDBS $ infixOp "<="
go ("<",2) = Just $ PDBS $ infixOp "<"
go ("=",2) = Just $ PDBS $ infixOp "="
return fn
return '%s(%s)' % (fn, ','.join(map(_repr, self.args)))
+ def __getstate__(self):
+ return (self.fn, self.args, self.value, self.aggregator)
+
+ def __setstate__(self, state):
+ (self.fn, self.args, self.value, self.aggregator) = state
+
__add__ = __sub__ = __mul__ = notimplemented
def __getitem__(self, s):
assert len(s) == self.arity + 1, \
- 'item width mismatch: arity %s, item %s' % (self.arity, len(s))
+ 'Chart %r: item width mismatch: arity %s, item %s' % (self.name, self.arity, len(s))
args, val = s[:-1], s[-1]
MISC
====
+ - TODO: dyna rules for chart display or visualization via viz_chart. Rules will
+ use string formatting or python eval magic.
+
+ - TODO: catch compiler errors (for example, ^C while compiling results in a
+ "Compiler panic! This is almost assuredly not your fault!...").
+
+ - TODO: dynac should provide routines for building terms. We can hack something
+ together with anf output.
+
- TODO: faster charts (dynamic argument types? jason's trie data structure)
- TODO: write all files to ~/.dyna
- - TODO: `None` does not propagate, eventually it will becase of the `?` prefix
+ - TODO: `None` does not propagate, eventually it will because of the `?` prefix
operator.
- TODO: (@nwf) String quoting (see example/stringquote.py)
- approximate deletion ("buckets"), find the nearest neighbor and delete it.
- - hybrid: maintain streaming sum and the bag check periodically for quality
- and null.
+ - hybrid: maintain streaming sum parallel to the BAggregator and check
+ periodically for quality and null.
- numeric approximations, stream folding (fails to get null)
named with numeric values of variables.
+JUST FOR FUN
+============
+
+ - overload everything so that values maintain provenance and we can inspect the
+ entire fine-grained circuit.
+
+ - play around with python modules uncertainties (error propagation and
+ gradients), look into tools for dimensional analysis.
+
+
What is null?
=============
from prioritydict import prioritydict
from config import dotdynadir, dynahome
+from time import time
class AggregatorConflict(Exception):
def __init__(self, key, expected, got):
"""
# and now, for something truely horrendous -- look up an item by it's
- # string value!
+ # string value! This could fail because of whitespace or trivial
+ # formatting differences.
items = {}
for c in self.chart.values():
for i in c.intern.values():
try:
item = items[item]
except KeyError:
- print 'item not found.'
+ print 'item not found. This could be because of a trivial formatting differences...'
return
print item
- while item.value:
- print item.value
- self.emit(item, item.value, None, sys.maxint, delete=True)
- self.go()
+ self.emit(item, item.value, None, sys.maxint, delete=True)
+ self.go()
def retract_rule(self, idx):
"Retract rule and all of it's edges."
assert isinstance(idx, str)
-
try:
rule = self.rules.pop(idx)
except KeyError:
print 'Rule %s not found.' % idx
return
-
# Step 1: remove update handlers
- print 'removing rule', rule
- print ' removing updaters'
for u in rule.updaters:
- print ' ', u.__doc__
- deleted = False
for hs in self.updaters.values():
for i, h in enumerate(hs):
if u is h:
del hs[i]
- assert not u in hs
- deleted = True
- assert deleted, 'should always find handler.'
- deleted = False
-
+ break
+ else:
+ assert False, "failed to find updater."
# Step 2: run initializer in delete mode
rule.init(emit=self.delete_emit)
-
# Step 3; go!
self.go()
def go(self):
+ try:
+ self._go()
+ except KeyboardInterrupt: # TODO: need to be safer in some parts of the code.
+ print '^C'
+ self.dump_charts()
+
+ def _go(self):
"the main loop"
changed = {}
item.aggregator.dec(val, ruleix, variables)
else:
item.aggregator.inc(val, ruleix, variables)
- self.agenda[item] = 0 # everything is high priority
+# self.agenda[item] = 0 # everything is high priority
+ self.agenda[item] = time()
def repl(self, hist):
import repl
print >> self.trace, magenta % 'Loading new code'
print >> self.trace, yellow % h.read()
+ from numpy.random import uniform
+
env = {'_initializers': [], '_updaters': [], '_agg_decl': {},
'chart': self.chart, 'build': self.build, 'peel': peel,
- 'parser_state': None}
+ 'parser_state': None, 'uniform': uniform}
# load generated code.
execfile(filename, env)
parser.add_argument('-o', dest='output', help='Output chart.')
parser.add_argument('--draw', action='store_true',
help='Output html page with hypergraph and chart.')
+ parser.add_argument('--postprocess', type=file,
+ help='run post-processing script.')
argv = parser.parse_args()
if argv.draw:
interp.draw()
+ if argv.postprocess is not None:
+ execfile(argv.postprocess.name, {'interp': interp})
+
if __name__ == '__main__':
main()
from config import dotdynadir
import debug
+
class REPL(cmd.Cmd, object):
def __init__(self, interp, hist):