MCPcopy Create free account
hub / github.com/consensus-shipyard/ipc / topo_sort

Function topo_sort

fendermint/testing/materializer/src/testnet.rs:661–710  ·  view source on GitHub ↗

Sort some values in a topological order. Cycles can be allowed, in which case it will do its best to order the items with the least amount of dependencies first. This is so we can support nodes mutually be seeded by each other.

(
    items: &BTreeMap<K, V>,
    allow_cycles: bool,
    f: F,
)

Source from the content-addressed store, hash-verified

659/// with the least amount of dependencies first. This is so we can support nodes
660/// mutually be seeded by each other.
661fn topo_sort<K, V, F, I>(
662 items: &BTreeMap<K, V>,
663 allow_cycles: bool,
664 f: F,
665) -> anyhow::Result<Vec<(&K, &V)>>
666where
667 F: Fn(&V) -> I,
668 K: Ord + Display + Clone,
669 I: IntoIterator<Item = K>,
670{
671 let mut deps = items
672 .iter()
673 .map(|(k, v)| (k, BTreeSet::from_iter(f(v))))
674 .collect::<BTreeMap<_, _>>();
675
676 for (k, ds) in deps.iter() {
677 for d in ds {
678 if !deps.contains_key(d) {
679 bail!("non-existing dependency: {d} <- {k}")
680 }
681 }
682 }
683
684 let mut sorted = Vec::new();
685
686 while !deps.is_empty() {
687 let leaf: K = match deps.iter().find(|(_, ds)| ds.is_empty()) {
688 Some((leaf, _)) => (*leaf).clone(),
689 None if allow_cycles => {
690 let mut dcs = deps.iter().map(|(k, ds)| (k, ds.len())).collect::<Vec<_>>();
691 dcs.sort_by_key(|(_, c)| *c);
692 let leaf = dcs.first().unwrap().0;
693 (*leaf).clone()
694 }
695 None => bail!("circular reference in dependencies"),
696 };
697
698 deps.remove(&leaf);
699
700 for (_, ds) in deps.iter_mut() {
701 ds.remove(&leaf);
702 }
703
704 if let Some(kv) = items.get_key_value(&leaf) {
705 sorted.push(kv);
706 }
707 }
708
709 Ok(sorted)
710}
711
712/// Sort nodes in a subnet in topological order, so we strive to first
713/// start the ones others use as a seed node. However, do allow cycles

Callers 2

sort_by_seedsFunction · 0.70
test_topo_sortFunction · 0.70

Calls 6

iterMethod · 0.45
contains_keyMethod · 0.45
is_emptyMethod · 0.45
lenMethod · 0.45
removeMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected