Skip to content

Commit

Permalink
Renamed internal structures.
Browse files Browse the repository at this point in the history
  • Loading branch information
ralfbiedert committed Aug 14, 2018
1 parent df7581b commit 60934db
Show file tree
Hide file tree
Showing 16 changed files with 96 additions and 96 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -42,7 +42,7 @@ features[3] = -0.221184;

svm.predict_value(&mut problem)?;

assert_eq!(problem.result(), SVMResult::Label(42));
assert_eq!(problem.result(), Outcome::Label(42));
```

From C / FFI:
Expand Down
4 changes: 2 additions & 2 deletions examples/basic.rs
Expand Up @@ -3,7 +3,7 @@
use ffsvm::*;
use std::convert::TryFrom;

fn main() -> Result<(), SVMError> {
fn main() -> Result<(), Error> {
let svm = DenseSVM::try_from(SAMPLE_MODEL)?;

let mut problem = Problem::from(&svm);
Expand All @@ -16,7 +16,7 @@ fn main() -> Result<(), SVMError> {

svm.predict_value(&mut problem)?;

assert_eq!(problem.result(), SVMResult::Label(12));
assert_eq!(problem.result(), Outcome::Label(12));

Ok(())
}
22 changes: 11 additions & 11 deletions src/errors.rs
Expand Up @@ -5,7 +5,7 @@ use std::{

/// Possible error types when classifying with a [SVMCore].
#[derive(Debug)]
pub enum SVMError {
pub enum Error {
/// This can be emitted when creating a [SVM] from a [ModelFile]. For models generated by
/// libSVM's `svm-train`, the most common reason this occurs is skipping attributes.
/// All attributes must be in sequential order 0, 1, 2, ..., n. If they are not, this
Expand Down Expand Up @@ -44,24 +44,24 @@ pub enum SVMError {
ParsingError(String),
}

// impl<'a, T> From<Error<'a, T>> for SVMError {
// impl<'a, T> From<Error<'a, T>> for Error {
// fn from(_: Error<'a, T>) -> Self {
// SVMError::ParsingError
// Error::ParsingError
// }
// }

impl<'a> From<pest::Error<'a, crate::parser::Rule>> for SVMError {
fn from(e: pest::Error<'a, crate::parser::Rule>) -> Self { SVMError::ParsingError(format!("{}", e)) }
impl<'a> From<pest::Error<'a, crate::parser::Rule>> for Error {
fn from(e: pest::Error<'a, crate::parser::Rule>) -> Self { Error::ParsingError(format!("{}", e)) }
}

impl From<NoneError> for SVMError {
fn from(_: NoneError) -> Self { SVMError::ParsingError("NoneError".to_owned()) }
impl From<NoneError> for Error {
fn from(_: NoneError) -> Self { Error::ParsingError("NoneError".to_owned()) }
}

impl From<ParseFloatError> for SVMError {
fn from(_e: ParseFloatError) -> Self { SVMError::ParsingError("ParseFloatError".to_owned()) }
impl From<ParseFloatError> for Error {
fn from(_e: ParseFloatError) -> Self { Error::ParsingError("ParseFloatError".to_owned()) }
}

impl From<ParseIntError> for SVMError {
fn from(_: ParseIntError) -> Self { SVMError::ParsingError("ParseIntError".to_owned()) }
impl From<ParseIntError> for Error {
fn from(_: ParseIntError) -> Self { Error::ParsingError("ParseIntError".to_owned()) }
}
8 changes: 4 additions & 4 deletions src/lib.rs
Expand Up @@ -46,7 +46,7 @@
//! use ffsvm::*;
//! use std::convert::TryFrom;
//!
//! fn main() -> Result<(), SVMError> {
//! fn main() -> Result<(), Error> {
//! // Replace `SAMPLE_MODEL` with a `&str` to your model.
//! let svm = DenseSVM::try_from(SAMPLE_MODEL)?;
//!
Expand All @@ -60,7 +60,7 @@
//!
//! svm.predict_value(&mut problem)?;
//!
//! assert_eq!(problem.result(), SVMResult::Label(42));
//! assert_eq!(problem.result(), Outcome::Label(42));
//!
//! Ok(())
//! }
Expand All @@ -82,13 +82,13 @@ mod vectors;
pub static SAMPLE_MODEL: &str = include_str!("sample.model");

pub use crate::{
errors::SVMError,
errors::Error,
parser::ModelFile,
svm::{
core::SVMCore,
kernel::{KernelDense, Linear, Poly, Rbf, Sigmoid},
predict::Predict,
problem::{Problem, SVMResult},
problem::{Outcome, Problem},
DenseSVM, SVMType, SparseSVM,
},
};
6 changes: 3 additions & 3 deletions src/parser/mod.rs
Expand Up @@ -7,7 +7,7 @@ pub use self::raw::*;
use pest::Parser;
use pest_derive::Parser;

use crate::errors::SVMError;
use crate::errors::Error;

// Hack to make `pest` re-generate parser every time file changes.
#[cfg(debug_assertions)]
Expand Down Expand Up @@ -43,10 +43,10 @@ macro_rules! convert {
}

impl<'a> TryFrom<&'a str> for ModelFile<'a> {
type Error = SVMError;
type Error = Error;

/// Parses a string into a SVM model
fn try_from(input: &str) -> Result<ModelFile<'_>, SVMError> {
fn try_from(input: &str) -> Result<ModelFile<'_>, Error> {
let parsed = LibSVMModel::parse(Rule::file, input)?.next()?;

let mut svm_type = Option::None;
Expand Down
30 changes: 15 additions & 15 deletions src/svm/core/dense.rs
Expand Up @@ -2,14 +2,14 @@ use simd_aligned::{f32s, f64s, RowOptimized, SimdMatrix, SimdVector};
use std::{convert::TryFrom, marker::PhantomData};

use crate::{
errors::SVMError,
errors::Error,
parser::ModelFile,
svm::{
class::Class,
core::SVMCore,
kernel::{KernelDense, Linear, Poly, Rbf, Sigmoid},
predict::Predict,
problem::{Problem, SVMResult},
problem::{Problem, Outcome},
Probabilities, SVMType,
},
util::{find_max_index, set_all, sigmoid_predict},
Expand All @@ -36,7 +36,7 @@ impl SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, Simd
// based on Method 2 from the paper "Probability Estimates for Multi-class
// Classification by Pairwise Coupling", Journal of Machine Learning Research 5 (2004) 975-1005,
// by Ting-Fan Wu, Chih-Jen Lin and Ruby C. Weng.
crate fn compute_multiclass_probabilities(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), SVMError> {
crate fn compute_multiclass_probabilities(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), Error> {
let num_classes = self.classes.len();
let max_iter = 100.max(num_classes);
let mut q = problem.q.flat_mut();
Expand Down Expand Up @@ -96,7 +96,7 @@ impl SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, Simd
// In case we are on the last iteration round past the threshold
// we know something went wrong. Signal we exceeded the threshold.
if i == max_iter {
return Err(SVMError::IterationsExceeded);
return Err(Error::IterationsExceeded);
}

// This seems to be the main function performing (23) and (24).
Expand Down Expand Up @@ -170,19 +170,19 @@ impl SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, Simd

sum -= self.rho[0];

problem.result = SVMResult::Value(sum as f32);
problem.result = Outcome::Value(sum as f32);
}
}

impl Predict<SimdVector<f32s>, SimdVector<f64s>> for SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>> {
fn predict_probability(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), SVMError> {
fn predict_probability(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), Error> {
match self.svm_type {
SVMType::CSvc | SVMType::NuSvc => {
const MIN_PROB: f64 = 1e-7;

// Ensure we have probabilities set. If not, somebody used us the wrong way
if self.probabilities.is_none() {
return Err(SVMError::NoProbabilities);
return Err(Error::NoProbabilities);
}

let num_classes = self.classes.len();
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Predict<SimdVector<f32s>, SimdVector<f64s>> for SVMCore<KernelDense, SimdMa
}

let max_index = find_max_index(problem.probabilities.flat());
problem.result = SVMResult::Label(self.classes[max_index].label);
problem.result = Outcome::Label(self.classes[max_index].label);

Ok(())
}
Expand All @@ -227,7 +227,7 @@ impl Predict<SimdVector<f32s>, SimdVector<f64s>> for SVMCore<KernelDense, SimdMa
}

// Predict the value for one problem.
fn predict_value(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), SVMError> {
fn predict_value(&self, problem: &mut Problem<SimdVector<f32s>>) -> Result<(), Error> {
match self.svm_type {
SVMType::CSvc | SVMType::NuSvc => {
// Compute kernel, decision values and eventually the label
Expand All @@ -236,7 +236,7 @@ impl Predict<SimdVector<f32s>, SimdVector<f64s>> for SVMCore<KernelDense, SimdMa

// Compute highest vote
let highest_vote = find_max_index(&problem.vote);
problem.result = SVMResult::Label(self.classes[highest_vote].label);
problem.result = Outcome::Label(self.classes[highest_vote].label);

Ok(())
}
Expand All @@ -250,18 +250,18 @@ impl Predict<SimdVector<f32s>, SimdVector<f64s>> for SVMCore<KernelDense, SimdMa
}

impl<'a, 'b> TryFrom<&'a str> for SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>> {
type Error = SVMError;
type Error = Error;

fn try_from(input: &'a str) -> Result<SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>>, SVMError> {
fn try_from(input: &'a str) -> Result<SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>>, Error> {
let raw_model = ModelFile::try_from(input)?;
Self::try_from(&raw_model)
}
}

impl<'a, 'b> TryFrom<&'a ModelFile<'b>> for SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>> {
type Error = SVMError;
type Error = Error;

fn try_from(raw_model: &'a ModelFile) -> Result<SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>>, SVMError> {
fn try_from(raw_model: &'a ModelFile) -> Result<SVMCore<KernelDense, SimdMatrix<f32s, RowOptimized>, SimdVector<f32s>, SimdVector<f64s>>, Error> {
// To quickly check what broke again during parsing ...
// println!("{:?}", raw_model);

Expand Down Expand Up @@ -361,7 +361,7 @@ impl<'a, 'b> TryFrom<&'a ModelFile<'b>> for SVMCore<KernelDense, SimdMatrix<f32s
// In case we have seen an attribute already, this one must be strictly
// the successor attribute
if attribute.index != last + 1 {
return Result::Err(SVMError::AttributesUnordered {
return Result::Err(Error::AttributesUnordered {
index: attribute.index,
value: attribute.value,
last_index: last,
Expand Down
4 changes: 2 additions & 2 deletions src/svm/core/mod.rs
Expand Up @@ -5,13 +5,13 @@ use simd_aligned::{f32s, f64s, RowOptimized, SimdMatrix, SimdVector};
use std::{convert::TryFrom, marker::PhantomData};

use crate::{
errors::SVMError,
errors::Error,
parser::ModelFile,
svm::{
class::Class,
kernel::{KernelDense, Linear, Poly, Rbf, Sigmoid},
predict::Predict,
problem::{Problem, SVMResult},
problem::{Outcome, Problem},
Probabilities, SVMType,
},
util::{find_max_index, set_all, sigmoid_predict},
Expand Down
28 changes: 14 additions & 14 deletions src/svm/core/sparse.rs
Expand Up @@ -3,14 +3,14 @@ use crate::sparse::{SparseMatrix, SparseVector};
use std::{convert::TryFrom, marker::PhantomData};

use crate::{
errors::SVMError,
errors::Error,
parser::ModelFile,
svm::{
class::Class,
core::SVMCore,
kernel::{KernelSparse, Linear, Poly, Rbf, Sigmoid},
predict::Predict,
problem::{Problem, SVMResult},
problem::{Outcome, Problem},
Probabilities, SVMType,
},
util::{find_max_index, set_all, sigmoid_predict},
Expand All @@ -37,7 +37,7 @@ impl SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f6
// based on Method 2 from the paper "Probability Estimates for Multi-class
// Classification by Pairwise Coupling", Journal of Machine Learning Research 5 (2004) 975-1005,
// by Ting-Fan Wu, Chih-Jen Lin and Ruby C. Weng.
crate fn compute_multiclass_probabilities(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), SVMError> {
crate fn compute_multiclass_probabilities(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), Error> {
let num_classes = self.classes.len();
let max_iter = 100.max(num_classes);
let mut q = problem.q.flat_mut();
Expand Down Expand Up @@ -97,7 +97,7 @@ impl SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f6
// In case we are on the last iteration round past the threshold
// we know something went wrong. Signal we exceeded the threshold.
if i == max_iter {
return Err(SVMError::IterationsExceeded);
return Err(Error::IterationsExceeded);
}

// This seems to be the main function performing (23) and (24).
Expand Down Expand Up @@ -171,19 +171,19 @@ impl SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f6

sum -= self.rho[0];

problem.result = SVMResult::Value(sum as f32);
problem.result = Outcome::Value(sum as f32);
}
}

impl Predict<SparseVector<f32>, SparseVector<f64>> for SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>> {
fn predict_probability(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), SVMError> {
fn predict_probability(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), Error> {
match self.svm_type {
SVMType::CSvc | SVMType::NuSvc => {
const MIN_PROB: f64 = 1e-7;

// Ensure we have probabilities set. If not, somebody used us the wrong way
if self.probabilities.is_none() {
return Err(SVMError::NoProbabilities);
return Err(Error::NoProbabilities);
}

let num_classes = self.classes.len();
Expand Down Expand Up @@ -218,7 +218,7 @@ impl Predict<SparseVector<f32>, SparseVector<f64>> for SVMCore<KernelSparse, Spa
}

let max_index = find_max_index(problem.probabilities.flat());
problem.result = SVMResult::Label(self.classes[max_index].label);
problem.result = Outcome::Label(self.classes[max_index].label);

Ok(())
}
Expand All @@ -228,7 +228,7 @@ impl Predict<SparseVector<f32>, SparseVector<f64>> for SVMCore<KernelSparse, Spa
}

// Predict the value for one problem.
fn predict_value(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), SVMError> {
fn predict_value(&self, problem: &mut Problem<SparseVector<f32>>) -> Result<(), Error> {
match self.svm_type {
SVMType::CSvc | SVMType::NuSvc => {
// Compute kernel, decision values and eventually the label
Expand All @@ -237,7 +237,7 @@ impl Predict<SparseVector<f32>, SparseVector<f64>> for SVMCore<KernelSparse, Spa

// Compute highest vote
let highest_vote = find_max_index(&problem.vote);
problem.result = SVMResult::Label(self.classes[highest_vote].label);
problem.result = Outcome::Label(self.classes[highest_vote].label);

Ok(())
}
Expand All @@ -251,18 +251,18 @@ impl Predict<SparseVector<f32>, SparseVector<f64>> for SVMCore<KernelSparse, Spa
}

impl<'a, 'b> TryFrom<&'a str> for SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>> {
type Error = SVMError;
type Error = Error;

fn try_from(input: &'a str) -> Result<SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>>, SVMError> {
fn try_from(input: &'a str) -> Result<SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>>, Error> {
let raw_model = ModelFile::try_from(input)?;
Self::try_from(&raw_model)
}
}

impl<'a, 'b> TryFrom<&'a ModelFile<'b>> for SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>> {
type Error = SVMError;
type Error = Error;

fn try_from(raw_model: &'a ModelFile) -> Result<SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>>, SVMError> {
fn try_from(raw_model: &'a ModelFile) -> Result<SVMCore<KernelSparse, SparseMatrix<f32>, SparseVector<f32>, SparseVector<f64>>, Error> {
// To quickly check what broke again during parsing ...
// println!("{:?}", raw_model);

Expand Down
12 changes: 6 additions & 6 deletions src/svm/kernel/poly.rs
Expand Up @@ -2,7 +2,7 @@ use std::convert::{From, TryFrom};

use super::{KernelDense, KernelSparse};
use crate::{
errors::SVMError,
errors::Error,
parser::ModelFile,
sparse::{SparseMatrix, SparseVector},
};
Expand Down Expand Up @@ -60,12 +60,12 @@ impl KernelSparse for Poly {
}

impl<'a, 'b> TryFrom<&'a ModelFile<'b>> for Poly {
type Error = SVMError;
type Error = Error;

fn try_from(raw_model: &'a ModelFile<'b>) -> Result<Poly, SVMError> {
let gamma = raw_model.header.gamma.ok_or(SVMError::NoGamma)?;
let coef0 = raw_model.header.coef0.ok_or(SVMError::NoCoef0)?;
let degree = raw_model.header.degree.ok_or(SVMError::NoDegree)?;
fn try_from(raw_model: &'a ModelFile<'b>) -> Result<Poly, Error> {
let gamma = raw_model.header.gamma.ok_or(Error::NoGamma)?;
let coef0 = raw_model.header.coef0.ok_or(Error::NoCoef0)?;
let degree = raw_model.header.degree.ok_or(Error::NoDegree)?;

Ok(Poly { gamma, coef0, degree })
}
Expand Down

0 comments on commit 60934db

Please sign in to comment.