pub(crate) mod add_subgraph_constraints;
pub(crate) mod barycenter;
pub(crate) mod build_layer_graph;
pub(crate) mod cross_count;
pub(crate) mod init_order;
pub(crate) mod resolve_conflicts;
pub(crate) mod sort;
pub(crate) mod sort_subgraph;
use std::collections::BTreeMap;
use crate::graph::Graph;
use crate::layout::types::{EdgeLabel, GraphLabel, NodeLabel};
use crate::layout::util::{build_layer_matrix, max_rank};
use self::add_subgraph_constraints::add_subgraph_constraints;
use self::build_layer_graph::{Relationship, build_layer_graph, get_root};
use self::cross_count::cross_count;
use self::init_order::init_order;
use self::sort_subgraph::sort_subgraph;
pub(crate) fn order(g: &mut Graph<NodeLabel, EdgeLabel>) {
let mr = max_rank(g);
if mr < 0 {
return;
}
let tie_keep_first = g
.graph_label::<GraphLabel>()
.is_some_and(|gl| gl.tie_keep_first);
let down_ranks: Vec<i32> = (1..=mr).collect();
let up_ranks: Vec<i32> = (0..mr).rev().collect();
let mut nodes_by_rank: BTreeMap<i32, Vec<String>> = BTreeMap::new();
for v in g.nodes() {
if let Some(node) = g.node(&v) {
if let Some(rank) = node.rank {
nodes_by_rank.entry(rank).or_default().push(v.clone());
}
if let (Some(min_r), Some(max_r)) = (node.min_rank, node.max_rank) {
for r in min_r..=max_r {
if Some(r) != node.rank {
nodes_by_rank.entry(r).or_default().push(v.clone());
}
}
}
}
}
let layering = init_order(g);
assign_order(g, &layering);
let mut best_cc = usize::MAX;
let mut best: Option<Vec<Vec<String>>> = None;
let mut i = 0_usize;
let mut last_best = 0_usize;
while last_best < 4 {
let (ranks, relationship) = if !i.is_multiple_of(2) {
(&down_ranks, Relationship::InEdges)
} else {
(&up_ranks, Relationship::OutEdges)
};
let bias_right = i % 4 >= 2;
sweep_layer_graphs(g, ranks, &nodes_by_rank, relationship, bias_right);
let layering = build_layer_matrix(g);
let cc = cross_count(g, &layering);
if cc < best_cc {
last_best = 0;
best = Some(layering.clone());
best_cc = cc;
} else if cc == best_cc && !tie_keep_first {
best = Some(layering);
}
i += 1;
last_best += 1;
}
if let Some(ref best_layering) = best {
assign_order(g, best_layering);
}
}
fn sweep_layer_graphs(
g: &mut Graph<NodeLabel, EdgeLabel>,
ranks: &[i32],
nodes_by_rank: &std::collections::BTreeMap<i32, Vec<String>>,
relationship: Relationship,
bias_right: bool,
) {
let mut cg: Graph<(), ()> = Graph::new();
for &rank in ranks {
let empty = Vec::new();
let nodes = nodes_by_rank.get(&rank).unwrap_or(&empty);
let lg = build_layer_graph(g, rank, relationship, nodes);
let root = get_root(&lg);
let sorted = sort_subgraph(&lg, &root, &cg, bias_right);
for (i, v) in sorted.vs.iter().enumerate() {
if let Some(node) = g.node_mut(v) {
node.order = Some(i);
}
}
add_subgraph_constraints(&lg, &mut cg, &sorted.vs);
}
}
fn assign_order(g: &mut Graph<NodeLabel, EdgeLabel>, layering: &[Vec<String>]) {
for layer in layering {
for (i, v) in layer.iter().enumerate() {
if !v.is_empty()
&& let Some(node) = g.node_mut(v)
{
node.order = Some(i);
}
}
}
}