use crate::motif::MotifResult;
use crate::types::{CentralityResult, CommunityResult, CsrGraph, SimilarityResult};
use rustkernel_core::messages::CorrelationId;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum PageRankOp {
Query {
node_id: u64,
},
Iterate,
Initialize,
Reset,
ConvergeUntil {
threshold: f64,
max_iterations: u32,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PageRankRequest {
pub correlation_id: CorrelationId,
pub operation: PageRankOp,
pub graph: Option<CsrGraph>,
pub damping: Option<f32>,
}
impl PageRankRequest {
pub fn query(node_id: u64) -> Self {
Self {
correlation_id: CorrelationId::new(),
operation: PageRankOp::Query { node_id },
graph: None,
damping: None,
}
}
pub fn iterate() -> Self {
Self {
correlation_id: CorrelationId::new(),
operation: PageRankOp::Iterate,
graph: None,
damping: None,
}
}
pub fn initialize(graph: CsrGraph, damping: f32) -> Self {
Self {
correlation_id: CorrelationId::new(),
operation: PageRankOp::Initialize,
graph: Some(graph),
damping: Some(damping),
}
}
pub fn converge(threshold: f64, max_iterations: u32) -> Self {
Self {
correlation_id: CorrelationId::new(),
operation: PageRankOp::ConvergeUntil {
threshold,
max_iterations,
},
graph: None,
damping: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PageRankResponse {
pub correlation_id: CorrelationId,
pub score: Option<f64>,
pub converged: bool,
pub iteration: u32,
pub result: Option<CentralityResult>,
pub error: Option<String>,
}
impl PageRankResponse {
pub fn score(correlation_id: CorrelationId, score: f64, iteration: u32) -> Self {
Self {
correlation_id,
score: Some(score),
converged: false,
iteration,
result: None,
error: None,
}
}
pub fn converged(
correlation_id: CorrelationId,
result: CentralityResult,
iteration: u32,
) -> Self {
Self {
correlation_id,
score: None,
converged: true,
iteration,
result: Some(result),
error: None,
}
}
pub fn error(correlation_id: CorrelationId, error: impl Into<String>) -> Self {
Self {
correlation_id,
score: None,
converged: false,
iteration: 0,
result: None,
error: Some(error.into()),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CentralityInput {
pub graph: CsrGraph,
pub normalize: bool,
pub max_iterations: Option<u32>,
pub tolerance: Option<f64>,
pub params: CentralityParams,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CentralityParams {
PageRank {
damping: f32,
},
Degree,
Betweenness,
Closeness {
harmonic: bool,
},
Eigenvector,
Katz {
alpha: f64,
beta: f64,
},
}
impl Default for CentralityInput {
fn default() -> Self {
Self {
graph: CsrGraph::empty(),
normalize: true,
max_iterations: Some(100),
tolerance: Some(1e-6),
params: CentralityParams::Degree,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CentralityOutput {
pub result: CentralityResult,
pub compute_time_us: u64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum CommunityAlgorithm {
Louvain,
ModularityScore,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommunityInput {
pub graph: CsrGraph,
pub algorithm: CommunityAlgorithm,
pub resolution: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommunityOutput {
pub result: CommunityResult,
pub compute_time_us: u64,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum SimilarityMetric {
Jaccard,
Cosine,
AdamicAdar,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimilarityInput {
pub graph: CsrGraph,
pub metric: SimilarityMetric,
pub node_pairs: Option<Vec<(u64, u64)>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SimilarityOutput {
pub result: SimilarityResult,
pub compute_time_us: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MotifInput {
pub graph: CsrGraph,
pub motif_size: usize,
pub enumerate: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MotifOutput {
pub result: MotifResult,
pub compute_time_us: u64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pagerank_request_query() {
let req = PageRankRequest::query(42);
assert!(matches!(req.operation, PageRankOp::Query { node_id: 42 }));
}
#[test]
fn test_pagerank_request_converge() {
let req = PageRankRequest::converge(1e-6, 100);
assert!(matches!(
req.operation,
PageRankOp::ConvergeUntil {
threshold: _,
max_iterations: 100
}
));
}
#[test]
fn test_pagerank_response_score() {
let cid = CorrelationId::new();
let resp = PageRankResponse::score(cid, 0.5, 10);
assert_eq!(resp.score, Some(0.5));
assert!(!resp.converged);
}
}