networkit_rs/
graph.rs

1use std::ops::Deref;
2
3use cxx::UniquePtr;
4use miette::{bail, IntoDiagnostic, Result};
5
6use crate::bridge::{self, *};
7
8pub struct Graph {
9    pub(crate) inner: UniquePtr<bridge::Graph>,
10}
11
12unsafe impl Send for Graph {}
13
14impl Deref for Graph {
15    type Target = bridge::Graph;
16
17    fn deref(&self) -> &Self::Target {
18        &self.inner
19    }
20}
21
22impl Clone for Graph {
23    fn clone(&self) -> Self {
24        Self {
25            inner: CopyGraph(&self.inner),
26        }
27    }
28}
29
30impl From<UniquePtr<bridge::Graph>> for Graph {
31    fn from(value: UniquePtr<bridge::Graph>) -> Self {
32        Self { inner: value }
33    }
34}
35
36impl Graph {
37    pub fn new(n: u64, weighted: bool, directed: bool, edges_indexed: bool) -> Self {
38        Self {
39            inner: bridge::NewGraph(n, weighted, directed, edges_indexed),
40        }
41    }
42
43    pub fn add_edge(&mut self, u: u64, v: u64, ew: Option<f64>, check_multi_edge: bool) -> bool {
44        self.inner
45            .pin_mut()
46            .addEdge(u, v, ew.unwrap_or(1.), check_multi_edge)
47    }
48
49    pub fn add_node(&mut self) -> u64 {
50        self.inner.pin_mut().addNode()
51    }
52
53    pub fn add_nodes(&mut self, number_of_new_nodes: u64) -> u64 {
54        self.inner.pin_mut().addNodes(number_of_new_nodes)
55    }
56
57    pub fn check_consistency(&self) -> bool {
58        self.inner.checkConsistency()
59    }
60
61    pub fn compact_edges(&mut self) {
62        self.inner.pin_mut().compactEdges()
63    }
64
65    pub unsafe fn degree_unchecked(&self, v: u64) -> u64 {
66        self.inner.degree(v)
67    }
68
69    pub fn degree(&self, v: u64) -> Result<u64> {
70        if self.inner.hasNode(v) {
71            Ok(unsafe { self.inner.degree(v) })
72        } else {
73            bail!("Node {} doesn't exist", v)
74        }
75    }
76
77    pub unsafe fn degree_in_unchecked(&self, v: u64) -> u64 {
78        self.inner.degreeIn(v)
79    }
80
81    pub fn degree_in(&self, v: u64) -> Result<u64> {
82        if self.inner.hasNode(v) {
83            Ok(unsafe { self.inner.degreeIn(v) })
84        } else {
85            bail!("Node {} doesn't exist", v)
86        }
87    }
88
89    pub unsafe fn degree_out_unchecked(&self, v: u64) -> u64 {
90        self.inner.degreeOut(v)
91    }
92
93    pub fn degree_out(&self, v: u64) -> Result<u64> {
94        if self.inner.hasNode(v) {
95            Ok(unsafe { self.inner.degreeOut(v) })
96        } else {
97            bail!("Node {} doesn't exist", v)
98        }
99    }
100
101    pub fn edge_id(&self, u: u64, v: u64) -> Result<u64> {
102        unsafe { self.inner.edgeId(u, v).into_diagnostic() }
103    }
104
105    pub fn has_edge(&self, u: u64, v: u64) -> bool {
106        self.inner.hasEdge(u, v)
107    }
108
109    pub fn has_edge_ids(&self) -> bool {
110        self.inner.hasEdgeIds()
111    }
112
113    pub fn has_node(&self, v: u64) -> bool {
114        self.inner.hasNode(v)
115    }
116
117    pub unsafe fn increase_weight_unchecked(&mut self, u: u64, v: u64, ew: f64) -> Result<()> {
118        self.inner
119            .pin_mut()
120            .increaseWeight(u, v, ew)
121            .into_diagnostic()
122    }
123
124    pub fn increase_weight(&mut self, u: u64, v: u64, ew: f64) -> Result<()> {
125        if !self.inner.hasNode(u) {
126            bail!("Node {} doesn't exist", u)
127        }
128        if !self.inner.hasNode(v) {
129            bail!("Node {} doesn't exist", v)
130        }
131        unsafe {
132            self.inner
133                .pin_mut()
134                .increaseWeight(u, v, ew)
135                .into_diagnostic()
136        }
137    }
138
139    pub fn index_edges(&mut self, force: bool) {
140        self.inner.pin_mut().indexEdges(force)
141    }
142
143    pub fn is_directed(&self) -> bool {
144        self.inner.isDirected()
145    }
146
147    pub unsafe fn is_isolated_unchecked(&self, u: u64) -> Result<bool> {
148        self.inner.isIsolated(u).into_diagnostic()
149    }
150
151    pub fn is_isolated(&self, u: u64) -> Result<bool> {
152        if !self.inner.hasNode(u) {
153            bail!("Node {} doesn't exist", u)
154        }
155        self.inner.isIsolated(u).into_diagnostic()
156    }
157
158    pub fn is_weighted(&self) -> bool {
159        self.inner.isWeighted()
160    }
161
162    pub fn number_of_edges(&self) -> u64 {
163        self.inner.numberOfEdges()
164    }
165
166    pub fn number_of_nodes(&self) -> u64 {
167        self.inner.numberOfNodes()
168    }
169
170    pub fn number_of_self_loops(&self) -> u64 {
171        self.inner.numberOfSelfLoops()
172    }
173
174    pub fn remove_all_edges(&mut self) {
175        self.inner.pin_mut().removeAllEdges()
176    }
177
178    pub fn remove_edge(&mut self, u: u64, v: u64) -> Result<()> {
179        self.inner.pin_mut().removeEdge(u, v).into_diagnostic()
180    }
181
182    pub fn remove_multi_edges(&mut self) {
183        self.inner.pin_mut().removeMultiEdges()
184    }
185
186    pub unsafe fn remove_node_unchecked(&mut self, u: u64) {
187        self.inner.pin_mut().removeNode(u)
188    }
189
190    pub fn remove_node(&mut self, u: u64) -> Result<()> {
191        if !self.inner.hasNode(u) {
192            bail!("Node {} doesn't exist", u)
193        }
194        unsafe { self.inner.pin_mut().removeNode(u) };
195        Ok(())
196    }
197
198    pub fn remove_self_loops(&mut self) {
199        self.inner.pin_mut().removeSelfLoops()
200    }
201
202    pub unsafe fn restore_node_unchecked(&mut self, u: u64) {
203        self.inner.pin_mut().restoreNode(u)
204    }
205
206    pub fn restore_node(&mut self, u: u64) -> Result<()> {
207        if u >= self.inner.upperNodeIdBound() {
208            bail!("Node {} out of bound", u)
209        }
210        unsafe { self.inner.pin_mut().restoreNode(u) }
211        Ok(())
212    }
213    pub unsafe fn set_weight_unchecked(&mut self, u: u64, v: u64, ew: f64) -> Result<()> {
214        self.inner.pin_mut().setWeight(u, v, ew).into_diagnostic()
215    }
216
217    pub fn set_weight(&mut self, u: u64, v: u64, ew: f64) -> Result<()> {
218        if !self.inner.hasNode(u) {
219            bail!("Node {} doesn't exist", u)
220        }
221        if !self.inner.hasNode(v) {
222            bail!("Node {} doesn't exist", v)
223        }
224        unsafe { self.inner.pin_mut().setWeight(u, v, ew).into_diagnostic() }
225    }
226
227    pub fn sort_edges(&mut self) {
228        self.inner.pin_mut().sortEdges()
229    }
230
231    pub unsafe fn swap_edge_unchecked(&mut self, s1: u64, t1: u64, s2: u64, t2: u64) {
232        self.inner.pin_mut().swapEdge(s1, t1, s2, t2)
233    }
234
235    pub fn swap_edge(&mut self, s1: u64, t1: u64, s2: u64, t2: u64) -> Result<()> {
236        for u in [s1, t1, s2, t2] {
237            if !self.inner.hasNode(u) {
238                bail!("Node {} doesn't exist", u)
239            }
240        }
241        unsafe { self.inner.pin_mut().swapEdge(s1, t1, s2, t2) }
242        Ok(())
243    }
244    pub fn total_edge_weight(&self) -> f64 {
245        self.inner.totalEdgeWeight()
246    }
247    pub fn upper_edge_id_bound(&self) -> u64 {
248        self.inner.upperEdgeIdBound()
249    }
250    pub fn upper_node_id_bound(&self) -> u64 {
251        self.inner.upperNodeIdBound()
252    }
253
254    pub unsafe fn weight_unchecked(&self, u: u64, v: u64) -> f64 {
255        self.inner.weight(u, v)
256    }
257
258    pub fn weight(&self, u: u64, v: u64) -> Result<f64> {
259        if !self.inner.hasNode(u) {
260            bail!("Node {} doesn't exist", u)
261        }
262        if !self.inner.hasNode(v) {
263            bail!("Node {} doesn't exist", v)
264        }
265        Ok(unsafe { self.inner.weight(u, v) })
266    }
267
268    pub unsafe fn weighted_degree_unchecked(
269        self: &Graph,
270        u: u64,
271        count_self_loops_twice: bool,
272    ) -> f64 {
273        self.inner.weightedDegree(u, count_self_loops_twice)
274    }
275
276    pub fn weighted_degree(&self, u: u64, count_self_loops_twice: bool) -> Result<f64> {
277        if !self.inner.hasNode(u) {
278            bail!("Node {} doesn't exist", u)
279        }
280        Ok(unsafe { self.inner.weightedDegree(u, count_self_loops_twice) })
281    }
282    pub unsafe fn weighted_degree_in_unchecked(
283        self: &Graph,
284        u: u64,
285        count_self_loops_twice: bool,
286    ) -> f64 {
287        self.inner.weightedDegreeIn(u, count_self_loops_twice)
288    }
289
290    pub fn weighted_degree_in(&self, u: u64, count_self_loops_twice: bool) -> Result<f64> {
291        if !self.inner.hasNode(u) {
292            bail!("Node {} doesn't exist", u)
293        }
294        Ok(unsafe { self.inner.weightedDegreeIn(u, count_self_loops_twice) })
295    }
296
297    pub fn iter_nodes<'a>(&'a self) -> impl Iterator<Item = u64> + 'a {
298        struct It(UniquePtr<GraphNodeIter>);
299
300        impl Iterator for It {
301            type Item = u64;
302            fn next(&mut self) -> Option<Self::Item> {
303                let mut cur = 0;
304                if self.0.pin_mut().advance(&mut cur) {
305                    Some(cur)
306                } else {
307                    None
308                }
309            }
310        }
311
312        It(NewGraphNodeIter(&self.inner))
313    }
314    pub fn iter_edges<'a>(&'a self) -> impl Iterator<Item = (u64, u64)> + 'a {
315        struct It(UniquePtr<GraphEdgeIter>);
316
317        impl Iterator for It {
318            type Item = (u64, u64);
319            fn next(&mut self) -> Option<Self::Item> {
320                let mut src = 0;
321                let mut dst = 0;
322                if self.0.pin_mut().advance(&mut src, &mut dst) {
323                    Some((src, dst))
324                } else {
325                    None
326                }
327            }
328        }
329
330        It(NewGraphEdgeIter(&self.inner))
331    }
332
333    pub fn iter_edges_weight<'a>(&'a self) -> impl Iterator<Item = (u64, u64, f64)> + 'a {
334        struct It(UniquePtr<GraphEdgeWeightIter>);
335
336        impl Iterator for It {
337            type Item = (u64, u64, f64);
338            fn next(&mut self) -> Option<Self::Item> {
339                let mut src = 0;
340                let mut dst = 0;
341                let mut wt = 0.0;
342                if self.0.pin_mut().advance(&mut src, &mut dst, &mut wt) {
343                    Some((src, dst, wt))
344                } else {
345                    None
346                }
347            }
348        }
349
350        It(NewGraphEdgeWeightIter(&self.inner))
351    }
352    pub fn iter_neighbours<'a>(&'a self, u: u64) -> Result<impl Iterator<Item = u64> + 'a> {
353        self.iter_neighbours_impl(u, false)
354    }
355    pub fn iter_in_neighbours<'a>(&'a self, u: u64) -> Result<impl Iterator<Item = u64> + 'a> {
356        self.iter_neighbours_impl(u, true)
357    }
358    fn iter_neighbours_impl<'a>(
359        &'a self,
360        u: u64,
361        in_neighbours: bool,
362    ) -> Result<impl Iterator<Item = u64> + 'a> {
363        if !self.inner.hasNode(u) {
364            bail!("Node {} doesn't exist", u)
365        }
366
367        struct It(UniquePtr<GraphNeighbourIter>);
368        impl Iterator for It {
369            type Item = u64;
370            fn next(&mut self) -> Option<Self::Item> {
371                let mut cur = 0;
372                if self.0.pin_mut().advance(&mut cur) {
373                    Some(cur)
374                } else {
375                    None
376                }
377            }
378        }
379        Ok(It(unsafe {
380            NewGraphNeighbourIter(&self.inner, u, in_neighbours)
381        }))
382    }
383    pub fn iter_neighbours_weight<'a>(
384        &'a self,
385        u: u64,
386    ) -> Result<impl Iterator<Item = (u64, f64)> + 'a> {
387        self.iter_neighbours_weight_impl(u, false)
388    }
389    pub fn iter_in_neighbours_weight<'a>(
390        &'a self,
391        u: u64,
392    ) -> Result<impl Iterator<Item = (u64, f64)> + 'a> {
393        self.iter_neighbours_weight_impl(u, true)
394    }
395    fn iter_neighbours_weight_impl<'a>(
396        &'a self,
397        u: u64,
398        in_neighbours: bool,
399    ) -> Result<impl Iterator<Item = (u64, f64)> + 'a> {
400        if !self.inner.isWeighted() {
401            bail!("Graph is unweighted")
402        }
403        if !self.inner.hasNode(u) {
404            bail!("Node {} doesn't exist", u)
405        }
406
407        struct It(UniquePtr<GraphNeighbourWeightIter>);
408        impl Iterator for It {
409            type Item = (u64, f64);
410            fn next(&mut self) -> Option<Self::Item> {
411                let mut cur = 0;
412                let mut wt = 0.0;
413                if self.0.pin_mut().advance(&mut cur, &mut wt) {
414                    Some((cur, wt))
415                } else {
416                    None
417                }
418            }
419        }
420        Ok(It(unsafe {
421            NewGraphNeighbourWeightIter(&self.inner, u, in_neighbours).into_diagnostic()?
422        }))
423    }
424}