1use std::{fmt, sync::Arc};
3
4use arrow::datatypes::DataType;
5
6use super::{
7 Field, GraphAlgorithmParams, GraphBetweennessCentralityParams, GraphBfsParams, GraphCoreNumberParams,
8 GraphDegreesAllParams, GraphEcgParams, GraphEdgeBetweennessCentralityParams, GraphEigenvectorCentralityParams,
9 GraphForceAtlas2Params, GraphHitsParams, GraphInDegreesAllParams, GraphKCoreParams, GraphKatzCentralityParams,
10 GraphLayoutRequirement, GraphLeidenParams, GraphLouvainParams, GraphMstParams, GraphOutDegreesAllParams,
11 GraphPageRankParams, GraphPersonalizedPageRankParams, GraphSccParams, GraphSimilarityParams,
12 GraphSpectralClusteringParams, GraphSsspParams, GraphSsspSource, GraphTriangleCountAllParams, GraphWccParams,
13 Schema, SchemaRef, stable_graph_result_schema,
14};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
21pub enum GraphAlgorithm {
22 PageRank,
24 PersonalizedPageRank,
26 Bfs,
28 Louvain,
30 EigenvectorCentrality,
32 KatzCentrality,
34 Hits,
36 BetweennessCentrality,
38 EdgeBetweennessCentrality,
40 Sssp,
42 DegreesAll,
45 InDegreesAll,
47 OutDegreesAll,
49 WeaklyConnectedComponents,
51 StronglyConnectedComponents,
53 TriangleCountAll,
55 CoreNumber,
57 KCore,
59 MinimumSpanningTree,
61 Leiden,
63 Ecg,
66 SpectralModularityMaximization,
68 ForceAtlas2,
71 Jaccard,
74 Sorensen,
77 Overlap,
80 Cosine,
83}
84
85impl GraphAlgorithm {
86 pub const fn as_str(self) -> &'static str {
88 match self {
89 Self::PageRank => "pagerank",
90 Self::PersonalizedPageRank => "personalized_pagerank",
91 Self::Bfs => "bfs",
92 Self::Louvain => "louvain",
93 Self::EigenvectorCentrality => "eigenvector_centrality",
94 Self::KatzCentrality => "katz_centrality",
95 Self::Hits => "hits",
96 Self::BetweennessCentrality => "betweenness_centrality",
97 Self::EdgeBetweennessCentrality => "edge_betweenness_centrality",
98 Self::Sssp => "sssp",
99 Self::DegreesAll => "degrees_all",
100 Self::InDegreesAll => "in_degrees_all",
101 Self::OutDegreesAll => "out_degrees_all",
102 Self::WeaklyConnectedComponents => "weakly_connected_components",
103 Self::StronglyConnectedComponents => "strongly_connected_components",
104 Self::TriangleCountAll => "triangle_count_all",
105 Self::CoreNumber => "core_number",
106 Self::KCore => "k_core",
107 Self::MinimumSpanningTree => "minimum_spanning_tree",
108 Self::Leiden => "leiden",
109 Self::Ecg => "ecg",
110 Self::SpectralModularityMaximization => "spectral_modularity_maximization",
111 Self::ForceAtlas2 => "force_atlas2",
112 Self::Jaccard => "jaccard",
113 Self::Sorensen => "sorensen",
114 Self::Overlap => "overlap",
115 Self::Cosine => "cosine",
116 }
117 }
118
119 pub const fn is_similarity(self) -> bool {
121 matches!(self, Self::Jaccard | Self::Sorensen | Self::Overlap | Self::Cosine)
122 }
123
124 pub fn definition(self) -> &'static GraphOperationDefinition {
131 GRAPH_OPERATION_REGISTRY
132 .iter()
133 .find(|def| def.algorithm == self)
134 .expect("graph operation registry is missing an algorithm variant")
135 }
136
137 pub fn all() -> impl ExactSizeIterator<Item = Self> + Clone {
139 GRAPH_OPERATION_REGISTRY.iter().map(|def| def.algorithm)
140 }
141
142 pub fn consumes_weight(self) -> bool {
147 self.definition().weight_policy().consumes_weight()
148 }
149
150 pub fn requires_source_vertex(self) -> bool {
152 self.definition().source_vertex_requirement().requires_source_vertex()
153 }
154
155 pub fn weight_policy(self) -> GraphWeightPolicy {
157 self.definition().weight_policy()
158 }
159
160 pub fn output_schema_kind(self) -> GraphOutputSchemaKind {
162 self.definition().output_schema_kind()
163 }
164
165 pub fn vertex_id_type_support(self) -> GraphVertexIdTypeSupport {
167 self.definition().vertex_id_type_support()
168 }
169}
170
171impl fmt::Display for GraphAlgorithm {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 f.write_str(self.as_str())
174 }
175}
176
177#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
179pub enum GraphVertexIdTypeSupport {
180 Int32OrInt64,
182 Int32OnlyLegacyEdgeType,
186}
187
188impl GraphVertexIdTypeSupport {
189 pub(crate) const fn as_str(self) -> &'static str {
191 match self {
192 Self::Int32OrInt64 => "int32_or_int64",
193 Self::Int32OnlyLegacyEdgeType => "int32_only_legacy_edge_type",
194 }
195 }
196
197 pub const fn supported_dtypes_label(self) -> &'static str {
199 match self {
200 Self::Int32OrInt64 => "Int32|Int64",
201 Self::Int32OnlyLegacyEdgeType => "Int32",
202 }
203 }
204
205 pub fn accepts_arrow_data_type(self, data_type: &DataType) -> bool {
207 match self {
208 Self::Int32OrInt64 => matches!(data_type, DataType::Int32 | DataType::Int64),
209 Self::Int32OnlyLegacyEdgeType => matches!(data_type, DataType::Int32),
210 }
211 }
212}
213
214impl fmt::Display for GraphVertexIdTypeSupport {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 f.write_str(self.as_str())
217 }
218}
219
220#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
222pub enum GraphSourceVertexRequirement {
223 None,
225 Required,
227}
228
229impl GraphSourceVertexRequirement {
230 pub const fn requires_source_vertex(self) -> bool {
232 matches!(self, Self::Required)
233 }
234}
235
236#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
238pub enum GraphWeightPolicy {
239 Ignored,
242 Optional,
245 Required,
247}
248
249impl GraphWeightPolicy {
250 pub const fn consumes_weight(self) -> bool {
253 matches!(self, Self::Optional | Self::Required)
254 }
255
256 pub const fn requires_weight(self) -> bool {
258 matches!(self, Self::Required)
259 }
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
264pub enum GraphOutputSchemaKind {
265 Fixed,
267 DefaultMode,
270}
271
272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
279pub struct EmptyGraphInputPolicy {
280 pub edge_input: EmptyGraphEdgeInputAction,
282 pub side_inputs: EmptyGraphSideInputPolicy,
284}
285
286impl EmptyGraphInputPolicy {
287 const RETURN_EMPTY: Self =
288 Self { edge_input: EmptyGraphEdgeInputAction::ReturnEmpty, side_inputs: EmptyGraphSideInputPolicy::None };
289 const VALIDATE_SELECTORS_THEN_RETURN_EMPTY: Self = Self {
290 edge_input: EmptyGraphEdgeInputAction::ValidateSelectorsThenReturnEmpty,
291 side_inputs: EmptyGraphSideInputPolicy::None,
292 };
293 const REQUIRE_GRAPH: Self =
294 Self { edge_input: EmptyGraphEdgeInputAction::Reject, side_inputs: EmptyGraphSideInputPolicy::None };
295 const REQUIRE_GRAPH_AND_PERSONALIZATION: Self = Self {
296 edge_input: EmptyGraphEdgeInputAction::Reject,
297 side_inputs: EmptyGraphSideInputPolicy::RequirePersonalization,
298 };
299 const SIMILARITY: Self = Self {
300 edge_input: EmptyGraphEdgeInputAction::SimilarityVertexPairs,
301 side_inputs: EmptyGraphSideInputPolicy::RequireVertexPairs,
302 };
303 const BFS: Self = Self {
304 edge_input: EmptyGraphEdgeInputAction::BfsEndpointPolicy,
305 side_inputs: EmptyGraphSideInputPolicy::BfsPredicates,
306 };
307}
308
309#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
311pub enum EmptyGraphEdgeInputAction {
312 ReturnEmpty,
314 ValidateSelectorsThenReturnEmpty,
317 Reject,
319 BfsEndpointPolicy,
321 SimilarityVertexPairs,
324}
325
326impl EmptyGraphEdgeInputAction {
327 pub const fn as_str(self) -> &'static str {
329 match self {
330 Self::ReturnEmpty => "return_empty",
331 Self::ValidateSelectorsThenReturnEmpty => "validate_selectors_then_return_empty",
332 Self::Reject => "reject",
333 Self::BfsEndpointPolicy => "bfs_endpoint_policy",
334 Self::SimilarityVertexPairs => "similarity_vertex_pairs",
335 }
336 }
337}
338
339#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
341pub enum EmptyGraphSideInputPolicy {
342 None,
344 RequirePersonalization,
346 BfsPredicates,
349 RequireVertexPairs,
351}
352
353impl EmptyGraphSideInputPolicy {
354 pub const fn as_str(self) -> &'static str {
356 match self {
357 Self::None => "none",
358 Self::RequirePersonalization => "require_personalization",
359 Self::BfsPredicates => "bfs_predicates",
360 Self::RequireVertexPairs => "require_vertex_pairs",
361 }
362 }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
372pub struct GraphOperationDefinition {
373 pub algorithm: GraphAlgorithm,
375 pub name: &'static str,
378 pub layout_requirement: GraphLayoutRequirement,
380 pub empty_input_policy: EmptyGraphInputPolicy,
382}
383
384impl GraphOperationDefinition {
385 pub(crate) const fn vertex_output_columns(&self) -> &'static [&'static str] {
387 match self.algorithm {
388 GraphAlgorithm::Bfs => &["vertex", "predecessor", "source", "target"],
389 GraphAlgorithm::Sssp => &["vertex", "predecessor"],
390 GraphAlgorithm::EdgeBetweennessCentrality => &["src", "dst"],
391 GraphAlgorithm::KCore | GraphAlgorithm::MinimumSpanningTree => &["src", "dst"],
392 GraphAlgorithm::Jaccard | GraphAlgorithm::Sorensen | GraphAlgorithm::Overlap | GraphAlgorithm::Cosine => {
393 &["first", "second"]
394 },
395 GraphAlgorithm::PageRank
396 | GraphAlgorithm::PersonalizedPageRank
397 | GraphAlgorithm::Louvain
398 | GraphAlgorithm::EigenvectorCentrality
399 | GraphAlgorithm::KatzCentrality
400 | GraphAlgorithm::Hits
401 | GraphAlgorithm::BetweennessCentrality
402 | GraphAlgorithm::DegreesAll
403 | GraphAlgorithm::InDegreesAll
404 | GraphAlgorithm::OutDegreesAll
405 | GraphAlgorithm::WeaklyConnectedComponents
406 | GraphAlgorithm::StronglyConnectedComponents
407 | GraphAlgorithm::TriangleCountAll
408 | GraphAlgorithm::CoreNumber
409 | GraphAlgorithm::Leiden
410 | GraphAlgorithm::Ecg
411 | GraphAlgorithm::SpectralModularityMaximization
412 | GraphAlgorithm::ForceAtlas2 => &["vertex"],
413 }
414 }
415
416 pub const fn source_vertex_requirement(&self) -> GraphSourceVertexRequirement {
418 match self.algorithm {
419 GraphAlgorithm::Bfs | GraphAlgorithm::Sssp => GraphSourceVertexRequirement::Required,
420 _ => GraphSourceVertexRequirement::None,
421 }
422 }
423
424 pub const fn weight_policy(&self) -> GraphWeightPolicy {
426 match self.algorithm {
427 GraphAlgorithm::MinimumSpanningTree => GraphWeightPolicy::Required,
428 GraphAlgorithm::PageRank
429 | GraphAlgorithm::PersonalizedPageRank
430 | GraphAlgorithm::Sssp
431 | GraphAlgorithm::ForceAtlas2
432 | GraphAlgorithm::Jaccard
433 | GraphAlgorithm::Sorensen
434 | GraphAlgorithm::Overlap
435 | GraphAlgorithm::Cosine => GraphWeightPolicy::Optional,
436 _ => GraphWeightPolicy::Ignored,
437 }
438 }
439
440 pub const fn output_schema_kind(&self) -> GraphOutputSchemaKind {
442 match self.algorithm {
443 GraphAlgorithm::Bfs => GraphOutputSchemaKind::DefaultMode,
444 _ => GraphOutputSchemaKind::Fixed,
445 }
446 }
447
448 pub(crate) const fn output_vertex_is_unique(&self) -> bool {
450 matches!(
451 self.algorithm,
452 GraphAlgorithm::PageRank
453 | GraphAlgorithm::PersonalizedPageRank
454 | GraphAlgorithm::Bfs
455 | GraphAlgorithm::Louvain
456 | GraphAlgorithm::EigenvectorCentrality
457 | GraphAlgorithm::KatzCentrality
458 | GraphAlgorithm::Hits
459 | GraphAlgorithm::BetweennessCentrality
460 | GraphAlgorithm::Sssp
461 | GraphAlgorithm::DegreesAll
462 | GraphAlgorithm::InDegreesAll
463 | GraphAlgorithm::OutDegreesAll
464 | GraphAlgorithm::WeaklyConnectedComponents
465 | GraphAlgorithm::StronglyConnectedComponents
466 | GraphAlgorithm::TriangleCountAll
467 | GraphAlgorithm::CoreNumber
468 | GraphAlgorithm::Leiden
469 | GraphAlgorithm::Ecg
470 | GraphAlgorithm::SpectralModularityMaximization
471 | GraphAlgorithm::ForceAtlas2
472 )
473 }
474
475 pub const fn required_graph_directedness(&self) -> Option<bool> {
478 match self.algorithm {
479 GraphAlgorithm::WeaklyConnectedComponents
480 | GraphAlgorithm::MinimumSpanningTree
481 | GraphAlgorithm::SpectralModularityMaximization
482 | GraphAlgorithm::Jaccard
483 | GraphAlgorithm::Sorensen
484 | GraphAlgorithm::Overlap
485 | GraphAlgorithm::Cosine => Some(false),
486 GraphAlgorithm::StronglyConnectedComponents => Some(true),
487 _ => None,
488 }
489 }
490
491 pub(crate) const fn vertex_id_type_support(&self) -> GraphVertexIdTypeSupport {
492 match self.algorithm {
493 GraphAlgorithm::MinimumSpanningTree | GraphAlgorithm::SpectralModularityMaximization => {
494 GraphVertexIdTypeSupport::Int32OnlyLegacyEdgeType
495 },
496 _ => GraphVertexIdTypeSupport::Int32OrInt64,
497 }
498 }
499
500 pub const fn empty_input_policy(&self) -> EmptyGraphInputPolicy {
502 self.empty_input_policy
503 }
504
505 pub fn output_schema(&self) -> SchemaRef {
510 stable_graph_result_schema(self.algorithm)
511 }
512
513 pub fn base_result_schema(&self) -> SchemaRef {
515 stable_graph_result_schema(self.algorithm)
516 }
517
518 pub fn default_graph_options(&self, defaults: &GraphConstructionOptions) -> GraphConstructionOptions {
520 let mut options = defaults.clone();
521 if matches!(
522 self.algorithm,
523 GraphAlgorithm::Louvain
524 | GraphAlgorithm::WeaklyConnectedComponents
525 | GraphAlgorithm::TriangleCountAll
526 | GraphAlgorithm::CoreNumber
527 | GraphAlgorithm::KCore
528 | GraphAlgorithm::MinimumSpanningTree
529 | GraphAlgorithm::Leiden
530 | GraphAlgorithm::Ecg
531 | GraphAlgorithm::SpectralModularityMaximization
532 | GraphAlgorithm::ForceAtlas2
533 | GraphAlgorithm::Jaccard
534 | GraphAlgorithm::Sorensen
535 | GraphAlgorithm::Overlap
536 | GraphAlgorithm::Cosine
537 ) {
538 options.directed = false;
539 }
540 options
541 }
542
543 pub fn default_params(&self) -> GraphAlgorithmParams {
548 match self.algorithm {
549 GraphAlgorithm::PageRank => GraphAlgorithmParams::PageRank(GraphPageRankParams::default()),
550 GraphAlgorithm::PersonalizedPageRank => {
551 GraphAlgorithmParams::PersonalizedPageRank(GraphPersonalizedPageRankParams::default())
552 },
553 GraphAlgorithm::Bfs => GraphAlgorithmParams::Bfs(Box::new(GraphBfsParams::new(0, None))),
554 GraphAlgorithm::Louvain => GraphAlgorithmParams::Louvain(GraphLouvainParams::default()),
555 GraphAlgorithm::EigenvectorCentrality => {
556 GraphAlgorithmParams::EigenvectorCentrality(GraphEigenvectorCentralityParams::default())
557 },
558 GraphAlgorithm::KatzCentrality => {
559 GraphAlgorithmParams::KatzCentrality(GraphKatzCentralityParams::default())
560 },
561 GraphAlgorithm::Hits => GraphAlgorithmParams::Hits(GraphHitsParams::default()),
562 GraphAlgorithm::BetweennessCentrality => {
563 GraphAlgorithmParams::BetweennessCentrality(GraphBetweennessCentralityParams::default())
564 },
565 GraphAlgorithm::EdgeBetweennessCentrality => {
566 GraphAlgorithmParams::EdgeBetweennessCentrality(GraphEdgeBetweennessCentralityParams::default())
567 },
568 GraphAlgorithm::Sssp => {
569 GraphAlgorithmParams::Sssp(GraphSsspParams { source_vertex: GraphSsspSource::I64(0), cutoff: None })
570 },
571 GraphAlgorithm::DegreesAll => GraphAlgorithmParams::DegreesAll(GraphDegreesAllParams),
572 GraphAlgorithm::InDegreesAll => GraphAlgorithmParams::InDegreesAll(GraphInDegreesAllParams),
573 GraphAlgorithm::OutDegreesAll => GraphAlgorithmParams::OutDegreesAll(GraphOutDegreesAllParams),
574 GraphAlgorithm::WeaklyConnectedComponents => {
575 GraphAlgorithmParams::WeaklyConnectedComponents(GraphWccParams)
576 },
577 GraphAlgorithm::StronglyConnectedComponents => {
578 GraphAlgorithmParams::StronglyConnectedComponents(GraphSccParams)
579 },
580 GraphAlgorithm::TriangleCountAll => GraphAlgorithmParams::TriangleCountAll(GraphTriangleCountAllParams),
581 GraphAlgorithm::CoreNumber => GraphAlgorithmParams::CoreNumber(GraphCoreNumberParams::default()),
582 GraphAlgorithm::KCore => GraphAlgorithmParams::KCore(GraphKCoreParams::default()),
583 GraphAlgorithm::MinimumSpanningTree => GraphAlgorithmParams::MinimumSpanningTree(GraphMstParams),
584 GraphAlgorithm::Leiden => GraphAlgorithmParams::Leiden(GraphLeidenParams::default()),
585 GraphAlgorithm::Ecg => GraphAlgorithmParams::Ecg(GraphEcgParams::default()),
586 GraphAlgorithm::SpectralModularityMaximization => {
587 GraphAlgorithmParams::SpectralModularityMaximization(GraphSpectralClusteringParams::default())
588 },
589 GraphAlgorithm::ForceAtlas2 => GraphAlgorithmParams::ForceAtlas2(GraphForceAtlas2Params::default()),
590 GraphAlgorithm::Jaccard | GraphAlgorithm::Sorensen | GraphAlgorithm::Overlap | GraphAlgorithm::Cosine => {
591 GraphAlgorithmParams::Similarity(GraphSimilarityParams::default())
592 },
593 }
594 }
595
596 pub fn result_schema_for_params(&self, params: &GraphAlgorithmParams) -> SchemaRef {
602 assert!(params.supports_algorithm(self.algorithm), "graph algorithm and parameter variant must match");
603 if let GraphAlgorithmParams::Bfs(params) = params
604 && params.path_output.is_some()
605 {
606 return Arc::new(Schema::new(vec![
607 Field::new("path_index", DataType::Int64, false),
608 Field::new("source", DataType::Int64, false),
609 Field::new("target", DataType::Int64, false),
610 Field::new("vertex", DataType::Int64, false),
611 Field::new("distance", DataType::Int64, false),
612 ]));
613 }
614 self.base_result_schema()
615 }
616}
617
618pub const GRAPH_OPERATION_REGISTRY: &[GraphOperationDefinition] = &[
623 GraphOperationDefinition {
624 algorithm: GraphAlgorithm::PageRank,
625 name: "pagerank",
626 layout_requirement: GraphLayoutRequirement::Transposed,
627 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
628 },
629 GraphOperationDefinition {
630 algorithm: GraphAlgorithm::Bfs,
631 name: "bfs",
632 layout_requirement: GraphLayoutRequirement::Forward,
633 empty_input_policy: EmptyGraphInputPolicy::BFS,
634 },
635 GraphOperationDefinition {
636 algorithm: GraphAlgorithm::Louvain,
637 name: "louvain",
638 layout_requirement: GraphLayoutRequirement::Forward,
639 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
640 },
641 GraphOperationDefinition {
642 algorithm: GraphAlgorithm::EigenvectorCentrality,
643 name: "eigenvector_centrality",
644 layout_requirement: GraphLayoutRequirement::Transposed,
645 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
646 },
647 GraphOperationDefinition {
648 algorithm: GraphAlgorithm::KatzCentrality,
649 name: "katz_centrality",
650 layout_requirement: GraphLayoutRequirement::Transposed,
651 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
652 },
653 GraphOperationDefinition {
654 algorithm: GraphAlgorithm::Hits,
655 name: "hits",
656 layout_requirement: GraphLayoutRequirement::Transposed,
657 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
658 },
659 GraphOperationDefinition {
660 algorithm: GraphAlgorithm::BetweennessCentrality,
661 name: "betweenness_centrality",
662 layout_requirement: GraphLayoutRequirement::Any,
663 empty_input_policy: EmptyGraphInputPolicy::VALIDATE_SELECTORS_THEN_RETURN_EMPTY,
664 },
665 GraphOperationDefinition {
666 algorithm: GraphAlgorithm::EdgeBetweennessCentrality,
667 name: "edge_betweenness_centrality",
668 layout_requirement: GraphLayoutRequirement::Any,
669 empty_input_policy: EmptyGraphInputPolicy::VALIDATE_SELECTORS_THEN_RETURN_EMPTY,
670 },
671 GraphOperationDefinition {
672 algorithm: GraphAlgorithm::Sssp,
673 name: "sssp",
674 layout_requirement: GraphLayoutRequirement::Forward,
675 empty_input_policy: EmptyGraphInputPolicy::REQUIRE_GRAPH,
676 },
677 GraphOperationDefinition {
678 algorithm: GraphAlgorithm::DegreesAll,
679 name: "degrees_all",
680 layout_requirement: GraphLayoutRequirement::Transposed,
681 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
682 },
683 GraphOperationDefinition {
684 algorithm: GraphAlgorithm::InDegreesAll,
685 name: "in_degrees_all",
686 layout_requirement: GraphLayoutRequirement::Transposed,
687 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
688 },
689 GraphOperationDefinition {
690 algorithm: GraphAlgorithm::OutDegreesAll,
691 name: "out_degrees_all",
692 layout_requirement: GraphLayoutRequirement::Any,
693 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
694 },
695 GraphOperationDefinition {
696 algorithm: GraphAlgorithm::WeaklyConnectedComponents,
697 name: "weakly_connected_components",
698 layout_requirement: GraphLayoutRequirement::Any,
699 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
700 },
701 GraphOperationDefinition {
702 algorithm: GraphAlgorithm::StronglyConnectedComponents,
703 name: "strongly_connected_components",
704 layout_requirement: GraphLayoutRequirement::Any,
705 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
706 },
707 GraphOperationDefinition {
708 algorithm: GraphAlgorithm::TriangleCountAll,
709 name: "triangle_count_all",
710 layout_requirement: GraphLayoutRequirement::Any,
711 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
712 },
713 GraphOperationDefinition {
714 algorithm: GraphAlgorithm::CoreNumber,
715 name: "core_number",
716 layout_requirement: GraphLayoutRequirement::Any,
717 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
718 },
719 GraphOperationDefinition {
720 algorithm: GraphAlgorithm::KCore,
721 name: "k_core",
722 layout_requirement: GraphLayoutRequirement::Any,
723 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
724 },
725 GraphOperationDefinition {
726 algorithm: GraphAlgorithm::MinimumSpanningTree,
727 name: "minimum_spanning_tree",
728 layout_requirement: GraphLayoutRequirement::Any,
729 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
730 },
731 GraphOperationDefinition {
732 algorithm: GraphAlgorithm::PersonalizedPageRank,
733 name: "personalized_pagerank",
734 layout_requirement: GraphLayoutRequirement::Transposed,
735 empty_input_policy: EmptyGraphInputPolicy::REQUIRE_GRAPH_AND_PERSONALIZATION,
736 },
737 GraphOperationDefinition {
738 algorithm: GraphAlgorithm::Leiden,
739 name: "leiden",
740 layout_requirement: GraphLayoutRequirement::Forward,
741 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
742 },
743 GraphOperationDefinition {
744 algorithm: GraphAlgorithm::Ecg,
745 name: "ecg",
746 layout_requirement: GraphLayoutRequirement::Forward,
747 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
748 },
749 GraphOperationDefinition {
750 algorithm: GraphAlgorithm::SpectralModularityMaximization,
751 name: "spectral_modularity_maximization",
752 layout_requirement: GraphLayoutRequirement::Forward,
753 empty_input_policy: EmptyGraphInputPolicy::REQUIRE_GRAPH,
754 },
755 GraphOperationDefinition {
756 algorithm: GraphAlgorithm::ForceAtlas2,
757 name: "force_atlas2",
758 layout_requirement: GraphLayoutRequirement::Any,
759 empty_input_policy: EmptyGraphInputPolicy::RETURN_EMPTY,
760 },
761 GraphOperationDefinition {
762 algorithm: GraphAlgorithm::Jaccard,
763 name: "jaccard",
764 layout_requirement: GraphLayoutRequirement::Any,
765 empty_input_policy: EmptyGraphInputPolicy::SIMILARITY,
766 },
767 GraphOperationDefinition {
768 algorithm: GraphAlgorithm::Sorensen,
769 name: "sorensen",
770 layout_requirement: GraphLayoutRequirement::Any,
771 empty_input_policy: EmptyGraphInputPolicy::SIMILARITY,
772 },
773 GraphOperationDefinition {
774 algorithm: GraphAlgorithm::Overlap,
775 name: "overlap",
776 layout_requirement: GraphLayoutRequirement::Any,
777 empty_input_policy: EmptyGraphInputPolicy::SIMILARITY,
778 },
779 GraphOperationDefinition {
780 algorithm: GraphAlgorithm::Cosine,
781 name: "cosine",
782 layout_requirement: GraphLayoutRequirement::Any,
783 empty_input_policy: EmptyGraphInputPolicy::SIMILARITY,
784 },
785];
786
787#[derive(Debug, Clone, PartialEq, Eq)]
796pub struct GraphEdgeColumnBindings {
797 pub source: String,
799 pub destination: String,
801 pub weight: Option<String>,
803 pub edge_id: Option<String>,
805}
806
807impl GraphEdgeColumnBindings {
808 pub fn new(source: impl Into<String>, destination: impl Into<String>, weight: Option<impl Into<String>>) -> Self {
810 Self { source: source.into(), destination: destination.into(), weight: weight.map(Into::into), edge_id: None }
811 }
812
813 pub fn with_edge_id(mut self, edge_id: impl Into<String>) -> Self {
815 self.edge_id = Some(edge_id.into());
816 self
817 }
818}
819
820#[derive(Debug, Clone, PartialEq, Eq)]
827pub struct GraphConstructionOptions {
828 pub directed: bool,
830 pub renumber: bool,
832 pub policy: GraphConstructionPolicy,
834}
835
836impl Default for GraphConstructionOptions {
837 fn default() -> Self {
838 Self { directed: true, renumber: true, policy: GraphConstructionPolicy::PythonCugraph }
839 }
840}
841
842#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
848pub enum GraphConstructionPolicy {
849 PythonCugraph,
851 RawLibcugraph,
853}
854
855impl GraphConstructionPolicy {
856 pub const fn as_str(self) -> &'static str {
858 match self {
859 Self::PythonCugraph => "python_cugraph",
860 Self::RawLibcugraph => "raw_libcugraph",
861 }
862 }
863}
864
865impl fmt::Display for GraphConstructionPolicy {
866 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
867 f.write_str(self.as_str())
868 }
869}