43 #include "Moocho_ConfigDefs.hpp"
46 #ifdef CONSTRAINED_OPTIMIZATION_PACK_USE_QPKWIK
53 #include "ConstrainedOptPack_QPSolverRelaxedQPKWIK.hpp"
54 #include "AbstractLinAlgPack_SpVectorClass.hpp"
55 #include "AbstractLinAlgPack_MatrixSymOp.hpp"
56 #include "AbstractLinAlgPack_EtaVector.hpp"
57 #include "AbstractLinAlgPack_VectorAuxiliaryOps.hpp"
58 #include "AbstractLinAlgPack_MatrixExtractInvCholFactor.hpp"
59 #include "AbstractLinAlgPack_SortByDescendingAbsValue.hpp"
60 #include "AbstractLinAlgPack_VectorDenseEncap.hpp"
61 #include "AbstractLinAlgPack_LinAlgOpPackHack.hpp"
62 #include "DenseLinAlgPack_LinAlgOpPack.hpp"
63 #include "AbstractLinAlgPack_sparse_bounds.hpp"
64 #include "AbstractLinAlgPack_SpVectorOp.hpp"
65 #include "DenseLinAlgPack_LinAlgOpPack.hpp"
66 #include "Teuchos_dyn_cast.hpp"
67 #include "Teuchos_Assert.hpp"
69 namespace QPKWIKNEW_CppDecl {
74 using FortranTypes::f_int;
75 using FortranTypes::f_real;
76 using FortranTypes::f_dbl_prec;
77 using FortranTypes::f_logical;
85 FORTRAN_FUNC_DECL_UL(
void,QPKWIKNEW,qpkwiknew) (
86 const f_int& N,
const f_int& M1,
const f_int& M2,
const f_int& M3
87 ,
const f_dbl_prec GRAD[], f_dbl_prec UINV[],
const f_int& LDUINV
88 ,
const f_int IBND[],
const f_dbl_prec BL[],
const f_dbl_prec BU[]
89 ,
const f_dbl_prec A[],
const f_int& LDA,
const f_dbl_prec YPY[]
90 ,
const f_int& IYPY,
const f_int& WARM, f_dbl_prec NUMPARAM[],
const f_int& MAX_ITER
91 ,f_dbl_prec X[], f_int* NACTSTORE, f_int IACTSTORE[], f_int* INF
92 ,f_int* NACT, f_int IACT[], f_dbl_prec UR[], f_dbl_prec* EXTRA
93 ,f_int* ITER, f_int* NUM_ADDS, f_int* NUM_DROPS
94 ,f_int ISTATE[],
const f_int& LRW, f_dbl_prec RW[]
97 FORTRAN_FUNC_DECL_UL_(f_int,QPKWIKNEW_LISTATE,qpkwiknew_listate) (
98 const f_int& n,
const f_int& m1,
const f_int& m2,
const f_int& m3);
100 FORTRAN_FUNC_DECL_UL_(f_int,QPKWIKNEW_LRW,qpkwiknew_lrw) (
101 const f_int& n,
const f_int& m1,
const f_int& m2,
const f_int& m3);
114 const f_int& n,
const f_int& m1,
const f_int& m2,
const f_int& m3
115 ,
const f_dbl_prec grad[], f_dbl_prec uinv[],
const f_int& lduinv
116 ,
const f_int ibnd[],
const f_dbl_prec bl[],
const f_dbl_prec bu[]
117 ,
const f_dbl_prec a[],
const f_int& lda,
const f_dbl_prec ypy[]
118 ,
const f_int& iypy,
const f_int& warm, f_dbl_prec numparam[],
const f_int& max_iter
119 ,f_dbl_prec x[], f_int* nactstore, f_int iactstore[], f_int* inf
120 ,f_int* nact, f_int iact[], f_dbl_prec ur[], f_dbl_prec* extra
121 ,f_int* iter, f_int* num_adds, f_int* num_drops
122 ,f_int istate[],
const f_int& lrw, f_dbl_prec rw[]
125 Fortran::FORTRAN_FUNC_CALL_UL(QPKWIKNEW,qpkwiknew) (
126 n, m1, m2, m3, grad, uinv, lduinv
127 , ibnd, bl, bu, a, lda, ypy, iypy, warm, numparam, max_iter, x, nactstore
128 , iactstore, inf, nact, iact, ur, extra, iter, num_adds, num_drops, istate
135 f_int qpkwiknew_listate(
const f_int& n,
const f_int& m1,
const f_int& m2
138 return Fortran::FORTRAN_FUNC_CALL_UL_(QPKWIKNEW_LISTATE,qpkwiknew_listate) (n, m1, m2, m3);
143 f_int qpkwiknew_lrw(
const f_int& n,
const f_int& m1,
const f_int& m2
146 return Fortran::FORTRAN_FUNC_CALL_UL_(QPKWIKNEW_LRW,qpkwiknew_lrw) (n, m1, m2, m3);
158 T my_max(
const T& v1,
const T& v2 ) {
return v1 > v2 ? v1 : v2; }
160 using FortranTypes::f_int;
161 typedef DenseLinAlgPack::value_type value_type;
163 enum EConstraintType { NU_L, NU_U, GAMA_L, GAMA_U, LAMBDA, RELAXATION };
164 char constraint_type_name[6][15] = {
"NU_L",
"NU_U",
"GAMA_L",
"GAMA_U",
"LAMBDA",
"RELAXATION" };
166 EConstraintType constraint_type(
const f_int m1,
const f_int m2,
const f_int m3,
const f_int j )
168 if (1 <= j && j <= m1 )
return NU_L;
169 else if(m1+1 <= j && j <= m1+m2 )
return GAMA_L;
170 else if(m1+m2+1 <= j && j <= 2*m1+m2 )
return NU_U;
171 else if(2*m1+m2+1 <= j && j <= 2*m1+2*m2 )
return GAMA_U;
172 else if(2*m1+2*m2+1 <= j && j <= 2*m1+2*m2+m3)
return LAMBDA;
173 else if( j == 2*m1+2*m2+m3 + 1 )
return RELAXATION;
178 f_int constraint_index(
const f_int m1,
const f_int m2,
const f_int m3,
const f_int ibnd[]
179 ,
const EConstraintType type,
const f_int j )
182 case NU_L :
return ibnd[j-1];
183 case GAMA_L :
return j-m1;
184 case NU_U :
return ibnd[j-m1-m2-1];
185 case GAMA_U :
return j-2*m1-m2;
186 case LAMBDA :
return j-2*m1-2*m2;
187 case RELAXATION :
return 0;
198 namespace ConstrainedOptPack {
201 value_type max_qp_iter_frac
202 ,value_type infinite_bound
204 :max_qp_iter_frac_(max_qp_iter_frac)
205 ,infinite_bound_(infinite_bound)
211 NUMPARAM_[0] = 1e-10;
212 NUMPARAM_[1] = 1e-20;
213 NUMPARAM_[2] = 1e+20;
236 std::ostream* out, EOutputLevel olevel, ERunTests test_what
237 ,
const Vector& g,
const MatrixSymOp& G
239 ,
const Vector* dL,
const Vector* dU
241 ,
const Vector* eL,
const Vector* eU
244 ,value_type* eta, VectorMutable* d
246 ,VectorMutable* mu, VectorMutable* Ed
247 ,VectorMutable* lambda, VectorMutable* Fd
251 using DenseLinAlgPack::nonconst_tri_ele;
256 using LinAlgOpPack::V_MtV;
260 using ConstrainedOptPack::MatrixExtractInvCholFactor;
266 const MatrixExtractInvCholFactor &cG
267 =
dyn_cast<
const MatrixExtractInvCholFactor>(G);
271 const value_type inf = this->infinite_bound();
274 m_in = E ? b->dim() : 0,
275 m_eq = F ? f->dim() : 0,
277 ninequbounds = E ? num_bounded(*eL,*eU,inf) : 0,
278 nequalities = F ? f->dim() : 0;
283 const bool same_qp_struct = ( N_ == nd && M1_ == nvarbounds && M2_ == ninequbounds && M3_ == nequalities );
301 GRAD_ = VectorDenseEncap(g)();
308 UINV_AUG_.resize(N_+1,N_+1);
309 cG.extract_inv_chol( &nonconst_tri_ele( UINV_AUG_(2,N_+1,2,N_+1), BLAS_Cpp::upper ) );
310 UINV_AUG_(1,1) = 1.0 / ::sqrt( NUMPARAM_[2] );
311 UINV_AUG_.col(1)(2,N_+1) = 0.0;
312 UINV_AUG_.row(1)(2,N_+1) = 0.0;
315 LDUINV_AUG_ = UINV_AUG_.rows();
319 IBND_INV_.resize( nd + m_in);
320 std::fill( IBND_INV_.begin(), IBND_INV_.end(), 0 );
321 IBND_.resize( my_max( 1, M1_ + M2_ ) );
322 BL_.resize( my_max( 1, M1_ + M2_ ) );
323 BU_.resize( my_max( 1, M1_ + M2_ + M3_ ) );
324 LDA_ = my_max( 1, M2_ + M3_ );
325 A_.resize( LDA_, ( M2_ + M3_ > 0 ? N_ : 1 ) );
326 YPY_.resize( my_max( 1, M1_ + M2_ ) );
332 VectorDenseEncap dL_de(*dL);
333 VectorDenseEncap dU_de(*dU);
336 dLU_itr( dL_de().begin(), dL_de().end()
337 ,dU_de().begin(), dU_de().end()
341 IBND_itr = IBND_.begin(),
342 IBND_end = IBND_.begin() + M1_;
344 BL_itr = BL_.begin(),
345 BU_itr = BU_.begin(),
346 YPY_itr = YPY_.begin();
348 for(
size_type ibnd_i = 1; IBND_itr != IBND_end; ++ibnd_i, ++dLU_itr ) {
349 IBND_INV_[dLU_itr.index()-1] = ibnd_i;
350 *IBND_itr++ = dLU_itr.index();
351 *BL_itr++ = dLU_itr.lbound();
352 *BU_itr++ = dLU_itr.ubound();
360 VectorDenseEncap eL_de(*eL);
361 VectorDenseEncap eU_de(*eU);
362 VectorDenseEncap b_de(*b);
364 eLU_itr( eL_de().begin(), eL_de().end()
365 ,eU_de().begin(), eU_de().end()
371 BL_itr = BL_.begin() + M1_,
372 BU_itr = BU_.begin() + M1_,
373 YPY_itr = YPY_.begin() + M1_;
375 ibnds_itr = IBND_.begin() + M1_;
377 for(
size_type i = 1; i <= M2_; ++i, ++eLU_itr, ++ibnds_itr ) {
380 *BL_itr++ = eLU_itr.lbound();
381 *BU_itr++ = eLU_itr.ubound();
382 *YPY_itr++ = b_de()(k);
384 IBND_INV_[nd+k-1] = M1_ + i;
388 DVectorSlice y = A_.row(i);
389 EtaVector e_k(k,eL_de().dim());
400 BL_itr = BL_.begin() + M1_,
401 BU_itr = BU_.begin() + M1_;
403 ibnds_itr = IBND_.begin() + M1_;
405 if( !eLU_itr.at_end() && eLU_itr.index() == i ) {
406 *BL_itr++ = eLU_itr.lbound();
407 *BU_itr++ = eLU_itr.ubound();
415 IBND_INV_[nd+i-1]= M1_ + i;
418 assign( &A_(1,M2_,1,N_), *E, trans_E );
420 YPY_(M1_+1,M1_+M2_) = b_de();
427 V_StV( &BU_( M1_ + M2_ + 1, M1_ + M2_ + M3_ ), -1.0, VectorDenseEncap(*f)() );
428 assign( &A_( M2_ + 1, M2_ + M3_, 1, N_ ), *F, trans_F );
438 MAX_ITER_ =
static_cast<f_int
>(max_qp_iter_frac() * N_);
441 INF_ = ( same_qp_struct ? 1 : 0 );
444 if(!same_qp_struct) {
447 IACTSTORE_.resize(N_+1);
450 ISTATE_.resize( QPKWIKNEW_CppDecl::qpkwiknew_listate(N_,M1_,M2_,M3_) );
451 LRW_ = QPKWIKNEW_CppDecl::qpkwiknew_lrw(N_,M1_,M2_,M3_);
471 IACTSTORE_[NACTSTORE_] = 2*M1_ + 2*M2_ + j;
475 if( ( nu && nu->nz() ) || ( mu && mu->nz() ) ) {
478 nu_nz = nu ? nu->nz() : 0,
479 mu_nz = mu ? mu->nz() : 0;
484 SpVector gamma( nd + 1 + m_in , nu_nz + mu_nz );
485 typedef SpVector::element_type ele_t;
487 VectorDenseEncap nu_de(*nu);
488 DVectorSlice::const_iterator
489 nu_itr = nu_de().begin(),
490 nu_end = nu_de().end();
492 while( nu_itr != nu_end ) {
493 for( ; *nu_itr == 0.0; ++nu_itr, ++i );
494 gamma.add_element(ele_t(i,*nu_itr));
499 VectorDenseEncap mu_de(*mu);
500 DVectorSlice::const_iterator
501 mu_itr = mu_de().begin(),
502 mu_end = mu_de().end();
504 while( mu_itr != mu_end ) {
505 for( ; *mu_itr == 0.0; ++mu_itr, ++i );
506 gamma.add_element(ele_t(i+nd,*mu_itr));
510 std::sort( gamma.begin(), gamma.end()
513 const SpVector::difference_type o = gamma.offset();
514 for( SpVector::const_iterator itr = gamma.begin(); itr != gamma.end(); ++itr ) {
516 const value_type val = itr->value();
520 IACTSTORE_[NACTSTORE_]
527 else if( j <= nd + m_in ) {
530 IACTSTORE_[NACTSTORE_]
545 if( out && olevel > PRINT_NONE ) {
547 <<
"\nCalling QPKWIK to solve QP problem ...\n";
550 QPKWIKNEW_CppDecl::qpkwiknew(
551 N_, M1_, M2_, M3_, &GRAD_(1), &UINV_AUG_(1,1), LDUINV_AUG_, &IBND_[0]
552 ,&BL_(1), &BU_(1), &A_(1,1), LDA_, &YPY_(1), IYPY_, WARM_, NUMPARAM_, MAX_ITER_, &X_(1)
553 ,&NACTSTORE_, &IACTSTORE_[0], &INF_, &NACT_, &IACT_[0], &UR_[0], &EXTRA_
554 ,&ITER_, &NUM_ADDS_, &NUM_DROPS_, &ISTATE_[0], LRW_, &RW_[0]
563 (VectorDenseMutableEncap(*d))() = X_();
570 EConstraintType type = constraint_type(M1_,M2_,M3_,j);
571 FortranTypes::f_int idc = constraint_index(M1_,M2_,M3_,&IBND_[0],type,j);
574 nu->set_ele( idc , -UR_(i) );
577 mu->set_ele( IBND_[ M1_ + idc - 1 ], -UR_(i) );
580 nu->set_ele( idc, UR_(i)) ;
583 mu->set_ele( IBND_[ M1_ + idc - 1 ], UR_(i) );
586 lambda->set_ele( idc, UR_(i) );
597 V_MtV( Ed, *E, trans_E, *d );
601 V_MtV( Fd, *F, trans_F, *d );
606 solution_type = QPSolverStats::OPTIMAL_SOLUTION;
608 else if( INF_ == -1 ) {
610 true, QPSolverRelaxed::Infeasible
611 ,
"QPSolverRelaxedQPKWIK::solve_qp(...) : Error, QP is infeasible" );
613 else if( INF_ == -2 ) {
616 else if( INF_ == -3 ) {
617 solution_type = QPSolverStats::DUAL_FEASIBLE_POINT;
623 solution_type, QPSolverStats::CONVEX
624 ,ITER_, NUM_ADDS_, NUM_DROPS_
625 ,WARM_==1, *eta > 0.0 );
634 #endif // CONSTRAINED_OPTIMIZATION_PACK_USE_QPKWIK
void set_stats(ESolutionType solution_type, EConvexity convexity, int num_qp_iter, int num_adds, int num_drops, bool warm_start, bool infeasible_qp)
Initialize the statistics.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
T_To & dyn_cast(T_From &from)
void V_StV(VectorMutable *v_lhs, value_type alpha, const V &V_rhs)
QPSolverStats::ESolutionType imp_solve_qp(std::ostream *out, EOutputLevel olevel, ERunTests test_what, const Vector &g, const MatrixSymOp &G, value_type etaL, const Vector *dL, const Vector *dU, const MatrixOp *E, BLAS_Cpp::Transp trans_E, const Vector *b, const Vector *eL, const Vector *eU, const MatrixOp *F, BLAS_Cpp::Transp trans_F, const Vector *f, value_type *obj_d, value_type *eta, VectorMutable *d, VectorMutable *nu, VectorMutable *mu, VectorMutable *Ed, VectorMutable *lambda, VectorMutable *Fd)
value_type transVtMtV(const Vector &v_rhs1, const MatrixOp &M_rhs2, BLAS_Cpp::Transp trans_rhs2, const Vector &v_rhs3)
void assign(MatrixOp *M_lhs, const MatrixOp &M_rhs, BLAS_Cpp::Transp trans_rhs)
QPSolverStats get_qp_stats() const
size_type num_bounded(const Vector &xl, const Vector &xu, value_type inf_bound)
QPSolverRelaxedQPKWIK(value_type max_qp_iter_frac=10.0, value_type infinite_bound=1e+20)
value_type dot(const Vector &v_rhs1, const Vector &v_rhs2)
Transp trans_not(Transp _trans)
ESolutionType
Enumeration for the type of point returned from solve_qp(...).
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
ESolutionType solution_type() const