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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
/*! Totsu ([凸](http://www.decodeunicode.org/en/u+51F8) in Japanese) means convex. <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> This crate for Rust provides **a first-order conic linear program solver**. # Target problem A common target problem is continuous scalar **convex optimization** such as LP, QP, QCQP, SOCP and SDP. Each of those problems can be represented as a conic linear program: \\[ \begin{array}{ll} {\rm minimize} & c^T x \\\\ {\rm subject \ to} & A x + s = b \\\\ & s \in \mathcal{K}, \end{array} \\] where * variables \\( x \in \mathbb{R}^n,\ s \in \mathbb{R}^m \\) * \\( c \in \mathbb{R}^n \\) as an objective linear operator * \\( A \in \mathbb{R}^{m \times n} \\) and \\( b \in \mathbb{R}^m \\) as constraint linear operators * a nonempty, closed, convex cone \\( \mathcal{K} \\). # Algorithm and design concepts The author combines the two papers [\[1\]](https://ieeexplore.ieee.org/abstract/document/6126441) [\[2\]](https://arxiv.org/abs/1312.3039) so that the homogeneous self-dual embedding matrix in [\[2\]](https://arxiv.org/abs/1312.3039) is formed as a linear operator in [\[1\]](https://ieeexplore.ieee.org/abstract/document/6126441). A core method [`solver::Solver::solve`] takes the following arguments: * objective and constraint linear operators that implement [`operator::Operator`] trait and * a projection onto a cone that implements [`cone::Cone`] trait. Therefore solving a specific problem requires an implementation of those traits. You can use pre-defined implementations (see [`problem`]), as well as construct a user-defined tailored version for the reason of functionality and efficiency. Modules [`operator`] and [`cone`] include several basic structs that implement [`operator::Operator`] and [`cone::Cone`] trait. Core linear algebra operations that [`solver::Solver`] requires are abstracted by [`linalg::LinAlg`] trait, while subtrait [`linalg::LinAlgEx`] is used for [`operator`], [`cone`] and [`problem`] modules. This crate includes two [`linalg::LinAlgEx`] implementors: * [`linalg::FloatGeneric`] - `num::Float`-generic implementation (pure Rust but slow) * [`linalg::F64LAPACK`] - `f64`-specific implementation using `cblas-sys` and `lapacke-sys`. ## Features ### Using [`linalg::F64LAPACK`] ```toml [dependencies.totsu] version = "0.8.0" features = ["f64lapack"] ``` In addition you need a [BLAS/LAPACK source](https://github.com/blas-lapack-rs/blas-lapack-rs.github.io/wiki#sources) to link. ### Without `std` This crate can be used without the standard library (`#![no_std]`). Use this in `Cargo.toml`: ```toml [dependencies.totsu] version = "0.8.0" default-features = false features = ["libm"] ``` Some module and structs are not availale in this case: * [`problem`] * [`operator::MatBuild`] ## Changelog Changelog is available in [CHANGELOG.md](https://github.com/convexbrain/Totsu/blob/master/solver_rust_conic/CHANGELOG.md). # Examples ## QP ``` # #[cfg(feature = "f64lapack")] # use intel_mkl_src as _; use float_eq::assert_float_eq; use totsu::prelude::*; use totsu::operator::MatBuild; use totsu::problem::ProbQP; //env_logger::init(); type LA = FloatGeneric<f64>; type AMatBuild = MatBuild<LA, f64>; type AProbQP = ProbQP<LA, f64>; type ASolver = Solver<LA, f64>; let n = 2; // x0, x1 let m = 1; let p = 0; // (1/2)(x - a)^2 + const let mut sym_p = AMatBuild::new(MatType::SymPack(n)); sym_p[(0, 0)] = 1.; sym_p[(1, 1)] = 1.; let mut vec_q = AMatBuild::new(MatType::General(n, 1)); vec_q[(0, 0)] = -(-1.); // -a0 vec_q[(1, 0)] = -(-2.); // -a1 // 1 - x0/b0 - x1/b1 <= 0 let mut mat_g = AMatBuild::new(MatType::General(m, n)); mat_g[(0, 0)] = -1. / 2.; // -1/b0 mat_g[(0, 1)] = -1. / 3.; // -1/b1 let mut vec_h = AMatBuild::new(MatType::General(m, 1)); vec_h[(0, 0)] = -1.; let mat_a = AMatBuild::new(MatType::General(p, n)); let vec_b = AMatBuild::new(MatType::General(p, 1)); let s = ASolver::new().par(|p| { p.max_iter = Some(100_000); }); let mut qp = AProbQP::new(sym_p, vec_q, mat_g, vec_h, mat_a, vec_b, s.par.eps_zero); let rslt = s.solve(qp.problem()).unwrap(); assert_float_eq!(rslt.0[0..2], [2., 0.].as_ref(), abs_all <= 1e-3); ``` ## Other examples You can find other [tests](https://github.com/convexbrain/Totsu/tree/master/solver_rust_conic/tests) of pre-defined problems. More practical [examples](https://github.com/convexbrain/Totsu/tree/master/examples) are also available. ## References 1. T. Pock and A. Chambolle. "Diagonal preconditioning for first order primal-dual algorithms in convex optimization." 2011 International Conference on Computer Vision. IEEE, 2011. 1. B. O’donoghue, et al. "Conic optimization via operator splitting and homogeneous self-dual embedding." Journal of Optimization Theory and Applications 169.3 (2016): 1042-1068. 1. N. Parikh and S. Boyd. "Proximal algorithms." Foundations and Trends in optimization 1.3 (2014): 127-239. 1. Mosek ApS. "MOSEK modeling cookbook." (2020). 1. S. Boyd and L. Vandenberghe. "Convex Optimization." (2004). */ #![no_std] #[cfg(feature = "std")] extern crate std; pub mod solver; // core, Float mod utils; pub mod linalg; pub mod operator; pub mod cone; #[cfg(feature = "std")] pub mod problem; /// Prelude pub mod prelude // core, Float { pub use super::solver::{Solver, SolverError, SolverParam}; pub use super::linalg::{LinAlg, LinAlgEx, FloatGeneric}; pub use super::operator::{Operator, MatType, MatOp}; pub use super::cone::{Cone, ConeZero, ConeRPos, ConeSOC, ConePSD}; } // TODO: more tests