1use cxx::{CxxVector, UniquePtr};
2use miette::IntoDiagnostic;
3
4use crate::{
5 base::Algorithm,
6 bridge::{self, *},
7 coarsening::GraphCoarsening,
8 scd::SelectiveCommunityDetectorBase,
9 QualityMeasure,
10};
11use miette::Result;
12
13pub struct AdjustedRandMeasure {
14 inner: UniquePtr<bridge::AdjustedRandMeasure>,
15}
16
17impl Default for AdjustedRandMeasure {
18 fn default() -> Self {
19 Self {
20 inner: NewAdjustedRandMeasure(),
21 }
22 }
23}
24
25impl AdjustedRandMeasure {
26 pub fn get_dissimilarity(
27 &mut self,
28 g: &crate::Graph,
29 zeta: &crate::Partition,
30 eta: &crate::Partition,
31 ) -> f64 {
32 self.inner.pin_mut().getDissimilarity(g, zeta, eta)
33 }
34}
35
36pub struct ClusteringGenerator {
37 inner: UniquePtr<bridge::ClusteringGenerator>,
38}
39
40impl Default for ClusteringGenerator {
41 fn default() -> Self {
42 Self {
43 inner: NewClusteringGenerator(),
44 }
45 }
46}
47
48impl ClusteringGenerator {
49 pub fn make_continuous_balanced_clustering(
50 &mut self,
51 g: &crate::Graph,
52 k: u64,
53 ) -> crate::Partition {
54 CMMakeContinuousBalancedClustering(self.inner.pin_mut(), g, k).into()
55 }
56 pub fn make_noncontinuous_balanced_clustering(
57 &mut self,
58 g: &crate::Graph,
59 k: u64,
60 ) -> crate::Partition {
61 CMMakeNoncontinuousBalancedClustering(self.inner.pin_mut(), g, k).into()
62 }
63 pub fn make_one_clustering(&mut self, g: &crate::Graph) -> crate::Partition {
64 CMMakeOneClustering(self.inner.pin_mut(), g).into()
65 }
66 pub fn make_random_clustering(&mut self, g: &crate::Graph, k: u64) -> crate::Partition {
67 CMMakeRandomClustering(self.inner.pin_mut(), g, k).into()
68 }
69 pub fn make_singleton_clustering(&mut self, g: &crate::Graph) -> crate::Partition {
70 CMMakeSingletonClustering(self.inner.pin_mut(), g).into()
71 }
72}
73
74pub struct ValueIter {
75 pub(crate) inner: UniquePtr<CxxVector<f64>>,
76 pub(crate) at: usize,
77}
78
79impl Iterator for ValueIter {
80 type Item = f64;
81
82 fn next(&mut self) -> Option<Self::Item> {
83 match self.inner.get(self.at) {
84 Some(v) => {
85 self.at += 1;
86 Some(*v)
87 }
88 None => None,
89 }
90 }
91}
92
93pub trait LocalCommunityEvaluation: Algorithm {
94 fn get_weighted_average(&self) -> f64;
95 fn get_unweighted_average(&self) -> f64;
96 fn get_maximum_value(&self) -> f64;
97 fn get_minimum_value(&self) -> f64;
98 fn get_value(&self, i: u64) -> f64;
99 fn get_values(&self) -> ValueIter;
100 fn is_small_better(&self) -> bool;
101}
102
103pub struct CoverF1Similarity {
104 inner: UniquePtr<bridge::CoverF1Similarity>,
105}
106
107impl Algorithm for CoverF1Similarity {
108 fn run(&mut self) -> miette::Result<()> {
109 self.inner.pin_mut().run().into_diagnostic()
110 }
111
112 fn has_finished(&self) -> bool {
113 self.inner.hasFinished()
114 }
115}
116
117impl LocalCommunityEvaluation for CoverF1Similarity {
118 fn get_weighted_average(&self) -> f64 {
119 self.inner.getWeightedAverage()
120 }
121
122 fn get_unweighted_average(&self) -> f64 {
123 self.inner.getUnweightedAverage()
124 }
125
126 fn get_maximum_value(&self) -> f64 {
127 self.inner.getMaximumValue()
128 }
129
130 fn get_minimum_value(&self) -> f64 {
131 self.inner.getMinimumValue()
132 }
133
134 fn get_value(&self, i: u64) -> f64 {
135 self.inner.getValue(i)
136 }
137
138 fn get_values(&self) -> ValueIter {
139 ValueIter {
140 inner: CoverF1SimilarityGetValues(&self.inner),
141 at: 0,
142 }
143 }
144
145 fn is_small_better(&self) -> bool {
146 self.inner.isSmallBetter()
147 }
148}
149
150impl CoverF1Similarity {
151 pub fn new(g: &crate::Graph, c: &crate::Cover, reference: &crate::Cover) -> Self {
152 Self {
153 inner: NewCoverF1Similarity(g, c, reference),
154 }
155 }
156}
157
158pub struct CoverHubDominance {
159 inner: UniquePtr<bridge::CoverHubDominance>,
160}
161
162impl Algorithm for CoverHubDominance {
163 fn run(&mut self) -> miette::Result<()> {
164 self.inner.pin_mut().run().into_diagnostic()
165 }
166
167 fn has_finished(&self) -> bool {
168 self.inner.hasFinished()
169 }
170}
171
172impl LocalCommunityEvaluation for CoverHubDominance {
173 fn get_weighted_average(&self) -> f64 {
174 self.inner.getWeightedAverage()
175 }
176
177 fn get_unweighted_average(&self) -> f64 {
178 self.inner.getUnweightedAverage()
179 }
180
181 fn get_maximum_value(&self) -> f64 {
182 self.inner.getMaximumValue()
183 }
184
185 fn get_minimum_value(&self) -> f64 {
186 self.inner.getMinimumValue()
187 }
188
189 fn get_value(&self, i: u64) -> f64 {
190 self.inner.getValue(i)
191 }
192
193 fn get_values(&self) -> ValueIter {
194 ValueIter {
195 inner: CoverHubDominanceGetValues(&self.inner),
196 at: 0,
197 }
198 }
199
200 fn is_small_better(&self) -> bool {
201 self.inner.isSmallBetter()
202 }
203}
204
205impl CoverHubDominance {
206 pub fn new(g: &crate::Graph, c: &crate::Cover) -> Self {
207 Self {
208 inner: NewCoverHubDominance(g, c),
209 }
210 }
211}
212
213pub struct Coverage {
214 inner: UniquePtr<bridge::Coverage>,
215}
216
217impl Default for Coverage {
218 fn default() -> Self {
219 Self {
220 inner: NewCoverage(),
221 }
222 }
223}
224
225impl QualityMeasure for Coverage {
226 fn get_quality(&mut self, partition: &crate::Partition, graph: &crate::Graph) -> f64 {
227 self.inner.pin_mut().getQuality(partition, graph)
228 }
229}
230
231pub trait CommunityDetector: Algorithm {
232 fn get_partition(&mut self) -> crate::Partition;
233}
234
235pub struct CutClustering {
236 inner: UniquePtr<bridge::CutClustering>,
237}
238
239impl CutClustering {
240 pub fn new(g: &crate::Graph, alpha: f64) -> Self {
241 Self {
242 inner: NewCutClustering(g, alpha),
243 }
244 }
245 pub fn get_cluster_hierarchy(
246 g: &crate::Graph,
247 ) -> impl Iterator<Item = (f64, crate::Partition)> {
248 let inner = CutClusteringGetClusterHierarchy(g);
249 struct It {
250 inner: UniquePtr<HierarchyIter>,
251 }
252 impl Iterator for It {
253 type Item = (f64, crate::Partition);
254
255 fn next(&mut self) -> Option<Self::Item> {
256 if self.inner.isAtEnd() {
257 None
258 } else {
259 let k = self.inner.curKey();
260 let v = self.inner.curVal();
261 self.inner.pin_mut().advance();
262 Some((k, v.into()))
263 }
264 }
265 }
266 It { inner }
267 }
268}
269
270impl CommunityDetector for CutClustering {
271 fn get_partition(&mut self) -> crate::Partition {
272 CutClusteringGetPartition(self.inner.pin_mut()).into()
273 }
274}
275
276impl Algorithm for CutClustering {
277 fn run(&mut self) -> miette::Result<()> {
278 self.inner.pin_mut().run().into_diagnostic()
279 }
280
281 fn has_finished(&self) -> bool {
282 self.inner.hasFinished()
283 }
284}
285
286pub struct EdgeCut {
287 inner: UniquePtr<bridge::EdgeCut>,
288}
289
290impl Default for EdgeCut {
291 fn default() -> Self {
292 Self {
293 inner: NewEdgeCut(),
294 }
295 }
296}
297
298impl QualityMeasure for EdgeCut {
299 fn get_quality(&mut self, partition: &crate::Partition, graph: &crate::Graph) -> f64 {
300 self.inner.pin_mut().getQuality(partition, graph)
301 }
302}
303
304pub mod clustering_tools {
305 use crate::bridge::*;
306
307 pub fn communication_graph(g: &crate::Graph, zeta: &mut crate::Partition) -> crate::Graph {
308 MakeCommunicationGraph(g, zeta.inner.pin_mut()).into()
309 }
310
311 pub fn equal_clusterings(
312 zeta: &crate::Partition,
313 eta: &crate::Partition,
314 g: &mut crate::Graph,
315 ) -> bool {
316 equalClusterings(zeta, eta, g.inner.pin_mut())
317 }
318
319 pub fn get_imbalance(zeta: &crate::Partition) -> f32 {
320 getImbalance(zeta)
321 }
322
323 pub fn is_one_clustering(g: &crate::Graph, zeta: &crate::Partition) -> bool {
324 isOneClustering(g, zeta)
325 }
326 pub fn is_proper_clustering(g: &crate::Graph, zeta: &crate::Partition) -> bool {
327 isProperClustering(g, zeta)
328 }
329 pub fn is_singleton_clustering(g: &crate::Graph, zeta: &crate::Partition) -> bool {
330 isSingletonClustering(g, zeta)
331 }
332 pub fn weighted_degree_with_cluster(
333 g: &crate::Graph,
334 zeta: &crate::Partition,
335 u: u64,
336 cid: u64,
337 ) -> u64 {
338 weightedDegreeWithCluster(g, zeta, u, cid)
339 }
340}
341
342pub struct GraphStructuralRandMeasure {
343 inner: UniquePtr<bridge::GraphStructuralRandMeasure>,
344}
345
346impl Default for GraphStructuralRandMeasure {
347 fn default() -> Self {
348 Self {
349 inner: NewGraphStructuralRandMeasure(),
350 }
351 }
352}
353
354impl GraphStructuralRandMeasure {
355 pub fn get_dissimilarity(
356 &mut self,
357 g: &crate::Graph,
358 first: &crate::Partition,
359 second: &crate::Partition,
360 ) -> f64 {
361 self.inner.pin_mut().getDissimilarity(g, first, second)
362 }
363}
364
365pub struct HubDominance {
366 inner: UniquePtr<bridge::HubDominance>,
367}
368
369impl Default for HubDominance {
370 fn default() -> Self {
371 Self {
372 inner: NewHubDominance(),
373 }
374 }
375}
376
377impl HubDominance {
378 pub fn get_quality(&mut self, partition: &crate::Partition, graph: &crate::Graph) -> f64 {
379 self.inner.pin_mut().getQuality(partition, graph)
380 }
381 pub fn get_quality_for_cover(&mut self, cover: &crate::Cover, graph: &crate::Graph) -> f64 {
382 self.inner.pin_mut().getQualityForCover(cover, graph)
383 }
384}
385
386pub struct IntrapartitionDensity {
387 inner: UniquePtr<bridge::IntrapartitionDensity>,
388}
389
390impl IntrapartitionDensity {
391 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
392 Self {
393 inner: NewIntrapartitionDensity(g, p),
394 }
395 }
396 pub fn get_global(&self) -> f64 {
397 self.inner.getGlobal()
398 }
399}
400
401impl Algorithm for IntrapartitionDensity {
402 fn run(&mut self) -> miette::Result<()> {
403 self.inner.pin_mut().run().into_diagnostic()
404 }
405
406 fn has_finished(&self) -> bool {
407 self.inner.hasFinished()
408 }
409}
410
411impl LocalCommunityEvaluation for IntrapartitionDensity {
412 fn get_weighted_average(&self) -> f64 {
413 self.inner.getWeightedAverage()
414 }
415
416 fn get_unweighted_average(&self) -> f64 {
417 self.inner.getUnweightedAverage()
418 }
419
420 fn get_maximum_value(&self) -> f64 {
421 self.inner.getMaximumValue()
422 }
423
424 fn get_minimum_value(&self) -> f64 {
425 self.inner.getMinimumValue()
426 }
427
428 fn get_value(&self, i: u64) -> f64 {
429 self.inner.getValue(i)
430 }
431
432 fn get_values(&self) -> ValueIter {
433 ValueIter {
434 inner: IntrapartitionDensityGetValues(&self.inner),
435 at: 0,
436 }
437 }
438
439 fn is_small_better(&self) -> bool {
440 self.inner.isSmallBetter()
441 }
442}
443
444pub struct IsolatedInterpartitionConductance {
445 inner: UniquePtr<bridge::IsolatedInterpartitionConductance>,
446}
447
448impl IsolatedInterpartitionConductance {
449 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
450 Self {
451 inner: NewIsolatedInterpartitionConductance(g, p),
452 }
453 }
454}
455
456impl Algorithm for IsolatedInterpartitionConductance {
457 fn run(&mut self) -> miette::Result<()> {
458 self.inner.pin_mut().run().into_diagnostic()
459 }
460
461 fn has_finished(&self) -> bool {
462 self.inner.hasFinished()
463 }
464}
465
466impl LocalCommunityEvaluation for IsolatedInterpartitionConductance {
467 fn get_weighted_average(&self) -> f64 {
468 self.inner.getWeightedAverage()
469 }
470
471 fn get_unweighted_average(&self) -> f64 {
472 self.inner.getUnweightedAverage()
473 }
474
475 fn get_maximum_value(&self) -> f64 {
476 self.inner.getMaximumValue()
477 }
478
479 fn get_minimum_value(&self) -> f64 {
480 self.inner.getMinimumValue()
481 }
482
483 fn get_value(&self, i: u64) -> f64 {
484 self.inner.getValue(i)
485 }
486
487 fn get_values(&self) -> ValueIter {
488 ValueIter {
489 inner: IsolatedInterpartitionConductanceGetValues(&self.inner),
490 at: 0,
491 }
492 }
493
494 fn is_small_better(&self) -> bool {
495 self.inner.isSmallBetter()
496 }
497}
498
499pub struct IsolatedInterpartitionExpansion {
500 inner: UniquePtr<bridge::IsolatedInterpartitionExpansion>,
501}
502
503impl IsolatedInterpartitionExpansion {
504 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
505 Self {
506 inner: NewIsolatedInterpartitionExpansion(g, p),
507 }
508 }
509}
510
511impl Algorithm for IsolatedInterpartitionExpansion {
512 fn run(&mut self) -> miette::Result<()> {
513 self.inner.pin_mut().run().into_diagnostic()
514 }
515
516 fn has_finished(&self) -> bool {
517 self.inner.hasFinished()
518 }
519}
520
521impl LocalCommunityEvaluation for IsolatedInterpartitionExpansion {
522 fn get_weighted_average(&self) -> f64 {
523 self.inner.getWeightedAverage()
524 }
525
526 fn get_unweighted_average(&self) -> f64 {
527 self.inner.getUnweightedAverage()
528 }
529
530 fn get_maximum_value(&self) -> f64 {
531 self.inner.getMaximumValue()
532 }
533
534 fn get_minimum_value(&self) -> f64 {
535 self.inner.getMinimumValue()
536 }
537
538 fn get_value(&self, i: u64) -> f64 {
539 self.inner.getValue(i)
540 }
541
542 fn get_values(&self) -> ValueIter {
543 ValueIter {
544 inner: IsolatedInterpartitionExpansionGetValues(&self.inner),
545 at: 0,
546 }
547 }
548
549 fn is_small_better(&self) -> bool {
550 self.inner.isSmallBetter()
551 }
552}
553
554pub struct JaccardMeasure {
555 inner: UniquePtr<bridge::JaccardMeasure>,
556}
557
558impl Default for JaccardMeasure {
559 fn default() -> Self {
560 Self {
561 inner: NewJaccardMeasure(),
562 }
563 }
564}
565
566impl JaccardMeasure {
567 pub fn get_dissimilarity(
568 &mut self,
569 g: &crate::Graph,
570 zeta: &crate::Partition,
571 eta: &crate::Partition,
572 ) -> f64 {
573 self.inner.pin_mut().getDissimilarity(g, zeta, eta)
574 }
575}
576
577pub trait OverlappingCommunityDetector: Algorithm {
578 fn get_cover(&self) -> crate::Cover;
579}
580
581pub struct LFM {
582 inner: UniquePtr<bridge::LFM>,
583}
584
585impl LFM {
586 pub fn new(g: &crate::Graph, scd: &mut SelectiveCommunityDetectorBase) -> Self {
587 Self {
588 inner: NewLFM(g, scd.inner.pin_mut()),
589 }
590 }
591}
592
593impl OverlappingCommunityDetector for LFM {
594 fn get_cover(&self) -> crate::Cover {
595 LFMGetCover(&self.inner).into()
596 }
597}
598
599impl Algorithm for LFM {
600 fn run(&mut self) -> miette::Result<()> {
601 self.inner.pin_mut().run().into_diagnostic()
602 }
603
604 fn has_finished(&self) -> bool {
605 self.inner.hasFinished()
606 }
607}
608
609pub struct LPDegreeOrdered {
610 inner: UniquePtr<bridge::LPDegreeOrdered>,
611}
612
613impl LPDegreeOrdered {
614 pub fn new(g: &crate::Graph) -> Self {
615 Self {
616 inner: NewLPDegreeOrdered(g),
617 }
618 }
619 pub fn number_of_iterations(&mut self) -> u64 {
620 self.inner.pin_mut().numberOfIterations()
621 }
622}
623
624impl Algorithm for LPDegreeOrdered {
625 fn run(&mut self) -> miette::Result<()> {
626 self.inner.pin_mut().run().into_diagnostic()
627 }
628
629 fn has_finished(&self) -> bool {
630 self.inner.hasFinished()
631 }
632}
633
634impl CommunityDetector for LPDegreeOrdered {
635 fn get_partition(&mut self) -> crate::Partition {
636 LPDegreeOrderedGetPartition(self.inner.pin_mut()).into()
637 }
638}
639
640pub struct LouvainMapEquation {
641 inner: UniquePtr<bridge::LouvainMapEquation>,
642}
643
644impl LouvainMapEquation {
645 pub const RELAX_MAP: &str = "relaxmap";
646 pub const SYNCHRONOUS: &str = "synchronous";
647 pub const NONE: &str = "none";
648
649 pub fn new(
650 g: &crate::Graph,
651 hierarchical: bool,
652 max_iterations: Option<u64>,
653 parallelization_strategy: Option<&str>,
654 ) -> Self {
655 Self {
656 inner: NewLouvainMapEquation(
657 g,
658 hierarchical,
659 max_iterations.unwrap_or(32),
660 parallelization_strategy.unwrap_or(Self::RELAX_MAP),
661 ),
662 }
663 }
664}
665
666impl Algorithm for LouvainMapEquation {
667 fn run(&mut self) -> miette::Result<()> {
668 self.inner.pin_mut().run().into_diagnostic()
669 }
670
671 fn has_finished(&self) -> bool {
672 self.inner.hasFinished()
673 }
674}
675
676impl CommunityDetector for LouvainMapEquation {
677 fn get_partition(&mut self) -> crate::Partition {
678 LouvainMapEquationGetPartition(self.inner.pin_mut()).into()
679 }
680}
681
682pub struct Modularity {
683 inner: UniquePtr<bridge::Modularity>,
684}
685
686impl Default for Modularity {
687 fn default() -> Self {
688 Self {
689 inner: NewModularity(),
690 }
691 }
692}
693
694impl QualityMeasure for Modularity {
695 fn get_quality(&mut self, partition: &crate::Partition, graph: &crate::Graph) -> f64 {
696 self.inner.pin_mut().getQuality(partition, graph)
697 }
698}
699
700pub struct NMIDistance {
701 inner: UniquePtr<bridge::NMIDistance>,
702}
703
704impl Default for NMIDistance {
705 fn default() -> Self {
706 Self {
707 inner: NewNMIDistance(),
708 }
709 }
710}
711
712impl NMIDistance {
713 pub fn get_dissimilarity(
714 &mut self,
715 g: &crate::Graph,
716 zeta: &crate::Partition,
717 eta: &crate::Partition,
718 ) -> f64 {
719 self.inner.pin_mut().getDissimilarity(g, zeta, eta)
720 }
721}
722
723pub struct NodeStructuralRandMeasure {
724 inner: UniquePtr<bridge::NodeStructuralRandMeasure>,
725}
726
727impl Default for NodeStructuralRandMeasure {
728 fn default() -> Self {
729 Self {
730 inner: NewNodeStructuralRandMeasure(),
731 }
732 }
733}
734
735impl NodeStructuralRandMeasure {
736 pub fn get_dissimilarity(
737 &mut self,
738 g: &crate::Graph,
739 zeta: &crate::Partition,
740 eta: &crate::Partition,
741 ) -> f64 {
742 self.inner.pin_mut().getDissimilarity(g, zeta, eta)
743 }
744}
745
746pub struct OverlappingNMIDistance {
747 inner: UniquePtr<bridge::OverlappingNMIDistance>,
748}
749
750#[repr(u8)]
751#[derive(Default)]
752pub enum OverlappingNMIDistanceNormalization {
753 Min = 0,
754 GeometricMean = 1,
755 ArithmeticMean = 2,
756 #[default]
757 Max = 3,
758 JointEntropy = 4,
759}
760
761impl OverlappingNMIDistance {
762 pub fn new(normalization: OverlappingNMIDistanceNormalization) -> Self {
763 Self {
764 inner: NewOverlappingNMIDistance(normalization as u8),
765 }
766 }
767
768 pub fn get_dissimilarity(
769 &mut self,
770 g: &crate::Graph,
771 zeta: &crate::Partition,
772 eta: &crate::Partition,
773 ) -> f64 {
774 self.inner.pin_mut().getDissimilarity(g, zeta, eta)
775 }
776
777 pub fn get_dissimilarity_for_cover(
778 &mut self,
779 g: &crate::Graph,
780 zeta: &crate::Cover,
781 eta: &crate::Cover,
782 ) -> f64 {
783 self.inner.pin_mut().getDissimilarityForCover(g, zeta, eta)
784 }
785}
786
787pub struct PLM {
788 inner: UniquePtr<bridge::PLM>,
789}
790
791impl PLM {
792 pub const BALANCED: &str = "balanced";
793 pub const NONE: &str = "none";
794 pub const NONE_RANDOMIZED: &str = "none randomized";
795 pub const SIMPLE: &str = "simple";
796 pub fn new(
797 g: &crate::Graph,
798 refine: Option<bool>,
799 gamma: Option<f64>,
800 par: Option<&str>,
801 max_iter: Option<u64>,
802 turbo: Option<bool>,
803 recurse: Option<bool>,
804 ) -> Result<Self> {
805 Ok(Self {
806 inner: NewPLM(
807 g,
808 refine.unwrap_or(false),
809 gamma.unwrap_or(1.),
810 par.unwrap_or(Self::BALANCED),
811 max_iter.unwrap_or(32),
812 turbo.unwrap_or(true),
813 recurse.unwrap_or(true),
814 )
815 .into_diagnostic()?,
816 })
817 }
818 pub fn coarsen(g: &crate::Graph, zeta: &crate::Partition) -> (crate::Graph, Vec<u64>) {
819 let mut mapping = vec![];
820 let ret = PLMCoarsen(g, zeta, &mut mapping);
821 (ret.into(), mapping)
822 }
823 pub fn prolong(
824 g: &crate::Graph,
825 zeta_coarse: &crate::Partition,
826 g_fine: &crate::Graph,
827 node_to_meta_node: &[u64],
828 ) -> crate::Partition {
829 PLMProlong(g, zeta_coarse, g_fine, node_to_meta_node).into()
830 }
831}
832
833impl Algorithm for PLM {
834 fn run(&mut self) -> miette::Result<()> {
835 self.inner.pin_mut().run().into_diagnostic()
836 }
837
838 fn has_finished(&self) -> bool {
839 self.inner.hasFinished()
840 }
841}
842
843impl CommunityDetector for PLM {
844 fn get_partition(&mut self) -> crate::Partition {
845 PLMGetPartition(self.inner.pin_mut()).into()
846 }
847}
848
849pub struct PLP {
850 inner: UniquePtr<bridge::PLP>,
851}
852
853impl PLP {
854 pub fn new(g: &crate::Graph, theta: Option<u64>, max_iterations: Option<u64>) -> Self {
855 Self {
856 inner: NewPLP(
857 g,
858 theta.unwrap_or(u64::MAX),
859 max_iterations.unwrap_or(u64::MAX),
860 ),
861 }
862 }
863 pub fn number_of_iterations(&mut self) -> u64 {
864 self.inner.pin_mut().numberOfIterations()
865 }
866}
867
868impl Algorithm for PLP {
869 fn run(&mut self) -> miette::Result<()> {
870 self.inner.pin_mut().run().into_diagnostic()
871 }
872
873 fn has_finished(&self) -> bool {
874 self.inner.hasFinished()
875 }
876}
877
878impl CommunityDetector for PLP {
879 fn get_partition(&mut self) -> crate::Partition {
880 PLPGetPartition(self.inner.pin_mut()).into()
881 }
882}
883
884pub struct ParallelLeiden {
885 inner: UniquePtr<bridge::ParallelLeiden>,
886}
887
888impl ParallelLeiden {
889 pub fn new(
890 g: &crate::Graph,
891 iterations: Option<u64>,
892 randomize: Option<bool>,
893 gamma: Option<f64>,
894 ) -> Self {
895 Self {
896 inner: NewParallelLeiden(
897 g,
898 iterations.unwrap_or(u64::MAX),
899 randomize.unwrap_or(true),
900 gamma.unwrap_or(1.0),
901 ),
902 }
903 }
904}
905
906impl Algorithm for ParallelLeiden {
907 fn run(&mut self) -> miette::Result<()> {
908 self.inner.pin_mut().run().into_diagnostic()
909 }
910
911 fn has_finished(&self) -> bool {
912 self.inner.hasFinished()
913 }
914}
915
916impl CommunityDetector for ParallelLeiden {
917 fn get_partition(&mut self) -> crate::Partition {
918 ParallelLeidenGetPartition(self.inner.pin_mut()).into()
919 }
920}
921
922pub struct PartitionFragmentation {
923 inner: UniquePtr<bridge::PartitionFragmentation>,
924}
925
926impl Algorithm for PartitionFragmentation {
927 fn run(&mut self) -> miette::Result<()> {
928 self.inner.pin_mut().run().into_diagnostic()
929 }
930
931 fn has_finished(&self) -> bool {
932 self.inner.hasFinished()
933 }
934}
935
936impl LocalCommunityEvaluation for PartitionFragmentation {
937 fn get_weighted_average(&self) -> f64 {
938 self.inner.getWeightedAverage()
939 }
940
941 fn get_unweighted_average(&self) -> f64 {
942 self.inner.getUnweightedAverage()
943 }
944
945 fn get_maximum_value(&self) -> f64 {
946 self.inner.getMaximumValue()
947 }
948
949 fn get_minimum_value(&self) -> f64 {
950 self.inner.getMinimumValue()
951 }
952
953 fn get_value(&self, i: u64) -> f64 {
954 self.inner.getValue(i)
955 }
956
957 fn get_values(&self) -> ValueIter {
958 ValueIter {
959 inner: PartitionFragmentationGetValues(&self.inner),
960 at: 0,
961 }
962 }
963
964 fn is_small_better(&self) -> bool {
965 self.inner.isSmallBetter()
966 }
967}
968
969impl PartitionFragmentation {
970 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
971 Self {
972 inner: NewPartitionFragmentation(g, p),
973 }
974 }
975}
976
977pub struct PartitionHubDominance {
978 inner: UniquePtr<bridge::PartitionHubDominance>,
979}
980
981impl Algorithm for PartitionHubDominance {
982 fn run(&mut self) -> miette::Result<()> {
983 self.inner.pin_mut().run().into_diagnostic()
984 }
985
986 fn has_finished(&self) -> bool {
987 self.inner.hasFinished()
988 }
989}
990
991impl LocalCommunityEvaluation for PartitionHubDominance {
992 fn get_weighted_average(&self) -> f64 {
993 self.inner.getWeightedAverage()
994 }
995
996 fn get_unweighted_average(&self) -> f64 {
997 self.inner.getUnweightedAverage()
998 }
999
1000 fn get_maximum_value(&self) -> f64 {
1001 self.inner.getMaximumValue()
1002 }
1003
1004 fn get_minimum_value(&self) -> f64 {
1005 self.inner.getMinimumValue()
1006 }
1007
1008 fn get_value(&self, i: u64) -> f64 {
1009 self.inner.getValue(i)
1010 }
1011
1012 fn get_values(&self) -> ValueIter {
1013 ValueIter {
1014 inner: PartitionHubDominanceGetValues(&self.inner),
1015 at: 0,
1016 }
1017 }
1018
1019 fn is_small_better(&self) -> bool {
1020 self.inner.isSmallBetter()
1021 }
1022}
1023
1024impl PartitionHubDominance {
1025 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
1026 Self {
1027 inner: NewPartitionHubDominance(g, p),
1028 }
1029 }
1030}
1031
1032pub struct PartitionIntersection {
1033 inner: UniquePtr<bridge::PartitionIntersection>,
1034}
1035
1036impl Default for PartitionIntersection {
1037 fn default() -> Self {
1038 Self {
1039 inner: NewPartitionIntersection(),
1040 }
1041 }
1042}
1043
1044impl PartitionIntersection {
1045 pub fn calculate(
1046 &mut self,
1047 zeta: &crate::Partition,
1048 eta: &crate::Partition,
1049 ) -> crate::Partition {
1050 PartitionIntersectionCalculate(self.inner.pin_mut(), zeta, eta).into()
1051 }
1052}
1053
1054pub struct StablePartitionNodes {
1055 inner: UniquePtr<bridge::StablePartitionNodes>,
1056}
1057
1058impl Algorithm for StablePartitionNodes {
1059 fn run(&mut self) -> miette::Result<()> {
1060 self.inner.pin_mut().run().into_diagnostic()
1061 }
1062
1063 fn has_finished(&self) -> bool {
1064 self.inner.hasFinished()
1065 }
1066}
1067
1068impl LocalCommunityEvaluation for StablePartitionNodes {
1069 fn get_weighted_average(&self) -> f64 {
1070 self.inner.getWeightedAverage()
1071 }
1072
1073 fn get_unweighted_average(&self) -> f64 {
1074 self.inner.getUnweightedAverage()
1075 }
1076
1077 fn get_maximum_value(&self) -> f64 {
1078 self.inner.getMaximumValue()
1079 }
1080
1081 fn get_minimum_value(&self) -> f64 {
1082 self.inner.getMinimumValue()
1083 }
1084
1085 fn get_value(&self, i: u64) -> f64 {
1086 self.inner.getValue(i)
1087 }
1088
1089 fn get_values(&self) -> ValueIter {
1090 ValueIter {
1091 inner: StablePartitionNodesGetValues(&self.inner),
1092 at: 0,
1093 }
1094 }
1095
1096 fn is_small_better(&self) -> bool {
1097 self.inner.isSmallBetter()
1098 }
1099}
1100
1101impl StablePartitionNodes {
1102 pub fn new(g: &crate::Graph, p: &crate::Partition) -> Self {
1103 Self {
1104 inner: NewStablePartitionNodes(g, p),
1105 }
1106 }
1107 pub fn is_stable(&self, u: u64) -> bool {
1108 self.inner.isStable(u)
1109 }
1110}
1111
1112pub fn community_graph(g: &crate::Graph, zeta: &crate::Partition) -> Result<crate::Graph> {
1113 let mut cg = crate::coarsening::ParallelPartitionCoarsening::new(g, zeta, true);
1114 cg.run()?;
1115 Ok(cg.get_coarse_graph())
1116}
1117
1118