1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
//! Linear basis projection module.

use geometry::Vector;

pub(crate) type ActivationT = f64;
pub(crate) type IndexT = usize;

pub(crate) type DenseT = Vector<ActivationT>;
pub(crate) type SparseT = Vector<IndexT>;

#[inline]
pub(self) fn l1(x: &[ActivationT]) -> ActivationT {
    x.into_iter().fold(0.0, |acc, v| acc + v.abs())
}

/// Projected feature vector representation.
#[derive(Clone, Serialize, Deserialize)]
pub enum Projection {
    /// Dense, floating-point activation vector.
    Dense(DenseT),

    /// Sparse, index-based activation vector.
    Sparse(SparseT),
}

impl Projection {
    /// Compute the l1 normalisation constant of the projection.
    pub fn z(&self) -> ActivationT {
        match self {
            &Projection::Dense(ref activations) => l1(activations.as_slice().unwrap()),
            &Projection::Sparse(ref active_indices) => active_indices.len() as ActivationT,
        }
    }
}

impl Into<Projection> for DenseT {
    fn into(self) -> Projection { Projection::Dense(self) }
}

impl Into<Projection> for SparseT {
    fn into(self) -> Projection { Projection::Sparse(self) }
}

/// Trait for basis projectors.
pub trait Projector<I: ?Sized> {
    /// Project data from an input space onto the basis.
    fn project(&self, input: &I) -> Projection;

    /// Return the number of dimensions in the basis space.
    fn dim(&self) -> usize;

    /// Return the number of features in the basis space.
    fn size(&self) -> usize;

    /// Return the maximum number of active features in the basis space.
    fn activity(&self) -> usize;

    /// Check for equivalence with another projector of the same type.
    fn equivalent(&self, other: &Self) -> bool;

    /// Project data from an input space onto the basis and convert into a raw,
    /// dense vector.
    fn project_expanded(&self, input: &I) -> DenseT { self.expand_projection(self.project(input)) }

    /// Expand and normalise a given projection, and convert into a raw, dense
    /// vector.
    fn expand_projection(&self, projection: Projection) -> DenseT {
        #[inline]
        fn expand_sparse(active_indices: SparseT, z: ActivationT, size: usize) -> DenseT {
            let mut phi = Vector::zeros((size,));

            let activation = 1.0 / z;
            for idx in active_indices.iter() {
                phi[*idx] = activation;
            }

            phi
        }

        match projection.z() {
            z if z.abs() < 1e-6 => match projection {
                Projection::Dense(phi) => phi,
                Projection::Sparse(active_indices) => {
                    expand_sparse(active_indices, 1.0, self.size())
                },
            },
            z => match projection {
                Projection::Dense(phi) => phi.iter().map(|x| x / z).collect(),
                Projection::Sparse(active_indices) => expand_sparse(active_indices, z, self.size()),
            },
        }
    }
}

mod rbf_network;
pub use self::rbf_network::*;

mod fourier;
pub use self::fourier::*;

mod polynomial;
pub use self::polynomial::*;

mod tile_coding;
pub use self::tile_coding::*;

// mod uniform_grid;
// pub use self::uniform_grid::*;