Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework to conversion and allowing many input types #49

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,14 @@ println!("samples: {:?}", sampler.sample(&mut rng));

Most methods of this library can currently work with the following `input -> ouput` pairs :

- `Vec<f64> -> f64` a single, multidimensional, sample
- `Vec<Vec<f64>> -> Vec<f64>` each inner vector is a training sample
- `DMatrix<f64> -> DVector<f64>` using a [nalgebra](https://www.nalgebra.org/) matrix with one row per sample
- `ArrayBase<f64, Ix1> -> f64` a single sample stored in a [ndarray](https://crates.io/crates/ndarray) array (using the `friedrich_ndarray` feature)
- `ArrayBase<f64, Ix2> -> Array1<f64>` each row is a sample (using the `friedrich_ndarray` feature)
Input | Output | Description
---|---|---
[`Array2<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array2.html) | [`Array1<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array1.html) | Multiple input vectors to multiple output values (with `friedrich_ndarray` feature).
[`Array1<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array1.html) | [`f64`](https://doc.rust-lang.org/std/primitive.f64.html) | A single input vector to a single output value (with `friedrich_ndarray` feature).
[`DMatrix<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DMatrix.html) | [`DVector<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DVector.html) | Multiple input vectors to multiple output values.
[`DVector<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DVector.html) | [`f64`](https://doc.rust-lang.org/std/primitive.f64.html) | A single input vector to a single output value.
[`Vec<Vec<f64>>`](https://doc.rust-lang.org/std/vec/struct.Vec.html) | [`Vec<f64>` ](https://doc.rust-lang.org/std/vec/struct.Vec.html) | Multiple input vectors to multiple output values.
[`Vec<f64>`](https://doc.rust-lang.org/std/vec/struct.Vec.html) | [`f64` ](https://doc.rust-lang.org/std/primitive.f64.html) | A single input vector to a single input value.

The [Input trait](https://docs.rs/friedrich/latest/friedrich/trait.Input.html) is provided to add your own pairs.

Expand Down
4 changes: 2 additions & 2 deletions src/algebra/extendable_matrix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ impl EVector
mod tests
{
use super::*;
use crate::conversion::Input;
use crate::conversion::InternalConvert;

#[test]
fn ematrix_add_rows_extend_size_when_some_of_current_data_is_masked()
{
let x = Input::into_dmatrix(vec![vec![1.0f64], vec![2.0f64]]);
let x = (vec![vec![1.0f64], vec![2.0f64]]).i_into();
let mut e = EMatrix::new(x.clone());
for _ in 0..5
{
Expand Down
181 changes: 181 additions & 0 deletions src/conversion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/// Implemented by `Input -> Output` type pairs
///
/// Handles conversion to DMatrix type and stores information on associated output type.
/// Most methods of this library can currently work with the following `input -> output` pairs :
///
/// Input | Output | Description
/// ---|---|---
/// [`Array2<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array2.html) | [`Array1<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array1.html) | Multiple input vectors to multiple output values (with `friedrich_ndarray` feature).
/// [`Array1<f64>`](https://docs.rs/ndarray/0.15/ndarray/type.Array1.html) | [`f64`] | A single input vector to a single output value (with `friedrich_ndarray` feature).
/// [`DMatrix<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DMatrix.html) | [`DVector<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DVector.html) | Multiple input vectors to multiple output values.
/// [`DVector<f64>`](https://docs.rs/nalgebra/0.29/nalgebra/base/type.DVector.html) | [`f64`] | A single input vector to a single output value.
/// [`Vec<Vec<f64>>`] | [`Vec<f64>` ] | Multiple input vectors to multiple output values.
/// [`Vec<f64>`] | [`f64` ] | A single input vector to a single input value.
///
/// User-defined input type should implement this trait.
pub trait Input: InternalConvert<nalgebra::base::DMatrix<f64>> + Clone
{
type Output: InternalConvert<nalgebra::base::DVector<f64>> + Clone;
}
/// We cannot implement a foreign trait on foreign types, so we use this local trait to mimic [`std::convert::From`].
pub trait InternalConvert<T>
{
fn i_into(self) -> T;
fn i_from(x: T) -> Self;
}
// Implementing for ndarray
// -------------------------------------------
#[cfg(feature = "friedrich_ndarray")]
impl Input for ndarray::Array1<f64>
{
type Output = f64;
}
#[cfg(feature = "friedrich_ndarray")]
impl InternalConvert<nalgebra::base::DMatrix<f64>> for ndarray::Array1<f64>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
nalgebra::base::DMatrix::from_iterator(1, self.len(), self.into_iter())
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
Self::from_iter(x.into_iter())
}
}
// -------------------------------------------
#[cfg(feature = "friedrich_ndarray")]
impl Input for ndarray::Array2<f64>
{
type Output = ndarray::Array1<f64>;
}
#[cfg(feature = "friedrich_ndarray")]
impl InternalConvert<nalgebra::base::DMatrix<f64>> for ndarray::Array2<f64>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
nalgebra::base::DMatrix::from_iterator(self.dim().0, self.dim().1, self.into_iter())
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
Self::from_shape_vec(x.shape(), x.into_iter().collect::<Vec<_>>())
}
}
#[cfg(feature = "friedrich_ndarray")]
impl InternalConvert<nalgebra::base::DVector<f64>> for ndarray::Array1<f64>
{
fn i_into(self) -> nalgebra::base::DVector<f64>
{
nalgebra::base::DVector::from_iterator(self.len(), self.into_iter())
}
fn i_from(x: nalgebra::base::DVector<f64>) -> Self
{
Self::from_iter(x.into_iter())
}
}
// Implementing for nalgebra
// -------------------------------------------=
impl Input for nalgebra::base::DVector<f64>
{
type Output = f64;
}
impl InternalConvert<nalgebra::base::DMatrix<f64>> for nalgebra::base::DVector<f64>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
nalgebra::base::DMatrix::from_iterator(1, self.len(), self.iter().cloned())
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
Self::from_iterator(x.len(), x.into_iter().cloned())
}
}
impl InternalConvert<nalgebra::base::DVector<f64>> for f64
{
fn i_into(self) -> nalgebra::base::DVector<f64>
{
nalgebra::dvector![self]
}
fn i_from(x: nalgebra::base::DVector<f64>) -> Self
{
x[0]
}
}
// -------------------------------------------
impl Input for nalgebra::base::DMatrix<f64>
{
type Output = nalgebra::base::DVector<f64>;
}
impl InternalConvert<nalgebra::base::DMatrix<f64>> for nalgebra::base::DMatrix<f64>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
self
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
x
}
}
impl InternalConvert<nalgebra::base::DVector<f64>> for nalgebra::base::DVector<f64>
{
fn i_into(self) -> nalgebra::base::DVector<f64>
{
self
}
fn i_from(x: nalgebra::base::DVector<f64>) -> Self
{
x
}
}

// Implementing for vec
// -------------------------------------------
impl Input for Vec<Vec<f64>>
{
type Output = Vec<f64>;
}
impl InternalConvert<nalgebra::base::DMatrix<f64>> for Vec<Vec<f64>>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
assert!(!self.is_empty());
assert!(!self[0].is_empty());

nalgebra::base::DMatrix::from_vec(self.len(),
self[0].len(),
self.into_iter().flatten().collect::<Vec<_>>())
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
x.row_iter().map(|row| row.iter().cloned().collect::<Vec<_>>()).collect::<Vec<_>>()
}
}
impl InternalConvert<nalgebra::base::DVector<f64>> for Vec<f64>
{
fn i_into(self) -> nalgebra::base::DVector<f64>
{
nalgebra::base::DVector::from_vec(self)
}
fn i_from(x: nalgebra::base::DVector<f64>) -> Self
{
x.iter().cloned().collect::<Vec<_>>()
}
}
// -------------------------------------------
impl Input for Vec<f64>
{
type Output = f64;
}
impl InternalConvert<nalgebra::base::DMatrix<f64>> for Vec<f64>
{
fn i_into(self) -> nalgebra::base::DMatrix<f64>
{
assert!(!self.is_empty());

nalgebra::base::DMatrix::from_vec(self.len(), 1, self)
}
fn i_from(x: nalgebra::base::DMatrix<f64>) -> Self
{
x.iter().cloned().collect::<Vec<_>>()
}
}
Loading