whole_func_string: 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);
  }
func_code_string: 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);
  }
func_documentation_string: /*
  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