1 /** 2 * @file sdp.hpp 3 * @author Stephen Tu 4 * 5 * 6 * ensmallen is free software; you may redistribute it and/or modify it under 7 * the terms of the 3-clause BSD license. You should have received a copy of 8 * the 3-clause BSD license along with ensmallen. If not, see 9 * http://www.opensource.org/licenses/BSD-3-Clause for more information. 10 */ 11 #ifndef ENSMALLEN_SDP_SDP_HPP 12 #define ENSMALLEN_SDP_SDP_HPP 13 14 namespace ens { 15 16 /** 17 * Specify an SDP in primal form 18 * 19 * min dot(C, X) 20 * s.t. dot(Ai, X) = bi, i=1,...,m, X >= 0 21 * 22 * This representation allows the constraint matrices Ai to be specified as 23 * either dense matrices (arma::mat) or sparse matrices (arma::sp_mat). After 24 * initializing the SDP object, you will need to set the constraints yourself, 25 * via the SparseA(), SparseB(), DenseA(), DenseB(), and C() functions. Note 26 * that for each matrix you add to either SparseA() or DenseA(), you must add 27 * the corresponding b value to the corresponding vector SparseB() or DenseB(). 28 * 29 * The objective matrix (C) may be stored as either dense or sparse depending on 30 * the ObjectiveMatrixType parameter. 31 * 32 * @tparam ObjectiveMatrixType Should be either arma::mat or arma::sp_mat. 33 */ 34 template<typename ObjectiveMatrixType, 35 typename DenseConstraintMatrixType = 36 arma::Mat<typename ObjectiveMatrixType::elem_type>, 37 typename SparseConstraintMatrixType = 38 arma::SpMat<typename ObjectiveMatrixType::elem_type>, 39 typename BVectorType = 40 arma::Col<typename ObjectiveMatrixType::elem_type>> 41 class SDP 42 { 43 public: 44 //! Type of objective matrix. 45 typedef ObjectiveMatrixType ObjectiveType; 46 //! Type of element held by the SDP. 47 typedef typename ObjectiveMatrixType::elem_type ElemType; 48 //! Type of dense constraints. 49 typedef DenseConstraintMatrixType DenseConstraintType; 50 //! Type of sparse constraints. 51 typedef SparseConstraintMatrixType SparseConstraintType; 52 //! Type of B values. 53 typedef BVectorType BType; 54 55 /** 56 * Initialize this SDP to an empty state. To add constraints, you will have 57 * to modify the constraints via the SparseA(), DenseA(), SparseB(), DenseB(), 58 * and C() functions. For the sake of speed, there is no error checking, so 59 * if you specify an invalid SDP, whatever solver you use will gladly try to 60 * solve it! (And it will probably crash horribly.) 61 */ 62 SDP(); 63 64 /** 65 * Initialize this SDP to one which structurally has size n. To set the 66 * constraints you will still need to access through SparseA(), DenseA(), 67 * SparseB(), DenseB(), and C(). Consider using move semantics to keep things 68 * fast. As with the previous constructor, there is no error checking for the 69 * sake of speed, so if you build an invalid SDP, whatever solver you use will 70 * gladly try to solve it! (And it will probably crash horribly.) 71 * 72 * @param n Number of rows (and columns) in the objective matrix C. 73 * @param numSparseConstraints Number of sparse constraints. 74 * @param numDenseConstraints Number of dense constraints. 75 */ 76 SDP(const size_t n, 77 const size_t numSparseConstraints, 78 const size_t numDenseConstraints); 79 80 //! Return number of rows and columns in the objective matrix C. N() const81 size_t N() const { return c.n_rows; } 82 N2bar() const83 size_t N2bar() const { return N() * (N() + 1) / 2; } 84 85 //! Return the number of sparse constraints (constraints with sparse Ai) in 86 //! the SDP. NumSparseConstraints() const87 size_t NumSparseConstraints() const { return sparseB.n_elem; } 88 //! Return the number of dense constraints (constraints with dense Ai) in the 89 //! SDP. NumDenseConstraints() const90 size_t NumDenseConstraints() const { return denseB.n_elem; } 91 92 //! Return the total number of constraints in the SDP. NumConstraints() const93 size_t NumConstraints() const { return sparseB.n_elem + denseB.n_elem; } 94 95 //! Modify the sparse objective function matrix (sparseC). C()96 ObjectiveMatrixType& C() { return c; } 97 //! Return the sparse objective function matrix (sparseC). C() const98 const ObjectiveMatrixType& C() const { return c; } 99 100 //! Return the vector of sparse A matrices (which correspond to the sparse 101 //! constraints). SparseA() const102 const std::vector<SparseConstraintMatrixType>& SparseA() const 103 { return sparseA; } 104 105 //! Modify the vector of sparse A matrices (which correspond to the sparse 106 //! constraints). SparseA()107 std::vector<SparseConstraintMatrixType>& SparseA() { return sparseA; } 108 109 //! Return the vector of dense A matrices (which correspond to the dense 110 //! constraints). DenseA() const111 const std::vector<DenseConstraintMatrixType>& DenseA() const 112 { return denseA; } 113 114 //! Modify the vector of dense A matrices (which correspond to the dense 115 //! constraints). DenseA()116 std::vector<DenseConstraintMatrixType>& DenseA() { return denseA; } 117 118 //! Return the vector of sparse B values. SparseB() const119 const BVectorType& SparseB() const { return sparseB; } 120 //! Modify the vector of sparse B values. SparseB()121 BVectorType& SparseB() { return sparseB; } 122 123 //! Return the vector of dense B values. DenseB() const124 const BVectorType& DenseB() const { return denseB; } 125 //! Modify the vector of dense B values. DenseB()126 BVectorType& DenseB() { return denseB; } 127 128 /** 129 * Check whether or not the constraint matrices are linearly independent. 130 * 131 * Warning: possibly very expensive check. 132 */ 133 bool HasLinearlyIndependentConstraints() const; 134 135 //! Get an initial point for the primal coordinates. 136 template<typename MatType = arma::mat> 137 MatType GetInitialPoint() const; 138 139 //! Get initial points for the primal and dual coordinates. 140 template<typename MatType = arma::mat> 141 void GetInitialPoints(MatType& coordinates, 142 MatType& ySparse, 143 MatType& yDense, 144 MatType& dualCoordinates) const; 145 146 private: 147 //! Objective function matrix c. 148 ObjectiveMatrixType c; 149 150 //! A_i for each sparse constraint. 151 std::vector<SparseConstraintMatrixType> sparseA; 152 //! b_i for each sparse constraint. 153 BVectorType sparseB; 154 155 //! A_i for each dense constraint. 156 std::vector<DenseConstraintMatrixType> denseA; 157 //! b_i for each dense constraint. 158 BVectorType denseB; 159 }; 160 161 } // namespace ens 162 163 // Include implementation. 164 #include "sdp_impl.hpp" 165 166 #endif 167