From 3d5cc0efd35017e3d631a9484d538a63d049ed94 Mon Sep 17 00:00:00 2001 From: Josef Vonasek Date: Fri, 17 May 2019 19:46:13 +0200 Subject: [PATCH] Update README --- README.md | 31 ++++++++++++++++-- src/ILP.py | 8 ++--- src/{graph.coffee => heuristic.coffee} | 44 ++++++++++++++++---------- src/main.coffee | 12 +++---- 4 files changed, 66 insertions(+), 29 deletions(-) rename src/{graph.coffee => heuristic.coffee} (85%) diff --git a/README.md b/README.md index 5915c51..2773290 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,29 @@ -## RUN +## YOU NEED -1. npm install -2. npm start \ No newline at end of file +1. npm +2. nodejs +3. python, gurobi +4. coffeescript + +## RUN HEURISTIC +``` +cd src +node --require coffeescript/register heuristic.coffee +``` +the input folder name is hardcoded in the `heuristic.coffee` file on line: 266 + +`state = new State readCSV '../data/Bool/and'` + +## RUN ILP + +first run heuristic (this will create `src/layoutdata.coffee`) +``` +cd src +python ILP.py +``` + +## RUN VISUALIZATION +``` + npm install + npm start +``` \ No newline at end of file diff --git a/src/ILP.py b/src/ILP.py index d26823c..c9416ca 100644 --- a/src/ILP.py +++ b/src/ILP.py @@ -44,7 +44,7 @@ def main(graph): M = 1000 m = g.Model() - def abs(val): # |val| + def abs_(val): # |val| x = m.addVar(vtype=g.GRB.CONTINUOUS) m.addConstr(x >= val) m.addConstr(x >= -val) @@ -94,7 +94,7 @@ def imp(name, cond, vals): # c[i] >= 0 ===> v[i] >= 0 # - set objective : change in node position + total edge length m.setObjective( # sum(abs(node[n] - x) for n, (_, x, _, _) in graph.node.items() if x is not None)+ - sum(abs(node[s] - node[t]) for s, t, _ in graph.edge.values()), + sum(abs_(node[s] - node[t]) for s, t, _ in graph.edge.values()), g.GRB.MINIMIZE, ) @@ -102,9 +102,9 @@ def imp(name, cond, vals): # c[i] >= 0 ===> v[i] >= 0 m.write('debug.lp') m.optimize() - - for n in graph.node: graph.node[n] = graph.node[n][y], int(round(node[n].X)), graph.node[n][2], graph.node[n][3] + for n in graph.node: graph.node[n] = -graph.node[n][2], int(round(node[n].X)), graph.node[n][2], graph.node[n][3] for e in graph.edge: graph.edge[e] = graph.edge[e][0], graph.edge[e][1], int(round(edge[e].X)) + print(sum(graph.node[t][0] - graph.node[s][0] + abs(graph.node[s][1] - graph.node[t][1]) for (s,t,o) in graph.edge.values())) print(graph.node) print({e: edge[e].X for e in graph.edge}) print({var.VarName: int(round(var.X)) for var in m.getVars()}) diff --git a/src/graph.coffee b/src/heuristic.coffee similarity index 85% rename from src/graph.coffee rename to src/heuristic.coffee index 50d88c8..61aeb6c 100644 --- a/src/graph.coffee +++ b/src/heuristic.coffee @@ -10,6 +10,11 @@ chain = (args) -> for a from arg yield a +reverse = (arr) -> + if arr.length > 0 + for i in [arr.length-1..0] + yield arr[i] + class Stack stack: [] @@ -152,14 +157,14 @@ class GraphLayout dominanceLayout: () => # PRELIMINARY - [remains, xs, ys, x, y] = [[], [], [], 0, 0] + [remains, nByX, nByY, x, y] = [[], [], [], 0, 0] queue = new UniqueQueue Stack, {}, ([n, 2, 2] for n in @sourc) # console.log @ranks, @sourc, queue.queue.stack for n, _ of @nodes remains[n] = @graph.rdges[n].length for [n, _, _] from queue.iter() @nodes[n][1] = x++ - xs.push n + nByX.push n for t from @graph.edges[n] queue.insert t, 1 if --remains[t] == 0 queue = new UniqueQueue Stack, {}, ([n, 2, 2] for n in @sourc.reverse()) @@ -167,24 +172,31 @@ class GraphLayout remains[n] = @graph.rdges[n].length for [n, _, _] from queue.iter() @nodes[n][0] = y++ -# @nodes[n][0] = y++ if @trans[n] - ys.push n + nByY.push n for t from @graph.edges[n].reverse() queue.insert t, 1 if --remains[t] == 0 # COMPACTION - [x, ns] = [0, sort (n for n, _ of @nodes), (n) => @nodes[n][1]] - for i in [0..ns.length-2] - @nodes[ns[i+1]][1] = if int(ns[i+1]) == @graph.edges[ns[i]][0] then x else ++x - - for n, _ of @nodes when @graph.edges[n].length == 0 - @nodes[n][0] = 1 + Math.max.apply null, (@nodes[s][0] for s in @graph.rdges[n]) - - ns = sort (n for n, _ of @nodes), (n) => @nodes[n][0] - ys = (-1 for n, _ of @nodes) - for n in sort (n for n, _ of @nodes), (n) => @nodes[n][0] - parentY = Math.max.apply null, (@nodes[s][0] for s in @graph.rdges[n]) - ys[@nodes[n][1]] = @nodes[n][0] = 1 + Math.max parentY, ys[@nodes[n][1]] + x = 0 + for i in [0..nByX.length-2] + @nodes[nByX[i+1]][1] = if int(nByX[i+1]) == @graph.edges[nByX[i]][0] then x else ++x + + ys = (0 for n, _ of @nodes) + for n in nByY + [firstChildX, lastChildX] = [NaN, NaN] + + for c from @graph.edges[n] when @graph.rdges[c].length == 1 + firstChildX = @nodes[c][1]; break + for c from reverse(@graph.edges[n]) when @graph.rdges[c].length == 1 + lastChildX = @nodes[c][1]; break + childY = Math.max.apply null, (ys[x] for x in [firstChildX..lastChildX]) + + if @graph.rdges[n].length == 0 + parentY = 0 + else + [firstParentX, lastParentX] = [@nodes[@graph.rdges[n][0]][1], @nodes[@graph.rdges[n][@graph.rdges[n].length-1]][1]] + parentY = Math.max.apply null, (ys[x] for x in [firstParentX..lastParentX]) + ys[@nodes[n][1]] = @nodes[n][0] = 1 + Math.max (childY-2), parentY # # for n, pos of @nodes # pos[1] = pos[1] - pos[0] diff --git a/src/main.coffee b/src/main.coffee index abf1810..9304878 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -11,19 +11,19 @@ addNode = (n, {y, x, rank, label}, hsl) -> r = G/6 # name = basegl.tet.x {str: "HELLO", scene: scene, fontFamily: 'SourceCodePro', size: 16} src = addLine {y: y, x: x}, {y: y+.3, x: x} - trg = addLine {y: y, x: x}, {y: y-.3, x: x} node = scene.add basegl.symbol basegl.expr -> circle(r).move(r, r).fill(Color.hsl hsl) node.bbox.xy = [2*r, 2*r] node.position.xy = [G*x, G*y] node.addEventListener "mouseover", (e) => alert "Node: id:#{n}, label: #{label}" - group [node, src, trg] + group [node, src] addEdge = (s, t, offset) -> + line0 = addLine {y: s.y , x: s.x} , {y: s.y-.3, x: s.x} line1 = addLine {y: s.y-.3, x: s.x} , {y: s.y-.3, x: s.x+offset} line2 = addLine {y: s.y-.3, x: s.x+offset}, {y: t.y+.3, x: s.x+offset} line3 = addLine {y: t.y+.3, x: s.x+offset}, {y: t.y+.3, x: t.x} - group [line1, line2, line3] + group [line0, line1, line2, line3] addLine = (s, t) -> pi = if s.x > t.x then Math.PI else 0 @@ -58,9 +58,9 @@ main = () -> node.x += 30 - origin.x node.y = 20 - origin.y - node.y for _, {s, t} of graph.edges - if nodes[t][0] == 0 + if nodes[t][0] == 1 offset = graph.nodes[t].x - graph.nodes[s].x - else if nodes[s][1] == 1 + else if nodes[s][1] == 2 offset = 0 else offset = 0 @@ -75,5 +75,5 @@ scene = basegl.scene height: 2048 new KeyboardMouseReactor scene -console.log Color.hsl([1,1,.5]).toRGB() + main() \ No newline at end of file