linnet/
half_edge.rs

1//! # Half-Edge Graph Representation
2//!
3//! This module provides the core data structures and algorithms for representing
4//! and manipulating graphs using the **half-edge** (or doubly connected edge list - DCEL)
5//! data structure. This representation is particularly useful for algorithms that
6//! require efficient traversal of graph topology, such as iterating around faces,
7//! finding incident edges to a node, or quickly accessing an edge's opposite pair.
8//!
9//! ## Key Concepts and Components:
10//!
11//! ### 1. `HedgeGraph<E, V, S>`
12//! This is the central struct representing a graph.
13//!   - `E`: Generic type for data associated with edges.
14//!   - `V`: Generic type for data associated with nodes (vertices).
15//!   - `S`: A type implementing `NodeStorage`, which defines how node data and their connectivity to half-edges are stored.
16//!
17//! `HedgeGraph` stores half-edges in an `edge_store` (typically `SmartHedgeVec`)
18//! and nodes in a `node_store`.
19//!
20//! ### 2. `Hedge` and `NodeIndex`
21//!   - `Hedge`: An identifier (often an index) for a single directed half-edge.
22//!     Each undirected edge in the graph is typically represented by two oppositely
23//!     directed half-edges.
24//!   - `NodeIndex`: A simple wrapper around `usize` used to identify nodes in the graph.
25//!
26//! ### 3. Involutions (`involution` module)
27//! A crucial concept in this implementation is the **involution** on half-edges.
28//! An involution is a function that, when applied twice, returns the original input.
29//! In the context of a half-edge graph, the primary involution is finding the
30//! **opposite half-edge**.
31//!   - `Involution`: The struct managing this mapping.
32//!   - `HedgePair`: Represents how hedges are paired (e.g., forming a full edge,
33//!     being unpaired/dangling, or split).
34//!   - `Flow`: Indicates the underlying directionality of a half-edge (Source or Sink)
35//!     relative to its edge.
36//!   - `Orientation`: Indicates the superficial orientation of an edge (Default, Reversed,
37//!     Undirected).
38//!
39//! The `inv(hedge: Hedge) -> Hedge` method on `HedgeGraph` is the primary way to
40//! access the opposite half-edge.
41//!
42//! ### 4. Node Storage (`nodestore` module)
43//! This module defines how nodes are stored and how they relate to the half-edges
44//! that originate from them.
45//!   - `NodeStorage` trait: An abstraction for different node storage strategies.
46//!   - `NodeStorageOps` trait: Provides operations on node storage.
47//!   - Each node typically stores a collection of its outgoing (or incident) half-edges.
48//!
49//! ### 5. Subgraphs (`subgraph` module)
50//! This module provides extensive support for defining, manipulating, and querying
51//! subgraphs. A subgraph is essentially a subset of the half-edges of a parent graph.
52//!   - `SubGraph` trait: Defines the basic interface for a subgraph.
53//!   - `SubGraphOps` trait: Provides operations applicable to subgraphs.
54//!   - Various concrete subgraph types exist, such as:
55//!     - `InternalSubGraph`: Represents a subgraph composed of edges internal to a region.
56//!     - `HedgeNode`: Represents a "node" in a higher-level graph structure, possibly
57//!       formed by contracting a subgraph. It contains an `internal_graph` and `hairs`
58//!       (external connections).
59//!     - `Cycle`: Represents a cycle in the graph.
60//!     - `OrientedCut`: Represents a cut separating the graph.
61//!
62//! Operations include creating subgraphs from filters, extracting subgraphs,
63//! performing boolean operations (union, intersection, difference), and analyzing
64//! subgraph properties.
65//!
66//! ### 6. Graph Operations
67//! The `HedgeGraph` provides a rich API for:
68//!   - **Construction**: Building graphs using `HedgeGraphBuilder`, adding nodes and edges
69//!     (`add_dangling_edge`, `add_pair`).
70//!   - **Modification**: Deleting hedges (`delete_hedges`), splitting edges (`split_edge`),
71//!     joining graphs (`join`), sewing dangling edges (`sew`), and identifying/contracting
72//!     nodes (`identify_nodes`).
73//!   - **Traversal & Access**: Getting an edge's opposite (`inv`), finding the node a
74//!     hedge points to (`node_id`), iterating over neighbors (`iter_crown`), and
75//!     accessing edge/node data.
76//!   - **Analysis**: Checking connectivity (`is_connected`), counting components
77//!     (`count_connected_components`), finding cycle bases (`cycle_basis`), spanning trees
78//!     (`all_spanning_trees`), and calculating cyclotomatic numbers.
79//!   - **Serialization/Visualization**: Generating DOT format strings for graph visualization.
80//!
81//! This module forms the backbone of the `linnet` library, enabling complex graph
82//! manipulations with a focus on subgraphs and topological features.
83
84use core::panic;
85use std::cmp::Ordering;
86use std::fmt::Display;
87use std::hash::Hash;
88use std::num::TryFromIntError;
89use std::ops::{Index, IndexMut};
90
91use ahash::{AHashMap, AHashSet};
92
93use bitvec::prelude::*;
94use bitvec::{slice::IterOnes, vec::BitVec};
95use builder::{HedgeData, HedgeGraphBuilder};
96use hedgevec::{Accessors, SmartEdgeVec};
97use indexmap::IndexSet;
98use involution::{
99    EdgeData, EdgeIndex, EdgeVec, Flow, Hedge, HedgePair, HedgeVec, Involution, InvolutionError,
100    InvolutiveMapping, Orientation,
101};
102
103use itertools::Itertools;
104use nodestore::{NodeStorage, NodeStorageOps, NodeStorageVec};
105use rand::{rngs::SmallRng, Rng, SeedableRng};
106use swap::Swap;
107
108define_indexed_vec!(
109    /// A type-safe wrapper around a `usize` to represent the index of a node
110    /// in a graph.
111    ///
112    /// This helps prevent accidental misuse of raw `usize` values where a node
113    /// identifier is expected.
114    pub struct NodeIndex; // new‑type around usize
115
116    /// Vector whose items are `T`, indexable only by `EntityId`.
117    pub struct NodeVec;
118);
119
120impl NodeIndex {
121    pub fn add_data<H>(self, data: H) -> HedgeData<H> {
122        HedgeData {
123            data,
124            node: self,
125            is_in_subgraph: false,
126        }
127    }
128}
129
130impl std::fmt::Display for NodeIndex {
131    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132        write!(f, "{}", self.0)
133    }
134}
135
136/// Iterator over the powerset of a bitvec, of size n < 64.
137///
138/// Generates all possible subsets of a set of up to 63 elements.
139/// The subsets are represented as `BitVec`s.
140///
141/// **Note:** The maximum number of elements is limited due to the `usize`
142/// representation of the current subset index. On a 64-bit system, this
143/// could theoretically support up to 64 elements, but practically, iterating
144/// 2^64 items is not feasible. The comment "n < 64" suggests a practical limit.
145pub struct PowersetIterator {
146    /// The total number of subsets, equal to 2^(number of elements).
147    size: usize,
148    /// The current subset index, ranging from 0 to `size - 1`.
149    /// Each bit in `current` corresponds to an element's presence in the subset.
150    current: usize,
151}
152
153impl PowersetIterator {
154    pub fn new(n_elements: u8) -> Self {
155        PowersetIterator {
156            size: 1 << n_elements,
157            current: 0,
158        }
159    }
160}
161
162impl Iterator for PowersetIterator {
163    type Item = BitVec;
164
165    fn next(&mut self) -> Option<Self::Item> {
166        if self.current < self.size {
167            let out = BitVec::<_, Lsb0>::from_element(self.current);
168            self.current += 1;
169            Some(out)
170        } else {
171            None
172        }
173    }
174}
175pub mod involution;
176
177#[derive(Clone, Debug, Default)]
178#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
179#[cfg_attr(feature = "bincode", derive(bincode::Encode, bincode::Decode))]
180/// Represents attributes for an edge when generating Graphviz DOT output.
181///
182/// This struct allows specifying common DOT attributes like label, color,
183/// and other custom attributes for an edge.
184pub struct GVEdgeAttrs {
185    /// The label to be displayed on the edge.
186    pub label: Option<String>,
187    /// The color of the edge. Can be a color name (e.g., "red") or other
188    /// Graphviz color specifications.
189    pub color: Option<String>,
190    /// A field for any other custom DOT attributes for the edge,
191    /// represented as a single string (e.g., "style=dashed, arrowhead=vee").
192    pub other: Option<String>,
193}
194
195impl std::fmt::Display for GVEdgeAttrs {
196    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197        let out = [
198            ("label=", self.label.as_ref()),
199            (
200                "color=",
201                self.color.as_ref().map(|str| format!("\"{str}\"")).as_ref(),
202            ),
203            ("", self.other.as_ref()),
204        ]
205        .iter()
206        .filter_map(|(prefix, x)| x.map(|s| format!("{prefix}{s}")))
207        .join(" ")
208        .to_string();
209        if out.is_empty() {
210            write!(f, "")
211        } else {
212            write!(f, " {out}")
213        }
214    }
215}
216pub mod builder;
217pub mod nodestore;
218pub mod subgraph;
219pub mod swap;
220
221#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
222#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
223#[cfg_attr(
224    feature = "bincode",
225    derive(bincode_trait_derive::Encode, bincode_trait_derive::Decode)
226)]
227/// The main graph data structure, representing a graph using the half-edge
228/// (or doubly connected edge list - DCEL) principle.
229///
230/// A `HedgeGraph` stores nodes and edges (represented as pairs of half-edges).
231/// It is generic over the data associated with edges (`E`), nodes/vertices (`V`),
232/// and the specific storage strategy used for nodes (`S`).
233///
234/// The half-edge representation allows for efficient traversal of graph topology,
235/// such as iterating around faces (in planar embeddings), finding incident edges
236/// to a node, or quickly accessing an edge's opposite half-edge.
237///
238/// # Type Parameters
239///
240/// - `E`: The type of data associated with each edge (or pair of half-edges).
241/// - `V`: The type of data associated with each node (vertex).
242/// - `S`: The node storage strategy, implementing the [`NodeStorage`] trait.
243///   This determines how node data and their connectivity to half-edges
244///   are stored. Defaults to [`NodeStorageVec<V>`].
245pub struct HedgeGraph<E, V, H = NoData, S: NodeStorage<NodeData = V> = NodeStorageVec<V>> {
246    hedge_data: HedgeVec<H>,
247    /// Internal storage for all half-edges, their data, and their topological
248    /// relationships (e.g., opposite half-edge, next half-edge around a node).
249    /// This is typically a [`SmartHedgeVec<E>`].
250    edge_store: SmartEdgeVec<E>,
251    /// Storage for all nodes in the graph, including their data (`V`) and
252    /// information about the half-edges incident to them.
253    /// The specific implementation is determined by the `S` type parameter.
254    pub node_store: S,
255}
256
257#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
259#[cfg_attr(
260    feature = "bincode",
261    derive(bincode_trait_derive::Encode, bincode_trait_derive::Decode)
262)]
263pub struct NoData {}
264impl Display for NoData {
265    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
266        write!(f, "")
267    }
268}
269
270impl<E, V, H, S: NodeStorage<NodeData = V>> AsRef<Involution> for HedgeGraph<E, V, H, S> {
271    fn as_ref(&self) -> &Involution {
272        self.edge_store.as_ref()
273    }
274}
275
276impl<E, V: Default, H: Default, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
277    /// Creates a random graph with a specified number of nodes and edges.
278    ///
279    /// The graph generated will have `()` as edge data and default values for node data `V`.
280    /// The structure of the graph (connectivity) is determined randomly based on the provided seed.
281    ///
282    /// # Parameters
283    /// - `nodes`: The desired number of nodes in the graph.
284    /// - `edges`: The desired number of edges (pairs of half-edges) in the graph.
285    /// - `seed`: A seed for the random number generator to ensure reproducibility.
286    ///
287    /// # Returns
288    /// A new `HedgeGraph<(), V, N>` with a random structure.
289    ///
290    /// # Constraints
291    /// - `N::Neighbors` must implement `BaseSubgraph` and `SubGraphOps`.
292    /// - `V` must implement `Default`.
293    ///
294    /// # Panics
295    /// Panics if `sources.len()` (derived from `edges`) is 0 when `externals` (unpaired half-edges)
296    /// is not empty, or if `sinks.len()` is 0 when `externals` is not empty. This can occur if
297    /// `edges` is too small relative to the internal logic of pairing, leading to attempts to access
298    /// empty vectors `sources` or `sinks`. Also panics if node merging logic (to reduce node count
299    /// to `nodes`) attempts to operate on empty or insufficiently small `sources` or `sinks` lists.
300    pub fn random(nodes: usize, edges: usize, seed: u64) -> HedgeGraph<(), V, H, N>
301    where
302        N::Neighbors: BaseSubgraph + SubGraphOps,
303    {
304        let inv: Involution<()> = Involution::<()>::random(edges, seed);
305
306        let mut rng = SmallRng::seed_from_u64(seed);
307
308        let mut externals = Vec::new();
309        let mut sources = Vec::new();
310        let mut sinks = Vec::new();
311
312        for (i, e) in inv.iter() {
313            let n_h: Hedge = inv.len();
314            let mut nodeid = N::Neighbors::empty(n_h.0);
315            nodeid.add(i);
316            match e {
317                InvolutiveMapping::Identity { .. } => externals.push(nodeid),
318                InvolutiveMapping::Source { .. } => sources.push(nodeid),
319                InvolutiveMapping::Sink { .. } => sinks.push(nodeid),
320            }
321        }
322
323        assert_eq!(sources.len(), sinks.len());
324
325        while !externals.is_empty() {
326            if rng.gen_bool(0.5) {
327                let source_i = rng.gen_range(0..sources.len());
328
329                sources[source_i].union_with(&externals.pop().unwrap());
330            } else {
331                let sink_i = rng.gen_range(0..sinks.len());
332
333                sinks[sink_i].union_with(&externals.pop().unwrap());
334            }
335        }
336
337        let mut lengthone = false;
338
339        while sources.len() + sinks.len() > nodes {
340            if rng.gen_bool(0.5) {
341                if sources.len() <= 1 {
342                    if lengthone {
343                        break;
344                    }
345                    lengthone = true;
346                    continue;
347                }
348
349                let idx1 = rng.gen_range(0..sources.len());
350                let idx2 = rng.gen_range(0..sources.len() - 1);
351
352                let n_i = sources.swap_remove(idx1);
353                sources[idx2].union_with(&n_i);
354            } else {
355                if sinks.len() <= 1 {
356                    if lengthone {
357                        break;
358                    }
359                    lengthone = true;
360                    continue;
361                }
362                let idx1 = rng.gen_range(0..sinks.len());
363                let idx2 = rng.gen_range(0..sinks.len() - 1);
364                let n_i = sinks.swap_remove(idx1);
365                sinks[idx2].union_with(&n_i);
366            }
367        }
368
369        let mut hedge_data = HedgeVec::new();
370        let n_h: Hedge = inv.len();
371        for _ in 0..n_h.0 {
372            hedge_data.push(H::default());
373        }
374
375        HedgeGraph {
376            hedge_data,
377            node_store: N::random(&sources, &sinks),
378            edge_store: SmartEdgeVec::new(inv),
379        }
380    }
381}
382
383impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
384    pub fn check(&self) -> Result<(), HedgeGraphError> {
385        // Check involution
386        for (h, _) in self.iter_hedges() {
387            if h != self.inv(self.inv(h)) {
388                Err(InvolutionError::NonInvolutive(h))?;
389            }
390        }
391
392        // Check smart edge vec
393        self.edge_store.check_hedge_pairs()?;
394        Ok(())
395    }
396
397    /// Deletes all half-edges specified in the `subgraph` from the graph.
398    ///
399    /// This operation modifies both the `edge_store` and `node_store` to remove
400    /// the specified half-edges and update connectivity information.
401    ///
402    /// # Parameters
403    /// - `subgraph`: A subgraph specifying the set of half-edges to delete.
404    ///   `S` must implement `SubGraph` with `Base = N::Base`.
405    pub fn delete_hedges<S: SubGraph<Base = N::Base>>(&mut self, subgraph: &S) {
406        let mut left = Hedge(0);
407        let mut extracted: Hedge = self.len();
408        while left < extracted {
409            if !subgraph.includes(&left) {
410                //left is in the right place
411                left.0 += 1;
412            } else {
413                //left needs to be swapped
414                extracted.0 -= 1;
415                if !subgraph.includes(&extracted) {
416                    // println!("{extracted}<=>{left}");
417                    //only with an extracted that is in the wrong spot
418                    self.hedge_data.swap(left, extracted);
419                    left.0 += 1;
420                }
421            }
422        }
423        let _ = self.hedge_data.split_off(left);
424
425        self.edge_store.delete(subgraph);
426        self.node_store.delete(subgraph);
427    }
428
429    /// Creates a new `HedgeGraph` instance representing a "concretized" view of a given `subgraph`.
430    ///
431    /// This method effectively extracts the specified `subgraph` into a new, independent graph.
432    /// The new graph contains copies of the nodes and edges (and their data via references)
433    /// that are part of the `subgraph`.
434    ///
435    /// Node and edge data in the new graph are references (`&'a V`, `&'a E`) to the data
436    /// in the original graph.
437    ///
438    /// # Parameters
439    /// - `subgraph`: A reference to a subgraph `S` within the current graph.
440    ///
441    /// # Returns
442    /// A new `HedgeGraph` containing only the elements of the `subgraph`.
443    /// The node storage type of the new graph is `N::OpStorage<&'a V>`.
444    pub fn concretize<'a, S: SubGraph>(
445        &'a self,
446        subgraph: &'a S,
447    ) -> HedgeGraph<&'a E, &'a V, &'a H, N::OpStorage<&'a V>> {
448        let mut builder = HedgeGraphBuilder::new();
449
450        let mut node_map = AHashMap::new();
451
452        for (n, _, d) in self.iter_nodes_of(subgraph) {
453            node_map.insert(n, builder.add_node(d));
454        }
455
456        for (pair, _, d) in self.iter_edges_of(subgraph) {
457            match pair {
458                HedgePair::Paired { source, sink } => {
459                    let src = node_map[&self.node_id(source)].add_data(&self[source]);
460                    let dst = node_map[&self.node_id(sink)].add_data(&self[sink]);
461
462                    builder.add_edge(src, dst, d.data, d.orientation);
463                }
464                HedgePair::Unpaired { hedge, flow } => {
465                    let src = node_map[&self.node_id(hedge)].add_data(&self[hedge]);
466
467                    builder.add_external_edge(src, d.data, d.orientation, flow);
468                }
469                HedgePair::Split {
470                    source,
471                    sink,
472                    split,
473                } => match split {
474                    Flow::Sink => {
475                        let src = node_map[&self.node_id(sink)].add_data(&self[sink]);
476                        builder.add_external_edge(src, d.data, d.orientation, split);
477                    }
478                    Flow::Source => {
479                        let src = node_map[&self.node_id(source)].add_data(&self[source]);
480                        builder.add_external_edge(src, d.data, d.orientation, split);
481                    }
482                },
483            }
484        }
485
486        builder.build()
487    }
488
489    /// Extracts a subgraph and transforms its data, potentially splitting edges and nodes
490    /// that are on the boundary of the subgraph.
491    ///
492    /// This is a more advanced operation than `concretize`. It allows for:
493    /// - Transforming edge data for edges fully within the subgraph (`internal_data` closure).
494    /// - Transforming edge data for edges that are split by the subgraph boundary (`split_edge_fn` closure).
495    /// - Transforming node data for nodes that are part of split edges (`split_node` closure).
496    /// - Transforming node data for nodes fully within the subgraph and taking ownership (`owned_node` closure).
497    ///
498    /// The result is a new `HedgeGraph` with transformed edge data `O` and node data `V2`.
499    ///
500    /// # Parameters
501    /// - `subgraph`: The subgraph `S` to extract.
502    /// - `split_edge_fn`: A closure that transforms `EdgeData<&E>` (for edges on the boundary)
503    ///   to `EdgeData<O>`.
504    /// - `internal_data`: A closure that transforms `EdgeData<E>` (for edges fully inside)
505    ///   to `EdgeData<O>`.
506    /// - `split_node`: A closure that transforms node data `&V` (for nodes on the boundary)
507    ///   to `V2`.
508    /// - `owned_node`: A closure that transforms node data `V` (for nodes fully inside, taking ownership)
509    ///   to `V2`.
510    ///
511    /// # Returns
512    /// A new `HedgeGraph<O, V2, N::OpStorage<V2>>` representing the extracted and transformed subgraph.
513    pub fn extract<O, V2, S: SubGraph<Base = N::Base>>(
514        &mut self,
515        subgraph: &S,
516        split_edge_fn: impl FnMut(EdgeData<&E>) -> EdgeData<O>,
517        internal_data: impl FnMut(EdgeData<E>) -> EdgeData<O>,
518        split_node: impl FnMut(&V) -> V2,
519        owned_node: impl FnMut(V) -> V2,
520    ) -> HedgeGraph<O, V2, H, N::OpStorage<V2>> {
521        let new_edge_store = self
522            .edge_store
523            .extract(subgraph, split_edge_fn, internal_data);
524
525        let mut left = Hedge(0);
526        let mut extracted: Hedge = self.len();
527        while left < extracted {
528            if !subgraph.includes(&left) {
529                //left is in the right place
530                left.0 += 1;
531            } else {
532                //left needs to be swapped
533                extracted.0 -= 1;
534                if !subgraph.includes(&extracted) {
535                    // println!("{extracted}<=>{left}");
536                    //only with an extracted that is in the wrong spot
537                    self.hedge_data.swap(left, extracted);
538                    left.0 += 1;
539                }
540            }
541        }
542        let new_hedge_data = self.hedge_data.split_off(left);
543
544        let new_node_store = self.node_store.extract(subgraph, split_node, owned_node);
545        HedgeGraph {
546            hedge_data: new_hedge_data,
547            node_store: new_node_store,
548            edge_store: new_edge_store,
549        }
550    }
551
552    pub fn extract_nodes<O>(
553        &mut self,
554        nodes: impl IntoIterator<Item = NodeIndex>,
555        split_edge_fn: impl FnMut(EdgeData<&E>) -> EdgeData<O>,
556        internal_data: impl FnMut(EdgeData<E>) -> EdgeData<O>,
557    ) -> HedgeGraph<O, V, H, N>
558    where
559        N: NodeStorageOps<Base = BitVec>,
560    {
561        let (extracted, nodes) = self.node_store.extract_nodes(nodes);
562
563        let left = self.hedge_data.partition(|h| !extracted.includes(h));
564
565        let ne_hedge = self.hedge_data.split_off(left);
566
567        let new_edge_store = self
568            .edge_store
569            .extract(&extracted, split_edge_fn, internal_data);
570        HedgeGraph {
571            hedge_data: ne_hedge,
572            node_store: nodes,
573            edge_store: new_edge_store,
574        }
575    }
576    /// Gives the involved hedge.
577    /// Returns the opposite (or "twin") half-edge of the given `hedge`.
578    ///
579    /// - If `hedge` is part of a paired edge, this returns its sibling half-edge.
580    /// - If `hedge` is an identity (unpaired) half-edge, it returns itself.
581    ///
582    /// # Parameters
583    /// - `hedge`: The half-edge for which to find the opposite.
584    ///
585    /// # Returns
586    /// The opposite `Hedge`.
587    pub fn inv(&self, hedge: Hedge) -> Hedge {
588        self.edge_store.inv(hedge)
589    }
590
591    /// Splits a paired edge (identified by one of its half-edges, `hedge`) into two
592    /// new dangling (identity) half-edges.
593    ///
594    /// The original edge data is typically associated with one of the new dangling edges,
595    /// and the provided `data` is associated with the other. The underlying `Flow` of the
596    /// new half-edges corresponds to their roles in the original paired edge.
597    ///
598    /// # Parameters
599    /// - `hedge`: One of the half-edges of the paired edge to be split.
600    /// - `data`: The `EdgeData<E>` to be associated with the new dangling half-edge
601    ///   created from the `hedge` side of the split. The original edge's data will be
602    ///   associated with the other new dangling half-edge (created from `inv(hedge)`).
603    ///
604    /// # Returns
605    /// - `Ok(())` if the edge was successfully split.
606    /// - `Err(HedgeGraphError::InvolutionError(InvolutionError::NotPaired))` if `hedge` is an identity edge.
607    pub fn split_edge(&mut self, hedge: Hedge, data: EdgeData<E>) -> Result<(), HedgeGraphError> {
608        Ok(self.edge_store.split_edge(hedge, data)?)
609    }
610
611    /// Consumes two graphs (`self` and `other`) and joins them into a new graph.
612    ///
613    /// Dangling half-edges from both graphs are matched using `matching_fn`. If a match
614    /// is found, these two dangling edges are "sewn" together to form a new paired edge
615    /// in the resulting graph. The data for this new edge is determined by `merge_fn`.
616    ///
617    /// Node stores are extended, and the edge store is created by joining the two
618    /// original edge stores.
619    ///
620    /// # Parameters
621    /// - `other`: The other graph to join with `self`.
622    /// - `matching_fn`: A closure `(Flow, EdgeData<&E>, Flow, EdgeData<&E>) -> bool`
623    ///   that determines if two dangling half-edges (one from `self`, one from `other`)
624    ///   should be matched and sewn together. It takes the flow and edge data of both.
625    /// - `merge_fn`: A closure `(Flow, EdgeData<E>, Flow, EdgeData<E>) -> (Flow, EdgeData<E>)`
626    ///   that takes the flow and owned edge data of two matched dangling half-edges and
627    ///   returns the flow and edge data for the new combined edge.
628    ///
629    /// # Returns
630    /// - `Ok(Self)`: The new graph resulting from the join.
631    /// - `Err(HedgeGraphError)`: If an error occurs during the join process (e.g.,
632    ///   from `self.edge_store.join` or if node validation fails).
633    pub fn join(
634        mut self,
635        other: Self,
636        matching_fn: impl Fn(Flow, EdgeData<&E>, Flow, EdgeData<&E>) -> bool,
637        merge_fn: impl Fn(Flow, EdgeData<E>, Flow, EdgeData<E>) -> (Flow, EdgeData<E>),
638    ) -> Result<Self, HedgeGraphError> {
639        self.hedge_data.extend(other.hedge_data);
640        let mut g = HedgeGraph {
641            hedge_data: self.hedge_data,
642            node_store: self.node_store.extend(other.node_store),
643            edge_store: self
644                .edge_store
645                .join(other.edge_store, matching_fn, merge_fn)?,
646        };
647        g.node_store.check_and_set_nodes()?;
648
649        Ok(g)
650    }
651
652    /// Joins another graph (`other`) into `self` by consuming `other`.
653    ///
654    /// This is similar to `join`, but modifies `self` in place instead of returning a new graph.
655    /// Dangling edges are matched and merged according to `matching_fn` and `merge_fn`.
656    ///
657    /// # Parameters
658    /// - `other`: The graph to be consumed and joined into `self`.
659    /// - `matching_fn`: A closure to determine if two dangling half-edges should match.
660    /// - `merge_fn`: A closure to determine the data for the newly formed paired edge.
661    ///
662    /// # Returns
663    /// - `Ok(())` if the join was successful.
664    /// - `Err(HedgeGraphError)` if an error occurs (e.g. from `self.edge_store.join_mut` or
665    ///   if node validation fails).
666    pub fn join_mut(
667        &mut self,
668        other: Self,
669        matching_fn: impl Fn(Flow, EdgeData<&E>, Flow, EdgeData<&E>) -> bool,
670        merge_fn: impl Fn(Flow, EdgeData<E>, Flow, EdgeData<E>) -> (Flow, EdgeData<E>),
671    ) -> Result<(), HedgeGraphError> {
672        // self.node_store.check_and_set_nodes()?;
673
674        // other.node_store.check_and_set_nodes()?;
675        self.node_store.extend_mut(other.node_store);
676        self.edge_store
677            .join_mut(other.edge_store, matching_fn, merge_fn)?;
678
679        self.hedge_data.extend(other.hedge_data);
680
681        self.node_store.check_and_set_nodes()?;
682        Ok(())
683    }
684
685    /// Sews dangling edges internal to the graph, matching edges with the given function and merging them with the given function.
686    /// "Sews" together pairs of dangling (identity) half-edges within the graph `self`.
687    ///
688    /// This operation attempts to find pairs of dangling half-edges that satisfy `matching_fn`
689    /// and converts them into internal, paired edges. The data for the new paired edge
690    /// is determined by `merge_fn`.
691    ///
692    /// # Parameters
693    /// - `matching_fn`: A closure `(Flow, EdgeData<&E>, Flow, EdgeData<&E>) -> bool`
694    ///   that determines if two dangling half-edges within `self` should be matched.
695    /// - `merge_fn`: A closure `(Flow, EdgeData<E>, Flow, EdgeData<E>) -> (Flow, EdgeData<E>)`
696    ///   that provides the data for the new paired edge formed from two matched dangling edges.
697    ///
698    /// # Returns
699    /// - `Ok(())` if the sewing operation completes.
700    /// - `Err(HedgeGraphError::InvolutionError)` if an error occurs within the underlying
701    ///   `edge_store.sew` operation (e.g. `InvolutionError::NotIdentity` if an attempt is made
702    ///   to sew an edge that is not an identity edge).
703    pub fn sew(
704        &mut self,
705        matching_fn: impl Fn(Flow, EdgeData<&E>, Flow, EdgeData<&E>) -> bool,
706        merge_fn: impl Fn(Flow, EdgeData<E>, Flow, EdgeData<E>) -> (Flow, EdgeData<E>),
707    ) -> Result<(), HedgeGraphError> {
708        self.edge_store.sew(matching_fn, merge_fn)
709    }
710
711    /// Adds a new dangling (identity) half-edge to the graph, incident to the specified `source` node.
712    ///
713    /// This consumes the graph and returns a new graph with the added edge.
714    ///
715    /// # Parameters
716    /// - `source`: The `NodeIndex` to which the new dangling edge will be attached.
717    /// - `data`: The data `E` for the new edge.
718    /// - `flow`: The [`Flow`] (Source or Sink) of the new dangling half-edge.
719    /// - `orientation`: The [`Orientation`] of the new edge.
720    ///
721    /// # Returns
722    /// - `Ok((Hedge, Self))`: A tuple containing the `Hedge` identifier of the new
723    ///   dangling half-edge and the modified graph.
724    /// - `Err(HedgeGraphError::NoNode)`: If the `source` node index is invalid for the node store.
725    /// - Other `HedgeGraphError` variants may arise from internal node store operations.
726    pub fn add_dangling_edge(
727        mut self,
728        source: impl Into<HedgeData<H>>,
729        data: E,
730        flow: Flow,
731        orientation: impl Into<Orientation>,
732    ) -> Result<(Hedge, Self), HedgeGraphError> {
733        let source = source.into();
734
735        self.hedge_data.push(source.data);
736        let (edge_store, hedge) = self.edge_store.add_dangling_edge(data, flow, orientation);
737        let mut g = HedgeGraph {
738            hedge_data: self.hedge_data,
739            edge_store,
740            node_store: self.node_store.add_dangling_edge(source.node)?,
741        };
742
743        g.node_store.check_and_set_nodes()?;
744
745        Ok((hedge, g))
746    }
747
748    /// Adds a new paired edge between the `source` and `sink` nodes.
749    ///
750    /// This consumes the graph and returns a new graph with the added edge.
751    /// The new edge consists of two half-edges, one originating from `source` and
752    /// the other from `sink`, pointing towards each other.
753    ///
754    /// # Parameters
755    /// - `source`: The `NodeIndex` of the source node for the new edge.
756    /// - `sink`: The `NodeIndex` of the sink node for the new edge.
757    /// - `data`: The data `E` for the new edge.
758    /// - `orientation`: The [`Orientation`] of the new edge.
759    ///
760    /// # Returns
761    /// - `Ok((Hedge, Hedge, Self))`: A tuple containing the `Hedge` identifiers for the
762    ///   source-incident half-edge, the sink-incident half-edge, and the modified graph.
763    /// - `Err(HedgeGraphError::NoNode)`: If `source` or `sink` node indices are invalid.
764    /// - Other `HedgeGraphError` variants may arise from internal node store operations.
765    pub fn add_pair(
766        mut self,
767        source: impl Into<HedgeData<H>>,
768        sink: impl Into<HedgeData<H>>,
769        data: E,
770        orientation: impl Into<Orientation>,
771    ) -> Result<(Hedge, Hedge, Self), HedgeGraphError> {
772        let source = source.into();
773        let sink = sink.into();
774        self.hedge_data.push(source.data);
775        self.hedge_data.push(sink.data);
776        let (edge_store, sourceh, sinkh) = self.edge_store.add_paired(data, orientation);
777        let mut g = HedgeGraph {
778            hedge_data: self.hedge_data,
779            edge_store,
780            node_store: self
781                .node_store
782                .add_dangling_edge(source.node)?
783                .add_dangling_edge(sink.node)?,
784        };
785
786        g.node_store.check_and_set_nodes()?;
787
788        Ok((sourceh, sinkh, g))
789    }
790
791    /// Checks if the specified `subgraph` is connected.
792    ///
793    /// A subgraph is connected if there is a path between any two half-edges (or nodes
794    /// they are incident to) within that subgraph, using only edges also within the subgraph.
795    ///
796    /// # Parameters
797    /// - `subgraph`: The subgraph `S` to check for connectivity.
798    ///
799    /// # Returns
800    /// `true` if the subgraph is connected, `false` otherwise.
801    /// Returns `true` for an empty subgraph.
802    ///
803    /// # Panics
804    /// Panics if the traversal (used internally) fails, which can happen if the
805    /// starting node for traversal is not part of the `subgraph`.
806    pub fn is_connected<S: SubGraph>(&self, subgraph: &S) -> bool {
807        let n_edges = subgraph.nedges(self);
808        if let Some(start) = subgraph.included_iter().next() {
809            SimpleTraversalTree::depth_first_traverse(self, subgraph, &self.node_id(start), None)
810                .unwrap()
811                .covers(subgraph)
812                .nedges(self)
813                == n_edges
814        } else {
815            true
816        }
817    }
818
819    /// Modifies a [`HedgeNode`] subgraph by removing "branches" or "tendrils".
820    ///
821    /// A branch is typically a path of edges within the `subgraph` that ultimately
822    /// connects to the rest of the `subgraph` at only one point (one node with degree > 1
823    /// within the branch, relative to other branch edges). This operation iteratively
824    /// removes edges that are part of such terminal paths until no more such branches exist.
825    ///
826    /// It first removes purely external edges from the `subgraph`'s internal part,
827    /// then iteratively prunes edges that form degree-1 connections within the subgraph's context.
828    /// Finally, it fixes the `hairs` of the `HedgeNode` to be consistent.
829    ///
830    /// # Parameters
831    /// - `subgraph`: A mutable reference to the `HedgeNode` to be pruned.
832    pub fn cut_branches(&self, subgraph: &mut HedgeNode) {
833        let nodes = AHashSet::<NodeIndex>::from_iter(
834            subgraph
835                .internal_graph
836                .included_iter()
837                .map(|i| self.node_id(i)),
838        );
839        self.remove_externals(subgraph);
840
841        let mut has_branch = true;
842        while has_branch {
843            has_branch = false;
844
845            for n in &nodes {
846                let int = self.sub_iter_crown(*n, subgraph).collect::<Vec<_>>();
847                let first = int.first();
848                let next = int.get(1);
849
850                if let Some(first) = first {
851                    if next.is_none() {
852                        subgraph.internal_graph.filter.set(first.0, false);
853                        subgraph
854                            .internal_graph
855                            .filter
856                            .set(self.inv(*first).0, false);
857                        has_branch = true;
858                    }
859                }
860            }
861        }
862
863        self.nesting_node_fix(subgraph);
864    }
865
866    // fn _set_hedge_data(&mut self, hedge: Hedge, nodeid: NodeIndex) {
867    //     self.node_store.set_hedge_data(hedge, nodeid);
868    // }
869}
870
871// Subgraphs
872impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
873    /// Calculates the "internal crown" of a given `subgraph`.
874    ///
875    /// The internal crown consists of all half-edges within the `subgraph` that are
876    /// either unpaired (dangling/external) or part of a "split" edge (i.e., their
877    /// opposite half-edge is *not* in the `subgraph`). These are effectively the
878    /// boundary half-edges of the `subgraph` from its own perspective.
879    ///
880    /// # Parameters
881    /// - `subgraph`: The subgraph `S` for which to find the internal crown.
882    ///
883    /// # Returns
884    /// A new subgraph of type `S::Base` containing the internal crown half-edges.
885    /// `S::Base` must implement `ModifySubgraph<HedgePair>`.
886    pub fn internal_crown<S: SubGraph>(&self, subgraph: &S) -> S::Base
887    where
888        S::Base: ModifySubgraph<HedgePair>,
889    {
890        let mut crown = S::Base::empty(self.n_hedges());
891
892        for (p, _, _) in self.iter_edges_of(subgraph) {
893            if !p.is_paired() {
894                crown.add(p)
895            }
896        }
897
898        crown
899    }
900
901    /// Calculates the "full crown" of a given `subgraph`.
902    ///
903    /// The full crown consists of all half-edges that are incident to any node
904    /// touched by the `subgraph`, provided that these half-edges are either
905    /// unpaired (identity) or their opposite half-edge is also included in the `subgraph`.
906    ///
907    /// This is different from `internal_crown` as it considers all incident edges to
908    /// nodes in the subgraph's footprint, not just edges within the subgraph itself.
909    /// It might include edges not present in the initial `subgraph`.
910    ///
911    /// # Parameters
912    /// - `subgraph`: The subgraph `S` for which to find the full crown.
913    ///
914    /// # Returns
915    /// A new subgraph of type `S::Base` containing the full crown half-edges.
916    /// `S::Base` must implement `ModifySubgraph<Hedge>`.
917    pub fn full_crown<S: SubGraph>(&self, subgraph: &S) -> S::Base
918    where
919        S::Base: ModifySubgraph<Hedge>,
920    {
921        let mut crown = S::Base::empty(self.n_hedges());
922
923        for (_, n, _) in self.iter_nodes_of(subgraph) {
924            for h in n {
925                let invh = self.inv(h);
926                if h == invh || !subgraph.includes(&invh) {
927                    crown.add(h);
928                }
929            }
930        }
931
932        crown
933    }
934
935    pub fn paired_filter_from_pos(&self, pos: &[Hedge]) -> BitVec {
936        let mut filter = bitvec![usize, Lsb0; 0; self.n_hedges()];
937
938        for &i in pos {
939            filter.set(i.0, true);
940            filter.set(self.inv(i).0, true);
941        }
942
943        filter
944    }
945
946    /// Creates a `BitVec` representing a subgraph containing all external (identity/dangling)
947    /// half-edges in the entire graph.
948    ///
949    /// # Returns
950    /// A `BitVec` where bits corresponding to external half-edges are set to true.
951    pub fn external_filter(&self) -> BitVec {
952        let mut filter = bitvec![usize, Lsb0; 0; self.n_hedges()];
953
954        for (i, _, _) in self.iter_edges() {
955            if i.is_unpaired() {
956                filter.set(i.any_hedge().0, true);
957            }
958        }
959
960        filter
961    }
962
963    /// Creates a `BitVec` representing a subgraph containing all half-edges in the graph.
964    ///
965    /// # Returns
966    /// A `BitVec` of length `self.n_hedges()` with all bits set to true.
967    pub fn full_filter(&self) -> BitVec {
968        bitvec![usize, Lsb0; 1; self.n_hedges()]
969    }
970
971    /// Returns a [`FullOrEmpty`] subgraph representing the entire graph (all hedges included).
972    pub fn full(&self) -> FullOrEmpty {
973        FullOrEmpty::full(self.n_hedges())
974    }
975
976    /// Returns a [`FullOrEmpty`] subgraph representing an empty graph (no hedges included).
977    pub fn empty(&self) -> FullOrEmpty {
978        FullOrEmpty::empty(self.n_hedges())
979    }
980
981    /// Creates an [`InternalSubGraph`] from a `BitVec` filter, ensuring it has no "hairs".
982    ///
983    /// This uses a "pessimistic" approach: an edge is included only if both its
984    /// half-edges are set in the input `filter`. Dangling edges are removed.
985    ///
986    /// # Parameters
987    /// - `filter`: A `BitVec` representing the desired set of half-edges.
988    ///
989    /// # Returns
990    /// A new `InternalSubGraph`.
991    pub fn clean_subgraph(&self, filter: BitVec) -> InternalSubGraph {
992        InternalSubGraph::cleaned_filter_pessimist(filter, self)
993    }
994
995    /// Returns a [`HedgeNode`] that represents the entire graph.
996    /// The `internal_graph` of this `HedgeNode` will include all internal edges,
997    /// and its `hairs` will include all external (dangling) edges of the graph.
998    pub fn full_node(&self) -> HedgeNode {
999        self.nesting_node_from_subgraph(self.full_graph())
1000    }
1001
1002    /// Returns an [`InternalSubGraph`] that includes all fully internal edges of the graph.
1003    /// External (dangling) edges are excluded.
1004    pub fn full_graph(&self) -> InternalSubGraph {
1005        InternalSubGraph::cleaned_filter_optimist(self.full_filter(), self)
1006    }
1007
1008    /// Creates an empty subgraph of a specific type `S`.
1009    ///
1010    /// # Type Parameters
1011    /// - `S`: The type of subgraph to create, must implement `SubGraph`.
1012    ///
1013    /// # Returns
1014    /// A new, empty subgraph of type `S`, sized for this graph.
1015    pub fn empty_subgraph<S: SubGraph>(&self) -> S {
1016        S::empty(self.n_hedges())
1017    }
1018
1019    /// Creates a subgraph of type `S` by filtering edges based on their data.
1020    ///
1021    /// # Type Parameters
1022    /// - `S`: The type of subgraph to create, must implement `BaseSubgraph`.
1023    ///
1024    /// # Parameters
1025    /// - `filter`: A closure that takes edge data `&E` and returns `true` if the
1026    ///   edge should be included in the subgraph.
1027    ///
1028    /// # Returns
1029    /// A new subgraph of type `S`.
1030    pub fn from_filter<S: BaseSubgraph>(&self, filter: impl FnMut(&E) -> bool) -> S {
1031        S::from_filter(self, filter)
1032    }
1033
1034    /// Creates a [`HedgeNode`] from a given [`InternalSubGraph`].
1035    ///
1036    /// The `internal_graph` of the new `HedgeNode` is the one provided.
1037    /// The `hairs` of the `HedgeNode` are calculated as all half-edges incident to the
1038    /// `internal_graph` that are not part of the `internal_graph` itself.
1039    ///
1040    /// # Parameters
1041    /// - `internal_graph`: The `InternalSubGraph` to form the core of the `HedgeNode`.
1042    ///
1043    /// # Panics
1044    /// Panics if the provided `internal_graph` is not valid for this graph (e.g.,
1045    /// if it refers to hedges outside the graph's bounds or is not truly internal).
1046    pub fn nesting_node_from_subgraph(&self, internal_graph: InternalSubGraph) -> HedgeNode {
1047        let mut hairs = bitvec![usize, Lsb0; 0; self.n_hedges()];
1048
1049        if !internal_graph.valid::<E, V, H, N>(self) {
1050            panic!("Invalid subgraph")
1051        }
1052
1053        for i in internal_graph.included_iter() {
1054            hairs.union_with_iter(self.neighbors(i));
1055        }
1056
1057        HedgeNode {
1058            hairs: !(!hairs | &internal_graph.filter),
1059            internal_graph,
1060        }
1061    }
1062
1063    pub fn remove_internal_hedges(&self, subgraph: &BitVec) -> BitVec {
1064        let mut hairs = subgraph.clone();
1065        for i in subgraph.included_iter() {
1066            if subgraph.includes(&self.inv(i)) {
1067                hairs.set(i.0, false);
1068                hairs.set(self.inv(i).0, false);
1069            }
1070        }
1071        hairs
1072    }
1073
1074    pub(crate) fn split_hairs_and_internal_hedges(
1075        &self,
1076        mut subgraph: BitVec,
1077    ) -> (BitVec, InternalSubGraph) {
1078        let mut internal: InternalSubGraph = self.empty_subgraph();
1079        for i in subgraph.included_iter() {
1080            let invh = self.inv(i);
1081            if subgraph.includes(&invh) {
1082                internal.filter.set(i.0, true);
1083                internal.filter.set(invh.0, true);
1084            }
1085        }
1086        for i in internal.filter.included_iter() {
1087            subgraph.set(i.0, false);
1088        }
1089        (subgraph, internal)
1090    }
1091
1092    /// Adjusts the `hairs` of a `HedgeNode` to be consistent with its `internal_graph`.
1093    ///
1094    /// Ensures that `hairs` only contains true external connections relative to the
1095    /// `internal_graph`. It recalculates hairs based on neighbors of the internal graph
1096    /// and removes any that are already part of the internal graph.
1097    ///
1098    /// # Parameters
1099    /// - `node`: A mutable reference to the `HedgeNode` to fix.
1100    fn nesting_node_fix(&self, node: &mut HedgeNode) {
1101        let mut externalhedges = bitvec![usize, Lsb0; 0; self.n_hedges()];
1102
1103        for i in node.internal_graph.filter.included_iter() {
1104            externalhedges.union_with_iter(self.neighbors(i));
1105        }
1106
1107        node.hairs = !(!externalhedges | &node.internal_graph.filter);
1108    }
1109
1110    fn remove_externals(&self, subgraph: &mut HedgeNode) {
1111        let externals = self.external_filter();
1112
1113        subgraph.internal_graph.filter &= !externals;
1114    }
1115}
1116
1117// Counts
1118impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
1119    /// Counts the number of full internal edges within the given `subgraph`.
1120    ///
1121    /// An edge is considered internal if both its half-edges are included in the `subgraph`.
1122    /// This method avoids double-counting by only counting an edge once.
1123    ///
1124    /// # Parameters
1125    /// - `subgraph`: The subgraph `S` in which to count internal edges.
1126    ///
1127    /// # Returns
1128    /// The number of full internal edges.
1129    pub fn count_internal_edges<S: SubGraph>(&self, subgraph: &S) -> usize {
1130        let mut internal_edge_count = 0;
1131        // Iterate over all half-edges in the subgraph
1132        for hedge_index in subgraph.included_iter() {
1133            let inv_hedge_index = self.inv(hedge_index);
1134
1135            // Check if the involuted half-edge is also in the subgraph
1136            if subgraph.includes(&inv_hedge_index) {
1137                // To avoid double-counting, only count when hedge_index < inv_hedge_index
1138                if hedge_index < inv_hedge_index {
1139                    internal_edge_count += 1;
1140                }
1141            }
1142        }
1143        internal_edge_count
1144    }
1145
1146    /// Returns the total number of half-edges in the graph.
1147    pub fn n_hedges(&self) -> usize {
1148        let n_h: Hedge = self.len();
1149        n_h.0
1150    }
1151
1152    pub fn n_edges(&self) -> usize {
1153        let n_e: EdgeIndex = self.len();
1154        n_e.0
1155    }
1156
1157    /// Returns the total number of nodes in the graph.
1158    pub fn n_nodes(&self) -> usize {
1159        let n_n: NodeIndex = self.len();
1160        n_n.0
1161    }
1162
1163    /// Returns the number of external (dangling/identity) half-edges in the graph.
1164    pub fn n_externals(&self) -> usize {
1165        self.edge_store.n_dangling()
1166    }
1167
1168    /// Returns the number of internal (paired) half-edges in the graph.
1169    /// Note that this counts half-edges, so a single full internal edge contributes 2 to this count.
1170    pub fn n_internals(&self) -> usize {
1171        self.edge_store.n_paired()
1172    }
1173
1174    // pub fn n_base_nodes(&self) -> usize {
1175    //     self.nodes.iter().filter(|n| n.is_node()).count()
1176    // }
1177
1178    /// Counts the number of distinct nodes that are incident to at least one half-edge
1179    /// in the given `subgraph`.
1180    ///
1181    /// # Parameters
1182    /// - `subgraph`: The subgraph `S` to consider.
1183    ///
1184    /// # Returns
1185    /// The number of unique nodes touched by the `subgraph`.
1186    pub fn number_of_nodes_in_subgraph<S: SubGraph>(&self, subgraph: &S) -> usize {
1187        self.iter_nodes_of(subgraph).count()
1188    }
1189
1190    /// Calculates the degree of each node within the context of a given `InternalSubGraph`.
1191    ///
1192    /// The degree of a node in this context is the number of half-edges from the `subgraph`
1193    /// that are incident to that node.
1194    ///
1195    /// # Parameters
1196    /// - `subgraph`: The `InternalSubGraph` to calculate node degrees from.
1197    ///
1198    /// # Returns
1199    /// An `AHashMap` mapping each `NodeIndex` (for nodes involved in the `subgraph`)
1200    /// to its degree within that `subgraph`.
1201    pub fn node_degrees_in_subgraph(
1202        &self,
1203        subgraph: &InternalSubGraph,
1204    ) -> AHashMap<NodeIndex, usize> {
1205        let mut degrees = AHashMap::new();
1206
1207        for (_, node, _) in self.iter_nodes_of(subgraph) {
1208            let node_pos = self.id_from_crown(node).unwrap();
1209
1210            // Count the number of edges in the subgraph incident to this node
1211            let incident_edges =
1212                BitVec::from_hedge_iter(self.sub_iter_crown(node_pos, subgraph), subgraph.size());
1213            let degree = incident_edges.count_ones();
1214
1215            degrees.insert(node_pos, degree);
1216        }
1217
1218        degrees
1219    }
1220}
1221
1222pub trait EdgeAccessors<Index> {
1223    fn orientation(&self, index: Index) -> Orientation;
1224
1225    fn set_orientation(&mut self, index: Index, orientation: Orientation);
1226}
1227
1228impl<E, V, H, N: NodeStorageOps<NodeData = V>> EdgeAccessors<Hedge> for HedgeGraph<E, V, H, N> {
1229    fn orientation(&self, index: Hedge) -> Orientation {
1230        self.edge_store.orientation(index)
1231    }
1232
1233    fn set_orientation(&mut self, index: Hedge, orientation: Orientation) {
1234        self.edge_store.set_orientation(index, orientation);
1235    }
1236}
1237
1238impl<E, V, H, N: NodeStorageOps<NodeData = V>> EdgeAccessors<HedgePair> for HedgeGraph<E, V, H, N> {
1239    fn orientation(&self, index: HedgePair) -> Orientation {
1240        self.edge_store.orientation(index)
1241    }
1242
1243    fn set_orientation(&mut self, index: HedgePair, orientation: Orientation) {
1244        self.edge_store.set_orientation(index, orientation);
1245    }
1246}
1247
1248impl<E, V, H, N: NodeStorageOps<NodeData = V>> EdgeAccessors<EdgeIndex> for HedgeGraph<E, V, H, N> {
1249    fn orientation(&self, index: EdgeIndex) -> Orientation {
1250        self.edge_store.orientation(index)
1251    }
1252
1253    fn set_orientation(&mut self, index: EdgeIndex, orientation: Orientation) {
1254        self.edge_store.set_orientation(index, orientation);
1255    }
1256}
1257
1258// Accessors
1259impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
1260    /// including pos
1261    pub fn owned_neighbors<S: SubGraph>(&self, subgraph: &S, pos: Hedge) -> BitVec {
1262        subgraph.hairs(self.neighbors(pos))
1263    }
1264
1265    pub fn connected_neighbors<S: SubGraph>(&self, subgraph: &S, pos: Hedge) -> Option<BitVec> {
1266        Some(subgraph.hairs(self.involved_node_crown(pos)?))
1267    }
1268    pub fn get_edge_data(&self, edge: Hedge) -> &E {
1269        &self[self[&edge]]
1270    }
1271
1272    pub fn hedge_pair(&self, hedge: Hedge) -> HedgePair {
1273        self.edge_store[&self.edge_store[&hedge]].1
1274    }
1275
1276    pub fn get_edge_data_full(&self, hedge: Hedge) -> EdgeData<&E> {
1277        let orientation = self.edge_store.orientation(hedge);
1278        EdgeData::new(&self[self[&hedge]], orientation)
1279    }
1280
1281    /// Gives the underlying orientation of this half-edge.
1282    pub fn flow(&self, hedge: Hedge) -> Flow {
1283        self.edge_store.flow(hedge)
1284    }
1285
1286    pub fn superficial_hedge_orientation(&self, hedge: Hedge) -> Option<Flow> {
1287        self.edge_store.superficial_hedge_orientation(hedge)
1288    }
1289
1290    pub fn underlying_hedge_orientation(&self, hedge: Hedge) -> Flow {
1291        self.edge_store.underlying_hedge_orientation(hedge)
1292    }
1293
1294    pub fn neighbors(&self, hedge: Hedge) -> N::NeighborsIter<'_> {
1295        self.iter_crown(self.node_id(hedge))
1296    }
1297
1298    pub fn iter_crown(&self, id: NodeIndex) -> N::NeighborsIter<'_> {
1299        self.node_store.get_neighbor_iterator(id)
1300    }
1301
1302    pub fn sub_iter_crown<'a, S: SubGraph>(
1303        &'a self,
1304        id: NodeIndex,
1305        subgraph: &'a S,
1306    ) -> impl Iterator<Item = Hedge> + 'a {
1307        self.iter_crown(id).filter(|i| subgraph.includes(i))
1308    }
1309
1310    pub fn id_from_crown<'a>(&'a self, mut neighbors: N::NeighborsIter<'a>) -> Option<NodeIndex> {
1311        let e = neighbors.next()?;
1312        Some(self.node_id(e))
1313    }
1314
1315    pub fn involved_node_crown(&self, hedge: Hedge) -> Option<N::NeighborsIter<'_>> {
1316        self.involved_node_id(hedge).map(|id| self.iter_crown(id))
1317    }
1318
1319    pub fn involved_node_id(&self, hedge: Hedge) -> Option<NodeIndex> {
1320        let invh = self.inv(hedge);
1321        if invh == hedge {
1322            return None;
1323        }
1324        Some(self.node_id(invh))
1325    }
1326
1327    pub fn node_id(&self, hedge: Hedge) -> NodeIndex {
1328        self.node_store.node_id_ref(hedge)
1329    }
1330
1331    pub fn is_self_loop(&self, hedge: Hedge) -> bool {
1332        !self.is_dangling(hedge) && self.node_id(hedge) == self.node_id(self.inv(hedge))
1333    }
1334
1335    pub fn is_dangling(&self, hedge: Hedge) -> bool {
1336        self.inv(hedge) == hedge
1337    }
1338
1339    /// Collect all nodes in the subgraph (all nodes that the hedges are connected to)
1340    pub fn nodes<S: SubGraph>(&self, subgraph: &S) -> Vec<NodeIndex> {
1341        let mut nodes = IndexSet::new();
1342        for i in subgraph.included_iter() {
1343            let node = self.node_id(i);
1344            nodes.insert(node);
1345        }
1346
1347        nodes.into_iter().collect()
1348    }
1349
1350    pub fn set_flow(&mut self, hedge: Hedge, flow: Flow) {
1351        self.edge_store.set_flow(hedge, flow);
1352    }
1353
1354    ///Permutes nodes not pointing to any root anymore to end of nodestore and then extract it
1355    pub fn forget_identification_history(&mut self) -> NodeVec<V> {
1356        self.node_store.forget_identification_history()
1357    }
1358
1359    ///Retains the NodeIndex ordering and just appends a new node.
1360    pub fn identify_nodes(&mut self, nodes: &[NodeIndex], node_data_merge: V) -> NodeIndex {
1361        self.node_store.identify_nodes(nodes, node_data_merge)
1362    }
1363
1364    ///Identifies all nodes in this subgraph and gives value node_data_merge to identified node.
1365    ///Deletes all edges in the subgraph.
1366    ///This invalidates both hedge indices and node indices
1367    pub fn contract_subgraph<S: SubGraph<Base = N::Base>>(
1368        &mut self,
1369        subgraph: &S,
1370        node_data_merge: V,
1371    ) {
1372        let nodes: Vec<_> = self.iter_nodes_of(subgraph).map(|(a, _, _)| a).collect();
1373
1374        self.identify_nodes(&nodes, node_data_merge);
1375        self.forget_identification_history();
1376        self.delete_hedges(subgraph);
1377    }
1378
1379    ///Retains the NodeIndex ordering and just appends a new node.
1380    pub fn identify_nodes_without_self_edges<S>(
1381        &mut self,
1382        nodes: &[NodeIndex],
1383        node_data_merge: V,
1384    ) -> (NodeIndex, S)
1385    where
1386        S: ModifySubgraph<Hedge> + SubGraph,
1387    {
1388        let mut self_edges: S = self.empty_subgraph();
1389        for n in nodes {
1390            for h in self.iter_crown(*n) {
1391                if self.is_self_loop(h) {
1392                    self_edges.add(h);
1393                }
1394            }
1395        }
1396        let n = self.node_store.identify_nodes(nodes, node_data_merge);
1397
1398        for h in self.iter_crown(n) {
1399            if self.is_self_loop(h) {
1400                if self_edges.includes(&h) {
1401                    self_edges.sub(h);
1402                } else {
1403                    self_edges.add(h);
1404                }
1405            }
1406        }
1407
1408        // self_edges
1409
1410        (n, self_edges)
1411    }
1412
1413    /// Collect all edges in the subgraph
1414    /// (This is without double counting, i.e. if two half-edges are part of the same edge, only one `EdgeIndex` will be collected)
1415    pub fn edges<S: SubGraph>(&self, subgraph: &S) -> Vec<EdgeIndex> {
1416        self.iter_edges_of(subgraph).map(|(_, i, _)| i).collect()
1417    }
1418}
1419
1420pub enum NodeKind<Data> {
1421    Internal(Data),
1422    External { data: Data, flow: Flow },
1423}
1424
1425pub enum DanglingMatcher<Data> {
1426    Actual { hedge: Hedge, data: Data },
1427    Internal { data: Data },
1428    Saturator { hedge: Hedge },
1429}
1430
1431impl<Data> DanglingMatcher<Data> {
1432    fn new(pair: HedgePair, data: Data) -> Self {
1433        match pair {
1434            HedgePair::Unpaired { hedge, .. } => DanglingMatcher::Actual { hedge, data },
1435            HedgePair::Paired { .. } => DanglingMatcher::Internal { data },
1436            _ => panic!("Split"),
1437        }
1438    }
1439    pub fn matches(&self, other: &Self) -> bool {
1440        match (self, other) {
1441            (
1442                DanglingMatcher::Actual { hedge: h1, .. },
1443                DanglingMatcher::Saturator { hedge: h2 },
1444            ) => h1 == h2,
1445            _ => false,
1446        }
1447    }
1448
1449    pub fn unwrap(self) -> Data {
1450        match self {
1451            DanglingMatcher::Actual { data, .. } => data,
1452            DanglingMatcher::Internal { data } => data,
1453            DanglingMatcher::Saturator { .. } => panic!("Cannot unwrap a saturator"),
1454        }
1455    }
1456}
1457
1458// Mapping
1459impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
1460    pub fn saturate_dangling<V2>(
1461        self,
1462        node_map: impl FnMut(&Involution, NodeIndex, V) -> V2,
1463        mut dangling_map: impl FnMut(&Involution, &N, Hedge, Flow, EdgeData<&E>) -> (V2, H),
1464    ) -> HedgeGraph<E, V2, H, <<N as NodeStorageOps>::OpStorage<V2> as NodeStorageOps>::OpStorage<V2>>
1465    {
1466        let ext = self.external_filter();
1467
1468        let mut saturator = HedgeGraphBuilder::new();
1469        for i in ext.included_iter() {
1470            let flow = self.flow(i);
1471            let d = &self[[&i]];
1472            let orientation = self.orientation(i);
1473            let (new_node_data, h) = dangling_map(
1474                self.edge_store.as_ref(),
1475                &self.node_store,
1476                i,
1477                flow,
1478                EdgeData::new(d, orientation),
1479            );
1480
1481            let n = saturator.add_node(new_node_data).add_data(h);
1482
1483            saturator.add_external_edge(
1484                n,
1485                DanglingMatcher::Saturator { hedge: i },
1486                orientation,
1487                -flow,
1488            );
1489        }
1490
1491        let saturator = saturator.build();
1492        let new_graph = self.map(
1493            node_map,
1494            |_, _, p, _, e| e.map(|d| DanglingMatcher::new(p, d)),
1495            |_, h| h,
1496        );
1497        new_graph
1498            .join(
1499                saturator,
1500                |_, dl, _, dr| dl.data.matches(dr.data),
1501                |fl, dl, _, _| (fl, dl),
1502            )
1503            .unwrap()
1504            .map(|_, _, v| v, |_, _, _, _, e| e.map(|d| d.unwrap()), |_, h| h)
1505    }
1506
1507    pub fn map_data_ref<'a, E2, V2, H2>(
1508        &'a self,
1509        node_map: impl FnMut(&'a Self, N::NeighborsIter<'a>, &'a V) -> V2,
1510        edge_map: impl FnMut(&'a Self, EdgeIndex, HedgePair, EdgeData<&'a E>) -> EdgeData<E2>,
1511        mut hedge_map: impl FnMut(Hedge, &'a H) -> H2,
1512    ) -> HedgeGraph<E2, V2, H2, N::OpStorage<V2>> {
1513        HedgeGraph {
1514            hedge_data: self
1515                .hedge_data
1516                .iter()
1517                .map(|(i, a)| hedge_map(i, a))
1518                .collect(),
1519            node_store: self.node_store.map_data_ref_graph(self, node_map),
1520            edge_store: self.edge_store.map_data_ref(self, edge_map),
1521        }
1522    }
1523
1524    pub fn to_ref(&self) -> HedgeGraph<&E, &V, &H, N::OpStorage<&V>> {
1525        self.map_data_ref(|_, _, v| v, |_, _, _, e| e, |_, h| h)
1526    }
1527
1528    pub fn map_data_ref_mut<'a, E2, V2, H2>(
1529        &'a mut self,
1530        node_map: impl FnMut(N::NeighborsIter<'a>, &'a mut V) -> V2,
1531        edge_map: impl FnMut(EdgeIndex, HedgePair, EdgeData<&'a mut E>) -> EdgeData<E2>,
1532        hedge_map: impl FnMut((Hedge, &'a H)) -> H2,
1533    ) -> HedgeGraph<E2, V2, H2, N::OpStorage<V2>> {
1534        HedgeGraph {
1535            hedge_data: self.hedge_data.iter().map(hedge_map).collect(),
1536            node_store: self.node_store.map_data_ref_mut_graph(node_map),
1537            edge_store: self.edge_store.map_data_ref_mut(edge_map),
1538        }
1539    }
1540
1541    pub fn map_data_ref_result<'a, E2, V2, H2, Er>(
1542        &'a self,
1543        node_map: impl FnMut(&'a Self, N::NeighborsIter<'a>, &'a V) -> Result<V2, Er>,
1544        edge_map: impl FnMut(
1545            &'a Self,
1546            EdgeIndex,
1547            HedgePair,
1548            EdgeData<&'a E>,
1549        ) -> Result<EdgeData<E2>, Er>,
1550        hedge_map: impl FnMut((Hedge, &'a H)) -> Result<H2, Er>,
1551    ) -> Result<HedgeGraph<E2, V2, H2, N::OpStorage<V2>>, Er> {
1552        let hedge_data = self
1553            .hedge_data
1554            .iter()
1555            .map(hedge_map)
1556            .collect::<Result<HedgeVec<_>, _>>()?;
1557        Ok(HedgeGraph {
1558            hedge_data,
1559            node_store: self.node_store.map_data_ref_graph_result(self, node_map)?,
1560            edge_store: self.edge_store.map_data_ref_result(self, edge_map)?,
1561        })
1562    }
1563
1564    pub fn just_structure(&self) -> HedgeGraph<(), (), (), N::OpStorage<()>> {
1565        self.map_data_ref(|_, _, _| (), |_, _, _, d| d.map(|_| ()), |_, _| ())
1566    }
1567
1568    pub fn map_nodes_ref<'a, V2>(
1569        &'a self,
1570        f: impl FnMut(&'a Self, N::NeighborsIter<'a>, &'a V) -> V2,
1571    ) -> HedgeGraph<&'a E, V2, &'a H, N::OpStorage<V2>> {
1572        HedgeGraph {
1573            hedge_data: self.hedge_data.iter().collect(),
1574            node_store: self.node_store.map_data_ref_graph(self, f),
1575            edge_store: self.edge_store.map_data_ref(self, &|_, _, _, e| e),
1576        }
1577    }
1578    pub fn map<E2, V2, H2>(
1579        self,
1580        f: impl FnMut(&Involution, NodeIndex, V) -> V2,
1581        g: impl FnMut(&Involution, &N, HedgePair, EdgeIndex, EdgeData<E>) -> EdgeData<E2>,
1582        mut h: impl FnMut(Hedge, H) -> H2,
1583    ) -> HedgeGraph<E2, V2, H2, N::OpStorage<V2>> {
1584        let edge_store = self.edge_store.map_data(&self.node_store, g);
1585        HedgeGraph {
1586            hedge_data: self
1587                .hedge_data
1588                .into_iter()
1589                .map(|(heg, i)| h(heg, i))
1590                .collect(),
1591            node_store: self.node_store.map_data_graph(edge_store.as_ref(), f),
1592            edge_store,
1593        }
1594    }
1595    pub fn map_result<E2, V2, H2, Err>(
1596        self,
1597        f: impl FnMut(&Involution, NodeIndex, V) -> Result<V2, Err>,
1598        g: impl FnMut(&Involution, &N, HedgePair, EdgeIndex, EdgeData<E>) -> Result<EdgeData<E2>, Err>,
1599        mut h: impl FnMut(Hedge, H) -> Result<H2, Err>,
1600    ) -> Result<HedgeGraph<E2, V2, H2, N::OpStorage<V2>>, Err> {
1601        let edge_store = self.edge_store.map_data_result(&self.node_store, g)?;
1602        Ok(HedgeGraph {
1603            hedge_data: self
1604                .hedge_data
1605                .into_iter()
1606                .map(|(heg, i)| h(heg, i))
1607                .collect::<Result<HedgeVec<_>, Err>>()?,
1608            node_store: self
1609                .node_store
1610                .map_data_graph_result(edge_store.as_ref(), f)?,
1611            edge_store,
1612        })
1613    }
1614    pub fn new_smart_hedgevec<T>(
1615        &self,
1616        f: &impl Fn(HedgePair, EdgeData<&E>) -> EdgeData<T>,
1617    ) -> SmartEdgeVec<T> {
1618        self.edge_store.map(f)
1619    }
1620
1621    pub fn new_edgevec<T>(&self, f: impl FnMut(&E, EdgeIndex, &HedgePair) -> T) -> EdgeVec<T> {
1622        self.edge_store.new_edgevec(f)
1623    }
1624
1625    pub fn new_nodevec<'a, T>(
1626        &'a self,
1627        f: impl FnMut(NodeIndex, N::NeighborsIter<'a>, &'a V) -> T,
1628    ) -> NodeVec<T> {
1629        self.node_store.new_nodevec(f)
1630    }
1631
1632    pub fn new_hedgevec<T>(&self, mut f: impl FnMut(Hedge, &H) -> T) -> HedgeVec<T> {
1633        self.hedge_data.iter().map(|(i, h)| f(i, h)).collect()
1634    }
1635
1636    pub fn new_edgevec_from_iter<T, I: IntoIterator<Item = T>>(
1637        &self,
1638        iter: I,
1639    ) -> Result<EdgeVec<T>, HedgeGraphError> {
1640        self.edge_store.new_edgevec_from_iter(iter)
1641    }
1642}
1643
1644// Cuts
1645impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
1646    fn non_cut_edges_impl(
1647        &self,
1648        connected_components: usize,
1649        cyclotomatic_number: usize,
1650        start: Hedge,
1651        current: &mut BitVec,
1652        set: &mut AHashSet<BitVec>,
1653    ) {
1654        if current.count_ones() > 2 * cyclotomatic_number {
1655            return;
1656        }
1657
1658        let complement = current.complement(self);
1659
1660        if current.count_ones() > 0
1661            && self.count_connected_components(&complement) == connected_components
1662            && complement.covers(self) == self.full_filter()
1663        {
1664            // println!("//inserted with {con_comp}");
1665            set.insert(current.clone());
1666        }
1667
1668        for i in (start.0..self.n_hedges()).map(Hedge) {
1669            let j = self.inv(i);
1670            if i > j {
1671                current.set(i.0, true);
1672                current.set(j.0, true);
1673                self.non_cut_edges_impl(
1674                    connected_components,
1675                    cyclotomatic_number,
1676                    Hedge(i.0 + 1),
1677                    current,
1678                    set,
1679                );
1680                current.set(i.0, false);
1681                current.set(j.0, false);
1682            }
1683        }
1684    }
1685
1686    /// all sets of full edges that do not disconnect the graph/ increase its connected components
1687    pub fn non_cut_edges(&self) -> AHashSet<BitVec> {
1688        let connected_components = self.count_connected_components(&self.full_filter());
1689
1690        let cyclotomatic_number = self.cyclotomatic_number(&self.full_node().internal_graph);
1691
1692        let mut current = self.empty_subgraph::<BitVec>();
1693        let mut set = AHashSet::new();
1694
1695        self.non_cut_edges_impl(
1696            connected_components,
1697            cyclotomatic_number,
1698            Hedge(0),
1699            &mut current,
1700            &mut set,
1701        );
1702
1703        set
1704    }
1705
1706    // pub fn backtracking_cut_set(
1707    //     &self,
1708    //     source: HedgeNode,
1709    //     target: HedgeNode,
1710    // ) -> Vec<InternalSubGraph> {
1711    // }
1712
1713    pub fn non_bridges(&self) -> BitVec {
1714        let (c, _) = self.cycle_basis();
1715        let mut cycle_cover: BitVec = self.empty_subgraph();
1716        for cycle in c {
1717            cycle_cover.union_with(&cycle.filter);
1718        }
1719
1720        cycle_cover
1721    }
1722
1723    pub fn bridges(&self) -> BitVec {
1724        self.non_bridges().complement(self)
1725    }
1726
1727    pub fn combine_to_single_hedgenode(&self, source: &[NodeIndex]) -> HedgeNode {
1728        let s: BitVec =
1729            source
1730                .iter()
1731                .map(|a| self.iter_crown(*a))
1732                .fold(self.empty_subgraph(), |mut acc, e| {
1733                    acc.union_with_iter(e);
1734                    acc
1735                });
1736
1737        let (hairs, internal_graph) = self.split_hairs_and_internal_hedges(s);
1738
1739        HedgeNode {
1740            internal_graph,
1741            hairs,
1742        }
1743    }
1744
1745    pub fn all_cuts_from_ids(
1746        &self,
1747        source: &[NodeIndex],
1748        target: &[NodeIndex],
1749    ) -> Vec<(BitVec, OrientedCut, BitVec)>
1750    where
1751        N: NodeStorageOps,
1752    {
1753        let source = self.combine_to_single_hedgenode(source);
1754        let target = self.combine_to_single_hedgenode(target);
1755        self.all_cuts(source, target)
1756    }
1757
1758    pub fn tadpoles(&self, externals: &[NodeIndex]) -> Vec<BitVec> {
1759        let mut identified: HedgeGraph<(), (), (), N::OpStorage<()>> = self.just_structure();
1760
1761        let n = identified.identify_nodes(externals, ());
1762        let hairs = identified.iter_crown(n).next().unwrap();
1763
1764        let non_bridges = identified.non_bridges();
1765        identified
1766            .connected_components(&non_bridges)
1767            .into_iter()
1768            .filter_map(|mut a| {
1769                if !a.includes(&hairs) {
1770                    let full = a.covers(self);
1771
1772                    for i in full.included_iter() {
1773                        a.set(i.0, true);
1774                        a.set(self.inv(i).0, true);
1775                    }
1776                    Some(a)
1777                } else {
1778                    None
1779                }
1780            })
1781            .collect()
1782    }
1783
1784    pub fn all_cuts(
1785        &self,
1786        source: HedgeNode,
1787        target: HedgeNode,
1788    ) -> Vec<(BitVec, OrientedCut, BitVec)>
1789    where
1790        N: NodeStorageOps,
1791    {
1792        // println!("//Source\n{}", self.dot(&source.hairs));
1793        // println!("//Target\n{}", self.dot(&target.hairs));
1794
1795        let full_source = source.internal_and_hairs();
1796        let full_target = target.internal_and_hairs();
1797        let s_connectivity = self.count_connected_components(&full_source);
1798
1799        let t_connectivity = self.count_connected_components(&full_target);
1800
1801        let augmented: HedgeGraph<(), (), (), N::OpStorage<()>> = self.just_structure();
1802        let s_nodes = self
1803            .iter_nodes_of(&source)
1804            .map(|a| self.id_from_crown(a.1).unwrap())
1805            .collect::<Vec<_>>();
1806        let t_nodes = self
1807            .iter_nodes_of(&target)
1808            .map(|a| self.id_from_crown(a.1).unwrap())
1809            .collect::<Vec<_>>();
1810
1811        let t_node = t_nodes[0];
1812        let s_node = s_nodes[0];
1813
1814        let augmented = s_nodes.iter().fold(augmented, |aug, n| {
1815            let (_, _, augmented) = aug.add_pair(*n, t_node, (), false).unwrap();
1816            augmented
1817        });
1818
1819        let augmented = t_nodes.iter().fold(augmented, |aug, n| {
1820            let (_, _, augmented) = aug.add_pair(s_node, *n, (), false).unwrap();
1821            augmented
1822        });
1823
1824        let mut non_bridges = augmented.non_bridges();
1825
1826        for _ in &s_nodes {
1827            non_bridges.pop();
1828            non_bridges.pop();
1829        }
1830        for _ in &t_nodes {
1831            non_bridges.pop();
1832            non_bridges.pop();
1833        }
1834
1835        // println!("//non_bridges:\n{}", self.dot(&non_bridges));
1836
1837        non_bridges.union_with(&source.hairs);
1838        non_bridges.union_with(&target.hairs);
1839
1840        // println!("//non_bridges:\n{}", self.dot(&non_bridges));
1841
1842        let mut regions = AHashSet::new();
1843        self.all_s_t_cuts_impl(
1844            &non_bridges,
1845            s_connectivity,
1846            source,
1847            &target,
1848            t_connectivity,
1849            &mut regions,
1850        );
1851
1852        let mut cuts = vec![];
1853        let bridges = non_bridges.complement(self);
1854
1855        for mut r in regions.drain() {
1856            // let disconnected = r.complement(self);
1857
1858            // let mut s_side_covers = if s.hairs.intersects(&r) {
1859            //     s.hairs.clone()
1860            // } else {
1861            //     SimpleTraversalTree::depth_first_traverse(self, &disconnected, &source, None)
1862            //         .unwrap()
1863            //         .covers()
1864            // };
1865            let cut = OrientedCut::from_underlying_coerce(r.hairs.clone(), self).unwrap();
1866            r.add_all_hairs(self);
1867            let mut s_side_covers = r.internal_and_hairs();
1868            for i in bridges.included_iter() {
1869                if s_side_covers.includes(&self.inv(i)) {
1870                    s_side_covers.set(i.0, true);
1871                }
1872            }
1873
1874            let t_side_covers = s_side_covers.complement(self);
1875
1876            // let internal = InternalSubGraph::cleaned_filter_pessimist(t_side_covers, self);
1877            // let mut t_side = self.nesting_node_from_subgraph(internal);
1878            // t_side.hairs.union_with(&t.hairs);
1879            //
1880
1881            cuts.push((s_side_covers, cut, t_side_covers));
1882        }
1883
1884        cuts
1885    }
1886
1887    pub fn all_s_t_cuts_impl<S: SubGraph<Base = BitVec>>(
1888        &self,
1889        subgraph: &S,
1890        s_connectivity: usize,
1891        s: HedgeNode, // will grow
1892        t: &HedgeNode,
1893        t_connectivity: usize,
1894        regions: &mut AHashSet<HedgeNode>,
1895    ) {
1896        // println!("regions size:{}", regions.len());
1897        //
1898
1899        let hairy = s.internal_graph.filter.union(&s.hairs);
1900        let mut complement = hairy.complement(self);
1901        complement.intersect_with(subgraph.included());
1902        if !complement.includes(&t.hairs) {
1903            return;
1904        }
1905
1906        let t_count = self.count_connected_components(&complement);
1907        let s_count = self.count_connected_components(&hairy);
1908
1909        if t_count <= t_connectivity && s_count <= s_connectivity && regions.get(&s).is_none() {
1910            for h in s.hairs.included_iter() {
1911                let invh = self.inv(h);
1912
1913                if invh != h && !t.hairs.includes(&invh) && subgraph.includes(&invh) {
1914                    let mut new_node = s.clone();
1915
1916                    new_node.hairs.union_with_iter(self.neighbors(invh));
1917                    new_node.hairs.intersect_with(subgraph.included());
1918
1919                    new_node.fix(self);
1920                    self.all_s_t_cuts_impl(
1921                        subgraph,
1922                        s_connectivity,
1923                        new_node,
1924                        t,
1925                        t_connectivity,
1926                        regions,
1927                    );
1928                }
1929            }
1930            regions.insert(s);
1931        }
1932    }
1933}
1934
1935// Cycles
1936impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
1937    ///Gives all subgraphs corresponding to all the spanning trees of the graph
1938    ///Winter, Pawel. “An Algorithm for the Enumeration of Spanning Trees.” BIT Numerical Mathematics 26, no. 1 (March 1, 1986): 44–62. https://doi.org/10.1007/BF01939361.
1939    pub fn all_spanning_trees<S: SubGraph>(&self, subgraph: &S) -> Vec<S::Base>
1940    where
1941        for<'a> N::OpStorage<&'a V>: Clone,
1942        S::Base: SubGraph<Base = S::Base>
1943            + SubGraphOps
1944            + Clone
1945            + ModifySubgraph<HedgePair>
1946            + ModifySubgraph<Hedge>,
1947    {
1948        let ref_self = self.to_ref();
1949
1950        let exts = self.internal_crown(subgraph);
1951
1952        if let Some((root_node, _, _)) = self.iter_nodes_of(subgraph).next() {
1953            let tree = SimpleTraversalTree::depth_first_traverse(self, subgraph, &root_node, None)
1954                .unwrap();
1955            let mut nodes = tree.node_order();
1956            nodes.remove(0);
1957
1958            let mut included = subgraph.included().clone();
1959            for h in exts.included_iter() {
1960                included.sub(h);
1961            }
1962
1963            ref_self.contract_edge_for_spanning(nodes, included)
1964        } else {
1965            vec![]
1966        }
1967    }
1968
1969    fn contract_edge_for_spanning<S>(self, mut nodes: Vec<NodeIndex>, mut subgraph: S) -> Vec<S>
1970    where
1971        V: Clone,
1972        E: Clone,
1973        H: Clone,
1974        N: Clone,
1975        S: SubGraphOps
1976            + Clone
1977            + SubGraph<Base = S>
1978            + ModifySubgraph<HedgePair>
1979            + ModifySubgraph<Hedge>,
1980    {
1981        let mut trees = vec![];
1982        if let Some(node) = nodes.pop() {
1983            for h in self.iter_crown(node) {
1984                //This is an internal edge
1985                if subgraph.includes(&h) && subgraph.includes(&self.inv(h)) {
1986                    //we found an neighboring vertex in the graph
1987                    if let Some(new_node) = self.involved_node_id(h) {
1988                        // This is not a dangling edge
1989                        // if new_node != node {
1990
1991                        let node_data_merge = self[node].clone();
1992                        let mut new_self = self.clone();
1993
1994                        // We now identify node and new_node. All spanning trees of this contracted graph will be spanning trees of the full graph, when adding one of the parallel edges
1995                        let (mapped_node, parallel): (_, S::Base) = new_self
1996                            .identify_nodes_without_self_edges(&[node, new_node], node_data_merge);
1997
1998                        let mapped_nodes = nodes
1999                            .iter()
2000                            .map(|a| {
2001                                if *a == new_node || *a == node {
2002                                    mapped_node
2003                                } else {
2004                                    *a
2005                                }
2006                            })
2007                            .collect();
2008
2009                        for v in new_self
2010                            .contract_edge_for_spanning(mapped_nodes, subgraph.subtract(&parallel))
2011                        // recurse with a the node identified graph and the contracted edge subgraph
2012                        {
2013                            // v is the set of spanning trees of the contracted graph
2014                            for (p, _, _) in self.iter_edges_of(&parallel.intersection(&subgraph)) {
2015                                let mut with_p = v.clone();
2016                                with_p.add(p);
2017                                trees.push(with_p);
2018                            }
2019                        }
2020
2021                        // Remove all these edges from consideration.
2022                        subgraph.subtract_with(&parallel);
2023                    }
2024                }
2025            }
2026        } else {
2027            trees.push(self.empty_subgraph())
2028        }
2029
2030        trees
2031    }
2032}
2033
2034// Cycles
2035impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
2036    pub fn cyclotomatic_number<S: SubGraph>(&self, subgraph: &S) -> usize {
2037        let n_hedges = self.count_internal_edges(subgraph);
2038        // println!("n_hedges: {}", n_hedges);
2039        let n_nodes = self.number_of_nodes_in_subgraph(subgraph);
2040        // println!("n_nodes: {}", n_nodes);
2041        let n_components = self.count_connected_components(subgraph);
2042
2043        n_hedges + n_components - n_nodes
2044    }
2045
2046    pub fn cycle_basis(&self) -> (Vec<Cycle>, SimpleTraversalTree) {
2047        self.paton_cycle_basis(&self.full_graph(), &self.node_id(Hedge(0)), None)
2048            .unwrap()
2049    }
2050
2051    pub fn order_basis(&self, basis: &[HedgeNode]) -> Vec<Vec<InternalSubGraph>> {
2052        let mut seen = vec![basis[0].internal_graph.clone()];
2053        let mut partitions = vec![seen.clone()];
2054
2055        for cycle in basis.iter() {
2056            if seen
2057                .iter()
2058                .any(|p| !p.empty_intersection(&cycle.internal_graph))
2059            {
2060                partitions
2061                    .last_mut()
2062                    .unwrap()
2063                    .push(cycle.internal_graph.clone());
2064            } else {
2065                for p in partitions.last().unwrap() {
2066                    seen.push(p.clone());
2067                }
2068                partitions.push(vec![cycle.internal_graph.clone()]);
2069            }
2070        }
2071
2072        partitions
2073    }
2074
2075    pub fn all_cycles(&self) -> Vec<Cycle> {
2076        Cycle::all_sum_powerset_filter_map(&self.cycle_basis().0, &|mut c| {
2077            if c.is_circuit(self) {
2078                c.loop_count = Some(1);
2079                Some(c)
2080            } else {
2081                None
2082            }
2083        })
2084        .unwrap()
2085        .into_iter()
2086        .collect()
2087    }
2088
2089    pub fn all_cycle_sym_diffs(&self) -> Result<Vec<InternalSubGraph>, TryFromIntError> {
2090        Cycle::all_sum_powerset_filter_map(&self.cycle_basis().0, &Some)
2091            .map(|a| a.into_iter().map(|c| c.internal_graph(self)).collect())
2092    }
2093
2094    pub fn all_cycle_unions(&self) -> AHashSet<InternalSubGraph> {
2095        InternalSubGraph::all_unions_iterative(&self.all_cycle_sym_diffs().unwrap())
2096    }
2097    pub fn paton_count_loops(
2098        &self,
2099        subgraph: &InternalSubGraph,
2100        start: &NodeIndex,
2101    ) -> Result<usize, HedgeGraphError> {
2102        let tree = SimpleTraversalTree::depth_first_traverse(self, subgraph, start, None)?;
2103
2104        let cuts = subgraph.subtract(&tree.tree_subgraph(self));
2105        Ok(self.edge_store.n_internals(&cuts))
2106    }
2107
2108    pub fn paton_cycle_basis<S: SubGraph<Base = BitVec>>(
2109        &self,
2110        subgraph: &S,
2111        start: &NodeIndex,
2112        included_hedge: Option<Hedge>,
2113    ) -> Result<(Vec<Cycle>, SimpleTraversalTree), HedgeGraphError> {
2114        let tree =
2115            SimpleTraversalTree::depth_first_traverse(self, subgraph, start, included_hedge)?;
2116
2117        let cuts = subgraph.included().subtract(&tree.tree_subgraph);
2118
2119        let mut cycle_basis = Vec::new();
2120
2121        for c in cuts.included_iter() {
2122            if c > self.inv(c) && subgraph.includes(&self.inv(c)) {
2123                cycle_basis.push(tree.get_cycle(c, self).unwrap());
2124            }
2125        }
2126
2127        Ok((cycle_basis, tree))
2128    }
2129
2130    pub fn all_spinneys_with_basis(&self, basis: &[&InternalSubGraph]) -> AHashSet<HedgeNode> {
2131        let mut spinneys = AHashSet::new();
2132        let mut base_cycle: InternalSubGraph = self.empty_subgraph();
2133
2134        for cycle in basis {
2135            base_cycle.sym_diff_with(cycle);
2136        }
2137
2138        spinneys.insert(self.nesting_node_from_subgraph(base_cycle.clone()));
2139
2140        if basis.len() == 1 {
2141            return spinneys;
2142        }
2143
2144        for i in 0..basis.len() {
2145            for s in self.all_spinneys_with_basis(
2146                &basis
2147                    .iter()
2148                    .enumerate()
2149                    .filter_map(|(j, s)| if j != i { Some(*s) } else { None })
2150                    .collect_vec(),
2151            ) {
2152                spinneys
2153                    .insert(self.nesting_node_from_subgraph(s.internal_graph.union(&base_cycle)));
2154                spinneys.insert(s);
2155            }
2156        }
2157
2158        spinneys
2159    }
2160
2161    pub fn all_spinneys_rec(&self, spinneys: &mut AHashSet<HedgeNode>, cycle_sums: Vec<HedgeNode>) {
2162        let _len = spinneys.len();
2163
2164        let mut pset = PowersetIterator::new(cycle_sums.len() as u8);
2165
2166        pset.next(); //Skip empty set
2167
2168        for (ci, cj) in cycle_sums.iter().tuple_combinations() {
2169            let _union = ci.internal_graph.union(&cj.internal_graph);
2170
2171            // spinneys.insert(union);
2172        }
2173    }
2174
2175    pub fn all_spinneys(
2176        &self,
2177    ) -> AHashMap<InternalSubGraph, Vec<(InternalSubGraph, Option<InternalSubGraph>)>> {
2178        let basis_cycles = self.cycle_basis().0;
2179
2180        let mut all_combinations = PowersetIterator::new(basis_cycles.len() as u8);
2181        all_combinations.next(); //Skip empty set
2182
2183        let mut spinneys: AHashMap<
2184            InternalSubGraph,
2185            Vec<(InternalSubGraph, Option<InternalSubGraph>)>,
2186        > = AHashMap::new();
2187
2188        let mut cycles: Vec<InternalSubGraph> = Vec::new();
2189        for p in all_combinations {
2190            let mut base_cycle: InternalSubGraph = self.empty_subgraph();
2191
2192            for i in p.iter_ones() {
2193                base_cycle.sym_diff_with(&basis_cycles[i].clone().internal_graph(self));
2194            }
2195
2196            cycles.push(base_cycle);
2197        }
2198
2199        for (ci, cj) in cycles.iter().tuple_combinations() {
2200            let union = ci.union(cj);
2201
2202            if let Some(v) = spinneys.get_mut(&union) {
2203                v.push((ci.clone(), Some(cj.clone())));
2204            } else {
2205                spinneys.insert(union, vec![(ci.clone(), Some(cj.clone()))]);
2206            }
2207        }
2208
2209        for c in cycles {
2210            spinneys.insert(c.clone(), vec![(c.clone(), None)]);
2211        }
2212        spinneys
2213    }
2214
2215    pub fn all_spinneys_alt(&self) -> AHashSet<InternalSubGraph> {
2216        let mut spinneys = AHashSet::new();
2217        let cycles = self.all_cycles();
2218
2219        let mut pset = PowersetIterator::new(cycles.len() as u8);
2220        pset.next(); //Skip empty set
2221
2222        for p in pset {
2223            let mut union: InternalSubGraph = self.empty_subgraph();
2224
2225            for i in p.iter_ones() {
2226                union.union_with(&cycles[i].clone().internal_graph(self));
2227            }
2228
2229            spinneys.insert(union);
2230        }
2231
2232        for c in cycles {
2233            spinneys.insert(c.internal_graph(self));
2234        }
2235        spinneys
2236    }
2237}
2238
2239// Traversal Trees
2240impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
2241    pub fn count_connected_components<S: SubGraph>(&self, subgraph: &S) -> usize {
2242        self.connected_components(subgraph).len()
2243    }
2244
2245    pub fn connected_components<S: SubGraph>(&self, subgraph: &S) -> Vec<BitVec> {
2246        let mut visited_edges: BitVec = self.empty_subgraph();
2247
2248        let mut components = vec![];
2249
2250        // Iterate over all edges in the subgraph
2251        for hedge_index in subgraph.included_iter() {
2252            if !visited_edges.includes(&hedge_index) {
2253                // Perform DFS to find all reachable edges from this edge
2254
2255                //
2256                let root_node = self.node_id(hedge_index);
2257                let reachable_edges =
2258                    SimpleTraversalTree::depth_first_traverse(self, subgraph, &root_node, None)
2259                        .unwrap()
2260                        .covers(subgraph);
2261
2262                visited_edges.union_with(&reachable_edges);
2263
2264                components.push(reachable_edges);
2265            }
2266        }
2267        components
2268    }
2269    pub fn align_underlying_to_superficial(&mut self) {
2270        self.edge_store.align_underlying_to_superficial();
2271    }
2272
2273    /// aligns the underlying orientation of the graph to the tree, such that all tree edges are oriented towards the root, and all others point towards the leaves
2274    ///
2275    /// Relies on the tree being tremaux (i.e. the tree-order is total)
2276    /// This is the case for depth-first traversal.
2277    pub fn align_underlying_to_tree<P: ForestNodeStore<NodeData = ()>>(
2278        &mut self,
2279        tree: &SimpleTraversalTree<P>,
2280    ) {
2281        for (h, tt, i) in tree.iter_hedges() {
2282            // println!("hedge: {}, tt: {:?}, i: {:?}\n", h, tt, i);
2283            match tt {
2284                tree::TTRoot::Root => {
2285                    if i.is_some() {
2286                        self.edge_store.set_flow(h, Flow::Sink);
2287                    } else {
2288                        self.edge_store.set_flow(h, Flow::Source);
2289                    }
2290                }
2291                tree::TTRoot::Child(_) => {
2292                    if let Some(root_pointer) = i {
2293                        if root_pointer == h {
2294                            self.edge_store.set_flow(h, Flow::Source);
2295                        } else {
2296                            self.edge_store.set_flow(h, Flow::Sink);
2297                        }
2298                    } else {
2299                        let current_node_id = tree.node_id(h);
2300                        let involved_node_id = tree.node_id(self.inv(h));
2301
2302                        let order =
2303                            tree.tree_order(current_node_id, involved_node_id, &self.edge_store);
2304                        match order {
2305                            Some(Ordering::Equal) => {
2306                                // self.edge_store.set_flow(h);
2307                            }
2308                            Some(Ordering::Less) => {
2309                                //the path to the root from the current node, passes through the involved node
2310                                self.edge_store.set_flow(h, Flow::Sink);
2311                            }
2312                            Some(Ordering::Greater) => {
2313                                self.edge_store.set_flow(h, Flow::Source);
2314                            }
2315                            None => {}
2316                        }
2317                    }
2318                }
2319                tree::TTRoot::None => {}
2320            }
2321        }
2322    }
2323
2324    /// aligns the superficial orientation of the graph to the tree,
2325    ///
2326    /// such that all tree edges are oriented towards the root, and all others are unoriented.
2327    pub fn align_superficial_to_tree<P: ForestNodeStore<NodeData = ()>>(
2328        &mut self,
2329        tree: &SimpleTraversalTree<P>,
2330    ) {
2331        for (h, tt, i) in tree.iter_hedges() {
2332            match tt {
2333                tree::TTRoot::Root => {
2334                    if i.is_some() {
2335                        let flow = self.edge_store.flow(h);
2336                        match flow {
2337                            Flow::Source => {
2338                                self.edge_store.set_orientation(h, Orientation::Reversed);
2339                            }
2340                            Flow::Sink => {
2341                                self.edge_store.set_orientation(h, Orientation::Default);
2342                            }
2343                        }
2344                    } else {
2345                        self.edge_store.set_orientation(h, Orientation::Undirected);
2346                    }
2347                }
2348                tree::TTRoot::Child(_) => {
2349                    if let Some(root_pointer) = i {
2350                        let flow = self.edge_store.flow(h);
2351                        if root_pointer == h {
2352                            match flow {
2353                                Flow::Source => {
2354                                    self.edge_store.set_orientation(h, Orientation::Default);
2355                                }
2356                                Flow::Sink => {
2357                                    self.edge_store.set_orientation(h, Orientation::Reversed);
2358                                }
2359                            }
2360                        } else {
2361                            match flow {
2362                                Flow::Source => {
2363                                    self.edge_store.set_orientation(h, Orientation::Reversed);
2364                                }
2365                                Flow::Sink => {
2366                                    self.edge_store.set_orientation(h, Orientation::Default);
2367                                }
2368                            }
2369
2370                            // self.edge_store.involution.set_as_sink(h);
2371                        }
2372                    } else {
2373                        self.edge_store.set_orientation(h, Orientation::Undirected);
2374                    }
2375                }
2376                tree::TTRoot::None => {}
2377            }
2378        }
2379    }
2380
2381    // pub fn align_to_tree_superficial(&mut self, tree: &TraversalTree) {
2382    //     for (i, p) in tree.parent_iter() {
2383    //         match self.edge_store.involution.hedge_data_mut(i) {
2384    //             InvolutiveMapping::Identity { data, .. } => match p {
2385    //                 Parent::Root => {}
2386    //                 Parent::Hedge { hedge_to_root, .. } => {
2387    //                     if *hedge_to_root == i {
2388    //                         data.orientation = Orientation::Default;
2389    //                     } else {
2390    //                         data.orientation = Orientation::Reversed;
2391    //                     }
2392    //                 }
2393    //                 Parent::Unset => {}
2394    //             },
2395    //             InvolutiveMapping::Source { data, .. } => match p {
2396    //                 Parent::Root => {}
2397    //                 Parent::Hedge { hedge_to_root, .. } => {
2398    //                     if *hedge_to_root == i {
2399    //                         data.orientation = Orientation::Default;
2400    //                     } else {
2401    //                         data.orientation = Orientation::Reversed;
2402    //                     }
2403    //                 }
2404    //                 Parent::Unset => {}
2405    //             },
2406    //             _ => {}
2407    //         }
2408    //     }
2409    // }
2410}
2411
2412// Iterators
2413impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
2414    pub fn iter_hedges(&self) -> impl Iterator<Item = (Hedge, &H)> {
2415        self.hedge_data.iter()
2416    }
2417
2418    ///Iterate over all nodes, returns an iterator that yields
2419    pub fn iter_nodes(&self) -> impl Iterator<Item = (NodeIndex, N::NeighborsIter<'_>, &V)> {
2420        self.node_store.iter_nodes()
2421    }
2422
2423    pub fn iter_nodes_mut(
2424        &mut self,
2425    ) -> impl Iterator<Item = (NodeIndex, N::NeighborsIter<'_>, &mut V)> {
2426        self.node_store.iter_nodes_mut()
2427    }
2428
2429    pub fn iter_node_ids(&self) -> impl Iterator<Item = NodeIndex> + '_ {
2430        self.node_store.iter_node_id()
2431    }
2432
2433    pub fn iter_edge_ids_of<'a, S: SubGraph>(
2434        &'a self,
2435        subgraph: &'a S,
2436    ) -> EdgeIter<'a, E, V, H, S, N, S::BaseIter<'a>> {
2437        EdgeIter::new(self, subgraph)
2438    }
2439
2440    pub fn iter_edges_of<'a, S: SubGraph>(
2441        &'a self,
2442        subgraph: &'a S,
2443    ) -> impl Iterator<Item = (HedgePair, EdgeIndex, EdgeData<&'a E>)> + 'a {
2444        self.edge_store.iter_edges_of(subgraph)
2445    }
2446
2447    pub fn iter_edges(&self) -> impl Iterator<Item = (HedgePair, EdgeIndex, EdgeData<&E>)> {
2448        self.edge_store.iter_edges()
2449    }
2450
2451    pub fn iter_nodes_of<'a, S: SubGraph>(
2452        &'a self,
2453        subgraph: &'a S,
2454    ) -> impl Iterator<Item = (NodeIndex, N::NeighborsIter<'a>, &'a V)>
2455    where
2456        N::NeighborsIter<'a>: Clone,
2457    {
2458        NodeIterator {
2459            graph: self,
2460            edges: subgraph.included_iter(),
2461            seen: bitvec![usize, Lsb0; 0; self.n_nodes()],
2462        }
2463    }
2464}
2465
2466// Display
2467impl<E, V, H, N: NodeStorageOps<NodeData = V>> HedgeGraph<E, V, H, N> {
2468    pub fn dot_impl_fmt<S: SubGraph, Str1: AsRef<str>>(
2469        &self,
2470        writer: &mut impl std::fmt::Write,
2471        subgraph: &S,
2472        graph_info: Str1,
2473        hedge_attr: &impl Fn(&H) -> Option<String>,
2474        edge_attr: &impl Fn(&E) -> Option<String>,
2475        node_attr: &impl Fn(&V) -> Option<String>,
2476    ) -> Result<(), std::fmt::Error> {
2477        subgraph.dot_fmt(writer, self, graph_info, hedge_attr, edge_attr, node_attr)
2478    }
2479    pub fn dot_impl_io<S: SubGraph, Str1: AsRef<str>>(
2480        &self,
2481        writer: &mut impl std::io::Write,
2482        subgraph: &S,
2483        graph_info: Str1,
2484        hedge_attr: &impl Fn(&H) -> Option<String>,
2485        edge_attr: &impl Fn(&E) -> Option<String>,
2486        node_attr: &impl Fn(&V) -> Option<String>,
2487    ) -> Result<(), std::io::Error> {
2488        subgraph.dot_io(writer, self, graph_info, hedge_attr, edge_attr, node_attr)
2489    }
2490
2491    pub fn dot_impl<S: SubGraph, Str1: AsRef<str>>(
2492        &self,
2493        subgraph: &S,
2494        graph_info: Str1,
2495        hedge_attr: &impl Fn(&H) -> Option<String>,
2496        edge_attr: &impl Fn(&E) -> Option<String>,
2497        node_attr: &impl Fn(&V) -> Option<String>,
2498    ) -> String {
2499        let mut output = String::new();
2500        subgraph
2501            .dot_fmt(
2502                &mut output,
2503                self,
2504                graph_info,
2505                hedge_attr,
2506                edge_attr,
2507                node_attr,
2508            )
2509            .unwrap();
2510        output
2511    }
2512
2513    pub fn dot<S: SubGraph>(&self, node_as_graph: &S) -> String {
2514        let mut output = String::new();
2515        self.dot_impl_fmt(
2516            &mut output,
2517            node_as_graph,
2518            "start=2;\n",
2519            &|_| None,
2520            &|_| None,
2521            &|_| None,
2522        )
2523        .unwrap();
2524        output
2525    }
2526
2527    pub fn dot_display<S: SubGraph>(&self, node_as_graph: &S) -> String
2528    where
2529        E: Display,
2530        V: Display,
2531        H: Display,
2532    {
2533        let mut output = String::new();
2534        self.dot_impl_fmt(
2535            &mut output,
2536            node_as_graph,
2537            "start=2;\n",
2538            &|h| Some(format!("{h}")),
2539            &|a| Some(format!("{a}")),
2540            &|v| Some(format!("{v}")),
2541        )
2542        .unwrap();
2543        output
2544    }
2545
2546    pub fn dot_label<S: SubGraph>(&self, node_as_graph: &S) -> String
2547    where
2548        E: Display,
2549        V: Display,
2550    {
2551        let mut output = String::new();
2552        self.dot_impl_fmt(
2553            &mut output,
2554            node_as_graph,
2555            "start=2;\n",
2556            &|_| None,
2557            &|a| Some(format!("label=\"{a}\"")),
2558            &|v| Some(format!("label=\"{v}\"")),
2559        )
2560        .unwrap();
2561        output
2562    }
2563
2564    pub fn base_dot(&self) -> String {
2565        self.dot(&self.full_filter())
2566    }
2567}
2568
2569impl<E, V, H, N: NodeStorage<NodeData = V>> Index<Hedge> for HedgeGraph<E, V, H, N> {
2570    type Output = H;
2571    fn index(&self, index: Hedge) -> &Self::Output {
2572        &self.hedge_data[index]
2573    }
2574}
2575
2576impl<E, V, H, N: NodeStorage<NodeData = V>> IndexMut<Hedge> for HedgeGraph<E, V, H, N> {
2577    fn index_mut(&mut self, index: Hedge) -> &mut Self::Output {
2578        &mut self.hedge_data[index]
2579    }
2580}
2581
2582impl<E, V, H, N: NodeStorage<NodeData = V>> Index<&Hedge> for HedgeGraph<E, V, H, N> {
2583    type Output = EdgeIndex;
2584    fn index(&self, index: &Hedge) -> &Self::Output {
2585        &self.edge_store[index]
2586    }
2587}
2588
2589impl<E, V, H, N: NodeStorage<NodeData = V>> Index<[&Hedge; 1]> for HedgeGraph<E, V, H, N> {
2590    type Output = E;
2591    fn index(&self, index: [&Hedge; 1]) -> &Self::Output {
2592        &self[self[index[0]]]
2593    }
2594}
2595
2596impl<E, V, H, N: NodeStorage<NodeData = V>> IndexMut<[&Hedge; 1]> for HedgeGraph<E, V, H, N> {
2597    // type Output = E;
2598    fn index_mut(&mut self, index: [&Hedge; 1]) -> &mut Self::Output {
2599        let edgeid = self[index[0]];
2600        &mut self[edgeid]
2601    }
2602}
2603
2604impl<E, V, H, N: NodeStorageOps<NodeData = V>> Index<NodeIndex> for HedgeGraph<E, V, H, N> {
2605    type Output = V;
2606    fn index(&self, index: NodeIndex) -> &Self::Output {
2607        self.node_store.get_node_data(index)
2608    }
2609}
2610impl<E, V, H, N: NodeStorageOps<NodeData = V>> IndexMut<NodeIndex> for HedgeGraph<E, V, H, N> {
2611    fn index_mut(&mut self, index: NodeIndex) -> &mut Self::Output {
2612        self.node_store.get_node_data_mut(index)
2613    }
2614}
2615// impl<E, V, N: NodeStorageOps<NodeData = V>> Index<&NodeIndex> for HedgeGraph<E, V, N> {
2616//     type Output = HedgeNode;
2617//     fn index(&self, index: &NodeIndex) -> &Self::Output {
2618//         self.node_store.get_neighbor_iterator(*index)
2619//     }
2620// // }
2621// impl<E, V, N: NodeStorageOps<NodeData = V>> Index<&HedgeNode> for HedgeGraph<E, V, N> {
2622//     type Output = V;
2623//     fn index(&self, index: &HedgeNode) -> &Self::Output {
2624//         let id = self.id_from_hairs(index).unwrap();
2625//         &self[id]
2626//     }
2627// }
2628
2629// impl<E, V, N: NodeStorageOps<NodeData = V>> IndexMut<&HedgeNode> for HedgeGraph<E, V, N> {
2630//     fn index_mut(&mut self, index: &HedgeNode) -> &mut Self::Output {
2631//         let id = self.id_from_hairs(index).unwrap();
2632//         &mut self[id]
2633//     }
2634// }
2635
2636impl<E, V, H, N: NodeStorage<NodeData = V>> Index<EdgeIndex> for HedgeGraph<E, V, H, N> {
2637    type Output = E;
2638    fn index(&self, index: EdgeIndex) -> &Self::Output {
2639        &self.edge_store[index]
2640    }
2641}
2642
2643impl<E, V, H, N: NodeStorage<NodeData = V>> Index<&EdgeIndex> for HedgeGraph<E, V, H, N> {
2644    type Output = (E, HedgePair);
2645    fn index(&self, index: &EdgeIndex) -> &Self::Output {
2646        &self.edge_store[index]
2647    }
2648}
2649
2650impl<E, V, H, N: NodeStorage<NodeData = V>> IndexMut<EdgeIndex> for HedgeGraph<E, V, H, N> {
2651    fn index_mut(&mut self, index: EdgeIndex) -> &mut Self::Output {
2652        &mut self.edge_store[index]
2653    }
2654}
2655
2656impl<E, V, H, N: NodeStorage<NodeData = V>> IndexMut<&EdgeIndex> for HedgeGraph<E, V, H, N> {
2657    fn index_mut(&mut self, index: &EdgeIndex) -> &mut Self::Output {
2658        &mut self.edge_store[index]
2659    }
2660}
2661
2662pub struct NodeIterator<'a, E, V, H, N: NodeStorage<NodeData = V>, I = IterOnes<'a, usize, Lsb0>> {
2663    graph: &'a HedgeGraph<E, V, H, N>,
2664    edges: I,
2665    seen: BitVec,
2666}
2667
2668impl<'a, E, V, H, I: Iterator<Item = Hedge>, N: NodeStorageOps<NodeData = V>> Iterator
2669    for NodeIterator<'a, E, V, H, N, I>
2670where
2671    N::NeighborsIter<'a>: Clone,
2672{
2673    type Item = (NodeIndex, N::NeighborsIter<'a>, &'a V);
2674
2675    fn next(&mut self) -> Option<Self::Item> {
2676        if let Some(next) = self.edges.next() {
2677            let node = self.graph.neighbors(next);
2678            let node_pos = self.graph.id_from_crown(node.clone()).unwrap();
2679
2680            if self.seen[node_pos.0] {
2681                self.next()
2682            } else {
2683                self.seen.set(node_pos.0, true);
2684                Some((node_pos, node, &self.graph[node_pos]))
2685            }
2686        } else {
2687            None
2688        }
2689    }
2690}
2691
2692#[cfg(feature = "symbolica")]
2693pub mod symbolica_interop;
2694
2695use subgraph::{
2696    BaseSubgraph, Cycle, FullOrEmpty, HedgeNode, Inclusion, InternalSubGraph, ModifySubgraph,
2697    OrientedCut, SubGraph, SubGraphOps,
2698};
2699
2700use thiserror::Error;
2701use tree::SimpleTraversalTree;
2702
2703use crate::define_indexed_vec;
2704use crate::tree::ForestNodeStore;
2705
2706#[derive(Error, Debug)]
2707pub enum HedgeError {
2708    #[error("Invalid start node")]
2709    InvalidStart,
2710}
2711
2712pub struct EdgeIter<'a, E, V, H, S, N: NodeStorage<NodeData = V>, I: Iterator<Item = Hedge> + 'a> {
2713    graph: &'a HedgeGraph<E, V, H, N>,
2714    included_iter: I,
2715    subgraph: &'a S,
2716}
2717impl<'a, E, V, H, S, N: NodeStorage<NodeData = V>> EdgeIter<'a, E, V, H, S, N, S::BaseIter<'a>>
2718where
2719    S: SubGraph,
2720{
2721    pub fn new(graph: &'a HedgeGraph<E, V, H, N>, subgraph: &'a S) -> Self {
2722        EdgeIter {
2723            graph,
2724            subgraph,
2725            included_iter: subgraph.included_iter(),
2726        }
2727    }
2728}
2729
2730impl<'a, E, V, H, S, N: NodeStorage<NodeData = V>> Iterator
2731    for EdgeIter<'a, E, V, H, S, N, S::BaseIter<'a>>
2732where
2733    S: SubGraph,
2734{
2735    type Item = (HedgePair, EdgeData<&'a E>);
2736
2737    fn next(&mut self) -> Option<Self::Item> {
2738        let i = self.included_iter.next()?;
2739        let orientation = self.graph.edge_store.orientation(i);
2740        let data = &self.graph[self.graph[&i]];
2741        if let Some(e) =
2742            HedgePair::from_source_with_subgraph(i, &self.graph.edge_store, self.subgraph)
2743        {
2744            Some((e, EdgeData::new(data, orientation)))
2745        } else {
2746            self.next()
2747        }
2748    }
2749}
2750
2751#[derive(Debug, Error)]
2752pub enum HedgeGraphError {
2753    #[error("Node ({0}) that Hedge {1} points to does not contain it")]
2754    NodeDoesNotContainHedge(NodeIndex, Hedge),
2755    #[error("Nodes do not partition: {0}")]
2756    NodesDoNotPartition(String),
2757    #[error("Invalid node")]
2758    NoNode,
2759    #[error("Invalid hedge {0}")]
2760    InvalidHedge(Hedge),
2761    #[error("External hedge as included: {0}")]
2762    ExternalHedgeIncluded(Hedge),
2763
2764    #[error("Included hedge {0} is not in node {1}")]
2765    NotInNode(Hedge, NodeIndex),
2766
2767    #[error("Traversal Root node not in subgraph {0}")]
2768    RootNodeNotInSubgraph(NodeIndex),
2769    #[error("Invalid node {0}")]
2770    InvalidNode(NodeIndex),
2771    #[error("Invalid edge")]
2772    NoEdge,
2773    #[error("Dangling Half edge present")]
2774    HasIdentityHedge,
2775    #[error("SymbolicaError: {0}")]
2776    SymbolicaError(&'static str),
2777    #[error("InvolutionError: {0}")]
2778    InvolutionError(#[from] InvolutionError),
2779    #[error("Data length mismatch")]
2780    DataLengthMismatch,
2781    #[error("Invalid hedge pair {0:?} not equal to {1:?} for edge {2}")]
2782    InvalidHedgePair(HedgePair, HedgePair, EdgeIndex),
2783    // #[error("From file error: {0}")]
2784    // FromFileError(#[from] GraphFromFileError),
2785    // #[error("Parse error: {0}")]
2786    // ParseError(#[from] PestError),
2787}
2788
2789pub mod hedgevec;
2790pub mod tree;
2791pub mod typed_vec;
2792
2793#[cfg(feature = "drawing")]
2794pub mod drawing;
2795#[cfg(feature = "drawing")]
2796pub mod layout;
2797#[cfg(test)]
2798mod test_graphs;
2799#[cfg(test)]
2800mod tests;