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);
}
function run(g, useSimplex) {
  var selfLoops = removeSelfLoops(g);

  
  
  util.time('constraints.apply', constraints.apply)(g);

  
  
  
  
  
  var sidewaysEdges = removeSelfLoops(g)
    .map(function(edge) {
      return edge.value.originalEdge;
    });

  
  
  util.time('acyclic', acyclic)(g);

  
  var flatGraph = g.filterNodes(util.filterNonSubgraphs(g));

  
  initRank(flatGraph);

  
  components(flatGraph).forEach(function(cmpt) {
    var subgraph = flatGraph.filterNodes(filter.nodesFromList(cmpt));
    rankComponent(subgraph, useSimplex);
  });

  
  util.time('constraints.relax', constraints.relax(g));

  
  
  
  
  
  util.time('reorientEdges', reorientEdges)(g);

  
  g.graph().rankRemovedEdges = selfLoops.concat(sidewaysEdges);
}
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 ) ; }
/*
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
/ * 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 .