networkit_rs/
community.rs

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// compareCommunities: not implemented in upstream
1119
1120// TODO: detectCommunities, evalCommunityDetection, inspectCommunities, kCoreCommunityDetection, readCommunities, writeCommunities