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