Last active
February 16, 2020 20:29
-
-
Save philzook58/50209a590fb294849699e034875fd762 to your computer and use it in GitHub Desktop.
GraphViz category in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
plus = GraphCat.block("+", ["a","b"], ["c"]) | |
I = GraphCat.idd() | |
p1 = plus | |
p2 = p1 @ (p1 * p1) | |
p3 = p1 @ (p2 * p2) | |
p4 = p1 @ (p3 * p3) | |
d = p4.run() | |
d.format = "png" | |
d.render("adders") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import random | |
import graphviz | |
class GraphCat(): | |
GC = GraphCat | |
def __init__(self,res): # just hold the graphviz processor function | |
self.res = res | |
def fresh(n): # makes random numbers for fresh node labels | |
return list([str(random.randint(0,1e9)) for i in range(n)]) | |
def idd(): # identity morhism. 1 input 1 output. | |
def res(g): | |
#nodes = GC.fresh(n) | |
node = GC.fresh(1)[0] | |
#for node in nodes: | |
g.node(node, shape="point") | |
return [node], [node] | |
return GraphCat(res) | |
def compose(g, f): # compose morphisms. Makes graphviz edges between node labels generated by g and f | |
f = f.res | |
g = g.res | |
def res(G): | |
a, b = f(G) | |
b1, c = g(G) | |
assert(len(b) == len(b1)) | |
G.edges(zip(b,b1)) | |
return a, c | |
return GraphCat(res) | |
def par(f, g): #monoidal product. Puts f and g in parallel | |
f = f.res | |
g = g.res | |
def res(G): | |
a, b = f(G) | |
c, d = g(G) | |
return a + c, b + d | |
return GraphCat(res) | |
def dump(): # dump deletes this edge with an empty circle | |
def res(G): | |
node = GC.fresh(1)[0] | |
G.node(node, shape="point", fillcolor="white") | |
return [node], [] | |
return GraphCat(res) | |
def dup(): # duplicate this edge | |
def res(G): | |
node = GC.fresh(1)[0] | |
G.node(node, shape="point", fillcolor="green") | |
return [node], [node, node] | |
return GraphCat(res) | |
def converse(f): # turn input to output of this combinator | |
f = f.res | |
def res(G): | |
a, b = f(G) | |
return b, a | |
return GraphCat(res) | |
def named_simple(name): # a simple labeled 1 input 1 output object | |
def res(G): | |
node = GC.fresh(1)[0] | |
G.node(node,name) | |
return [node], [node] | |
return GraphCat(res) | |
def block(name, inputs, outputs): # an object with labelled ports | |
inputs_label = [f"<{inp}> {inp}" for inp in inputs] | |
outputs_label = [f"<{outp}> {outp}" for outp in outputs] | |
#return # use graphviz to build block with label and n ports | |
def res(G): | |
node = GC.fresh(1)[0] | |
inputs1 = [f"{node}:{inp}" for inp in inputs] | |
outputs1 = [f"{node}:{outp}" for outp in outputs] | |
grphstring = "{ {" + " | ".join(inputs_label) + "} | " + name + " | {" + "|".join(outputs_label) + "} }" | |
G.node(node,grphstring, shape="record") | |
return inputs1, outputs1 | |
return GC(res) | |
def fst(): # project out first par of tuple. semnatically equal to (id * dump) | |
return GraphCat.block("fst", ["a","b"], ["a1"]) | |
def snd(): # dump * id | |
return GraphCat.block("fst", ["a","b"], ["b1"]) | |
def run(self): # will run the object on a fresh graphviz object | |
dot = graphviz.Digraph() | |
self.res(dot) | |
return dot | |
def __matmul__(self, rhs): # matrix multiplication is a natural analog of composition | |
return GC.compose(self, rhs) | |
def __mul__(self, rhs): # monoidal product | |
return GC.par(self, rhs) | |
def __add__(self,rhs): # hmm. What should addition be? Join? | |
pass | |
def const(label): # inject a constant in. A labelled node with 1 outport and no input | |
def res(G): | |
node = GraphCat.fresh(1)[0] | |
G.node(node, str(label)) | |
return [], [node] | |
return GC(res) | |
def cup(): | |
def res(G): | |
nodes = GraphCat.fresh(2) | |
for node in nodes: | |
G.node(node, shape="point") | |
G.edge(nodes[0],nodes[1]) | |
return [], nodes | |
return GraphCat(res) | |
def cap(): | |
return GraphCat.converse(GraphCat.cup()) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment