Skip to main content

igraph/
constants.rs

1//! Rust enumerations for igraph's C constants (`igraph_constants.h`).
2//!
3//! Each enum converts into the raw C value with [`From`] (e.g.
4//! `igraph_neimode_t::from(NeighborMode::Out)`), and back with [`TryFrom`]
5//! (an [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue)
6//! error for values that are not part of the enumeration). All of them are
7//! re-exported by the [prelude](crate::prelude). Module-specific enums (e.g.
8//! layout or community options) live next to the functions that use them.
9//!
10//! ```
11//! use igraph::{ffi, prelude::*};
12//!
13//! // Out-neighbors follow the edge direction, in-neighbors go against it.
14//! let g = Graph::from_edges(&[(0, 1), (2, 1), (1, 1)], 3, true).unwrap();
15//! assert_eq!(g.neighbors(1, NeighborMode::Out).unwrap(), vec![1]);
16//! assert_eq!(g.neighbors(1, NeighborMode::In).unwrap(), vec![0, 1, 2]);
17//! assert_eq!(g.degree(1, NeighborMode::All, Loops::Twice).unwrap(), vec![4]);
18//! assert_eq!(g.degree(1, NeighborMode::All, Loops::None).unwrap(), vec![2]);
19//!
20//! // Conversions to and from the raw C constants.
21//! assert_eq!(ffi::igraph_neimode_t::from(NeighborMode::In), ffi::igraph_neimode_t_IGRAPH_IN);
22//! assert_eq!(NeighborMode::try_from(ffi::igraph_neimode_t_IGRAPH_ALL).unwrap(), NeighborMode::All);
23//! assert!(Order::try_from(42 as ffi::igraph_order_t).is_err());
24//! ```
25//!
26//! | Enum | C type | Used by (for example) |
27//! |------|--------|-----------------------|
28//! | [`NeighborMode`] | `igraph_neimode_t` | [`Graph::neighbors`](crate::Graph::neighbors), [`Graph::degree`](crate::Graph::degree), [`Graph::bfs`](crate::Graph::bfs), [`Graph::distances`](crate::Graph::distances) |
29//! | [`Loops`] | `igraph_loops_t` | [`Graph::degree`](crate::Graph::degree), [`Graph::neighbors_with`](crate::Graph::neighbors_with), [`Graph::get_adjacency`](crate::Graph::get_adjacency) |
30//! | [`EdgeTypeSw`], [`AllowedEdgeTypes`] | `igraph_edge_type_sw_t` | [`Graph::rewire`](crate::Graph::rewire), [`Graph::erdos_renyi_game_gnm`](crate::Graph::erdos_renyi_game_gnm) |
31//! | [`Order`] | `igraph_order_t` | [`VectorInt::sort_ind`](crate::vector::VectorInt::sort_ind), [`Graph::sort_vertex_ids_by_degree`](crate::Graph::sort_vertex_ids_by_degree) |
32//! | [`Connectedness`] | `igraph_connectedness_t` | [`Graph::connected_components`](crate::Graph::connected_components), [`Graph::is_connected`](crate::Graph::is_connected) |
33//! | [`Reciprocity`] | `igraph_reciprocity_t` | [`Graph::reciprocity`](crate::Graph::reciprocity) |
34//! | [`Adjacency`], [`GetAdjacency`] | `igraph_adjacency_t`, `igraph_get_adjacency_t` | [`Graph::adjacency`](crate::Graph::adjacency), [`Graph::get_adjacency`](crate::Graph::get_adjacency) |
35//! | [`StarMode`], [`WheelMode`], [`TreeMode`] | `igraph_star_mode_t`, `igraph_wheel_mode_t`, `igraph_tree_mode_t` | [`Graph::star`](crate::Graph::star), [`Graph::wheel`](crate::Graph::wheel), [`Graph::kary_tree`](crate::Graph::kary_tree) |
36//! | [`DegreeSequenceMethod`], [`RealizeDegseq`] | `igraph_degseq_t`, `igraph_realize_degseq_t` | [`Graph::degree_sequence_game`](crate::Graph::degree_sequence_game), [`Graph::realize_degree_sequence`](crate::Graph::realize_degree_sequence) |
37//! | [`RandomTreeMethod`], [`BarabasiAlgorithm`], [`ChungLuVariant`] | `igraph_random_tree_t`, `igraph_barabasi_algorithm_t`, `igraph_chung_lu_t` | [`Graph::tree_game`](crate::Graph::tree_game), [`Graph::barabasi_game`](crate::Graph::barabasi_game), [`Graph::chung_lu_game`](crate::Graph::chung_lu_game) |
38//! | [`EdgeOrder`] | `igraph_edgeorder_type_t` | [`EdgeSelector::AllOrdered`](crate::selector::EdgeSelector::AllOrdered) |
39//! | [`ToDirected`], [`ToUndirected`] | `igraph_to_directed_t`, `igraph_to_undirected_t` | [`Graph::to_directed`](crate::Graph::to_directed), [`Graph::to_undirected`](crate::Graph::to_undirected) |
40//! | [`VconnNei`] | `igraph_vconn_nei_t` | [`Graph::st_vertex_connectivity`](crate::Graph::st_vertex_connectivity) |
41//! | [`SpincommUpdate`], [`SpinglassImplementation`], [`LpaVariant`], [`CommunityComparison`] | `igraph_spincomm_update_t`, ... | [`Graph::community_spinglass`](crate::Graph::community_spinglass), [`Graph::community_label_propagation`](crate::Graph::community_label_propagation), [`compare_communities`](crate::community::compare_communities) |
42//! | [`TransitivityMode`] | `igraph_transitivity_mode_t` | [`Graph::transitivity_local_undirected`](crate::Graph::transitivity_local_undirected) |
43//! | [`AddWeights`] | `igraph_add_weights_t` | [`NcolLglOptions`](crate::foreign::NcolLglOptions) |
44//! | [`FasAlgorithm`], [`FvsAlgorithm`] | `igraph_fas_algorithm_t`, `igraph_fvs_algorithm_t` | [`Graph::feedback_arc_set`](crate::Graph::feedback_arc_set), [`Graph::feedback_vertex_set`](crate::Graph::feedback_vertex_set) |
45//! | [`SubgraphImplementation`] | `igraph_subgraph_implementation_t` | [`Graph::induced_subgraph`](crate::Graph::induced_subgraph) |
46//! | [`LayoutGrid`] | `igraph_layout_grid_t` | [`FruchtermanReingoldOptions`](crate::layout::FruchtermanReingoldOptions) |
47//! | [`RandomWalkStuck`], [`VoronoiTiebreaker`] | `igraph_random_walk_stuck_t`, `igraph_voronoi_tiebreaker_t` | [`Graph::random_walk`](crate::Graph::random_walk), [`Graph::voronoi`](crate::Graph::voronoi) |
48//! | [`MstAlgorithm`], [`Product`] | `igraph_mst_algorithm_t`, `igraph_product_t` | [`Graph::minimum_spanning_tree`](crate::Graph::minimum_spanning_tree), [`Graph::product`](crate::Graph::product) |
49//! | [`MatrixStorage`] | `igraph_matrix_storage_t` | raw FFI functions taking flat matrices |
50
51use crate::ffi::*;
52
53/// Declares a Rust enum mirroring a C enum, together with `From`/`TryFrom`
54/// conversions to and from the raw type.
55///
56/// ```ignore
57/// ffi_enum! {
58///     /// Docs.
59///     pub enum NeighborMode: igraph_neimode_t {
60///         /// Out-neighbors.
61///         Out = igraph_neimode_t_IGRAPH_OUT,
62///     }
63/// }
64/// ```
65#[macro_export]
66macro_rules! ffi_enum {
67    (
68        $(#[$meta:meta])*
69        $vis:vis enum $name:ident : $raw:ty {
70            $( $(#[$vmeta:meta])* $variant:ident = $value:path ),+ $(,)?
71        }
72    ) => {
73        $(#[$meta])*
74        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
75        $vis enum $name {
76            $( $(#[$vmeta])* $variant ),+
77        }
78
79        impl From<$name> for $raw {
80            fn from(value: $name) -> $raw {
81                match value {
82                    $( $name::$variant => $value as $raw ),+
83                }
84            }
85        }
86
87        impl TryFrom<$raw> for $name {
88            type Error = $crate::error::Error;
89            #[allow(non_upper_case_globals, unreachable_patterns)]
90            fn try_from(value: $raw) -> $crate::error::Result<Self> {
91                $( if value == $value as $raw { return Ok($name::$variant); } )+
92                Err($crate::error::Error::invalid(format!(
93                    "invalid value {} for {}", value, stringify!($name)
94                )))
95            }
96        }
97    };
98}
99
100ffi_enum! {
101    /// Which neighbors (or incident edges) to consider in directed graphs
102    /// (`igraph_neimode_t`). Ignored for undirected graphs.
103    pub enum NeighborMode: igraph_neimode_t {
104        /// Follow edges along their direction (successors).
105        Out = igraph_neimode_t_IGRAPH_OUT,
106        /// Follow edges against their direction (predecessors).
107        In = igraph_neimode_t_IGRAPH_IN,
108        /// Ignore edge directions.
109        All = igraph_neimode_t_IGRAPH_ALL,
110    }
111}
112
113impl NeighborMode {
114    /// The mode with the direction reversed (`All` stays `All`).
115    pub fn reverse(self) -> Self {
116        match self {
117            Self::Out => Self::In,
118            Self::In => Self::Out,
119            Self::All => Self::All,
120        }
121    }
122}
123
124ffi_enum! {
125    /// How self-loops are counted (`igraph_loops_t`).
126    pub enum Loops: igraph_loops_t {
127        /// Ignore loop edges.
128        None = igraph_loops_t_IGRAPH_NO_LOOPS,
129        /// Count each loop twice, as it has two endpoints at the same vertex
130        /// (the graph theoretical convention, which keeps the handshake
131        /// lemma true).
132        Twice = igraph_loops_t_IGRAPH_LOOPS_TWICE,
133        /// Count each loop once. Only meaningful when edge directions are
134        /// ignored: for out- or in-degrees of directed graphs each loop
135        /// counts once anyway.
136        Once = igraph_loops_t_IGRAPH_LOOPS_ONCE,
137    }
138}
139
140impl From<bool> for Loops {
141    /// `true` maps to [`Loops::Twice`] (igraph's `IGRAPH_LOOPS`), `false` to [`Loops::None`].
142    fn from(loops: bool) -> Self {
143        if loops { Loops::Twice } else { Loops::None }
144    }
145}
146
147ffi_enum! {
148    /// Which kind of edges a random generator may produce (`igraph_edge_type_sw_t`).
149    pub enum EdgeTypeSw: igraph_edge_type_sw_t {
150        /// Only simple graphs: no loops, no multi-edges.
151        Simple = IGRAPH_SIMPLE_SW,
152        /// Self-loops allowed.
153        Loops = IGRAPH_LOOPS_SW,
154        /// Multi-edges allowed.
155        Multi = IGRAPH_MULTI_SW,
156    }
157}
158
159/// Which kinds of edges a graph may contain, as a set of flags
160/// (`igraph_edge_type_sw_t`, including the combination
161/// `IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW`).
162///
163/// This is the single crate-wide type for igraph's edge-type switches: it is
164/// taken by the random generators of [`games`](crate::games) (e.g.
165/// [`Graph::erdos_renyi_game_gnm`](crate::Graph::erdos_renyi_game_gnm)), by the
166/// graphicality tests of [`mixing`](crate::mixing) (e.g.
167/// [`is_graphical`](crate::mixing::is_graphical)) and by the deterministic
168/// realizations of [`constructors`](crate::constructors) (e.g.
169/// [`Graph::realize_degree_sequence`](crate::Graph::realize_degree_sequence)).
170/// It is re-exported as `games::AllowedEdgeTypes`,
171/// `mixing::AllowedEdgeTypes` and `constructors::AllowedEdgeTypes`, and all
172/// these paths name the very same type.
173///
174/// Unlike [`EdgeTypeSw`], which lists the three basic flags, this type can
175/// express their combination: build it with the associated constants
176/// ([`SIMPLE`](Self::SIMPLE), [`LOOPS`](Self::LOOPS), [`MULTI`](Self::MULTI),
177/// [`ALL`](Self::ALL)), with a struct literal, or by or-ing flags together.
178/// Every function taking it accepts `impl Into<AllowedEdgeTypes>`, so an
179/// [`EdgeTypeSw`] can be passed directly.
180///
181/// ```
182/// use igraph::{ffi, prelude::*};
183///
184/// let both = AllowedEdgeTypes::LOOPS | AllowedEdgeTypes::MULTI;
185/// assert_eq!(both, AllowedEdgeTypes::ALL);
186/// assert_eq!(AllowedEdgeTypes::from(EdgeTypeSw::Multi), AllowedEdgeTypes::MULTI);
187/// assert_eq!(EdgeTypeSw::Loops | EdgeTypeSw::Multi, AllowedEdgeTypes::ALL);
188///
189/// // Raw C flags, both ways.
190/// let raw = ffi::igraph_edge_type_sw_t::from(AllowedEdgeTypes::ALL);
191/// assert_eq!(raw, ffi::IGRAPH_LOOPS_SW | ffi::IGRAPH_MULTI_SW);
192/// assert_eq!(AllowedEdgeTypes::try_from(raw).unwrap(), AllowedEdgeTypes::ALL);
193///
194/// // One name, one type, whatever the module path.
195/// let t: igraph::games::AllowedEdgeTypes = igraph::constructors::AllowedEdgeTypes::MULTI;
196/// assert_eq!(t, igraph::mixing::AllowedEdgeTypes::MULTI);
197/// ```
198#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
199pub struct AllowedEdgeTypes {
200    /// Whether self-loops are allowed.
201    pub loops: bool,
202    /// Whether multi-edges (parallel edges) are allowed.
203    pub multi: bool,
204}
205
206impl AllowedEdgeTypes {
207    /// Simple graphs only: neither self-loops nor multi-edges (`IGRAPH_SIMPLE_SW`).
208    pub const SIMPLE: Self = Self {
209        loops: false,
210        multi: false,
211    };
212    /// Self-loops allowed, but no multi-edges (`IGRAPH_LOOPS_SW`); at most
213    /// one self-loop per vertex.
214    pub const LOOPS: Self = Self {
215        loops: true,
216        multi: false,
217    };
218    /// Multi-edges allowed, but no self-loops (`IGRAPH_MULTI_SW`).
219    pub const MULTI: Self = Self {
220        loops: false,
221        multi: true,
222    };
223    /// Both self-loops and multi-edges allowed (`IGRAPH_LOOPS_SW | IGRAPH_MULTI_SW`).
224    pub const ALL: Self = Self {
225        loops: true,
226        multi: true,
227    };
228
229    /// Former enum variant name of [`SIMPLE`](Self::SIMPLE), kept so that
230    /// code written for the old `constructors::AllowedEdgeTypes` enum compiles.
231    #[doc(hidden)]
232    #[allow(non_upper_case_globals)]
233    pub const Simple: Self = Self::SIMPLE;
234    /// Former enum variant name of [`LOOPS`](Self::LOOPS).
235    #[doc(hidden)]
236    #[allow(non_upper_case_globals)]
237    pub const Loops: Self = Self::LOOPS;
238    /// Former enum variant name of [`MULTI`](Self::MULTI).
239    #[doc(hidden)]
240    #[allow(non_upper_case_globals)]
241    pub const Multi: Self = Self::MULTI;
242    /// Former enum variant name of [`ALL`](Self::ALL).
243    #[doc(hidden)]
244    #[allow(non_upper_case_globals)]
245    pub const LoopsAndMulti: Self = Self::ALL;
246
247    /// The raw igraph bit flags.
248    pub const fn to_raw(self) -> igraph_edge_type_sw_t {
249        let mut raw = IGRAPH_SIMPLE_SW as igraph_edge_type_sw_t;
250        if self.loops {
251            raw |= IGRAPH_LOOPS_SW as igraph_edge_type_sw_t;
252        }
253        if self.multi {
254            raw |= IGRAPH_MULTI_SW as igraph_edge_type_sw_t;
255        }
256        raw
257    }
258}
259
260impl From<EdgeTypeSw> for AllowedEdgeTypes {
261    fn from(sw: EdgeTypeSw) -> Self {
262        match sw {
263            EdgeTypeSw::Simple => Self::SIMPLE,
264            EdgeTypeSw::Loops => Self::LOOPS,
265            EdgeTypeSw::Multi => Self::MULTI,
266        }
267    }
268}
269
270impl From<AllowedEdgeTypes> for igraph_edge_type_sw_t {
271    fn from(types: AllowedEdgeTypes) -> Self {
272        types.to_raw()
273    }
274}
275
276impl TryFrom<igraph_edge_type_sw_t> for AllowedEdgeTypes {
277    type Error = crate::error::Error;
278    /// Accepts exactly the four valid flag combinations; any other bit
279    /// pattern is an [`ErrorKind::InvalidValue`](crate::error::ErrorKind::InvalidValue).
280    fn try_from(raw: igraph_edge_type_sw_t) -> crate::error::Result<Self> {
281        [Self::SIMPLE, Self::LOOPS, Self::MULTI, Self::ALL]
282            .into_iter()
283            .find(|t| t.to_raw() == raw)
284            .ok_or_else(|| {
285                crate::error::Error::invalid(format!("invalid value {raw} for AllowedEdgeTypes"))
286            })
287    }
288}
289
290impl std::ops::BitOr for AllowedEdgeTypes {
291    type Output = Self;
292    fn bitor(self, rhs: Self) -> Self {
293        Self {
294            loops: self.loops || rhs.loops,
295            multi: self.multi || rhs.multi,
296        }
297    }
298}
299
300impl std::ops::BitOr<EdgeTypeSw> for AllowedEdgeTypes {
301    type Output = Self;
302    fn bitor(self, rhs: EdgeTypeSw) -> Self {
303        self | Self::from(rhs)
304    }
305}
306
307impl std::ops::BitOr for EdgeTypeSw {
308    type Output = AllowedEdgeTypes;
309    fn bitor(self, rhs: Self) -> AllowedEdgeTypes {
310        AllowedEdgeTypes::from(self) | AllowedEdgeTypes::from(rhs)
311    }
312}
313
314/// Former name of [`EdgeTypeSw`], kept for backwards compatibility.
315#[deprecated(note = "use `EdgeTypeSw`")]
316#[allow(non_camel_case_types)]
317pub type edge_type_sw_t = EdgeTypeSw;
318
319ffi_enum! {
320    /// Sorting order (`igraph_order_t`).
321    pub enum Order: igraph_order_t {
322        /// Ascending.
323        Ascending = igraph_order_t_IGRAPH_ASCENDING,
324        /// Descending.
325        Descending = igraph_order_t_IGRAPH_DESCENDING,
326    }
327}
328
329ffi_enum! {
330    /// Weak or strong connectedness (`igraph_connectedness_t`).
331    pub enum Connectedness: igraph_connectedness_t {
332        /// Ignore edge directions.
333        Weak = igraph_connectedness_t_IGRAPH_WEAK,
334        /// Require directed paths in both directions.
335        Strong = igraph_connectedness_t_IGRAPH_STRONG,
336    }
337}
338
339ffi_enum! {
340    /// Reciprocity definition (`igraph_reciprocity_t`).
341    pub enum Reciprocity: igraph_reciprocity_t {
342        /// Ratio of reciprocated edges to all edges.
343        Default = igraph_reciprocity_t_IGRAPH_RECIPROCITY_DEFAULT,
344        /// Ratio of mutual vertex pairs to connected vertex pairs.
345        Ratio = igraph_reciprocity_t_IGRAPH_RECIPROCITY_RATIO,
346    }
347}
348
349ffi_enum! {
350    /// How to interpret an adjacency matrix (`igraph_adjacency_t`).
351    pub enum Adjacency: igraph_adjacency_t {
352        /// Directed graph, `A[i][j]` edges from `i` to `j`.
353        Directed = igraph_adjacency_t_IGRAPH_ADJ_DIRECTED,
354        /// Undirected graph, the matrix must be symmetric.
355        Undirected = igraph_adjacency_t_IGRAPH_ADJ_UNDIRECTED,
356        /// Undirected graph from the upper triangle.
357        Upper = igraph_adjacency_t_IGRAPH_ADJ_UPPER,
358        /// Undirected graph from the lower triangle.
359        Lower = igraph_adjacency_t_IGRAPH_ADJ_LOWER,
360        /// Undirected graph, `min(A[i][j], A[j][i])` edges.
361        Min = igraph_adjacency_t_IGRAPH_ADJ_MIN,
362        /// Undirected graph, `A[i][j] + A[j][i]` edges.
363        Plus = igraph_adjacency_t_IGRAPH_ADJ_PLUS,
364        /// Undirected graph, `max(A[i][j], A[j][i])` edges.
365        Max = igraph_adjacency_t_IGRAPH_ADJ_MAX,
366    }
367}
368
369ffi_enum! {
370    /// Orientation of a star graph (`igraph_star_mode_t`).
371    pub enum StarMode: igraph_star_mode_t {
372        /// Edges point from the center outwards.
373        Out = igraph_star_mode_t_IGRAPH_STAR_OUT,
374        /// Edges point to the center.
375        In = igraph_star_mode_t_IGRAPH_STAR_IN,
376        /// Undirected star.
377        Undirected = igraph_star_mode_t_IGRAPH_STAR_UNDIRECTED,
378        /// Mutual directed edges.
379        Mutual = igraph_star_mode_t_IGRAPH_STAR_MUTUAL,
380    }
381}
382
383ffi_enum! {
384    /// Orientation of a wheel graph (`igraph_wheel_mode_t`).
385    pub enum WheelMode: igraph_wheel_mode_t {
386        /// Spokes point from the center outwards.
387        Out = igraph_wheel_mode_t_IGRAPH_WHEEL_OUT,
388        /// Spokes point to the center.
389        In = igraph_wheel_mode_t_IGRAPH_WHEEL_IN,
390        /// Undirected wheel.
391        Undirected = igraph_wheel_mode_t_IGRAPH_WHEEL_UNDIRECTED,
392        /// Mutual directed edges.
393        Mutual = igraph_wheel_mode_t_IGRAPH_WHEEL_MUTUAL,
394    }
395}
396
397ffi_enum! {
398    /// Orientation of a tree (`igraph_tree_mode_t`).
399    pub enum TreeMode: igraph_tree_mode_t {
400        /// Edges point away from the root.
401        Out = igraph_tree_mode_t_IGRAPH_TREE_OUT,
402        /// Edges point towards the root.
403        In = igraph_tree_mode_t_IGRAPH_TREE_IN,
404        /// Undirected tree.
405        Undirected = igraph_tree_mode_t_IGRAPH_TREE_UNDIRECTED,
406    }
407}
408
409ffi_enum! {
410    /// Which part of the adjacency matrix to produce for undirected graphs
411    /// (`igraph_get_adjacency_t`).
412    pub enum GetAdjacency: igraph_get_adjacency_t {
413        /// Upper triangle only.
414        Upper = igraph_get_adjacency_t_IGRAPH_GET_ADJACENCY_UPPER,
415        /// Lower triangle only.
416        Lower = igraph_get_adjacency_t_IGRAPH_GET_ADJACENCY_LOWER,
417        /// Full symmetric matrix.
418        Both = igraph_get_adjacency_t_IGRAPH_GET_ADJACENCY_BOTH,
419    }
420}
421
422ffi_enum! {
423    /// Method for sampling graphs with a given degree sequence (`igraph_degseq_t`).
424    pub enum DegreeSequenceMethod: igraph_degseq_t {
425        /// Configuration model, may produce loops and multi-edges.
426        Configuration = igraph_degseq_t_IGRAPH_DEGSEQ_CONFIGURATION,
427        /// Viger–Latapy: undirected simple *connected* graphs, sampled
428        /// approximately uniformly (a Monte Carlo method based on
429        /// degree-preserving edge switches).
430        VigerLatapy = igraph_degseq_t_IGRAPH_DEGSEQ_VL,
431        /// Fast heuristic generating simple graphs: like the configuration
432        /// model, but avoiding loops and multi-edges and restarting when stuck
433        /// (not uniform).
434        FastHeurSimple = igraph_degseq_t_IGRAPH_DEGSEQ_FAST_HEUR_SIMPLE,
435        /// Configuration model with rejection of non-simple graphs: uniform
436        /// simple graphs (possibly slow).
437        ConfigurationSimple = igraph_degseq_t_IGRAPH_DEGSEQ_CONFIGURATION_SIMPLE,
438        /// Edge-switching Markov chain started from a realization of the
439        /// sequence: simple (directed or undirected) graphs.
440        EdgeSwitchingSimple = igraph_degseq_t_IGRAPH_DEGSEQ_EDGE_SWITCHING_SIMPLE,
441    }
442}
443
444ffi_enum! {
445    /// Vertex choice when realizing a degree sequence (`igraph_realize_degseq_t`).
446    pub enum RealizeDegseq: igraph_realize_degseq_t {
447        /// Pick the vertex with the smallest remaining degree.
448        Smallest = igraph_realize_degseq_t_IGRAPH_REALIZE_DEGSEQ_SMALLEST,
449        /// Pick the vertex with the largest remaining degree.
450        Largest = igraph_realize_degseq_t_IGRAPH_REALIZE_DEGSEQ_LARGEST,
451        /// Pick vertices in index order.
452        Index = igraph_realize_degseq_t_IGRAPH_REALIZE_DEGSEQ_INDEX,
453    }
454}
455
456ffi_enum! {
457    /// Random tree sampling algorithm (`igraph_random_tree_t`).
458    pub enum RandomTreeMethod: igraph_random_tree_t {
459        /// Random Prüfer sequence.
460        Prufer = igraph_random_tree_t_IGRAPH_RANDOM_TREE_PRUFER,
461        /// Loop-erased random walk.
462        Lerw = igraph_random_tree_t_IGRAPH_RANDOM_TREE_LERW,
463    }
464}
465
466ffi_enum! {
467    /// Edge ordering for edge selectors (`igraph_edgeorder_type_t`).
468    pub enum EdgeOrder: igraph_edgeorder_type_t {
469        /// By edge id.
470        Id = igraph_edgeorder_type_t_IGRAPH_EDGEORDER_ID,
471        /// By source vertex.
472        From = igraph_edgeorder_type_t_IGRAPH_EDGEORDER_FROM,
473        /// By target vertex.
474        To = igraph_edgeorder_type_t_IGRAPH_EDGEORDER_TO,
475    }
476}
477
478ffi_enum! {
479    /// How to convert undirected edges to directed ones (`igraph_to_directed_t`).
480    pub enum ToDirected: igraph_to_directed_t {
481        /// One directed edge with arbitrary direction.
482        Arbitrary = igraph_to_directed_t_IGRAPH_TO_DIRECTED_ARBITRARY,
483        /// Two mutual directed edges.
484        Mutual = igraph_to_directed_t_IGRAPH_TO_DIRECTED_MUTUAL,
485        /// One directed edge with random direction.
486        Random = igraph_to_directed_t_IGRAPH_TO_DIRECTED_RANDOM,
487        /// From lower to higher vertex id, giving an acyclic graph.
488        Acyclic = igraph_to_directed_t_IGRAPH_TO_DIRECTED_ACYCLIC,
489    }
490}
491
492ffi_enum! {
493    /// How to convert directed edges to undirected ones (`igraph_to_undirected_t`).
494    pub enum ToUndirected: igraph_to_undirected_t {
495        /// Keep every edge.
496        Each = igraph_to_undirected_t_IGRAPH_TO_UNDIRECTED_EACH,
497        /// One undirected edge per connected vertex pair.
498        Collapse = igraph_to_undirected_t_IGRAPH_TO_UNDIRECTED_COLLAPSE,
499        /// One undirected edge per mutual pair.
500        Mutual = igraph_to_undirected_t_IGRAPH_TO_UNDIRECTED_MUTUAL,
501    }
502}
503
504ffi_enum! {
505    /// What to do when computing the vertex connectivity of two *adjacent*
506    /// vertices, which no vertex removal can disconnect
507    /// (`igraph_vconn_nei_t`).
508    pub enum VconnNei: igraph_vconn_nei_t {
509        /// Report an error.
510        Error = igraph_vconn_nei_t_IGRAPH_VCONN_NEI_ERROR,
511        /// Return the number of vertices.
512        NumberOfNodes = igraph_vconn_nei_t_IGRAPH_VCONN_NEI_NUMBER_OF_NODES,
513        /// Ignore the edges between them: count the vertices needed to cut
514        /// all the other paths.
515        Ignore = igraph_vconn_nei_t_IGRAPH_VCONN_NEI_IGNORE,
516        /// Return -1.
517        Negative = igraph_vconn_nei_t_IGRAPH_VCONN_NEI_NEGATIVE,
518    }
519}
520
521ffi_enum! {
522    /// Update rule of the spinglass community detection (`igraph_spincomm_update_t`).
523    pub enum SpincommUpdate: igraph_spincomm_update_t {
524        /// Simple null model.
525        Simple = igraph_spincomm_update_t_IGRAPH_SPINCOMM_UPDATE_SIMPLE,
526        /// Configuration null model.
527        Config = igraph_spincomm_update_t_IGRAPH_SPINCOMM_UPDATE_CONFIG,
528    }
529}
530
531ffi_enum! {
532    /// Value of local transitivity for vertices of degree < 2 (`igraph_transitivity_mode_t`).
533    pub enum TransitivityMode: igraph_transitivity_mode_t {
534        /// NaN.
535        Nan = igraph_transitivity_mode_t_IGRAPH_TRANSITIVITY_NAN,
536        /// Zero.
537        Zero = igraph_transitivity_mode_t_IGRAPH_TRANSITIVITY_ZERO,
538    }
539}
540
541ffi_enum! {
542    /// Spinglass implementation (`igraph_spinglass_implementation_t`).
543    pub enum SpinglassImplementation: igraph_spinglass_implementation_t {
544        /// Original implementation (positive weights only).
545        Orig = igraph_spinglass_implementation_t_IGRAPH_SPINCOMM_IMP_ORIG,
546        /// Variant supporting negative weights.
547        Neg = igraph_spinglass_implementation_t_IGRAPH_SPINCOMM_IMP_NEG,
548    }
549}
550
551ffi_enum! {
552    /// Measure used to compare two community structures (`igraph_community_comparison_t`).
553    pub enum CommunityComparison: igraph_community_comparison_t {
554        /// Variation of information.
555        Vi = igraph_community_comparison_t_IGRAPH_COMMCMP_VI,
556        /// Normalized mutual information.
557        Nmi = igraph_community_comparison_t_IGRAPH_COMMCMP_NMI,
558        /// Split-join distance.
559        SplitJoin = igraph_community_comparison_t_IGRAPH_COMMCMP_SPLIT_JOIN,
560        /// Rand index.
561        Rand = igraph_community_comparison_t_IGRAPH_COMMCMP_RAND,
562        /// Adjusted Rand index.
563        AdjustedRand = igraph_community_comparison_t_IGRAPH_COMMCMP_ADJUSTED_RAND,
564    }
565}
566
567ffi_enum! {
568    /// Whether to add weights when converting from matrices (`igraph_add_weights_t`).
569    pub enum AddWeights: igraph_add_weights_t {
570        /// No weights.
571        No = igraph_add_weights_t_IGRAPH_ADD_WEIGHTS_NO,
572        /// Add weights.
573        Yes = igraph_add_weights_t_IGRAPH_ADD_WEIGHTS_YES,
574        /// Add weights if present.
575        IfPresent = igraph_add_weights_t_IGRAPH_ADD_WEIGHTS_IF_PRESENT,
576    }
577}
578
579ffi_enum! {
580    /// Algorithm of the Barabási–Albert generator (`igraph_barabasi_algorithm_t`).
581    pub enum BarabasiAlgorithm: igraph_barabasi_algorithm_t {
582        /// Bag algorithm (may produce multi-edges).
583        Bag = igraph_barabasi_algorithm_t_IGRAPH_BARABASI_BAG,
584        /// Partial prefix-sum tree, simple graphs.
585        Psumtree = igraph_barabasi_algorithm_t_IGRAPH_BARABASI_PSUMTREE,
586        /// Partial prefix-sum tree, multi-edges allowed.
587        PsumtreeMultiple = igraph_barabasi_algorithm_t_IGRAPH_BARABASI_PSUMTREE_MULTIPLE,
588    }
589}
590
591ffi_enum! {
592    /// Feedback arc set algorithm (`igraph_fas_algorithm_t`).
593    pub enum FasAlgorithm: igraph_fas_algorithm_t {
594        /// Minimum feedback arc set by integer programming, letting igraph
595        /// pick the best such method (currently [`FasAlgorithm::ExactIpCg`]).
596        ExactIp = igraph_fas_algorithm_t_IGRAPH_FAS_EXACT_IP,
597        /// Eades–Lin–Smyth heuristic: linear time, at most `|E|/2 - |V|/6`
598        /// edges, not necessarily minimum.
599        ApproxEades = igraph_fas_algorithm_t_IGRAPH_FAS_APPROX_EADES,
600        /// Exact integer programming on a set cover formulation, with
601        /// incremental generation of cycle constraints.
602        ExactIpCg = igraph_fas_algorithm_t_IGRAPH_FAS_EXACT_IP_CG,
603        /// Exact integer programming on a topological order formulation with
604        /// triangle inequalities (typically much slower than
605        /// [`FasAlgorithm::ExactIpCg`]).
606        ExactIpTi = igraph_fas_algorithm_t_IGRAPH_FAS_EXACT_IP_TI,
607    }
608}
609
610ffi_enum! {
611    /// Feedback vertex set algorithm (`igraph_fvs_algorithm_t`).
612    pub enum FvsAlgorithm: igraph_fvs_algorithm_t {
613        /// Exact integer programming.
614        ExactIp = igraph_fvs_algorithm_t_IGRAPH_FVS_EXACT_IP,
615    }
616}
617
618ffi_enum! {
619    /// Implementation strategy for induced subgraphs (`igraph_subgraph_implementation_t`).
620    pub enum SubgraphImplementation: igraph_subgraph_implementation_t {
621        /// Let igraph decide.
622        Auto = igraph_subgraph_implementation_t_IGRAPH_SUBGRAPH_AUTO,
623        /// Copy the graph and delete vertices.
624        CopyAndDelete = igraph_subgraph_implementation_t_IGRAPH_SUBGRAPH_COPY_AND_DELETE,
625        /// Build the subgraph from scratch.
626        CreateFromScratch = igraph_subgraph_implementation_t_IGRAPH_SUBGRAPH_CREATE_FROM_SCRATCH,
627    }
628}
629
630ffi_enum! {
631    /// Whether force-directed layouts use a grid (`igraph_layout_grid_t`).
632    pub enum LayoutGrid: igraph_layout_grid_t {
633        /// Use a grid.
634        Grid = igraph_layout_grid_t_IGRAPH_LAYOUT_GRID,
635        /// Do not use a grid.
636        NoGrid = igraph_layout_grid_t_IGRAPH_LAYOUT_NOGRID,
637        /// Use a grid for large graphs only.
638        AutoGrid = igraph_layout_grid_t_IGRAPH_LAYOUT_AUTOGRID,
639    }
640}
641
642ffi_enum! {
643    /// What a random walk does when stuck (`igraph_random_walk_stuck_t`).
644    pub enum RandomWalkStuck: igraph_random_walk_stuck_t {
645        /// Report an error.
646        Error = igraph_random_walk_stuck_t_IGRAPH_RANDOM_WALK_STUCK_ERROR,
647        /// Return the walk so far.
648        Return = igraph_random_walk_stuck_t_IGRAPH_RANDOM_WALK_STUCK_RETURN,
649    }
650}
651
652ffi_enum! {
653    /// Tie breaking in Voronoi partitioning (`igraph_voronoi_tiebreaker_t`).
654    pub enum VoronoiTiebreaker: igraph_voronoi_tiebreaker_t {
655        /// First generator.
656        First = igraph_voronoi_tiebreaker_t_IGRAPH_VORONOI_FIRST,
657        /// Last generator.
658        Last = igraph_voronoi_tiebreaker_t_IGRAPH_VORONOI_LAST,
659        /// Random generator.
660        Random = igraph_voronoi_tiebreaker_t_IGRAPH_VORONOI_RANDOM,
661    }
662}
663
664ffi_enum! {
665    /// Variant of the Chung–Lu model (`igraph_chung_lu_t`).
666    pub enum ChungLuVariant: igraph_chung_lu_t {
667        /// Original model.
668        Original = igraph_chung_lu_t_IGRAPH_CHUNG_LU_ORIGINAL,
669        /// Maximum entropy variant.
670        MaxEnt = igraph_chung_lu_t_IGRAPH_CHUNG_LU_MAXENT,
671        /// Norros–Reittu variant.
672        Nr = igraph_chung_lu_t_IGRAPH_CHUNG_LU_NR,
673    }
674}
675
676ffi_enum! {
677    /// Storage order of matrices given as flat arrays (`igraph_matrix_storage_t`).
678    pub enum MatrixStorage: igraph_matrix_storage_t {
679        /// Row-major.
680        RowMajor = igraph_matrix_storage_t_IGRAPH_ROW_MAJOR,
681        /// Column-major.
682        ColumnMajor = igraph_matrix_storage_t_IGRAPH_COLUMN_MAJOR,
683    }
684}
685
686ffi_enum! {
687    /// Minimum spanning tree algorithm (`igraph_mst_algorithm_t`).
688    pub enum MstAlgorithm: igraph_mst_algorithm_t {
689        /// Let igraph choose.
690        Automatic = igraph_mst_algorithm_t_IGRAPH_MST_AUTOMATIC,
691        /// Unweighted (BFS based).
692        Unweighted = igraph_mst_algorithm_t_IGRAPH_MST_UNWEIGHTED,
693        /// Prim's algorithm.
694        Prim = igraph_mst_algorithm_t_IGRAPH_MST_PRIM,
695        /// Kruskal's algorithm.
696        Kruskal = igraph_mst_algorithm_t_IGRAPH_MST_KRUSKAL,
697    }
698}
699
700ffi_enum! {
701    /// Kind of graph product (`igraph_product_t`).
702    pub enum Product: igraph_product_t {
703        /// Cartesian product.
704        Cartesian = igraph_product_t_IGRAPH_PRODUCT_CARTESIAN,
705        /// Lexicographic product.
706        Lexicographic = igraph_product_t_IGRAPH_PRODUCT_LEXICOGRAPHIC,
707        /// Strong product.
708        Strong = igraph_product_t_IGRAPH_PRODUCT_STRONG,
709        /// Tensor (categorical) product.
710        Tensor = igraph_product_t_IGRAPH_PRODUCT_TENSOR,
711        /// Modular product.
712        Modular = igraph_product_t_IGRAPH_PRODUCT_MODULAR,
713    }
714}
715
716ffi_enum! {
717    /// Label propagation variant (`igraph_lpa_variant_t`).
718    pub enum LpaVariant: igraph_lpa_variant_t {
719        /// Sample from the dominant labels, and check the dominance of all
720        /// vertices after each iteration.
721        Dominance = igraph_lpa_variant_t_IGRAPH_LPA_DOMINANCE,
722        /// Keep the current label if it is among the dominant ones; only
723        /// check the vertices whose labels changed.
724        Retention = igraph_lpa_variant_t_IGRAPH_LPA_RETENTION,
725        /// Sample from the dominant labels, only checking neighbors (fast).
726        Fast = igraph_lpa_variant_t_IGRAPH_LPA_FAST,
727    }
728}