blob: 13963d61e6664d1a1d6792d5beaee774f99bc228 [file] [log] [blame]
library graphlib.layout.order;
import "init_order.dart" show initOrder;
import "cross_count.dart" show crossCount;
import "sort_subgraph.dart" show sortSubgraph;
import "build_layer_graph.dart" show buildLayerGraph;
import "add_subgraph_constraints.dart" show addSubgraphConstraints;
import "../../graph.dart" show Graph;
import "../util.dart" as util;
/// Applies heuristics to minimize edge crossings in the graph and sets the best
/// order solution as an order attribute on each node.
///
/// Pre-conditions:
///
/// 1. Graph must be DAG
/// 2. Graph nodes must be objects with a "rank" attribute
/// 3. Graph edges must have the "weight" attribute
///
/// Post-conditions:
///
/// 1. Graph nodes will have an "order" attribute based on the results of the
/// algorithm.
order(Graph g) {
var maxRank = util.maxRank(g),
downLayerGraphs = _buildLayerGraphs(g, util.range(1, maxRank + 1), "inEdges"),
upLayerGraphs = _buildLayerGraphs(g, util.range(maxRank - 1, -1, -1), "outEdges");
var layering = initOrder(g);
_assignOrder(g, layering);
var bestCC = double.INFINITY;
List<List> best;
for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
_sweepLayerGraphs(i % 2 != 0 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
layering = util.buildLayerMatrix(g);
var cc = crossCount(g, layering);
if (cc < bestCC) {
lastBest = 0;
//best = _.cloneDeep(layering);
best = new List<List>.generate(layering.length, (i) => layering[i].toList());
bestCC = cc;
}
}
_assignOrder(g, best);
}
Iterable _buildLayerGraphs(Graph g, Iterable ranks, relationship) {
return ranks.map((rank) {
return buildLayerGraph(g, rank, relationship);
});
}
_sweepLayerGraphs(Iterable layerGraphs, biasRight) {
var cg = new Graph();
layerGraphs.forEach((lg) {
var root = lg.graph()["root"];
var sorted = sortSubgraph(lg, root, cg, biasRight);
int i = 0;
sorted["vs"].forEach((v) {
lg.node(v)["order"] = i;
i++;
});
addSubgraphConstraints(lg, cg, sorted["vs"]);
});
}
_assignOrder(Graph g, List<List> layering) {
layering.forEach((layer) {
int i = 0;
layer.forEach((v) {
g.node(v)["order"] = i++;
});
});
}