libsvm_rs/lib.rs
1//! # libsvm-rs
2//!
3//! `libsvm-rs` is a pure Rust reimplementation of
4//! [LIBSVM](https://github.com/cjlin1/libsvm) for training, prediction,
5//! cross-validation, and LIBSVM text model/problem I/O without an FFI boundary.
6//! The public API mirrors the original LIBSVM concepts while using owned Rust
7//! data and `Result`-based error handling; see the
8//! [migration guide](https://github.com/ricardofrantz/libsvm-rs/blob/main/docs/MIGRATION.md)
9//! for a C-to-Rust mapping.
10//!
11//! ## LIBSVM parity
12//!
13//! The crate targets numerical equivalence and model-file compatibility with
14//! upstream LIBSVM rather than bit-for-bit identity. Core counterparts include
15//! [`train::svm_train`] for `svm_train`,
16//! [`cross_validation::svm_cross_validation`] for `svm_cross_validation`,
17//! [`predict::predict_values`] / [`predict::predict`] /
18//! [`predict::predict_probability`] for the prediction APIs, and
19//! [`io::save_model`] / [`io::load_model`] for LIBSVM model persistence.
20//!
21//! ## Quick example
22//!
23//! ```
24//! use libsvm_rs::predict::predict;
25//! use libsvm_rs::train::svm_train;
26//! use libsvm_rs::{KernelType, SvmNode, SvmParameterBuilder, SvmProblem, SvmType};
27//!
28//! let problem = SvmProblem {
29//! labels: vec![-1.0, -1.0, 1.0, 1.0],
30//! instances: vec![
31//! vec![SvmNode { index: 1, value: -2.0 }],
32//! vec![SvmNode { index: 1, value: -1.0 }],
33//! vec![SvmNode { index: 1, value: 1.0 }],
34//! vec![SvmNode { index: 1, value: 2.0 }],
35//! ],
36//! };
37//! let param = SvmParameterBuilder::new()
38//! .svm_type(SvmType::CSvc)
39//! .kernel_type(KernelType::Linear)
40//! .build()?;
41//!
42//! let model = svm_train(&problem, ¶m);
43//! let label = predict(&model, &[SvmNode { index: 1, value: 1.5 }]);
44//! assert_eq!(label, 1.0);
45//! # Ok::<(), libsvm_rs::SvmError>(())
46//! ```
47//!
48//! ## Status
49//!
50//! Training works for all 5 SVM types (C-SVC, ν-SVC, one-class, ε-SVR,
51//! ν-SVR). See [`train::svm_train`] for training, [`predict::predict`]
52//! for inference, and [`predict::predict_probability`] for probabilistic
53//! outputs. The project repository is
54//! <https://github.com/ricardofrantz/libsvm-rs>.
55//!
56//! ## Trust Boundary
57//!
58//! Problem and model files are treated as untrusted text input by default.
59//! The [`io`] loaders apply [`LoadOptions`] caps, reject malformed sparse
60//! feature rows, and validate model-header consistency before allocating
61//! support-vector storage. These checks bound parsing work and memory use; they
62//! do not authenticate a model or prove that it is appropriate for a particular
63//! deployment.
64//!
65//! ## Feature Flags
66//!
67//! - `rayon` — Enable parallel cross-validation (off by default), including
68//! probability-calibration CV folds for binary SVC models. Fold assignment
69//! remains serial and deterministic, then each fold trains on an
70//! independent worker. Per-fold training diagnostics are suppressed while the
71//! parallel workers run so output cannot interleave; use the default serial
72//! path if you need fold-internal progress text. With `k` parallel folds, peak
73//! memory can include up to `min(k, rayon_threads)` simultaneous kernel caches
74//! of `SvmParameter::cache_size` each; the cache size is never divided
75//! implicitly.
76//! - `serde` — Enable `Serialize`/`Deserialize` for model and parameter
77//! types. `SvmType` and `KernelType` serialize as pinned LIBSVM integer
78//! codes (`0..4`). Deserializing `SvmModel` runs the same structural
79//! validation as the text model loader; LIBSVM text model files remain the
80//! C-compatible interchange format.
81
82#![deny(missing_docs)]
83#![cfg_attr(docsrs, feature(doc_cfg))]
84#![cfg_attr(
85 not(test),
86 deny(
87 clippy::unwrap_used,
88 clippy::expect_used,
89 clippy::panic,
90 clippy::unreachable
91 )
92)]
93
94use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
95
96static QUIET_MODE: AtomicBool = AtomicBool::new(false);
97static SUPPRESS_INFO_DEPTH: AtomicUsize = AtomicUsize::new(0);
98
99/// Enable or disable quiet mode. When quiet, solver diagnostic messages
100/// are suppressed (equivalent to LIBSVM's `-q` flag).
101pub fn set_quiet(quiet: bool) {
102 QUIET_MODE.store(quiet, Ordering::Relaxed);
103}
104
105/// Print an info message to stderr (suppressed in quiet mode).
106pub(crate) fn info(msg: &str) {
107 if !QUIET_MODE.load(Ordering::Relaxed) && SUPPRESS_INFO_DEPTH.load(Ordering::Relaxed) == 0 {
108 eprint!("{}", msg);
109 }
110}
111
112#[cfg(feature = "rayon")]
113pub(crate) fn with_suppressed_info<T>(f: impl FnOnce() -> T) -> T {
114 struct SuppressInfoGuard;
115
116 impl Drop for SuppressInfoGuard {
117 fn drop(&mut self) {
118 SUPPRESS_INFO_DEPTH.fetch_sub(1, Ordering::Relaxed);
119 }
120 }
121
122 SUPPRESS_INFO_DEPTH.fetch_add(1, Ordering::Relaxed);
123 let _guard = SuppressInfoGuard;
124 f()
125}
126
127/// Fluent builder for [`SvmParameter`](crate::SvmParameter) values.
128pub mod builder;
129/// Kernel-row cache used by the SMO solver.
130pub mod cache;
131/// Error types returned by fallible parsing, validation, and I/O APIs.
132pub mod error;
133/// LIBSVM problem/model text-format loading and saving.
134pub mod io;
135/// Kernel functions equivalent to LIBSVM's linear, polynomial, RBF, sigmoid, and precomputed kernels.
136pub mod kernel;
137/// Helpers for classification accuracy and regression error summaries.
138pub mod metrics;
139/// Q-matrix implementations consumed by the SMO solver.
140pub mod qmatrix;
141/// Sequential Minimal Optimization solver internals corresponding to LIBSVM's `Solver` and `Solver_NU`.
142pub mod solver;
143/// Training entry points corresponding to LIBSVM's `svm_train`.
144pub mod train;
145/// LIBSVM-compatible public data structures and C-style helper functions.
146pub mod types;
147/// Utility routines shared by training, parsing, and parity-oriented algorithms.
148pub mod util;
149
150/// Cross-validation entry point corresponding to LIBSVM's `svm_cross_validation`.
151pub mod cross_validation;
152/// Prediction entry points corresponding to LIBSVM's `svm_predict*` APIs.
153pub mod predict;
154/// Probability-estimation routines corresponding to LIBSVM's Platt-scaling and related helpers.
155pub mod probability;
156
157/// Fluent parameter builder with LIBSVM-compatible defaults.
158pub use builder::SvmParameterBuilder;
159/// Structured errors returned instead of LIBSVM integer/null failure codes.
160pub use error::SvmError;
161/// Resource caps for untrusted LIBSVM text input.
162pub use io::LoadOptions;
163/// Accuracy and regression metric helpers.
164pub use metrics::{accuracy_percentage, regression_metrics};
165/// Public LIBSVM-compatible types and helper functions.
166pub use types::*;