Skip to content

Commit

Permalink
Added styles and layout compaction.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kesanov committed May 13, 2019
1 parent 514256a commit 1ba8167
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 205 deletions.
37 changes: 26 additions & 11 deletions src/ILP.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,39 @@
class GraphLayout:

def __init__(self):
self.node = {} # id: (y,x)
self.styl = [] # label: style
self.node = {} # id: (y,x,rank,label)
self.edge = {} # id: (s,t,offset)

@classmethod
def loadJson(cls, file):
data = json.loads(open(file, 'r').read())
def loadCoffee(cls, file):
data = (line for line in open(file, 'r'))
grph = cls()
grph.node = {int(k): tuple(v) for k,v in data['nodes'].items()}
grph.edge = {int(k): tuple(v) for k,v in data['edges'].items()}
next(data)
next(data)
for line in data:
if 'nodes:' in line: break
grph.styl.append(line)
for line in data:
if 'edges:' in line: break
line = line.split(':')
[y,x,r,l] = [l.split(',')[0].split('}')[0] for l in line[2:]]
grph.node[int(line[0])] = int(y), int(x), int(r), l
for line in data:
line = line.split(':')
[s,t] = [l.split(',')[0].split('}')[0] for l in line[2:]]
grph.edge[int(line[0])] = int(s), int(t), 0
return grph

def saveCoffee(self, file):
f = open(file, 'w')
print('export graph =', file=f)
print(' styles:', file=f)
for s in self.styl: print(s, file=f, end='')
print(' nodes:', file=f)
for k, v in self.node.items(): print(f' {k}: {list(v)}', file=f)
for k, (y,x,r,l) in self.node.items(): print(f' {k}: {{y:{y}, x:{x}, rank:{r}, label:{l}}}', file=f)
print(' edges:', file=f)
for k, v in self.edge.items(): print(f' {k}: {list(v)}', file=f)
for k, (s,t,o) in self.edge.items(): print(f' {k}: {{s:{s}, t:{t}}}', file=f)

# exact, but slow grid layout algorithm
def main(graph):
Expand Down Expand Up @@ -78,7 +93,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[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()),
g.GRB.MINIMIZE,
)
Expand All @@ -88,13 +103,13 @@ def imp(name, cond, vals): # c[i] >= 0 ===> v[i] >= 0

m.optimize()

for n in graph.node: graph.node[n] = graph.node[n][y], int(round(node[n].X))
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 e in graph.edge: graph.edge[e] = graph.edge[e][0], graph.edge[e][1], int(round(edge[e].X))
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()})

if __name__ == '__main__':
grph = GraphLayout.loadJson('../data/graphlayout.json')
grph = GraphLayout.loadCoffee('./layoutdata.coffee')
main(grph)
grph.saveCoffee('./layoutData.coffee')
grph.saveCoffee('./layoutdata.coffee')
70 changes: 39 additions & 31 deletions src/graph.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Stack

constructor: (@stack = []) ->

empty: ( ) => @stack.length == 0
empty : ( ) => @stack.length == 0
insert: (x) => @stack.push x
remove: ( ) => @stack.pop()

Expand All @@ -27,10 +27,8 @@ class Queue

constructor: (@frnt = [], @back = []) ->

empty: ( ) =>
@frnt.length == 0 and @back.length == 0
insert: (x) =>
@back.push x
empty : ( ) => @frnt.length == 0 and @back.length == 0
insert: (x) => @back.push x
remove: ( ) =>
if @frnt.length == 0
@frnt = @back.reverse()
Expand Down Expand Up @@ -95,28 +93,26 @@ class Graph

class GraphLayout

label: {}
sourc: []
ranks: {}
nodes: {}
edges: {}
reach: {}
graph: null

constructor: (@sourc = [0], @ranks = {0: 0}, @nodes = {}, @edges = {}) ->
@graph = new Graph()

step: (newnodes, newedges, layout = true) =>
sourc = []
graph = new Graph()

@addEdges graph, newnodes, newedges
@getRanks graph, newedges
@rankNodes graph, newedges
@orientEdges graph, newedges

console.log ([n, @ranks[n]] for n of newnodes)

for i, _ of newnodes
for i, [label] of newnodes
@nodes[i] = [null, null]
@label[i] = label

@dominanceLayout() if layout

Expand All @@ -130,14 +126,13 @@ class GraphLayout
graph.addEdge s, t
@edges[i] = [s, t, o]

getRanks: (graph, newedges) =>
rankNodes: (graph, newedges) =>
queue = new UniqueQueue Queue, @ranks, []
nodes = []
for _, [s,t] of newedges
nodes.push(s) if s of @ranks
nodes.push(t) if t of @ranks
nodes = uniq(sort nodes, (n) => -@ranks[n])
console.log "HERE", nodes
for n in nodes
queue.reinsert n, @ranks[n]
for [n, r, _] from queue.iter()
Expand Down Expand Up @@ -172,30 +167,43 @@ 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
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]]
#
# for n, pos of @nodes
## pos[1] = pos[1] - pos[0]
# pos[0] = @ranks[n] #pos[1] + pos[0] * 2
## [x, xs] = [0, sort (n for n,[_,x] of @nodes when x <= 0), (n) => -@nodes[n][1]]
## for i in [0..xs.length-2]
## @nodes[xs[i+1]][1] = if int(xs[i+1]) in @graph.edges[xs[i]] then x else --x
# ns = sort (n for n,[_,x] of @nodes when x > 0), (n) => @nodes[n][1]
# xs = (-1 for _ of @nodes)
# for n in ns
# @nodes[n][1] = xs[-@ranks[n]] = Math.max xs[-@ranks[n]-1], xs[-@ranks[n]]+1
# pos[1] = pos[1] - pos[0]
# pos[0] = pos[1] + 2*pos[0]

write: () =>
file = fs.openSync('./layoutdata.coffee', 'w')
fs.writeSync(file, "export graph =\n")
fs.writeSync(file, " nodes:\n")
fs.writeSync(file, " " + n + " : [" + d + "]\n") for n, d of @nodes
fs.writeSync(file, " edges:\n")
fs.writeSync(file, " " + e + " : [" + d + "]\n") for e, d of @edges
fs.closeSync(file)
fs.writeSync file, "export graph =\n"
fs.writeSync file, " styles:\n"
labels = uniq (l for _, l of @label).sort()
for label, i in labels
fs.writeSync file, " #{label}: {hsl: [#{i/(labels.length-1)},1,.5]}\n"
fs.writeSync file, " nodes:\n"
for n, [y, x] of @nodes
fs.writeSync file, " #{n} : {y: #{y}, x: #{x}, rank: #{@ranks[n]}, label: '#{@label[n]}'}\n"
fs.writeSync file, " edges:\n"
for e, [s, t] of @edges
fs.writeSync file, " #{e} : {s: #{s}, t: #{t}}\n"
fs.closeSync file

class State

Expand Down Expand Up @@ -234,7 +242,7 @@ readCSV = (file) ->
while nodes[n][0] == 'remove'
t.remove.nodes.push int(nodes[n++][1])
while nodes[n][0] == 'insert'
t.insert.nodes[int(nodes[n][1])] = nodes[n][2]
t.insert.nodes[int(nodes[n][1])] = [nodes[n][2]]
n++
while edges[e][0] == 'remove'
t.remove.edges.push int(edges[e++][1])
Expand All @@ -243,11 +251,11 @@ readCSV = (file) ->
e++
yield t

state = new State readCSV '../data/27f'
state = new State readCSV '../data/q'

i=0
for graph from state.iter()
if i++ == 1
if i++ == 0
graph.write()
break

132 changes: 0 additions & 132 deletions src/layoutdata.coffee

This file was deleted.

Loading

0 comments on commit 1ba8167

Please sign in to comment.