petgraph/acyclic/
order_map.rs1use std::{collections::BTreeMap, fmt, ops::RangeBounds};
7
8use crate::{
9 algo::{toposort, Cycle},
10 visit::{GraphBase, IntoNeighborsDirected, IntoNodeIdentifiers, NodeIndexable, Visitable},
11};
12
13#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
20#[repr(transparent)]
21pub struct TopologicalPosition(pub(super) usize);
22
23#[derive(Clone)]
30pub(super) struct OrderMap<N> {
31 pos_to_node: BTreeMap<TopologicalPosition, N>,
33 node_to_pos: Vec<TopologicalPosition>,
37}
38
39impl<N> Default for OrderMap<N> {
40 fn default() -> Self {
41 Self {
42 pos_to_node: Default::default(),
43 node_to_pos: Default::default(),
44 }
45 }
46}
47
48impl<N: fmt::Debug> fmt::Debug for OrderMap<N> {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 f.debug_struct("OrderMap")
51 .field("order", &self.pos_to_node)
52 .finish()
53 }
54}
55
56impl<N: Copy> OrderMap<N> {
57 pub(super) fn try_from_graph<G>(graph: G) -> Result<Self, Cycle<G::NodeId>>
58 where
59 G: NodeIndexable<NodeId = N> + IntoNeighborsDirected + IntoNodeIdentifiers + Visitable,
60 {
61 let topo_vec = toposort(graph, None)?;
63
64 let mut pos_to_node = BTreeMap::new();
66 let mut node_to_pos = vec![TopologicalPosition::default(); graph.node_bound()];
67
68 for (i, &id) in topo_vec.iter().enumerate() {
70 let pos = TopologicalPosition(i);
71 pos_to_node.insert(pos, id);
72 node_to_pos[graph.to_index(id)] = pos;
73 }
74
75 Ok(Self {
76 pos_to_node,
77 node_to_pos,
78 })
79 }
80
81 pub(super) fn with_capacity(nodes: usize) -> Self {
82 Self {
83 pos_to_node: BTreeMap::new(),
84 node_to_pos: Vec::with_capacity(nodes),
85 }
86 }
87
88 pub(super) fn get_position(
92 &self,
93 id: N,
94 graph: impl NodeIndexable<NodeId = N>,
95 ) -> TopologicalPosition {
96 let idx = graph.to_index(id);
97 assert!(idx < self.node_to_pos.len());
98 self.node_to_pos[idx]
99 }
100
101 pub(super) fn at_position(&self, pos: TopologicalPosition) -> Option<N> {
103 self.pos_to_node.get(&pos).copied()
104 }
105
106 pub(super) fn nodes_iter(&self) -> impl Iterator<Item = N> + '_ {
108 self.pos_to_node.values().copied()
109 }
110
111 pub(super) fn range(
113 &self,
114 range: impl RangeBounds<TopologicalPosition>,
115 ) -> impl Iterator<Item = N> + '_ {
116 self.pos_to_node.range(range).map(|(_, &n)| n)
117 }
118
119 pub(super) fn add_node(
123 &mut self,
124 id: N,
125 graph: impl NodeIndexable<NodeId = N>,
126 ) -> TopologicalPosition {
127 let new_pos = self
129 .pos_to_node
130 .iter()
131 .next_back()
132 .map(|(TopologicalPosition(idx), _)| TopologicalPosition(idx + 1))
133 .unwrap_or_default();
134 let idx = graph.to_index(id);
135
136 if idx >= self.node_to_pos.len() {
138 self.node_to_pos
139 .resize(graph.node_bound(), TopologicalPosition::default());
140 }
141
142 self.pos_to_node.insert(new_pos, id);
144 self.node_to_pos[idx] = new_pos;
145
146 new_pos
147 }
148
149 pub(super) fn remove_node(&mut self, id: N, graph: impl NodeIndexable<NodeId = N>) {
153 let idx = graph.to_index(id);
154 assert!(idx < self.node_to_pos.len());
155
156 let pos = self.node_to_pos[idx];
157 self.node_to_pos[idx] = TopologicalPosition::default();
158 self.pos_to_node.remove(&pos);
159 }
160
161 pub(super) fn set_position(
165 &mut self,
166 id: N,
167 pos: TopologicalPosition,
168 graph: impl NodeIndexable<NodeId = N>,
169 ) {
170 let idx = graph.to_index(id);
171 assert!(idx < self.node_to_pos.len());
172
173 self.pos_to_node.insert(pos, id);
174 self.node_to_pos[idx] = pos;
175 }
176}
177
178impl<G: Visitable> super::Acyclic<G> {
179 pub fn get_position<'a>(&'a self, id: G::NodeId) -> TopologicalPosition
183 where
184 &'a G: NodeIndexable + GraphBase<NodeId = G::NodeId>,
185 {
186 self.order_map.get_position(id, &self.graph)
187 }
188
189 pub fn at_position(&self, pos: TopologicalPosition) -> Option<G::NodeId> {
191 self.order_map.at_position(pos)
192 }
193}