from dreamcoder.program import * def graphPrimitives(result, prefix, view=False): try: from graphviz import Digraph except: eprint("You are missing the graphviz library - cannot graph primitives!") return primitives = { p for g in result.grammars for p in g.primitives if p.isInvented } age = {p: min(j for j,g in enumerate(result.grammars) if p in g.primitives) + 1 for p in primitives } ages = set(age.values()) age2primitives = {a: {p for p,ap in age.items() if a == ap } for a in ages} def lb(s,T=20): s = s.split() l = [] n = 0 for w in s: if n + len(w) > T: l.append("
") n = 0 n += len(w) l.append(w) return " ".join(l) nameSimplification = { "fix1": 'Y', "tower_loopM": "for", "tower_embed": "get/set", "moveHand": "move", "reverseHand": "reverse", "logo_DIVA": '/', "logo_epsA": 'ε', "logo_epsL": 'ε', "logo_IFTY": '∞', "logo_forLoop": "for", "logo_UA": "2π", "logo_FWRT": "move", "logo_UL": "1", "logo_SUBA": "-", "logo_ZL": "0", "logo_ZA": "0", "logo_MULL": "*", "logo_MULA": "*", "logo_PT": "pen-up", "logo_GETSET": "get/set" } name = {} simplification = {} depth = {} def getName(p): if p in name: return name[p] children = {k: getName(k) for _,k in p.body.walk() if k.isInvented} simplification_ = p.body for k,childName in children.items(): simplification_ = simplification_.substitute(k, Primitive(childName,None,None)) for original, simplified in nameSimplification.items(): simplification_ = simplification_.substitute(Primitive(original,None,None), Primitive(simplified,None,None)) name[p] = "f%d"%len(name) simplification[p] = name[p] + '=' + lb(prettyProgram(simplification_, Lisp=True)) depth[p] = 1 + max([depth[k] for k in children] + [0]) return name[p] for p in primitives: getName(p) depths = {depth[p] for p in primitives} depth2primitives = {d: {p for p in primitives if depth[p] == d } for d in depths} englishDescriptions = {"#(lambda (lambda (map (lambda (index $0 $2)) (range $0))))": "Prefix", "#(lambda (lambda (fold $0 $1 (lambda (lambda (cons $1 $0))))))": "Append", "#(lambda (cons LPAREN (#(lambda (lambda (fold $0 $1 (lambda (lambda (cons $1 $0)))))) (cons RPAREN empty) $0)))": "Enclose w/ parens", "#(lambda (unfold $0 (lambda (empty? $0)) (lambda (car $0)) (lambda (#(lambda (lambda (fold $1 $1 (lambda (lambda (cdr (if (char-eq? $1 $2) $3 $0))))))) $0 SPACE))))": "Abbreviate", "#(lambda (lambda (fold $1 $1 (lambda (lambda (cdr (if (char-eq? $1 $2) $3 $0)))))))": "Drop until char", "#(lambda (lambda (fold $1 $1 (lambda (lambda (if (char-eq? $1 $2) empty (cons $1 $0)))))))": "Take until char", "#(lambda (lambda (#(lambda (lambda (fold $0 $1 (lambda (lambda (cons $1 $0)))))) (cons $0 $1))))": "Append char", "#(lambda (lambda (map (lambda (if (char-eq? $0 $1) $2 $0)))))": "Substitute char", "#(lambda (lambda (length (unfold $1 (lambda (char-eq? (car $0) $1)) (lambda ',') (lambda (cdr $0))))))": "Index of char", "#(lambda (#(lambda (lambda (fold $0 $1 (lambda (lambda (cons $1 $0)))))) $0 STRING))": "Append const", "#(lambda (lambda (fold $1 $1 (lambda (lambda (fold $0 $0 (lambda (lambda (cdr (if (char-eq? $1 $4) $0 (cons $1 $0)))))))))))": "Last word", "#(lambda (lambda (cons (car $1) (cons '.' (cons (car $0) (cons '.' empty))))))": "Abbreviate name", "#(lambda (lambda (cons (car $1) (cons $0 empty))))": "First char+char", "#(lambda (#(lambda (lambda (fold $0 $1 (lambda (lambda (cons $1 $0)))))) (#(lambda (lambda (fold $1 $1 (lambda (lambda (fold $0 $0 (lambda (lambda (cdr (if (char-eq? $1 $4) $0 (cons $1 $0))))))))))) STRING (index (length (cdr $0)) $0)) $0))": "Ensure suffix" } def makeUnorderedGraph(fn): g = Digraph() g.graph_attr['rankdir'] = 'LR' for p in primitives: g.node(getName(p), label="<%s>"%simplification[p]) for p in primitives: children = {k for _,k in p.body.walk() if k.isInvented} for k in children: g.edge(name[k],name[p]) try: g.render(fn,view=view) eprint("Exported primitive graph to",fn) except: eprint("Got some kind of error while trying to render primitive graph! Did you install graphviz/dot?") def makeGraph(ordering, fn): g = Digraph() g.graph_attr['rankdir'] = 'RL' if False: with g.subgraph(name='cluster_0') as sg: sg.graph_attr['rank'] = 'same' sg.attr(label='Primitives') for j, primitive in enumerate(result.grammars[-1].primitives): if primitive.isInvented: continue sg.node("primitive%d"%j, label=str(primitive)) for o in sorted(ordering.keys()): with g.subgraph(name='cluster_%d'%o) as sg: sg.graph_attr['rank'] = 'same' #sg.attr(label='Depth %d'%o) for p in ordering[o]: if str(p) in englishDescriptions: thisLabel = '<%s
%s>'%(englishDescriptions[str(p)],simplification[p]) else: eprint("WARNING: Do not have an English description of:\n",p) eprint() thisLabel = "<%s>"%simplification[p] sg.node(getName(p), label=thisLabel) for p in ordering[o]: children = {k for _,k in p.body.walk() if k.isInvented} for k in children: g.edge(name[k],name[p]) eprint("Exporting primitive graph to",fn) try: g.render(fn,view=view) except Exception as e: eprint("Got some kind of error while trying to render primitive graph! Did you install graphviz/dot?") print(e) makeGraph(depth2primitives,prefix+'depth.pdf') makeUnorderedGraph(prefix+'unordered.pdf') #makeGraph(age2primitives,prefix+'iter.pdf')