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}