First version of the optimizer
This commit is contained in:
+54
-1
@@ -1,4 +1,5 @@
|
||||
use std::ops::Range;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub mod naive;
|
||||
|
||||
@@ -30,4 +31,56 @@ pub trait Matrix: Into<Vec<f64>> + Clone{
|
||||
|
||||
fn add_mut(&mut self, other: &Self);
|
||||
|
||||
}
|
||||
fn add_scalar_mut(&mut self, scalar: f64);
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64);
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64);
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64);
|
||||
|
||||
fn transpose(&self) -> Self;
|
||||
|
||||
fn generate_positive_definite(nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self;
|
||||
|
||||
fn norm2(&self) -> f64;
|
||||
|
||||
fn negative_mut(&mut self);
|
||||
|
||||
}
|
||||
|
||||
pub trait Vector: Into<Vec<f64>> + Clone + Debug {
|
||||
|
||||
fn get(&self, i: usize) -> f64;
|
||||
|
||||
fn set(&mut self, i: usize, value: f64);
|
||||
|
||||
fn zeros(size: usize) -> Self;
|
||||
|
||||
fn ones(size: usize) -> Self;
|
||||
|
||||
fn fill(size: usize, value: f64) -> Self;
|
||||
|
||||
fn shape(&self) -> (usize, usize);
|
||||
|
||||
fn norm2(&self) -> f64;
|
||||
|
||||
fn negative_mut(&mut self) -> &Self;
|
||||
|
||||
fn negative(&self) -> Self;
|
||||
|
||||
fn add_mut(&mut self, other: &Self) -> &Self;
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) -> &Self;
|
||||
|
||||
fn dot(&self, other: &Self) -> f64;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::ops::Range;
|
||||
use crate::linalg::Matrix;
|
||||
use crate::math;
|
||||
use rand::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DenseMatrix {
|
||||
@@ -673,6 +674,78 @@ impl Matrix for DenseMatrix {
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_positive_definite(nrows: usize, ncols: usize) -> Self {
|
||||
let m = DenseMatrix::rand(nrows, ncols);
|
||||
m.dot(&m.transpose())
|
||||
}
|
||||
|
||||
fn transpose(&self) -> Self {
|
||||
let mut m = DenseMatrix {
|
||||
ncols: self.nrows,
|
||||
nrows: self.ncols,
|
||||
values: vec![0f64; self.ncols * self.nrows]
|
||||
};
|
||||
for c in 0..self.ncols {
|
||||
for r in 0..self.nrows {
|
||||
m.set(c, r, self.get(r, c));
|
||||
}
|
||||
}
|
||||
m
|
||||
|
||||
}
|
||||
|
||||
fn rand(nrows: usize, ncols: usize) -> Self {
|
||||
let mut rng = rand::thread_rng();
|
||||
let values: Vec<f64> = (0..nrows*ncols).map(|_| {
|
||||
rng.gen()
|
||||
}).collect();
|
||||
DenseMatrix {
|
||||
ncols: ncols,
|
||||
nrows: nrows,
|
||||
values: values
|
||||
}
|
||||
}
|
||||
|
||||
fn norm2(&self) -> f64 {
|
||||
let mut norm = 0f64;
|
||||
|
||||
for xi in self.values.iter() {
|
||||
norm += xi * xi;
|
||||
}
|
||||
|
||||
norm.sqrt()
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] += scalar;
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] -= scalar;
|
||||
}
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] *= scalar;
|
||||
}
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] /= scalar;
|
||||
}
|
||||
}
|
||||
|
||||
fn negative_mut(&mut self) {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = -self.values[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -799,5 +872,32 @@ mod tests {
|
||||
assert!(!m.approximate_eq(&m_neq, 0.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rand() {
|
||||
let m = DenseMatrix::rand(3, 3);
|
||||
for c in 0..3 {
|
||||
for r in 0..3 {
|
||||
assert!(m.get(r, c) != 0f64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transpose() {
|
||||
let m = DenseMatrix::from_2d_array(&[&[1.0, 3.0], &[2.0, 4.0]]);
|
||||
let expected = DenseMatrix::from_2d_array(&[&[1.0, 2.0], &[3.0, 4.0]]);
|
||||
let m_transposed = m.transpose();
|
||||
for c in 0..2 {
|
||||
for r in 0..2 {
|
||||
assert!(m_transposed.get(r, c) == expected.get(r, c));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn generate_positive_definite() {
|
||||
let m = DenseMatrix::generate_positive_definite(3, 3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
use crate::linalg::Vector;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DenseVector {
|
||||
|
||||
size: usize,
|
||||
values: Vec<f64>
|
||||
|
||||
}
|
||||
|
||||
impl DenseVector {
|
||||
|
||||
pub fn from_array(values: &[f64]) -> DenseVector {
|
||||
DenseVector::from_vec(Vec::from(values))
|
||||
}
|
||||
|
||||
pub fn from_vec(values: Vec<f64>) -> DenseVector {
|
||||
DenseVector {
|
||||
size: values.len(),
|
||||
values: values
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Into<Vec<f64>> for DenseVector {
|
||||
fn into(self) -> Vec<f64> {
|
||||
self.values
|
||||
}
|
||||
}
|
||||
|
||||
impl Vector for DenseVector {
|
||||
|
||||
fn get(&self, i: usize) -> f64 {
|
||||
self.values[i]
|
||||
}
|
||||
|
||||
fn set(&mut self, i: usize, value: f64) {
|
||||
self.values[i] = value;
|
||||
}
|
||||
|
||||
fn zeros(size: usize) -> Self {
|
||||
DenseVector::fill(size, 0f64)
|
||||
}
|
||||
|
||||
fn ones(size: usize) -> Self {
|
||||
DenseVector::fill(size, 1f64)
|
||||
}
|
||||
|
||||
fn fill(size: usize, value: f64) -> Self {
|
||||
DenseVector::from_vec(vec![value; size])
|
||||
}
|
||||
|
||||
fn shape(&self) -> (usize, usize) {
|
||||
(1, self.size)
|
||||
}
|
||||
|
||||
fn add_mut(&mut self, other: &Self) -> &Self {
|
||||
if self.size != other.size {
|
||||
panic!("A and B should have the same shape");
|
||||
}
|
||||
for i in 0..self.size {
|
||||
self.values[i] += other.values[i];
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
fn dot(&self, other: &Self) -> f64 {
|
||||
if self.size != other.size {
|
||||
panic!("A and B should be of the same size");
|
||||
}
|
||||
|
||||
let mut result = 0f64;
|
||||
for i in 0..self.size {
|
||||
result += self.get(i) * other.get(i);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn norm2(&self) -> f64 {
|
||||
let mut norm = 0f64;
|
||||
|
||||
for xi in self.values.iter() {
|
||||
norm += xi * xi;
|
||||
}
|
||||
|
||||
norm.sqrt()
|
||||
}
|
||||
|
||||
fn add_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] += scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn sub_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] -= scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn mul_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] *= scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn div_scalar_mut(&mut self, scalar: f64) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] /= scalar;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn negative_mut(&mut self) -> &Self {
|
||||
for i in 0..self.values.len() {
|
||||
self.values[i] = -self.values[i];
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
fn negative(&self) -> Self {
|
||||
let mut result = DenseVector {
|
||||
size: self.size,
|
||||
values: self.values.clone()
|
||||
};
|
||||
for i in 0..self.values.len() {
|
||||
result.values[i] = -self.values[i];
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
pub mod dense_matrix;
|
||||
pub mod dense_matrix;
|
||||
pub mod dense_vector;
|
||||
Reference in New Issue
Block a user