#![allow(dead_code)]
#![allow(non_snake_case)]
#![allow(missing_docs)]
#![allow(deprecated)]
#![allow(clippy::all)]
#![allow(clippy::pedantic)]
#![allow(clippy::nursery)]
#![allow(unused_imports)]
#![allow(unused_variables)]
#![allow(unused_mut)]
#![allow(unused_assignments)]
#![allow(unused_doc_comments)]
#![allow(unused_parens)]
#![allow(unused_comparisons)]
mod active_learning;
mod adversarial_graph_learning;
mod approximate_graph_methods;
mod batch_active_learning;
mod bayesian_methods;
mod co_training;
mod composable_graph;
mod contrastive_learning;
mod convergence_tests;
mod cross_modal_contrastive;
mod deep_learning;
mod democratic_co_learning;
mod dynamic_graph_learning;
mod entropy_methods;
mod few_shot;
mod graph;
mod graph_learning;
mod harmonic_functions;
mod hierarchical_graph;
mod information_theory;
mod label_propagation;
mod label_spreading;
mod landmark_methods;
mod local_global_consistency;
mod manifold_regularization;
mod mixture_discriminant_analysis;
mod multi_armed_bandits;
mod multi_view_graph;
mod optimal_transport;
pub mod parallel_graph;
mod robust_graph_methods;
mod self_training;
mod self_training_classifier;
mod semi_supervised_gmm;
mod semi_supervised_naive_bayes;
pub mod simd_distances;
mod streaming_graph_learning;
mod tri_training;
pub use active_learning::*;
pub use adversarial_graph_learning::*;
pub use approximate_graph_methods::*;
pub use batch_active_learning::*;
pub use bayesian_methods::*;
pub use co_training::*;
pub use composable_graph::*;
pub use contrastive_learning::*;
pub use convergence_tests::*;
pub use cross_modal_contrastive::*;
pub use deep_learning::*;
pub use democratic_co_learning::*;
pub use dynamic_graph_learning::*;
pub use entropy_methods::*;
pub use few_shot::*;
pub use graph::*;
pub use graph_learning::*;
pub use harmonic_functions::*;
pub use hierarchical_graph::*;
pub use information_theory::*;
pub use label_propagation::*;
pub use label_spreading::*;
pub use landmark_methods::*;
pub use local_global_consistency::*;
pub use manifold_regularization::*;
pub use mixture_discriminant_analysis::*;
pub use multi_armed_bandits::*;
pub use multi_view_graph::*;
pub use optimal_transport::*;
pub use robust_graph_methods::*;
pub use self_training::*;
pub use self_training_classifier::*;
pub use semi_supervised_gmm::*;
pub use semi_supervised_naive_bayes::*;
pub use streaming_graph_learning::*;
pub use tri_training::*;
#[allow(non_snake_case)]
#[cfg(test)]
mod tests {
use super::*;
use scirs2_core::array;
use scirs2_core::ndarray_ext::Array2;
use sklears_core::traits::{Fit, Predict, PredictProba};
#[test]
fn test_label_propagation() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let lp = LabelPropagation::new()
.kernel("rbf".to_string())
.gamma(20.0);
let fitted = lp
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
}
#[test]
fn test_label_spreading() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let ls = LabelSpreading::new()
.kernel("rbf".to_string())
.gamma(20.0)
.alpha(0.2);
let fitted = ls
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
}
#[test]
fn test_self_training() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let stc = SelfTrainingClassifier::new().threshold(0.5).max_iter(5);
let fitted = stc
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_enhanced_self_training() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let est = EnhancedSelfTraining::new()
.threshold(0.6)
.confidence_method("entropy".to_string())
.max_iter(5);
let fitted = est
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_co_training() {
let X = array![
[1.0, 2.0, 3.0, 4.0],
[2.0, 3.0, 4.0, 5.0],
[3.0, 4.0, 5.0, 6.0],
[4.0, 5.0, 6.0, 7.0]
];
let y = array![0, 1, -1, -1];
let ct = CoTraining::new()
.view1_features(vec![0, 1])
.view2_features(vec![2, 3])
.p(1)
.n(1)
.max_iter(5);
let fitted = ct
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_tri_training() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let tt = TriTraining::new().max_iter(5).theta(0.2);
let fitted = tt
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_knn_graph() {
let X = array![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
let W = knn_graph(&X, 1, "connectivity").expect("operation should succeed");
assert_eq!(W.dim(), (3, 3));
for i in 0..3 {
let non_zero_count = W.row(i).iter().filter(|&&x| x > 0.0).count();
assert!(non_zero_count <= 1);
}
}
#[test]
fn test_epsilon_graph() {
let X = array![[1.0, 2.0], [1.1, 2.1], [5.0, 6.0]];
let W = epsilon_graph(&X, 1.0, "connectivity").expect("operation should succeed");
assert_eq!(W.dim(), (3, 3));
assert!(W[[0, 1]] > 0.0 || W[[1, 0]] > 0.0);
}
#[test]
fn test_graph_laplacian() {
let W = array![[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0]];
let L = graph_laplacian(&W, false).expect("operation should succeed");
assert_eq!(L.dim(), (3, 3));
assert_eq!(L[[0, 0]], 1.0); assert_eq!(L[[1, 1]], 2.0); assert_eq!(L[[0, 1]], -1.0); }
#[test]
fn test_democratic_co_learning() {
let X = array![
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
[2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
[3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
[4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
];
let y = array![0, 1, -1, -1];
let dcl = DemocraticCoLearning::new()
.views(vec![vec![0, 1], vec![2, 3], vec![4, 5]])
.k_add(1)
.min_agreement(2)
.max_iter(5);
let fitted = dcl
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_harmonic_functions() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let hf = HarmonicFunctions::new()
.kernel("rbf".to_string())
.gamma(20.0)
.max_iter(100);
let fitted = hf
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
}
#[test]
fn test_local_global_consistency() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let lgc = LocalGlobalConsistency::new()
.kernel("rbf".to_string())
.gamma(20.0)
.alpha(0.99)
.max_iter(100);
let fitted = lgc
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
}
#[test]
fn test_manifold_regularization() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let mr = ManifoldRegularization::new()
.lambda_a(0.01)
.lambda_i(0.1)
.kernel("rbf".to_string())
.gamma(1.0)
.max_iter(100);
let fitted = mr
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
}
#[test]
fn test_semi_supervised_gmm() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let gmm = SemiSupervisedGMM::new()
.n_components(2)
.max_iter(50)
.labeled_weight(10.0);
let fitted = gmm
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
}
#[test]
fn test_multi_view_co_training() {
let X = array![
[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
[2.0, 3.0, 4.0, 5.0, 6.0, 7.0],
[3.0, 4.0, 5.0, 6.0, 7.0, 8.0],
[4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
[5.0, 6.0, 7.0, 8.0, 9.0, 10.0],
[6.0, 7.0, 8.0, 9.0, 10.0, 11.0]
];
let y = array![0, 1, -1, -1, -1, -1];
let mvct = MultiViewCoTraining::new()
.views(vec![vec![0, 1], vec![2, 3], vec![4, 5]])
.k_add(1)
.confidence_threshold(0.5)
.max_iter(5);
let fitted = mvct
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 6);
assert_eq!(predictions[0], 0);
assert_eq!(predictions[1], 1);
}
#[test]
fn test_semi_supervised_naive_bayes() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0]];
let y = array![0, 1, -1, -1];
let nb = SemiSupervisedNaiveBayes::new()
.alpha(1.0)
.max_iter(50)
.class_weight(1.0);
let fitted = nb
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert_eq!(predictions.len(), 4);
let probas = fitted
.predict_proba(&X.view())
.expect("operation should succeed");
assert_eq!(probas.dim(), (4, 2));
for i in 0..4 {
let sum: f64 = probas.row(i).sum();
assert!((sum - 1.0).abs() < 1e-10);
}
}
#[test]
fn test_random_walk_laplacian() {
let W = array![[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0]];
let L_rw = random_walk_laplacian(&W).expect("operation should succeed");
assert_eq!(L_rw.dim(), (3, 3));
assert!((L_rw[[0, 0]] - 1.0).abs() < 1e-10);
assert!((L_rw[[1, 1]] - 1.0).abs() < 1e-10);
assert!((L_rw[[2, 2]] - 1.0).abs() < 1e-10);
}
#[test]
fn test_diffusion_matrix() {
let W = array![[0.0, 1.0, 0.0], [1.0, 0.0, 1.0], [0.0, 1.0, 0.0]];
let P = diffusion_matrix(&W, 2).expect("operation should succeed");
assert_eq!(P.dim(), (3, 3));
for i in 0..3 {
for j in 0..3 {
assert!(P[[i, j]] >= 0.0);
}
}
}
#[test]
fn test_adaptive_knn_graph() {
let X = array![[1.0, 2.0], [1.1, 2.1], [5.0, 6.0]];
let W = adaptive_knn_graph(&X, "connectivity").expect("operation should succeed");
assert_eq!(W.dim(), (3, 3));
assert_eq!(W[[0, 1]], W[[1, 0]]);
assert_eq!(W[[0, 2]], W[[2, 0]]);
assert_eq!(W[[1, 2]], W[[2, 1]]);
}
#[test]
fn test_sparsify_graph() {
let W = array![
[0.0, 0.8, 0.2, 0.1],
[0.8, 0.0, 0.9, 0.3],
[0.2, 0.9, 0.0, 0.7],
[0.1, 0.3, 0.7, 0.0]
];
let W_sparse = sparsify_graph(&W, 0.5).expect("operation should succeed");
assert_eq!(W_sparse.dim(), (4, 4));
let original_edges = W.iter().filter(|&&x| x > 0.0).count();
let sparse_edges = W_sparse.iter().filter(|&&x| x > 0.0).count();
assert!(sparse_edges <= original_edges);
}
#[test]
fn test_spectral_clustering() {
let W = array![
[0.0, 1.0, 0.1, 0.0, 0.0],
[1.0, 0.0, 0.2, 0.0, 0.0],
[0.1, 0.2, 0.0, 0.0, 0.0],
[0.0, 0.0, 0.0, 0.0, 1.0],
[0.0, 0.0, 0.0, 1.0, 0.0]
];
let labels = spectral_clustering(&W, 2, true, Some(42)).expect("operation should succeed");
assert_eq!(labels.len(), 5);
for &label in labels.iter() {
assert!(label >= 0 && label < 2);
}
}
#[test]
fn test_spectral_embedding() {
let W = array![[0.0, 1.0, 0.1], [1.0, 0.0, 0.2], [0.1, 0.2, 0.0]];
let embedding = spectral_embedding(&W, 2, true).expect("operation should succeed");
assert_eq!(embedding.dim(), (3, 2));
}
#[test]
fn test_label_propagation_robustness() {
use scirs2_core::random::Random;
let mut rng = Random::seed(42);
let mut X = Array2::<f64>::zeros((50, 5));
for i in 0..50 {
for j in 0..5 {
X[(i, j)] = rng.random_range(-1.0..1.0);
}
}
let y_true = array![
0, 1, 0, 1, 0, 1, 0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1
];
let lp = LabelPropagation::new()
.kernel("rbf".to_string())
.gamma(20.0);
let fitted_clean = lp
.fit(&X.view(), &y_true.view())
.expect("operation should succeed");
let pred_clean = fitted_clean
.predict(&X.view())
.expect("operation should succeed");
let mut y_noisy = y_true.clone();
y_noisy[0] = 1; y_noisy[2] = 1;
let lp_noisy = LabelPropagation::new()
.kernel("rbf".to_string())
.gamma(20.0);
let fitted_noisy = lp_noisy
.fit(&X.view(), &y_noisy.view())
.expect("operation should succeed");
let pred_noisy = fitted_noisy
.predict(&X.view())
.expect("operation should succeed");
let different = pred_clean
.iter()
.zip(pred_noisy.iter())
.filter(|(a, b)| a != b)
.count();
let robustness = 1.0 - (different as f64 / pred_clean.len() as f64);
assert!(
robustness > 0.6,
"Label propagation should be somewhat robust to label noise"
);
}
#[test]
fn test_self_training_robustness() {
use scirs2_core::random::Random;
let mut rng = Random::seed(42);
let mut X = Array2::<f64>::zeros((30, 4));
for i in 0..30 {
for j in 0..4 {
X[(i, j)] = rng.random_range(-1.0..1.0);
}
}
let y_clean = array![
0, 1, 0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1
];
let stc_clean = SelfTrainingClassifier::new().threshold(0.8).max_iter(10);
let fitted_clean = stc_clean
.fit(&X.view(), &y_clean.view())
.expect("operation should succeed");
let pred_clean = fitted_clean
.predict(&X.view())
.expect("operation should succeed");
let mut y_noisy = y_clean.clone();
y_noisy[1] = 0;
let stc_noisy = SelfTrainingClassifier::new().threshold(0.8).max_iter(10);
let fitted_noisy = stc_noisy
.fit(&X.view(), &y_noisy.view())
.expect("operation should succeed");
let pred_noisy = fitted_noisy
.predict(&X.view())
.expect("operation should succeed");
assert!(
pred_clean.iter().all(|&p| p >= 0 && p <= 1),
"Clean predictions should be valid"
);
assert!(
pred_noisy.iter().all(|&p| p >= 0 && p <= 1),
"Noisy predictions should be valid"
);
}
#[test]
fn test_co_training_robustness() {
use scirs2_core::random::Random;
let mut rng = Random::seed(42);
let mut X = Array2::<f64>::zeros((20, 6));
for i in 0..20 {
for j in 0..6 {
X[(i, j)] = rng.random_range(-1.0..1.0);
}
}
let y_clean =
array![0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1];
let ct_clean = CoTraining::new()
.view1_features(vec![0, 1, 2])
.view2_features(vec![3, 4, 5])
.p(1)
.n(1)
.max_iter(5);
let fitted_clean = ct_clean
.fit(&X.view(), &y_clean.view())
.expect("operation should succeed");
let pred_clean = fitted_clean
.predict(&X.view())
.expect("operation should succeed");
let mut y_noisy = y_clean.clone();
y_noisy[0] = 1;
let ct_noisy = CoTraining::new()
.view1_features(vec![0, 1, 2])
.view2_features(vec![3, 4, 5])
.p(1)
.n(1)
.max_iter(5);
let fitted_noisy = ct_noisy
.fit(&X.view(), &y_noisy.view())
.expect("operation should succeed");
let pred_noisy = fitted_noisy
.predict(&X.view())
.expect("operation should succeed");
assert!(
pred_clean.iter().all(|&p| p >= 0 && p <= 1),
"Clean predictions should be valid"
);
assert!(
pred_noisy.iter().all(|&p| p >= 0 && p <= 1),
"Noisy predictions should be valid"
);
}
#[test]
fn test_label_efficiency_comparison() {
use scirs2_core::random::Random;
let mut rng = Random::seed(42);
let mut X = Array2::<f64>::zeros((40, 5));
for i in 0..40 {
for j in 0..5 {
X[(i, j)] = rng.random_range(-1.0..1.0);
}
}
let small_labeled = array![
0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
];
let large_labeled = array![
0, 1, 0, 1, 0, 1, 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
];
let lp_small = LabelPropagation::new()
.kernel("rbf".to_string())
.gamma(20.0);
let fitted_small = lp_small
.fit(&X.view(), &small_labeled.view())
.expect("operation should succeed");
let pred_small = fitted_small
.predict(&X.view())
.expect("operation should succeed");
let lp_large = LabelPropagation::new()
.kernel("rbf".to_string())
.gamma(20.0);
let fitted_large = lp_large
.fit(&X.view(), &large_labeled.view())
.expect("operation should succeed");
let pred_large = fitted_large
.predict(&X.view())
.expect("operation should succeed");
assert!(
pred_small.iter().all(|&p| p >= 0 && p <= 1),
"Small labeled predictions should be valid"
);
assert!(
pred_large.iter().all(|&p| p >= 0 && p <= 1),
"Large labeled predictions should be valid"
);
}
#[test]
fn test_algorithm_convergence() {
let X = array![[1.0, 2.0], [2.0, 3.0], [3.0, 4.0], [4.0, 5.0], [5.0, 6.0]];
let y = array![0, 1, -1, -1, -1];
let hf = HarmonicFunctions::new()
.kernel("rbf".to_string())
.gamma(20.0)
.max_iter(100);
let fitted = hf
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions = fitted.predict(&X.view()).expect("operation should succeed");
assert!(
predictions.iter().all(|&p| p >= 0 && p <= 1),
"Predictions should be stable and valid"
);
let lgc = LocalGlobalConsistency::new()
.kernel("rbf".to_string())
.gamma(20.0)
.alpha(0.99)
.max_iter(100);
let fitted_lgc = lgc
.fit(&X.view(), &y.view())
.expect("operation should succeed");
let predictions_lgc = fitted_lgc
.predict(&X.view())
.expect("operation should succeed");
assert!(
predictions_lgc.iter().all(|&p| p >= 0 && p <= 1),
"LGC predictions should be stable and valid"
);
}
}