1extern crate nalgebra as na;
2
3use na::{OMatrix, OVector, Vector, Matrix, Scalar, Dim, default_allocator::DefaultAllocator, allocator::Allocator, convert, RealField, DimMin, DimSub, Const, storage::Owned};
4
5
6#[allow(non_snake_case)]
11pub fn solve<T, M, N>(A: &OMatrix<T,M,N>, b: &OVector<T,M>, c: &OVector<T,N>, eps: T, theta: T, gamma: T, max_it: usize) -> (OVector<T, N>,OVector<T,M>)
12 where
13 T: Scalar + RealField + Copy,
14 M: Dim + DimMin<M, Output = M> + DimSub<Const<1>>,
15 N: Dim + DimMin<N, Output = N>,
16 DefaultAllocator: Allocator<T, M> + Allocator<T, M, N> + Allocator<T, N, M> + Allocator<T, N, N> + Allocator<T, N> + Allocator<T, M, M> + Allocator<(T, usize), M> + Allocator<(usize, usize), M> + Allocator<T, <M as DimSub<Const<1>>>::Output> {
17 let one: T = convert(1.0);
18 let max_val = T::max_value().unwrap();
19 let svd_eps: T = convert(1e-20);
20 let A_transpose = A.transpose();
21 let n = A.ncols();
22 let m = A.nrows();
23
24 let mut gamma_mu = Vector::<T,N, Owned<T,N,Const<1>>>::from_element_generic(Dim::from_usize(n), Const::<1>,one);
25 let mut x = Vector::<T,N, Owned<T,N,Const<1>>>::from_element_generic(Dim::from_usize(n), Const::<1>,one);
26 let mut s = Vector::<T,N, Owned<T,N,Const<1>>>::from_element_generic(Dim::from_usize(n), Const::<1>,one);
27 let mut y = Vector::<T,M, Owned<T,M,Const<1>>>::zeros_generic(Dim::from_usize(m), Const::<1>);
28 let mut r_primal = Vector::<T,M, Owned<T,M,Const<1>>>::from_element_generic(Dim::from_usize(m), Const::<1>,max_val);
29 let mut r_dual = Vector::<T,N, Owned<T,N,Const<1>>>::from_element_generic(Dim::from_usize(n), Const::<1>,max_val);
30 let mut k = 0;
31 let mut S_inv = Matrix::<T,N,N,Owned<T,N,N>>::zeros_generic(Dim::from_usize(n), Dim::from_usize(n));
32 let mut X = Matrix::<T,N,N,Owned<T,N,N>>::zeros_generic(Dim::from_usize(n), Dim::from_usize(n));
33 let n_f64 : T = convert(n as f64);
34
35 while k < max_it && (r_primal.norm() > eps || r_dual.norm() > eps || x.dot(&s) > eps) {
36 r_primal = b - A*(&x);
37 r_dual = c - (&A_transpose)*(&y) - (&s);
38 let mu = x.dot(&s)/n_f64;
39 for i in 0..n {
40 S_inv[(i,i)] = one/s[i];
41 X[(i,i)] = x[i];
42 gamma_mu[i] = gamma*mu;
43 }
44 let M = A*(&S_inv)*(&X)*(&A_transpose);
45 let r = b + A*(&S_inv)*((&X)*(&r_dual) - (&gamma_mu));
46 let d_y = M.svd(true,true).solve(&r, svd_eps).expect("direction y failed");
47 let d_s = (&r_dual) - (&A_transpose)*(&d_y);
48 let d_x = -(&x) + (&S_inv)*((&gamma_mu)-(&X)*(&d_s));
49
50 let mut step_primal = max_val;
51 let mut step_dual = max_val;
52
53 for i in 0..n {
54 let dx_i = d_x[i];
55 let ds_i = d_s[i];
56
57 if dx_i < T::zero() {
58 let v = -x[i]/dx_i;
59 step_primal = step_primal.min(v);
60 }
61
62 if ds_i < T::zero() {
63 let v = -s[i]/ds_i;
64 step_dual = step_dual.min(v);
65 }
66 }
67
68 let step_max = step_primal.min(step_dual);
69 let step = one.min(theta*step_max);
70
71 x = x+d_x.scale(step);
72 y = y+d_y.scale(step);
73 s = s+d_s.scale(step);
74 k = k+1;
75 }
76
77 (x,y)
78}