/*
Heuristic function that assigns a rank to each node of the input graph with
the intent of minimizing edge lengths, while respecting the `minLen`
attribute of incident edges.

Prerequisites:

* Each edge in the input graph must have an assigned 'minLen' attribute
function run(g, useSimplex) {
  var selfLoops = removeSelfLoops(g);

  // If there are rank constraints on nodes, then build a new graph that
  // encodes the constraints.
  util.time('constraints.apply', constraints.apply)(g);

  // Since we already removed self loops before applying rank constraints we
  // know that self loops indicate sideways edges induced by rank constraints.
  // Currently we do not have any support for sideways edges, so we remove
  // them. Since the edges we remove are between collapsed nodes, we need to
  // take care to save the original edge information.
  var sidewaysEdges = removeSelfLoops(g)
    .map(function(edge) {
      return edge.value.originalEdge;
    });

  // Reverse edges to get an acyclic graph, we keep the graph in an acyclic
  // state until the very end.
  util.time('acyclic', acyclic)(g);

  // Convert the graph into a flat graph for ranking
  var flatGraph = g.filterNodes(util.filterNonSubgraphs(g));

  // Assign an initial ranking using DFS.
  initRank(flatGraph);

  // For each component improve the assigned ranks.
  components(flatGraph).forEach(function(cmpt) {
    var subgraph = flatGraph.filterNodes(filter.nodesFromList(cmpt));
    rankComponent(subgraph, useSimplex);
  });

  // Relax original constraints
  util.time('constraints.relax', constraints.relax(g));

  // When handling nodes with constrained ranks it is possible to end up with
  // edges that point to previous ranks. Most of the subsequent algorithms assume
  // that edges are pointing to successive ranks only. Here we reverse any "back
  // edges" and mark them as such. The acyclic algorithm will reverse them as a
  // post processing step.
  util.time('reorientEdges', reorientEdges)(g);

  // Save removed edges so that they can be restored later
  g.graph().rankRemovedEdges = selfLoops.concat(sidewaysEdges);
}