1use rustc_hash::FxBuildHasher;
4use std::cell::RefCell;
5
6use super::adj_cache::{DirectedAdjCache, UndirectedAdjCache};
7use super::edge_key::{EdgeKey, EdgeKeyView};
8use super::entries::{EdgeEntry, NodeEntry};
9use super::options::GraphOptions;
10
11type HashMap<K, V> = hashbrown::HashMap<K, V, FxBuildHasher>;
12type HashSet<T> = hashbrown::HashSet<T, FxBuildHasher>;
13
14pub struct Graph<N, E, G>
15where
16 N: Default + 'static,
17 E: Default + 'static,
18 G: Default,
19{
20 options: GraphOptions,
21
22 graph_label: G,
23 default_node_label: Box<dyn Fn() -> N + Send + Sync>,
24 default_edge_label: Box<dyn Fn() -> E + Send + Sync>,
25
26 nodes: Vec<Option<NodeEntry<N>>>,
27 node_len: usize,
28 node_index: HashMap<String, usize>,
29
30 edges: Vec<Option<EdgeEntry<E>>>,
31 edge_len: usize,
32 edge_index: HashMap<EdgeKey, usize>,
33
34 parent_ix: Vec<Option<usize>>,
40 children_ix: Vec<Vec<usize>>,
41
42 directed_adj_gen: u64,
48 directed_adj_cache: RefCell<Option<DirectedAdjCache>>,
49
50 undirected_adj_gen: u64,
53 undirected_adj_cache: RefCell<Option<UndirectedAdjCache>>,
54}
55
56impl<N, E, G> Graph<N, E, G>
57where
58 N: Default + 'static,
59 E: Default + 'static,
60 G: Default,
61{
62 fn insert_node_entry(&mut self, id: String, label: N) -> usize {
63 self.invalidate_adj();
64 let idx = self.nodes.len();
65 self.nodes.push(Some(NodeEntry {
66 id: id.clone(),
67 label,
68 }));
69 self.node_len += 1;
70 self.node_index.insert(id, idx);
71 self.parent_ix.push(None);
72 self.children_ix.push(Vec::new());
73 idx
74 }
75
76 fn trim_trailing_node_tombstones(&mut self) {
77 while matches!(self.nodes.last(), Some(None)) {
78 self.nodes.pop();
79 self.parent_ix.pop();
80 self.children_ix.pop();
81 }
82 }
83
84 fn trim_trailing_edge_tombstones(&mut self) {
85 while matches!(self.edges.last(), Some(None)) {
86 self.edges.pop();
87 }
88 }
89
90 pub fn compact_if_sparse(&mut self, max_capacity_factor: f64) -> bool {
91 let nodes_sparse = if self.node_len == 0 {
96 !self.nodes.is_empty()
97 } else {
98 max_capacity_factor > 1.0
99 && (self.nodes.len() as f64) > (self.node_len as f64) * max_capacity_factor
100 };
101 let edges_sparse = if self.edge_len == 0 {
102 !self.edges.is_empty()
103 } else {
104 max_capacity_factor > 1.0
105 && (self.edges.len() as f64) > (self.edge_len as f64) * max_capacity_factor
106 };
107
108 if !(nodes_sparse || edges_sparse) {
109 return false;
110 }
111
112 self.compact();
113 true
114 }
115
116 fn compact(&mut self) {
117 self.invalidate_adj();
118
119 if self.node_len == 0 {
120 self.nodes.clear();
121 self.node_index.clear();
122 self.node_len = 0;
123
124 self.edges.clear();
125 self.edge_index.clear();
126 self.edge_len = 0;
127
128 self.parent_ix.clear();
129 self.children_ix.clear();
130 return;
131 }
132
133 let old_nodes = std::mem::take(&mut self.nodes);
134 let old_parent_ix = std::mem::take(&mut self.parent_ix);
135 let old_children_ix = std::mem::take(&mut self.children_ix);
136 let mut node_remap: Vec<Option<usize>> = vec![None; old_nodes.len()];
137
138 let mut new_nodes: Vec<Option<NodeEntry<N>>> = Vec::with_capacity(self.node_len);
139 let mut new_node_index: HashMap<String, usize> = HashMap::default();
140 for (old_ix, slot) in old_nodes.into_iter().enumerate() {
141 let Some(node) = slot else {
142 continue;
143 };
144 let new_ix = new_nodes.len();
145 new_node_index.insert(node.id.clone(), new_ix);
146 node_remap[old_ix] = Some(new_ix);
147 new_nodes.push(Some(node));
148 }
149
150 self.nodes = new_nodes;
151 self.node_index = new_node_index;
152 self.node_len = self.nodes.len();
153
154 self.parent_ix = vec![None; self.nodes.len()];
155 self.children_ix = vec![Vec::new(); self.nodes.len()];
156 if self.options.compound {
157 for (old_parent, old_children) in old_children_ix.into_iter().enumerate() {
158 let Some(new_parent) = node_remap.get(old_parent).copied().flatten() else {
159 continue;
160 };
161 let new_children_vec = self
162 .children_ix
163 .get_mut(new_parent)
164 .expect("children_ix resized to node slots");
165 for old_child in old_children {
166 let Some(new_child) = node_remap.get(old_child).copied().flatten() else {
167 continue;
168 };
169 new_children_vec.push(new_child);
170 if let Some(slot) = self.parent_ix.get_mut(new_child) {
171 *slot = Some(new_parent);
172 }
173 }
174 }
175
176 for (old_child, old_parent) in old_parent_ix.into_iter().enumerate() {
179 let Some(old_parent) = old_parent else {
180 continue;
181 };
182 let Some(new_child) = node_remap.get(old_child).copied().flatten() else {
183 continue;
184 };
185 let Some(new_parent) = node_remap.get(old_parent).copied().flatten() else {
186 continue;
187 };
188 if self.parent_ix.get(new_child).copied().flatten().is_some() {
189 continue;
190 }
191 if let Some(slot) = self.parent_ix.get_mut(new_child) {
192 *slot = Some(new_parent);
193 }
194 if let Some(ch) = self.children_ix.get_mut(new_parent) {
195 if !ch.contains(&new_child) {
196 ch.push(new_child);
197 }
198 }
199 }
200 }
201
202 let old_edges = std::mem::take(&mut self.edges);
203 let mut new_edges: Vec<Option<EdgeEntry<E>>> = Vec::with_capacity(self.edge_len);
204 let mut new_edge_index: HashMap<EdgeKey, usize> = HashMap::default();
205 let mut new_edge_len: usize = 0;
206
207 for slot in old_edges.into_iter() {
208 let Some(mut edge) = slot else {
209 continue;
210 };
211 let Some(v_ix) = node_remap.get(edge.v_ix).copied().flatten() else {
212 continue;
213 };
214 let Some(w_ix) = node_remap.get(edge.w_ix).copied().flatten() else {
215 continue;
216 };
217 edge.v_ix = v_ix;
218 edge.w_ix = w_ix;
219
220 let new_ix = new_edges.len();
221 new_edge_index.insert(edge.key.clone(), new_ix);
222 new_edges.push(Some(edge));
223 new_edge_len += 1;
224 }
225
226 self.edges = new_edges;
227 self.edge_index = new_edge_index;
228 self.edge_len = new_edge_len;
229 }
230
231 fn invalidate_directed_adj(&mut self) {
232 if !self.options.directed {
233 return;
234 }
235 self.directed_adj_gen = self.directed_adj_gen.wrapping_add(1);
236 *self.directed_adj_cache.get_mut() = None;
237 }
238
239 fn invalidate_undirected_adj(&mut self) {
240 if self.options.directed {
241 return;
242 }
243 self.undirected_adj_gen = self.undirected_adj_gen.wrapping_add(1);
244 *self.undirected_adj_cache.get_mut() = None;
245 }
246
247 fn invalidate_adj(&mut self) {
248 self.invalidate_directed_adj();
249 self.invalidate_undirected_adj();
250 }
251
252 fn ensure_directed_adj<'a>(&'a self) -> std::cell::RefMut<'a, DirectedAdjCache> {
253 debug_assert!(self.options.directed);
254 let generation = self.directed_adj_gen;
255 let mut cache = self.directed_adj_cache.borrow_mut();
256 let stale = cache
257 .as_ref()
258 .map(|c| c.generation != generation)
259 .unwrap_or(true);
260 if stale {
261 let node_slots = self.nodes.len();
264 let mut out_offsets: Vec<usize> = vec![0; node_slots + 1];
265 let mut in_offsets: Vec<usize> = vec![0; node_slots + 1];
266
267 for e in self.edges.iter().filter_map(|e| e.as_ref()) {
268 out_offsets[e.v_ix + 1] += 1;
269 in_offsets[e.w_ix + 1] += 1;
270 }
271
272 for i in 1..=node_slots {
273 out_offsets[i] += out_offsets[i - 1];
274 in_offsets[i] += in_offsets[i - 1];
275 }
276
277 let mut out_edges: Vec<usize> = vec![0; out_offsets[node_slots]];
278 let mut in_edges: Vec<usize> = vec![0; in_offsets[node_slots]];
279 let mut out_cursors = out_offsets.clone();
280 let mut in_cursors = in_offsets.clone();
281
282 for (edge_idx, e) in self.edges.iter().enumerate() {
283 let Some(e) = e.as_ref() else {
284 continue;
285 };
286 let out_pos = out_cursors[e.v_ix];
287 out_edges[out_pos] = edge_idx;
288 out_cursors[e.v_ix] += 1;
289
290 let in_pos = in_cursors[e.w_ix];
291 in_edges[in_pos] = edge_idx;
292 in_cursors[e.w_ix] += 1;
293 }
294
295 *cache = Some(DirectedAdjCache {
296 generation,
297 out_offsets,
298 out_edges,
299 in_offsets,
300 in_edges,
301 });
302 }
303 std::cell::RefMut::map(cache, |c| {
304 c.as_mut()
305 .expect("directed adjacency cache should be present after ensure")
306 })
307 }
308
309 fn ensure_undirected_adj<'a>(&'a self) -> std::cell::RefMut<'a, UndirectedAdjCache> {
310 debug_assert!(!self.options.directed);
311 let generation = self.undirected_adj_gen;
312 let mut cache = self.undirected_adj_cache.borrow_mut();
313 let stale = cache
314 .as_ref()
315 .map(|c| c.generation != generation)
316 .unwrap_or(true);
317 if stale {
318 let node_slots = self.nodes.len();
319 let mut offsets: Vec<usize> = vec![0; node_slots + 1];
320
321 for e in self.edges.iter().filter_map(|e| e.as_ref()) {
322 offsets[e.v_ix + 1] += 1;
323 offsets[e.w_ix + 1] += 1;
324 }
325
326 for i in 1..=node_slots {
327 offsets[i] += offsets[i - 1];
328 }
329
330 let mut edges: Vec<usize> = vec![0; offsets[node_slots]];
331 let mut cursors = offsets.clone();
332 for (edge_idx, e) in self.edges.iter().enumerate() {
333 let Some(e) = e.as_ref() else {
334 continue;
335 };
336 let v_pos = cursors[e.v_ix];
337 edges[v_pos] = edge_idx;
338 cursors[e.v_ix] += 1;
339
340 let w_pos = cursors[e.w_ix];
341 edges[w_pos] = edge_idx;
342 cursors[e.w_ix] += 1;
343 }
344
345 *cache = Some(UndirectedAdjCache {
346 generation,
347 offsets,
348 edges,
349 });
350 }
351
352 std::cell::RefMut::map(cache, |c| {
353 c.as_mut()
354 .expect("undirected adjacency cache should be present after ensure")
355 })
356 }
357
358 fn edge_key_view<'a>(&self, v: &'a str, w: &'a str, name: Option<&'a str>) -> EdgeKeyView<'a> {
359 let (v, w) = if self.options.directed || v <= w {
360 (v, w)
361 } else {
362 (w, v)
363 };
364 let name = if self.options.multigraph { name } else { None };
365 EdgeKeyView { v, w, name }
366 }
367
368 fn edge_key_view_from_key<'a>(&self, key: &'a EdgeKey) -> EdgeKeyView<'a> {
369 let mut v = key.v.as_str();
370 let mut w = key.w.as_str();
371 if !self.options.directed && v > w {
372 (v, w) = (w, v);
373 }
374 let name = if self.options.multigraph {
375 key.name.as_deref()
376 } else {
377 None
378 };
379 EdgeKeyView { v, w, name }
380 }
381
382 fn edge_index_of_view(&self, view: EdgeKeyView<'_>) -> Option<usize> {
383 self.edge_index.get(&view).copied()
384 }
385
386 fn canonicalize_endpoints(&self, v: String, w: String) -> (String, String) {
387 if self.options.directed || v <= w {
388 (v, w)
389 } else {
390 (w, v)
391 }
392 }
393
394 fn canonicalize_name(&self, name: Option<String>) -> Option<String> {
395 if self.options.multigraph { name } else { None }
396 }
397
398 fn canonicalize_key(&self, mut key: EdgeKey) -> EdgeKey {
399 if !self.options.directed && key.v > key.w {
400 (key.v, key.w) = (key.w, key.v);
401 }
402 key.name = self.canonicalize_name(key.name);
403 key
404 }
405
406 pub fn new(options: GraphOptions) -> Self {
407 Self {
408 options,
409 graph_label: G::default(),
410 default_node_label: Box::new(N::default),
411 default_edge_label: Box::new(E::default),
412 nodes: Vec::new(),
413 node_len: 0,
414 node_index: HashMap::default(),
415 edges: Vec::new(),
416 edge_len: 0,
417 edge_index: HashMap::default(),
418 parent_ix: Vec::new(),
419 children_ix: Vec::new(),
420 directed_adj_gen: 0,
421 directed_adj_cache: RefCell::new(None),
422 undirected_adj_gen: 0,
423 undirected_adj_cache: RefCell::new(None),
424 }
425 }
426
427 pub fn with_capacity(
428 options: GraphOptions,
429 node_capacity: usize,
430 edge_capacity: usize,
431 ) -> Self {
432 let mut g = Self::new(options);
433 g.nodes.reserve(node_capacity);
434 g.edges.reserve(edge_capacity);
435 g.node_index.reserve(node_capacity);
436 g.edge_index.reserve(edge_capacity);
437 g.parent_ix.reserve(node_capacity);
438 g.children_ix.reserve(node_capacity);
439 g
440 }
441
442 pub fn options(&self) -> GraphOptions {
443 self.options
444 }
445
446 pub fn is_multigraph(&self) -> bool {
447 self.options.multigraph
448 }
449
450 pub fn is_compound(&self) -> bool {
451 self.options.compound
452 }
453
454 pub fn is_directed(&self) -> bool {
455 self.options.directed
456 }
457
458 pub fn set_graph(&mut self, label: G) -> &mut Self {
459 self.graph_label = label;
460 self
461 }
462
463 pub fn graph(&self) -> &G {
464 &self.graph_label
465 }
466
467 pub fn graph_mut(&mut self) -> &mut G {
468 &mut self.graph_label
469 }
470
471 pub fn set_default_node_label<F>(&mut self, f: F) -> &mut Self
472 where
473 F: Fn() -> N + Send + Sync + 'static,
474 {
475 self.default_node_label = Box::new(f);
476 self
477 }
478
479 pub fn set_default_edge_label<F>(&mut self, f: F) -> &mut Self
480 where
481 F: Fn() -> E + Send + Sync + 'static,
482 {
483 self.default_edge_label = Box::new(f);
484 self
485 }
486
487 pub fn has_node(&self, id: &str) -> bool {
488 self.node_index.contains_key(id)
489 }
490
491 pub fn node_ix(&self, id: &str) -> Option<usize> {
492 self.node_index.get(id).copied()
493 }
494
495 pub fn node_id_by_ix(&self, ix: usize) -> Option<&str> {
496 self.nodes
497 .get(ix)
498 .and_then(|n| n.as_ref())
499 .map(|n| n.id.as_str())
500 }
501
502 pub fn node_label_by_ix(&self, ix: usize) -> Option<&N> {
503 self.nodes
504 .get(ix)
505 .and_then(|n| n.as_ref())
506 .map(|n| &n.label)
507 }
508
509 pub fn node_label_mut_by_ix(&mut self, ix: usize) -> Option<&mut N> {
510 self.nodes
511 .get_mut(ix)
512 .and_then(|n| n.as_mut())
513 .map(|n| &mut n.label)
514 }
515
516 pub fn has_edge_ix(&self, v_ix: usize, w_ix: usize) -> bool {
517 self.edge_by_endpoints_ix(v_ix, w_ix).is_some()
518 }
519
520 pub fn edge_by_endpoints_ix(&self, v_ix: usize, w_ix: usize) -> Option<&E> {
521 if self.options.directed {
522 let cache = self.ensure_directed_adj();
523 for &edge_idx in cache.out_edges(v_ix) {
524 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
525 continue;
526 };
527 debug_assert_eq!(e.v_ix, v_ix);
528 if e.w_ix == w_ix {
529 return Some(&e.label);
530 }
531 }
532 return None;
533 }
534
535 for e in self.edges.iter().filter_map(|e| e.as_ref()) {
536 if (e.v_ix == v_ix && e.w_ix == w_ix) || (e.v_ix == w_ix && e.w_ix == v_ix) {
537 return Some(&e.label);
538 }
539 }
540 None
541 }
542
543 pub fn set_node(&mut self, id: impl Into<String>, label: N) -> &mut Self {
544 let id = id.into();
545 if let Some(&idx) = self.node_index.get(&id) {
546 if let Some(node) = self.nodes.get_mut(idx).and_then(|n| n.as_mut()) {
547 node.label = label;
548 }
549 return self;
550 }
551 let _ = self.insert_node_entry(id, label);
552 self
553 }
554
555 pub fn ensure_node(&mut self, id: impl Into<String>) -> &mut Self {
556 let id = id.into();
557 if self.node_index.contains_key(&id) {
558 return self;
559 }
560 let label = (self.default_node_label)();
561 self.set_node(id, label)
562 }
563
564 pub fn ensure_node_ref(&mut self, id: &str) -> &mut Self {
565 if self.node_index.contains_key(id) {
566 return self;
567 }
568 let label = (self.default_node_label)();
569 self.set_node(id.to_string(), label)
570 }
571
572 pub fn node(&self, id: &str) -> Option<&N> {
573 let idx = *self.node_index.get(id)?;
574 self.nodes
575 .get(idx)
576 .and_then(|n| n.as_ref())
577 .map(|n| &n.label)
578 }
579
580 pub fn node_mut(&mut self, id: &str) -> Option<&mut N> {
581 let idx = *self.node_index.get(id)?;
582 self.nodes
583 .get_mut(idx)
584 .and_then(|n| n.as_mut())
585 .map(|n| &mut n.label)
586 }
587
588 pub fn node_count(&self) -> usize {
589 self.node_len
590 }
591
592 pub fn nodes(&self) -> impl Iterator<Item = &str> {
593 self.nodes
594 .iter()
595 .filter_map(|n| n.as_ref().map(|n| n.id.as_str()))
596 }
597
598 pub fn node_ids(&self) -> Vec<String> {
599 self.nodes
600 .iter()
601 .filter_map(|n| n.as_ref().map(|n| n.id.clone()))
602 .collect()
603 }
604
605 pub fn edge_count(&self) -> usize {
606 self.edge_len
607 }
608
609 pub fn edge_key_by_ix(&self, edge_ix: usize) -> Option<&EdgeKey> {
610 self.edges
611 .get(edge_ix)
612 .and_then(|e| e.as_ref())
613 .map(|e| &e.key)
614 }
615
616 pub fn edges(&self) -> impl Iterator<Item = &EdgeKey> {
617 self.edges.iter().filter_map(|e| e.as_ref().map(|e| &e.key))
618 }
619
620 pub fn for_each_edge<F>(&self, mut f: F)
621 where
622 F: FnMut(&EdgeKey, &E),
623 {
624 for e in &self.edges {
625 let Some(e) = e.as_ref() else {
626 continue;
627 };
628 f(&e.key, &e.label);
629 }
630 }
631
632 pub fn for_each_edge_ix<F>(&self, mut f: F)
633 where
634 F: FnMut(usize, usize, &EdgeKey, &E),
635 {
636 for e in &self.edges {
637 let Some(e) = e.as_ref() else {
638 continue;
639 };
640 f(e.v_ix, e.w_ix, &e.key, &e.label);
641 }
642 }
643
644 pub fn for_each_edge_entry_ix<F>(&self, mut f: F)
645 where
646 F: FnMut(usize, usize, usize, &EdgeKey, &E),
647 {
648 for (edge_ix, e) in self.edges.iter().enumerate() {
649 let Some(e) = e.as_ref() else {
650 continue;
651 };
652 f(edge_ix, e.v_ix, e.w_ix, &e.key, &e.label);
653 }
654 }
655
656 pub fn for_each_edge_mut<F>(&mut self, mut f: F)
657 where
658 F: FnMut(&EdgeKey, &mut E),
659 {
660 for e in &mut self.edges {
661 let Some(e) = e.as_mut() else {
662 continue;
663 };
664 f(&e.key, &mut e.label);
665 }
666 }
667
668 pub fn for_each_node<F>(&self, mut f: F)
669 where
670 F: FnMut(&str, &N),
671 {
672 for n in &self.nodes {
673 let Some(n) = n.as_ref() else {
674 continue;
675 };
676 f(&n.id, &n.label);
677 }
678 }
679
680 pub fn for_each_node_ix<F>(&self, mut f: F)
681 where
682 F: FnMut(usize, &str, &N),
683 {
684 for (idx, n) in self.nodes.iter().enumerate() {
685 let Some(n) = n.as_ref() else {
686 continue;
687 };
688 f(idx, &n.id, &n.label);
689 }
690 }
691
692 pub fn for_each_node_mut<F>(&mut self, mut f: F)
693 where
694 F: FnMut(&str, &mut N),
695 {
696 for n in &mut self.nodes {
697 let Some(n) = n.as_mut() else {
698 continue;
699 };
700 f(&n.id, &mut n.label);
701 }
702 }
703
704 pub fn edge_keys(&self) -> Vec<EdgeKey> {
705 self.edges
706 .iter()
707 .filter_map(|e| e.as_ref().map(|e| e.key.clone()))
708 .collect()
709 }
710
711 pub fn set_edge(&mut self, v: impl Into<String>, w: impl Into<String>) -> &mut Self {
712 self.set_edge_named(v, w, None::<String>, None)
713 }
714
715 pub fn set_edge_with_label(
716 &mut self,
717 v: impl Into<String>,
718 w: impl Into<String>,
719 label: E,
720 ) -> &mut Self {
721 self.set_edge_named(v, w, None::<String>, Some(label))
722 }
723
724 pub fn set_edge_named(
725 &mut self,
726 v: impl Into<String>,
727 w: impl Into<String>,
728 name: Option<impl Into<String>>,
729 label: Option<E>,
730 ) -> &mut Self {
731 let (v, w) = self.canonicalize_endpoints(v.into(), w.into());
732 self.ensure_node(v.clone());
733 self.ensure_node(w.clone());
734
735 let name = self.canonicalize_name(name.map(Into::into));
736 let key = EdgeKey { v, w, name };
737
738 if let Some(&idx) = self.edge_index.get(&key) {
739 if let Some(label) = label {
740 if let Some(edge) = self.edges.get_mut(idx).and_then(|e| e.as_mut()) {
741 edge.label = label;
742 }
743 }
744 return self;
745 }
746
747 self.invalidate_adj();
748 let v_ix = *self
749 .node_index
750 .get(&key.v)
751 .expect("ensure_node should have inserted the endpoint node");
752 let w_ix = *self
753 .node_index
754 .get(&key.w)
755 .expect("ensure_node should have inserted the endpoint node");
756 let idx = self.edges.len();
757 self.edges.push(Some(EdgeEntry {
758 key: key.clone(),
759 v_ix,
760 w_ix,
761 label: label.unwrap_or_else(|| (self.default_edge_label)()),
762 }));
763 self.edge_len += 1;
764 self.edge_index.insert(key, idx);
765 self
766 }
767
768 pub fn set_path(&mut self, nodes: &[&str]) -> &mut Self {
769 if nodes.len() < 2 {
770 return self;
771 }
772 for pair in nodes.windows(2) {
773 let v = pair[0];
774 let w = pair[1];
775 self.set_edge(v, w);
776 }
777 self
778 }
779
780 pub fn has_edge(&self, v: &str, w: &str, name: Option<&str>) -> bool {
781 let view = self.edge_key_view(v, w, name);
782 self.edge_index_of_view(view).is_some()
783 }
784
785 pub fn edge(&self, v: &str, w: &str, name: Option<&str>) -> Option<&E> {
786 let view = self.edge_key_view(v, w, name);
787 let idx = self.edge_index_of_view(view)?;
788 self.edges
789 .get(idx)
790 .and_then(|e| e.as_ref())
791 .map(|e| &e.label)
792 }
793
794 pub fn edge_mut(&mut self, v: &str, w: &str, name: Option<&str>) -> Option<&mut E> {
795 let view = self.edge_key_view(v, w, name);
796 let idx = self.edge_index_of_view(view)?;
797 self.edges
798 .get_mut(idx)
799 .and_then(|e| e.as_mut())
800 .map(|e| &mut e.label)
801 }
802
803 pub fn edge_by_key(&self, key: &EdgeKey) -> Option<&E> {
804 let view = self.edge_key_view_from_key(key);
805 let idx = self.edge_index_of_view(view)?;
806 self.edges
807 .get(idx)
808 .and_then(|e| e.as_ref())
809 .map(|e| &e.label)
810 }
811
812 pub fn edge_mut_by_key(&mut self, key: &EdgeKey) -> Option<&mut E> {
813 let view = self.edge_key_view_from_key(key);
814 let idx = self.edge_index_of_view(view)?;
815 self.edges
816 .get_mut(idx)
817 .and_then(|e| e.as_mut())
818 .map(|e| &mut e.label)
819 }
820
821 fn remove_edge_at_index(&mut self, idx: usize) {
822 self.invalidate_adj();
823 let Some(edge) = self.edges.get(idx).and_then(|e| e.as_ref()) else {
824 return;
825 };
826 let _ = self.edge_index.remove_entry(&edge.key);
827 self.edges[idx] = None;
828 self.edge_len = self.edge_len.saturating_sub(1);
829 self.trim_trailing_edge_tombstones();
830 }
831
832 pub fn remove_edge_key(&mut self, key: &EdgeKey) -> bool {
833 let view = self.edge_key_view_from_key(key);
834 let Some(idx) = self.edge_index_of_view(view) else {
835 return false;
836 };
837 self.remove_edge_at_index(idx);
838 true
839 }
840
841 pub fn remove_edge(&mut self, v: &str, w: &str, name: Option<&str>) -> bool {
842 let view = self.edge_key_view(v, w, name);
843 let Some(idx) = self.edge_index_of_view(view) else {
844 return false;
845 };
846 self.remove_edge_at_index(idx);
847 true
848 }
849
850 pub fn remove_node(&mut self, id: &str) -> bool {
851 let Some(idx) = self.node_index.remove(id) else {
852 return false;
853 };
854
855 self.invalidate_adj();
856 if let Some(slot) = self.nodes.get_mut(idx) {
857 if slot.is_some() {
858 *slot = None;
859 self.node_len = self.node_len.saturating_sub(1);
860 }
861 }
862
863 for e in self.edges.iter_mut() {
865 let Some(edge) = e.as_ref() else {
866 continue;
867 };
868 if edge.v_ix == idx || edge.w_ix == idx {
869 let key = edge.key.clone();
870 let _ = self.edge_index.remove_entry(&key);
871 *e = None;
872 self.edge_len = self.edge_len.saturating_sub(1);
873 }
874 }
875
876 if self.options.compound {
877 if let Some(prev_parent_ix) = self.parent_ix.get_mut(idx).and_then(|p| p.take()) {
879 if let Some(ch) = self.children_ix.get_mut(prev_parent_ix) {
880 ch.retain(|&c| c != idx);
881 }
882 }
883
884 if let Some(ch) = self.children_ix.get_mut(idx) {
886 for &child_ix in ch.iter() {
887 if let Some(slot) = self.parent_ix.get_mut(child_ix) {
888 if *slot == Some(idx) {
889 *slot = None;
890 }
891 }
892 }
893 ch.clear();
894 }
895 }
896
897 self.trim_trailing_edge_tombstones();
898 self.trim_trailing_node_tombstones();
899
900 true
901 }
902
903 pub fn successors(&self, v: &str) -> Vec<&str> {
904 if !self.options.directed {
905 return self.adjacent_nodes(v);
906 }
907 let Some(&v_idx) = self.node_index.get(v) else {
908 return Vec::new();
909 };
910 let cache = self.ensure_directed_adj();
911 let out_edges = cache.out_edges(v_idx);
912 let mut out: Vec<&str> = Vec::with_capacity(out_edges.len());
913 for &edge_idx in out_edges {
914 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
915 continue;
916 };
917 out.push(edge.key.w.as_str());
918 }
919 out
920 }
921
922 pub fn predecessors(&self, v: &str) -> Vec<&str> {
923 if !self.options.directed {
924 return self.adjacent_nodes(v);
925 }
926 let Some(&v_idx) = self.node_index.get(v) else {
927 return Vec::new();
928 };
929 let cache = self.ensure_directed_adj();
930 let in_edges = cache.in_edges(v_idx);
931 let mut out: Vec<&str> = Vec::with_capacity(in_edges.len());
932 for &edge_idx in in_edges {
933 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
934 continue;
935 };
936 out.push(edge.key.v.as_str());
937 }
938 out
939 }
940
941 pub fn first_successor<'a>(&'a self, v: &str) -> Option<&'a str> {
942 if !self.options.directed {
943 return self.adjacent_nodes(v).into_iter().next();
944 }
945 let &v_idx = self.node_index.get(v)?;
946 let w = {
947 let cache = self.ensure_directed_adj();
948 let edge_idx = *cache.out_edges(v_idx).first()?;
949 self.edges.get(edge_idx)?.as_ref()?.key.w.as_str()
950 };
951 Some(w)
952 }
953
954 pub fn first_predecessor<'a>(&'a self, v: &str) -> Option<&'a str> {
955 if !self.options.directed {
956 return self.adjacent_nodes(v).into_iter().next();
957 }
958 let &v_idx = self.node_index.get(v)?;
959 let u = {
960 let cache = self.ensure_directed_adj();
961 let edge_idx = *cache.in_edges(v_idx).first()?;
962 self.edges.get(edge_idx)?.as_ref()?.key.v.as_str()
963 };
964 Some(u)
965 }
966
967 pub fn extend_successors<'a>(&'a self, v: &str, out: &mut Vec<&'a str>) {
968 if !self.options.directed {
969 out.extend(self.adjacent_nodes(v));
970 return;
971 }
972 let Some(&v_idx) = self.node_index.get(v) else {
973 return;
974 };
975 let cache = self.ensure_directed_adj();
976 let out_edges = cache.out_edges(v_idx);
977 out.reserve(out_edges.len());
978 for &edge_idx in out_edges {
979 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
980 continue;
981 };
982 out.push(edge.key.w.as_str());
983 }
984 }
985
986 pub fn extend_predecessors<'a>(&'a self, v: &str, out: &mut Vec<&'a str>) {
987 if !self.options.directed {
988 out.extend(self.adjacent_nodes(v));
989 return;
990 }
991 let Some(&v_idx) = self.node_index.get(v) else {
992 return;
993 };
994 let cache = self.ensure_directed_adj();
995 let in_edges = cache.in_edges(v_idx);
996 out.reserve(in_edges.len());
997 for &edge_idx in in_edges {
998 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
999 continue;
1000 };
1001 out.push(edge.key.v.as_str());
1002 }
1003 }
1004
1005 pub fn for_each_successor<'a, F>(&'a self, v: &str, mut f: F)
1006 where
1007 F: FnMut(&'a str),
1008 {
1009 if !self.options.directed {
1010 for w in self.adjacent_nodes(v) {
1011 f(w);
1012 }
1013 return;
1014 }
1015 let Some(&v_idx) = self.node_index.get(v) else {
1016 return;
1017 };
1018 let cache = self.ensure_directed_adj();
1019 for &edge_idx in cache.out_edges(v_idx) {
1020 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1021 continue;
1022 };
1023 f(edge.key.w.as_str());
1024 }
1025 }
1026
1027 pub fn for_each_predecessor<'a, F>(&'a self, v: &str, mut f: F)
1028 where
1029 F: FnMut(&'a str),
1030 {
1031 if !self.options.directed {
1032 for u in self.adjacent_nodes(v) {
1033 f(u);
1034 }
1035 return;
1036 }
1037 let Some(&v_idx) = self.node_index.get(v) else {
1038 return;
1039 };
1040 let cache = self.ensure_directed_adj();
1041 for &edge_idx in cache.in_edges(v_idx) {
1042 let Some(edge) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1043 continue;
1044 };
1045 f(edge.key.v.as_str());
1046 }
1047 }
1048
1049 pub fn neighbors(&self, v: &str) -> Vec<&str> {
1050 if !self.options.directed {
1051 return self.adjacent_nodes(v);
1052 }
1053 let mut out: Vec<&str> = Vec::new();
1054 for w in self.successors(v) {
1055 if !out.iter().any(|x| x == &w) {
1056 out.push(w);
1057 }
1058 }
1059 for u in self.predecessors(v) {
1060 if !out.iter().any(|x| x == &u) {
1061 out.push(u);
1062 }
1063 }
1064 out
1065 }
1066
1067 fn adjacent_nodes(&self, v: &str) -> Vec<&str> {
1068 debug_assert!(!self.options.directed);
1069 let Some(&v_ix) = self.node_index.get(v) else {
1070 return Vec::new();
1071 };
1072 let cache = self.ensure_undirected_adj();
1073 let mut seen: HashSet<usize> = HashSet::default();
1074 let mut out: Vec<&str> = Vec::new();
1075 for &edge_idx in cache.edges(v_ix) {
1076 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1077 continue;
1078 };
1079 let other_ix = if e.v_ix == v_ix { e.w_ix } else { e.v_ix };
1080 if !seen.insert(other_ix) {
1081 continue;
1082 }
1083 let Some(other) = self.node_id_by_ix(other_ix) else {
1084 continue;
1085 };
1086 out.push(other);
1087 }
1088 out
1089 }
1090
1091 pub fn out_edges(&self, v: &str, w: Option<&str>) -> Vec<EdgeKey> {
1092 if self.options.directed {
1093 let Some(&v_idx) = self.node_index.get(v) else {
1094 return Vec::new();
1095 };
1096 let cache = self.ensure_directed_adj();
1097 let out_edges = cache.out_edges(v_idx);
1098 let mut out: Vec<EdgeKey> = Vec::with_capacity(out_edges.len());
1099 for &edge_idx in out_edges {
1100 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1101 continue;
1102 };
1103 if w.is_none_or(|w| e.key.w == w) {
1104 out.push(e.key.clone());
1105 }
1106 }
1107 return out;
1108 }
1109
1110 let Some(&v_ix) = self.node_index.get(v) else {
1111 return Vec::new();
1112 };
1113 let cache = self.ensure_undirected_adj();
1114 let mut out: Vec<EdgeKey> = Vec::new();
1115 for &edge_idx in cache.edges(v_ix) {
1116 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1117 continue;
1118 };
1119 if let Some(w) = w {
1120 let other_ix = if e.v_ix == v_ix { e.w_ix } else { e.v_ix };
1121 if self.node_id_by_ix(other_ix).is_some_and(|id| id == w) {
1122 out.push(e.key.clone());
1123 }
1124 } else {
1125 out.push(e.key.clone());
1126 }
1127 }
1128 out
1129 }
1130
1131 pub fn in_edges(&self, v: &str, w: Option<&str>) -> Vec<EdgeKey> {
1132 if self.options.directed {
1133 let Some(&v_idx) = self.node_index.get(v) else {
1134 return Vec::new();
1135 };
1136 let cache = self.ensure_directed_adj();
1137 let in_edges = cache.in_edges(v_idx);
1138 let mut out: Vec<EdgeKey> = Vec::with_capacity(in_edges.len());
1139 for &edge_idx in in_edges {
1140 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1141 continue;
1142 };
1143 if w.is_none_or(|w| e.key.v == w) {
1144 out.push(e.key.clone());
1145 }
1146 }
1147 return out;
1148 }
1149 self.out_edges(v, w)
1150 }
1151
1152 pub fn for_each_out_edge<F>(&self, v: &str, w: Option<&str>, mut f: F)
1153 where
1154 F: FnMut(&EdgeKey, &E),
1155 {
1156 if self.options.directed {
1157 let Some(&v_idx) = self.node_index.get(v) else {
1158 return;
1159 };
1160 let cache = self.ensure_directed_adj();
1161 for &edge_idx in cache.out_edges(v_idx) {
1162 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1163 continue;
1164 };
1165 if w.is_none_or(|w| e.key.w == w) {
1166 f(&e.key, &e.label);
1167 }
1168 }
1169 return;
1170 }
1171
1172 let Some(&v_ix) = self.node_index.get(v) else {
1173 return;
1174 };
1175 let cache = self.ensure_undirected_adj();
1176 for &edge_idx in cache.edges(v_ix) {
1177 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1178 continue;
1179 };
1180 if let Some(w) = w {
1181 let other_ix = if e.v_ix == v_ix { e.w_ix } else { e.v_ix };
1182 if self.node_id_by_ix(other_ix).is_some_and(|id| id == w) {
1183 f(&e.key, &e.label);
1184 }
1185 } else {
1186 f(&e.key, &e.label);
1187 }
1188 }
1189 }
1190
1191 pub fn for_each_in_edge<F>(&self, v: &str, w: Option<&str>, mut f: F)
1192 where
1193 F: FnMut(&EdgeKey, &E),
1194 {
1195 if self.options.directed {
1196 let Some(&v_idx) = self.node_index.get(v) else {
1197 return;
1198 };
1199 let cache = self.ensure_directed_adj();
1200 for &edge_idx in cache.in_edges(v_idx) {
1201 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1202 continue;
1203 };
1204 if w.is_none_or(|w| e.key.v == w) {
1205 f(&e.key, &e.label);
1206 }
1207 }
1208 return;
1209 }
1210
1211 self.for_each_out_edge(v, w, f);
1212 }
1213
1214 pub fn set_edge_key(&mut self, key: EdgeKey, label: E) -> &mut Self {
1215 let key = self.canonicalize_key(key);
1216 self.set_edge_named(key.v, key.w, key.name, Some(label))
1217 }
1218
1219 pub fn for_each_out_edge_ix<F>(&self, v_ix: usize, w_ix: Option<usize>, mut f: F)
1220 where
1221 F: FnMut(usize, usize, &EdgeKey, &E),
1222 {
1223 if !self.options.directed {
1224 return;
1225 }
1226 let cache = self.ensure_directed_adj();
1227 for &edge_idx in cache.out_edges(v_ix) {
1228 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1229 continue;
1230 };
1231 debug_assert_eq!(e.v_ix, v_ix);
1232 if w_ix.is_none_or(|w_ix| e.w_ix == w_ix) {
1233 f(e.v_ix, e.w_ix, &e.key, &e.label);
1234 }
1235 }
1236 }
1237
1238 pub fn for_each_out_edge_entry_ix<F>(&self, v_ix: usize, w_ix: Option<usize>, mut f: F)
1239 where
1240 F: FnMut(usize, usize, usize, &EdgeKey, &E),
1241 {
1242 if !self.options.directed {
1243 return;
1244 }
1245 let cache = self.ensure_directed_adj();
1246 for &edge_ix in cache.out_edges(v_ix) {
1247 let Some(e) = self.edges.get(edge_ix).and_then(|e| e.as_ref()) else {
1248 continue;
1249 };
1250 debug_assert_eq!(e.v_ix, v_ix);
1251 if w_ix.is_none_or(|w_ix| e.w_ix == w_ix) {
1252 f(edge_ix, e.v_ix, e.w_ix, &e.key, &e.label);
1253 }
1254 }
1255 }
1256
1257 pub fn for_each_neighbor_ix<F>(&self, v_ix: usize, mut f: F)
1258 where
1259 F: FnMut(usize),
1260 {
1261 if self.options.directed {
1262 let cache = self.ensure_directed_adj();
1263 for &edge_idx in cache.out_edges(v_ix) {
1264 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1265 continue;
1266 };
1267 debug_assert_eq!(e.v_ix, v_ix);
1268 f(e.w_ix);
1269 }
1270 for &edge_idx in cache.in_edges(v_ix) {
1271 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1272 continue;
1273 };
1274 debug_assert_eq!(e.w_ix, v_ix);
1275 f(e.v_ix);
1276 }
1277 return;
1278 }
1279
1280 let cache = self.ensure_undirected_adj();
1281 for &edge_idx in cache.edges(v_ix) {
1282 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1283 continue;
1284 };
1285 let other_ix = if e.v_ix == v_ix { e.w_ix } else { e.v_ix };
1286 f(other_ix);
1287 }
1288 }
1289
1290 pub fn for_each_in_edge_ix<F>(&self, v_ix: usize, w_ix: Option<usize>, mut f: F)
1291 where
1292 F: FnMut(usize, usize, &EdgeKey, &E),
1293 {
1294 if !self.options.directed {
1295 return;
1296 }
1297 let cache = self.ensure_directed_adj();
1298 for &edge_idx in cache.in_edges(v_ix) {
1299 let Some(e) = self.edges.get(edge_idx).and_then(|e| e.as_ref()) else {
1300 continue;
1301 };
1302 debug_assert_eq!(e.w_ix, v_ix);
1303 if w_ix.is_none_or(|w_ix| e.v_ix == w_ix) {
1304 f(e.v_ix, e.w_ix, &e.key, &e.label);
1305 }
1306 }
1307 }
1308
1309 pub fn for_each_in_edge_entry_ix<F>(&self, v_ix: usize, w_ix: Option<usize>, mut f: F)
1310 where
1311 F: FnMut(usize, usize, usize, &EdgeKey, &E),
1312 {
1313 if !self.options.directed {
1314 return;
1315 }
1316 let cache = self.ensure_directed_adj();
1317 for &edge_ix in cache.in_edges(v_ix) {
1318 let Some(e) = self.edges.get(edge_ix).and_then(|e| e.as_ref()) else {
1319 continue;
1320 };
1321 debug_assert_eq!(e.w_ix, v_ix);
1322 if w_ix.is_none_or(|w_ix| e.v_ix == w_ix) {
1323 f(edge_ix, e.v_ix, e.w_ix, &e.key, &e.label);
1324 }
1325 }
1326 }
1327
1328 pub fn set_parent(&mut self, child: impl Into<String>, parent: impl Into<String>) -> &mut Self {
1329 if !self.options.compound {
1330 return self;
1331 }
1332 let child = child.into();
1333 let parent = parent.into();
1334 self.ensure_node(child.clone());
1335 self.ensure_node(parent.clone());
1336 let Some(&child_ix) = self.node_index.get(&child) else {
1337 return self;
1338 };
1339 let Some(&parent_ix) = self.node_index.get(&parent) else {
1340 return self;
1341 };
1342 self.set_parent_ix(child_ix, parent_ix);
1343 self
1344 }
1345
1346 pub fn set_parent_ref(&mut self, child: &str, parent: &str) -> &mut Self {
1347 if !self.options.compound {
1348 return self;
1349 }
1350 self.ensure_node_ref(child);
1351 self.ensure_node_ref(parent);
1352 let Some(&child_ix) = self.node_index.get(child) else {
1353 return self;
1354 };
1355 let Some(&parent_ix) = self.node_index.get(parent) else {
1356 return self;
1357 };
1358 self.set_parent_ix(child_ix, parent_ix);
1359 self
1360 }
1361
1362 pub fn set_parent_ix(&mut self, child_ix: usize, parent_ix: usize) -> &mut Self {
1363 if !self.options.compound {
1364 return self;
1365 }
1366 if child_ix >= self.nodes.len() || parent_ix >= self.nodes.len() {
1367 return self;
1368 }
1369
1370 let prev = self.parent_ix.get(child_ix).copied().flatten();
1371 if prev == Some(parent_ix) {
1372 return self;
1373 }
1374
1375 if let Some(prev_parent_ix) = prev {
1376 if let Some(ch) = self.children_ix.get_mut(prev_parent_ix) {
1377 ch.retain(|&c| c != child_ix);
1378 }
1379 }
1380
1381 if let Some(slot) = self.parent_ix.get_mut(child_ix) {
1382 *slot = Some(parent_ix);
1383 }
1384 if let Some(ch) = self.children_ix.get_mut(parent_ix) {
1385 if !ch.contains(&child_ix) {
1386 ch.push(child_ix);
1387 }
1388 }
1389 self
1390 }
1391
1392 pub fn clear_parent(&mut self, child: &str) -> &mut Self {
1393 if !self.options.compound {
1394 return self;
1395 }
1396 let Some(&child_ix) = self.node_index.get(child) else {
1397 return self;
1398 };
1399 let Some(prev_parent_ix) = self.parent_ix.get(child_ix).copied().flatten() else {
1400 return self;
1401 };
1402 if let Some(slot) = self.parent_ix.get_mut(child_ix) {
1403 *slot = None;
1404 }
1405 if let Some(ch) = self.children_ix.get_mut(prev_parent_ix) {
1406 ch.retain(|&c| c != child_ix);
1407 }
1408 self
1409 }
1410
1411 pub fn parent(&self, child: &str) -> Option<&str> {
1412 if !self.options.compound {
1413 return None;
1414 }
1415 let &child_ix = self.node_index.get(child)?;
1416 let parent_ix = self.parent_ix.get(child_ix).copied().flatten()?;
1417 self.node_id_by_ix(parent_ix)
1418 }
1419
1420 pub fn children_iter<'a>(&'a self, parent: &str) -> impl Iterator<Item = &'a str> + 'a {
1421 let children = if self.options.compound {
1422 self.node_index
1423 .get(parent)
1424 .and_then(|&p_ix| self.children_ix.get(p_ix))
1425 .map(|v| v.as_slice())
1426 .unwrap_or(&[])
1427 } else {
1428 &[]
1429 };
1430 let mut i = 0usize;
1431 std::iter::from_fn(move || {
1432 while i < children.len() {
1433 let child_ix = children[i];
1434 i += 1;
1435 if let Some(id) = self.node_id_by_ix(child_ix) {
1436 return Some(id);
1437 }
1438 }
1439 None
1440 })
1441 }
1442
1443 pub fn children(&self, parent: &str) -> Vec<&str> {
1444 self.children_iter(parent).collect()
1445 }
1446
1447 pub fn children_root(&self) -> Vec<&str> {
1448 if !self.options.compound {
1449 return self.nodes().collect();
1450 }
1451 let mut out: Vec<&str> = Vec::new();
1452 for (ix, n) in self.nodes.iter().enumerate() {
1453 let Some(n) = n.as_ref() else {
1454 continue;
1455 };
1456 if self.parent_ix.get(ix).copied().flatten().is_none() {
1457 out.push(n.id.as_str());
1458 }
1459 }
1460 out
1461 }
1462
1463 pub fn sources(&self) -> Vec<&str> {
1464 if !self.options.directed {
1465 return self.nodes().collect();
1466 }
1467 self.nodes
1468 .iter()
1469 .filter_map(|n| n.as_ref())
1470 .filter(|n| self.in_edges(&n.id, None).is_empty())
1471 .map(|n| n.id.as_str())
1472 .collect()
1473 }
1474
1475 pub fn node_edges(&self, v: &str) -> Vec<EdgeKey> {
1476 let mut out: Vec<EdgeKey> = Vec::new();
1477 let mut seen: HashSet<EdgeKey> = HashSet::default();
1478 for e in &self.edges {
1479 let Some(e) = e.as_ref() else {
1480 continue;
1481 };
1482 if (e.key.v == v || e.key.w == v) && seen.insert(e.key.clone()) {
1483 out.push(e.key.clone());
1484 }
1485 }
1486 out
1487 }
1488}