bool QPSolver::solve(VectorXd& sol) { bool ret = false; #ifdef _WIN32 VectorXd solution; preSolve(); convertMatrixVectorFormat(); MSKenv_t env; MSKtask_t task; MSKrescodee r; r = MSK_makeenv(&env, NULL, NULL, NULL, NULL); if (r == MSK_RES_OK) { r = MSK_linkfunctoenvstream(env, MSK_STREAM_LOG, NULL, printstr); } r = MSK_initenv(env); if (r == MSK_RES_OK) { r = MSK_maketask(env, mNumCon, mNumVar, &task); if (r == MSK_RES_OK) { r = MSK_linkfunctotaskstream(task, MSK_STREAM_LOG, NULL, printstr); } if (r == MSK_RES_OK) r = MSK_putmaxnumvar(task, mNumVar); if (r == MSK_RES_OK) r = MSK_putmaxnumcon(task, mNumCon); /* Append ¡¯NUMCON ¡¯ empty constraints . The constraints will initially have no bounds . */ if (r == MSK_RES_OK) r = MSK_append(task, MSK_ACC_CON, mNumCon); /* Append ¡¯NUMVAR ¡¯ variables . The variables will initially be fixed at zero (x =0). */ if (r == MSK_RES_OK) r = MSK_append(task, MSK_ACC_VAR, mNumVar); /* Optionally add a constant term to the objective . */ if (r == MSK_RES_OK) r = MSK_putcfix(task, mConstant); for (int j = 0; j < mNumVar && r == MSK_RES_OK; ++j) { /* Set the linear term c_j in the objective .*/ if (r == MSK_RES_OK) r = MSK_putcj(task, j, mCU[j]); /* Set the bounds on variable j.*/ if (r == MSK_RES_OK) { if (mbLowerBounded[j] && mbUpperBounded[j]) { if (mlb[j] == mub[j]) r = MSK_putbound(task, MSK_ACC_VAR, j, MSK_BK_FX, mlb[j], mub[j]); else { CHECK(mlb[j] < mub[j]); r = MSK_putbound(task, MSK_ACC_VAR, j, MSK_BK_RA, mlb[j], mub[j]); } } else if (mbLowerBounded[j]) { r = MSK_putbound(task, MSK_ACC_VAR, j , MSK_BK_LO, mlb[j], +MSK_INFINITY); } else if (mbUpperBounded[j]) { r = MSK_putbound(task, MSK_ACC_VAR, j, MSK_BK_UP, -MSK_INFINITY, mub[j]); } else { r = MSK_putbound(task, MSK_ACC_VAR, j, MSK_BK_FR, -MSK_INFINITY, +MSK_INFINITY); } } /* Input column j of A */ if (r == MSK_RES_OK && mNumCon) { int currentColumnIdx = mAColumnStartIdx[j]; int nextColumnIdx = mAColumnStartIdx[j + 1]; r = MSK_putavec(task, MSK_ACC_VAR, j, nextColumnIdx - currentColumnIdx, &(mARowIdx[currentColumnIdx]), &(mAValues[currentColumnIdx])); } } /* Set the bounds on constraints . for i=1, ... , NUMCON : blc [i] <= constraint i <= buc [i] */ for (int i = 0; i < mNumCon && r == MSK_RES_OK; ++i) { if (mbConstraintLowerBounded[i] && mbConstraintUpperBounded[i]) { if (mlbc[i] == mubc[i]) { r = MSK_putbound(task, MSK_ACC_CON, i, MSK_BK_FX, mlbc[i], mubc[i]); } else { r = MSK_putbound(task, MSK_ACC_CON, i, MSK_BK_RA, mlbc[i], mubc[i]); } } else if (mbConstraintLowerBounded[i]) { r = MSK_putbound(task, MSK_ACC_CON, i, MSK_BK_LO, mlbc[i], +MSK_INFINITY); } else if (mbConstraintUpperBounded[i]) { r = MSK_putbound(task, MSK_ACC_CON, i, MSK_BK_UP, -MSK_INFINITY, mubc[i]); } else { LOG(WARNING) << "Every constraint should not be free."; } } if (r == MSK_RES_OK) { /* Input the Q for the objective . */ r = MSK_putqobj(task, mQValues.size(), &(mQSubi[0]), &(mQSubj[0]), &(mQValues[0])); } if (r == MSK_RES_OK) { MSKrescodee trmcode; r = MSK_optimizetrm(task, &trmcode); MSK_solutionsummary(task, MSK_STREAM_LOG); if (r == MSK_RES_OK) { MSKsolstae solsta; MSK_getsolutionstatus(task, MSK_SOL_ITR, NULL, &solsta); double* result = new double[mNumVar]; switch (solsta) { case MSK_SOL_STA_OPTIMAL: case MSK_SOL_STA_NEAR_OPTIMAL: MSK_getsolutionslice(task, MSK_SOL_ITR, MSK_SOL_ITEM_XX, 0, mNumVar, result); LOG(INFO) << "Optimal primal solution"; ret = true; solution = VectorXd::Zero(mNumVar); for (int k = 0; k < mNumVar; ++k) solution[k] = result[k]; break; case MSK_SOL_STA_DUAL_INFEAS_CER: case MSK_SOL_STA_PRIM_INFEAS_CER: case MSK_SOL_STA_NEAR_DUAL_INFEAS_CER: case MSK_SOL_STA_NEAR_PRIM_INFEAS_CER: LOG(WARNING) << "Primal or dual infeasibility certificate found."; break; case MSK_SOL_STA_UNKNOWN: LOG(WARNING) << "The status of the solution could not be determined."; break; default: LOG(WARNING) << "Other solution status."; break; } delete[] result; } } else { LOG(WARNING) << "Error while optimizing."; } if (r != MSK_RES_OK) { char symname[MSK_MAX_STR_LEN]; char desc[MSK_MAX_STR_LEN]; LOG(WARNING) << "An error occurred while optimizing."; MSK_getcodedesc(r, symname, desc); LOG(WARNING) << "Error " << symname << " - " << desc; } } MSK_deletetask(&task); MSK_deleteenv(&env); postSolve(solution, ret, sol); #endif return ret; }
int mosek_qp_optimize(double** G, double* delta, double* alpha, long k, double C, double *dual_obj) { long i,j,t; double *c; MSKlidxt *aptrb; MSKlidxt *aptre; MSKidxt *asub; double *aval; MSKboundkeye bkc[1]; double blc[1]; double buc[1]; MSKboundkeye *bkx; double *blx; double *bux; MSKidxt *qsubi,*qsubj; double *qval; MSKenv_t env; MSKtask_t task; MSKrescodee r; /*double dual_obj;*/ c = (double*) malloc(sizeof(double)*k); assert(c!=NULL); aptrb = (MSKlidxt*) malloc(sizeof(MSKlidxt)*k); assert(aptrb!=NULL); aptre = (MSKlidxt*) malloc(sizeof(MSKlidxt)*k); assert(aptre!=NULL); asub = (MSKidxt*) malloc(sizeof(MSKidxt)*k); assert(asub!=NULL); aval = (double*) malloc(sizeof(double)*k); assert(aval!=NULL); bkx = (MSKboundkeye*) malloc(sizeof(MSKboundkeye)*k); assert(bkx!=NULL); blx = (double*) malloc(sizeof(double)*k); assert(blx!=NULL); bux = (double*) malloc(sizeof(double)*k); assert(bux!=NULL); qsubi = (MSKidxt*) malloc(sizeof(MSKidxt)*(k*(k+1)/2)); assert(qsubi!=NULL); qsubj = (MSKidxt*) malloc(sizeof(MSKidxt)*(k*(k+1)/2)); assert(qsubj!=NULL); qval = (double*) malloc(sizeof(double)*(k*(k+1)/2)); assert(qval!=NULL); /* DEBUG */ /* for (i=0;i<k;i++) { printf("delta: %.4f\n", delta[i]); } printf("G:\n"); for (i=0;i<k;i++) { for (j=0;j<k;j++) { printf("%.4f ", G[i][j]); } printf("\n"); } fflush(stdout); */ /* DEBUG */ for (i=0;i<k;i++) { c[i] = -delta[i]; aptrb[i] = i; aptre[i] = i+1; asub[i] = 0; aval[i] = 1.0; bkx[i] = MSK_BK_LO; blx[i] = 0.0; bux[i] = MSK_INFINITY; } bkc[0] = MSK_BK_UP; blc[0] = -MSK_INFINITY; buc[0] = C; /* bkc[0] = MSK_BK_FX; blc[0] = C; buc[0] = C; */ /* create mosek environment */ r = MSK_makeenv(&env, NULL, NULL, NULL, NULL); /* check return code */ if (r==MSK_RES_OK) { /* directs output to printstr function */ MSK_linkfunctoenvstream(env, MSK_STREAM_LOG, NULL, printstr); } /* initialize the environment */ r = MSK_initenv(env); if (r==MSK_RES_OK) { /* create the optimization task */ r = MSK_maketask(env,1,k,&task); if (r==MSK_RES_OK) { r = MSK_linkfunctotaskstream(task, MSK_STREAM_LOG,NULL,printstr); if (r==MSK_RES_OK) { r = MSK_inputdata(task, 1,k, 1,k, c,0.0, aptrb,aptre, asub,aval, bkc,blc,buc, bkx,blx,bux); } if (r==MSK_RES_OK) { /* coefficients for the Gram matrix */ t = 0; for (i=0;i<k;i++) { for (j=0;j<=i;j++) { qsubi[t] = i; qsubj[t] = j; qval[t] = G[i][j]; t++; } } r = MSK_putqobj(task, k*(k+1)/2, qsubi,qsubj,qval); } /* DEBUG */ /* printf("t: %ld\n", t); for (i=0;i<t;i++) { printf("qsubi: %d, qsubj: %d, qval: %.4f\n", qsubi[i], qsubj[i], qval[i]); } fflush(stdout); */ /* DEBUG */ /* set relative tolerance gap (DEFAULT = 1E-8)*/ //MSK_putdouparam(task, MSK_DPAR_INTPNT_TOL_REL_GAP, 1E-10); MSK_putdouparam(task, MSK_DPAR_INTPNT_TOL_REL_GAP, 1E-14); if (r==MSK_RES_OK) { r = MSK_optimize(task); } if (r==MSK_RES_OK) { MSK_getsolutionslice(task, MSK_SOL_ITR, MSK_SOL_ITEM_XX, 0, k, alpha); /* print out alphas */ /* for (i=0;i<k;i++) { printf("alpha[%ld]: %.8f\n", i, alpha[i]); fflush(stdout); } */ /* output the objective value */ MSK_getprimalobj(task, MSK_SOL_ITR, dual_obj); //printf("ITER DUAL_OBJ %.8g\n", -(*dual_obj)); fflush(stdout); } MSK_deletetask(&task); } MSK_deleteenv(&env); } /* free the memory */ free(c); free(aptrb); free(aptre); free(asub); free(aval); free(bkx); free(blx); free(bux); free(qsubi); free(qsubj); free(qval); if(r == MSK_RES_OK) return(0); else return(r); }
/********************** lap: the upper RHS of the symmetric graph laplacian matrix which will be transformed to the hessian of the non-linear part of the optimisation function n: number of nodes (length of coords array) ordering: array containing sequences of nodes for each level, ie, ordering[levels[i]] is first node of (i+1)th level level_indexes: array of starting node for each level in ordering ie, levels[i] is index to first node of (i+1)th level also, levels[0] is number of nodes in first level and, levels[i]-levels[i-1] is number of nodes in ith level and, n - levels[num_divisions-1] is number of nodes in last level num_divisions: number of divisions between levels, ie number of levels - 1 separation: the minimum separation between nodes on different levels ***********************/ MosekEnv *mosek_init_hier(float *lap, int n, int *ordering, int *level_indexes, int num_divisions, float separation) { int count = 0; int i, j, num_levels = num_divisions + 1; int num_constraints; MosekEnv *mskEnv = GNEW(MosekEnv); DigColaLevel *levels; int nonzero_lapsize = (n * (n - 1)) / 2; /* vars for nodes (except x0) + dummy nodes between levels * x0 is fixed at 0, and therefore is not included in the opt problem * add 2 more vars for top and bottom constraints */ mskEnv->num_variables = n + num_divisions + 1; logfile = fopen("quad_solve_log", "w"); levels = assign_digcola_levels(ordering, n, level_indexes, num_divisions); #ifdef DUMP_CONSTRAINTS print_digcola_levels(logfile, levels, num_levels); #endif /* nonlinear coefficients matrix of objective function */ /* int lapsize=mskEnv->num_variables+(mskEnv->num_variables*(mskEnv->num_variables-1))/2; */ mskEnv->qval = N_GNEW(nonzero_lapsize, double); mskEnv->qsubi = N_GNEW(nonzero_lapsize, int); mskEnv->qsubj = N_GNEW(nonzero_lapsize, int); /* solution vector */ mskEnv->xx = N_GNEW(mskEnv->num_variables, double); /* constraint matrix */ separation /= 2.0; /* separation between each node and it's adjacent constraint */ num_constraints = get_num_digcola_constraints(levels, num_levels) + num_divisions + 1; /* constraints of the form x_i - x_j >= sep so 2 non-zero entries per constraint in LHS matrix * except x_0 (fixed at 0) constraints which have 1 nz val each. */ #ifdef EQUAL_WIDTH_LEVELS num_constraints += num_divisions; #endif /* pointer to beginning of nonzero sequence in a column */ for (i = 0; i < n - 1; i++) { for (j = i; j < n - 1; j++) { mskEnv->qval[count] = -2 * lap[count + n]; assert(mskEnv->qval[count] != 0); mskEnv->qsubi[count] = j; mskEnv->qsubj[count] = i; count++; } } #ifdef DUMP_CONSTRAINTS fprintf(logfile, "Q=["); int lapcntr = n; for (i = 0; i < mskEnv->num_variables; i++) { if (i != 0) fprintf(logfile, ";"); for (j = 0; j < mskEnv->num_variables; j++) { if (j < i || i >= n - 1 || j >= n - 1) { fprintf(logfile, "0 "); } else { fprintf(logfile, "%f ", -2 * lap[lapcntr++]); } } } fprintf(logfile, "]\nQ=Q-diag(diag(Q))+Q'\n"); #endif fprintf(logfile, "\n"); /* Make the mosek environment. */ mskEnv->r = MSK_makeenv(&mskEnv->env, NULL, NULL, NULL, NULL); /* Check whether the return code is ok. */ if (mskEnv->r == MSK_RES_OK) { /* Directs the log stream to the user * specified procedure 'printstr'. */ MSK_linkfunctoenvstream(mskEnv->env, MSK_STREAM_LOG, NULL, printstr); } /* Initialize the environment. */ mskEnv->r = MSK_initenv(mskEnv->env); if (mskEnv->r == MSK_RES_OK) { /* Make the optimization task. */ mskEnv->r = MSK_maketask(mskEnv->env, num_constraints, mskEnv->num_variables, &mskEnv->task); if (mskEnv->r == MSK_RES_OK) { int c_ind = 0; int c_var = n - 1; mskEnv->r = MSK_linkfunctotaskstream(mskEnv->task, MSK_STREAM_LOG, NULL, printstr); /* Resize the task. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_resizetask(mskEnv->task, num_constraints, mskEnv->num_variables, 0, /* no cones!! */ /* each constraint applies to 2 vars */ 2 * num_constraints + num_divisions, nonzero_lapsize); /* Append the constraints. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_append(mskEnv->task, 1, num_constraints); /* Append the variables. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_append(mskEnv->task, 0, mskEnv->num_variables); /* Put variable bounds. */ for (j = 0; j < mskEnv->num_variables && mskEnv->r == MSK_RES_OK; ++j) mskEnv->r = MSK_putbound(mskEnv->task, 0, j, MSK_BK_RA, -MSK_INFINITY, MSK_INFINITY); for (j = 0; j < levels[0].num_nodes && mskEnv->r == MSK_RES_OK; j++) { int node = levels[0].nodes[j] - 1; if (node >= 0) { INIT_sub_val(c_var,node); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 2, subi, vali); } else { /* constraint for y0 (fixed at 0) */ mskEnv->r = MSK_putaij(mskEnv->task, c_ind, c_var, 1.0); } mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_LO, separation, MSK_INFINITY); c_ind++; } for (i = 0; i < num_divisions && mskEnv->r == MSK_RES_OK; i++) { c_var = n + i; for (j = 0; j < levels[i].num_nodes && mskEnv->r == MSK_RES_OK; j++) { /* create separation constraint a>=b+separation */ int node = levels[i].nodes[j] - 1; if (node >= 0) { /* no constraint for fixed node */ INIT_sub_val(node,c_var); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 2, subi, vali); } else { /* constraint for y0 (fixed at 0) */ mskEnv->r = MSK_putaij(mskEnv->task, c_ind, c_var, -1.0); } mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_LO, separation, MSK_INFINITY); c_ind++; } for (j = 0; j < levels[i + 1].num_nodes && mskEnv->r == MSK_RES_OK; j++) { int node = levels[i + 1].nodes[j] - 1; if (node >= 0) { INIT_sub_val(c_var,node); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 2, subi, vali); } else { /* constraint for y0 (fixed at 0) */ mskEnv->r = MSK_putaij(mskEnv->task, c_ind, c_var, 1.0); } mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_LO, separation, MSK_INFINITY); c_ind++; } } c_var = n + i; for (j = 0; j < levels[i].num_nodes && mskEnv->r == MSK_RES_OK; j++) { /* create separation constraint a>=b+separation */ int node = levels[i].nodes[j] - 1; if (node >= 0) { /* no constraint for fixed node */ INIT_sub_val(node,c_var); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 2, subi, vali); } else { /* constraint for y0 (fixed at 0) */ mskEnv->r = MSK_putaij(mskEnv->task, c_ind, c_var, -1.0); } mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_LO, separation, MSK_INFINITY); c_ind++; } /* create constraints preserving the order of dummy vars */ for (i = 0; i < num_divisions + 1 && mskEnv->r == MSK_RES_OK; i++) { int c_var = n - 1 + i, c_var2 = c_var + 1; INIT_sub_val(c_var,c_var2); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 2, subi, vali); mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_LO, 0, MSK_INFINITY); c_ind++; } #ifdef EQUAL_WIDTH_LEVELS for (i = 1; i < num_divisions + 1 && mskEnv->r == MSK_RES_OK; i++) { int c_var = n - 1 + i, c_var_lo = c_var - 1, c_var_hi = c_var + 1; INIT_sub_val3(c_var_lo, c_var, c_var_h); mskEnv->r = MSK_putavec(mskEnv->task, 1, c_ind, 3, subi, vali); mskEnv->r = MSK_putbound(mskEnv->task, 1, c_ind, MSK_BK_FX, 0, 0); c_ind++; } #endif assert(c_ind == num_constraints); #ifdef DUMP_CONSTRAINTS fprintf(logfile, "A=["); for (i = 0; i < num_constraints; i++) { if (i != 0) fprintf(logfile, ";"); for (j = 0; j < mskEnv->num_variables; j++) { double aij; MSK_getaij(mskEnv->task, i, j, &aij); fprintf(logfile, "%f ", aij); } } fprintf(logfile, "]\n"); fprintf(logfile, "b=["); for (i = 0; i < num_constraints; i++) { fprintf(logfile, "%f ", separation); } fprintf(logfile, "]\n"); #endif if (mskEnv->r == MSK_RES_OK) { /* * The lower triangular part of the Q * matrix in the objective is specified. */ mskEnv->r = MSK_putqobj(mskEnv->task, nonzero_lapsize, mskEnv->qsubi, mskEnv->qsubj, mskEnv->qval); } } } delete_digcola_levels(levels, num_levels); return mskEnv; }
template <typename _Scalar> typename MosekOpt<_Scalar>::ReturnType MosekOpt<_Scalar>:: update( bool verbose ) { if ( _task != NULL ) { std::cerr << "[" << __func__ << "]: " << "update can only be called once! returning." << std::endl; return MSK_RES_ERR_UNKNOWN; } /* Create the optimization task. */ if ( MSK_RES_OK == _r ) { _r = MSK_maketask( _env, this->getConstraintCount(), this->getVarCount(), &_task ); if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "could not create task with " << this->getVarCount() << " vars, and " << this->getConstraintCount() << " constraints" << std::endl; } // redirect output if ( MSK_RES_OK == _r ) { _r = MSK_linkfunctotaskstream( _task, MSK_STREAM_LOG, NULL, mosekPrintStr ); if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "could not create rewire output to mosekPrintStr(), continuing though..." << std::endl; } // Append _numCon empty constraints. The constraints will initially have no bounds. if ( MSK_RES_OK == _r ) { if ( verbose ) std::cout << "my: MSK_appendcons(_task,"<< this->getConstraintCount() <<");" << std::endl; _r = MSK_appendcons( _task, this->getConstraintCount() ); if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "could not append " << this->getConstraintCount() << " constraints" << std::endl; } // Append _numVar variables. The variables will initially be fixed at zero (x=0). if ( MSK_RES_OK == _r ) { if ( verbose ) std::cout << "my: MSK_appendvars(_task," << this->getVarCount() <<");" << std::endl; _r = MSK_appendvars( _task, this->getVarCount() ); if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "could not append " << this->getVarCount() << " variables" << std::endl; } // Optionally add a constant term to the objective. if ( MSK_RES_OK == _r ) { if ( verbose ) std::cout << "my: MSK_putcfix(_task," << this->getObjectiveBias() << ");" << std::endl; _r = MSK_putcfix( _task, this->getObjectiveBias() ); if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "could not add constant " << this->getObjectiveBias() << " to objective function" << std::endl; } // set Variables for ( size_t j = 0; (j < this->getVarCount()) && (MSK_RES_OK == _r); ++j ) { // set Variable j's Bounds // blx[j] <= x_j <= bux[j] if ( MSK_RES_OK == _r ) { _r = MSK_putvarbound( _task, j, /* Index of variable.*/ MosekOpt<Scalar>::getBoundTypeCustom( this->getVarBoundType(j) ), /* Bound key.*/ this->getVarLowerBound(j), /* Numerical value of lower bound.*/ this->getVarUpperBound(j) ); /* Numerical value of upper bound.*/ if ( verbose ) std::cout << "my: MSK_putvarbound(_task," << j << "," << this->getVarBoundType(j) << "," << this->getVarLowerBound(j) << "," << this->getVarUpperBound(j) << ");" << std::endl; } // set Variable j's Type if ( MSK_RES_OK == _r ) { _r = MSK_putvartype( _task, j, MosekOpt<Scalar>::getVarTypeCustom(this->getVarType(j)) ); } // set Variable j's linear coefficient in the objective function if ( MSK_RES_OK == _r ) { if ( verbose ) std::cout << "my: putcj(_task," << j << "," << this->getLinObjectives()[j] << ")" << std::endl; _r = MSK_putcj( _task, j, this->getLinObjectives()[j] ); } } // set Quadratic Objectives if ( MSK_RES_OK == _r ) { const int numNonZeros = this->getQuadraticObjectives().size(); MSKint32t *qsubi = new MSKint32t[numNonZeros], *qsubj = new MSKint32t[numNonZeros]; double *qval = new double[numNonZeros]; for ( size_t qi = 0; qi != this->getQuadraticObjectives().size(); ++qi ) { qsubi[qi] = this->getQuadraticObjectives()[qi].row(); qsubj[qi] = this->getQuadraticObjectives()[qi].col(); qval [qi] = this->getQuadraticObjectives()[qi].value(); } if ( verbose ) std::cout<<"my: putqobj( _task, " << numNonZeros << ",\n"; for ( size_t vi = 0; vi != numNonZeros; ++vi ) { if ( verbose ) std::cout << qsubi[vi] << "," << qsubj[vi] << ", " << qval[vi] << std::endl; } if ( verbose ) std::cout << ");" << std::endl; _r = MSK_putqobj( _task, numNonZeros, qsubi, qsubj, qval ); if ( qsubi ) { delete[] qsubi; qsubi = NULL; } if ( qsubj ) { delete[] qsubj; qsubj = NULL; } if ( qval ) { delete[] qval ; qval = NULL; } if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "Setting Quadratic Objectives caused error code " << (int)_r << std::endl; } // ...Quadratic objective // set Linear Constraints { typename ParentType::SparseMatrix A( this->getLinConstraintsMatrix() ); // ( this->getConstraintCount(), this->getVarCount() ); // A.setFromTriplets( this->getLinConstraints().begin(), this->getLinConstraints().end() ); std::vector<double> aval; // Linear constraints coeff matrix (sparse) std::vector<int> asub; // Linear constraints coeff matrix indices std::vector<int> aptrb, aptre; for ( int row = 0; (row < A.outerSize()) && (MSK_RES_OK == _r); ++row ) { // set Constraint Bounds for row if ( MSK_RES_OK == _r ) { if ( verbose ) std::cout << "my: MSK_putconbound( _task, " << row << ", " << MosekOpt<Scalar>::getBoundTypeCustom( this->getConstraintBoundType(row) ) << ", " << this->getConstraintLowerBound( row ) << ", " << this->getConstraintUpperBound( row ) << ")" << std::endl; fflush( stdout ); _r = MSK_putconbound( _task, row, /* Index of constraint.*/ MosekOpt<Scalar>::getBoundTypeCustom(this->getConstraintBoundType(row)), /* Bound key.*/ this->getConstraintLowerBound(row), /* Numerical value of lower bound.*/ this->getConstraintUpperBound(row) ); /* Numerical value of upper bound.*/ } // set Linear Constraint row if ( MSK_RES_OK == _r ) { // new line starts at index == current size aptrb.push_back( aval.size() ); // add coeffs from new line for ( typename ParentType::SparseMatrix::InnerIterator it(A,row); it; ++it ) { if ( row != it.row() ) std::cerr << "[" << __func__ << "]: " << "this shouldn't happen" << std::endl; // coeff value aval.push_back( it.value() ); // TODO: A should be a matrix, not a vector... // coeff subscript asub.push_back( it.col() ); } // new line ends at index == new size aptre.push_back( aval.size() ); if ( verbose ) { std::cout << "my: MSK_putarow( _task, " << row << ", " << aptre[row] - aptrb[row] << ", " << *(asub.data() + aptrb[row]) << ", " << *(aval.data() + aptrb[row]) << ");" << std::endl; fflush( stdout ); } _r = MSK_putarow( _task, row, /* Row index.*/ aptre[row] - aptrb[row], /* Number of non-zeros in row i.*/ asub.data() + aptrb[row], /* Pointer to column indexes of row i.*/ aval.data() + aptrb[row]); /* Pointer to values of row i.*/ } } // ... for A.rows // report error if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "Setting Lin constraints caused error code " << (int)_r << std::endl; } // ...set Linear Constraints // set Quadratic constraints if ( verbose ) std::cout << "[" << __func__ << "]: " << "adding q constraints" << std::endl; for ( size_t constr_id = 0; (constr_id != this->getQuadraticConstraints().size()) && (MSK_RES_OK == _r); ++constr_id ) { const int numNonZeros = this->getQuadraticConstraints(constr_id).size(); MSKint32t *qsubi = new MSKint32t[numNonZeros], *qsubj = new MSKint32t[numNonZeros]; double *qval = new double[numNonZeros]; for ( size_t qi = 0; qi != this->getQuadraticConstraints(constr_id).size(); ++qi ) { qsubi[qi] = this->getQuadraticConstraints(constr_id)[qi].row(); qsubj[qi] = this->getQuadraticConstraints(constr_id)[qi].col(); qval [qi] = this->getQuadraticConstraints(constr_id)[qi].value(); } if ( verbose ) std::cout<<"my: MSK_putqonk( _task, " << constr_id << ", " << numNonZeros << ",\n"; for(size_t vi=0;vi!=numNonZeros;++vi) { if ( verbose ) std::cout << qsubi[vi] << "," << qsubj[vi] << ", " << qval[vi] << std::endl; } if ( verbose ) std::cout << "); " << std::endl; _r = MSK_putqconk(_task, constr_id, numNonZeros, qsubi, qsubj, qval); if ( qsubi ) { delete[] qsubi; qsubi = NULL; } if ( qsubj ) { delete[] qsubj; qsubj = NULL; } if ( qval ) { delete[] qval ; qval = NULL; } if ( MSK_RES_OK != _r ) std::cerr << "[" << __func__ << "]: " << "Setting Quad constraints caused error code " << (int)_r << std::endl; } // ...set Quadratic Constraints // save to file { if ( _r == MSK_RES_OK ) { _r = MSK_putintparam( _task, MSK_IPAR_WRITE_DATA_FORMAT, MSK_DATA_FORMAT_LP ); if ( _r == MSK_RES_OK ) { _r = MSK_writedata( _task, "mosek.lp" ); if ( _r != MSK_RES_OK ) { std::cerr << "[" << __func__ << "]: " << "Writedata did not work" << (int)_r << std::endl; } } } } if ( _r == MSK_RES_OK ) { this->_x.setZero(); this->_updated = true; } // return error code return _r; } // ...MosekOpt::update()
/********************** lap: the upper RHS of the symmetric graph laplacian matrix which will be transformed to the hessian of the non-linear part of the optimisation function has dimensions num_variables, dummy vars do not have entries in lap cs: array of pointers to separation constraints ***********************/ MosekEnv *mosek_init_sep(float *lap, int num_variables, int num_dummy_vars, Constraint ** cs, int num_constraints) { int i, j; MosekEnv *mskEnv = GNEW(MosekEnv); int count = 0; int nonzero_lapsize = num_variables * (num_variables - 1) / 2; /* fix var 0 */ mskEnv->num_variables = num_variables + num_dummy_vars - 1; fprintf(stderr, "MOSEK!\n"); logfile = fopen("quad_solve_log", "w"); /* nonlinear coefficients matrix of objective function */ mskEnv->qval = N_GNEW(nonzero_lapsize, double); mskEnv->qsubi = N_GNEW(nonzero_lapsize, int); mskEnv->qsubj = N_GNEW(nonzero_lapsize, int); /* solution vector */ mskEnv->xx = N_GNEW(mskEnv->num_variables, double); /* pointer to beginning of nonzero sequence in a column */ for (i = 0; i < num_variables - 1; i++) { for (j = i; j < num_variables - 1; j++) { mskEnv->qval[count] = -2 * lap[count + num_variables]; /* assert(mskEnv->qval[count]!=0); */ mskEnv->qsubi[count] = j; mskEnv->qsubj[count] = i; count++; } } #ifdef DUMP_CONSTRAINTS fprintf(logfile, "Q=["); count = 0; for (i = 0; i < num_variables - 1; i++) { if (i != 0) fprintf(logfile, ";"); for (j = 0; j < num_variables - 1; j++) { if (j < i) { fprintf(logfile, "0 "); } else { fprintf(logfile, "%f ", -2 * lap[num_variables + count++]); } } } fprintf(logfile, "]\nQ=Q-diag(diag(Q))+Q'\n"); #endif /* Make the mosek environment. */ mskEnv->r = MSK_makeenv(&mskEnv->env, NULL, NULL, NULL, NULL); /* Check whether the return code is ok. */ if (mskEnv->r == MSK_RES_OK) { /* Directs the log stream to the user specified procedure 'printstr'. */ MSK_linkfunctoenvstream(mskEnv->env, MSK_STREAM_LOG, NULL, printstr); } /* Initialize the environment. */ mskEnv->r = MSK_initenv(mskEnv->env); if (mskEnv->r == MSK_RES_OK) { /* Make the optimization task. */ mskEnv->r = MSK_maketask(mskEnv->env, num_constraints, mskEnv->num_variables, &mskEnv->task); if (mskEnv->r == MSK_RES_OK) { mskEnv->r = MSK_linkfunctotaskstream(mskEnv->task, MSK_STREAM_LOG, NULL, printstr); /* Resize the task. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_resizetask(mskEnv->task, num_constraints, mskEnv->num_variables, 0, /* no cones!! */ /* number of non-zero constraint matrix entries: * each constraint applies to 2 vars */ 2 * num_constraints, nonzero_lapsize); /* Append the constraints. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_append(mskEnv->task, 1, num_constraints); /* Append the variables. */ if (mskEnv->r == MSK_RES_OK) mskEnv->r = MSK_append(mskEnv->task, 0, mskEnv->num_variables); /* Put variable bounds. */ for (j = 0; j < mskEnv->num_variables && mskEnv->r == MSK_RES_OK; j++) mskEnv->r = MSK_putbound(mskEnv->task, 0, j, MSK_BK_RA, -MSK_INFINITY, MSK_INFINITY); for (i = 0; i < num_constraints; i++) { int u = getLeftVarID(cs[i]) - 1; int v = getRightVarID(cs[i]) - 1; double separation = getSeparation(cs[i]); if (u < 0) { mskEnv->r = MSK_putbound(mskEnv->task, 0, v, MSK_BK_RA, -MSK_INFINITY, -separation); assert(mskEnv->r == MSK_RES_OK); } else if (v < 0) { mskEnv->r = MSK_putbound(mskEnv->task, 0, u, MSK_BK_RA, separation, MSK_INFINITY); assert(mskEnv->r == MSK_RES_OK); } else { /* fprintf(stderr,"u=%d,v=%d,sep=%f\n",u,v,separation); */ INIT_sub_val(u,v); mskEnv->r = MSK_putavec(mskEnv->task, 1, i, 2, subi, vali); assert(mskEnv->r == MSK_RES_OK); mskEnv->r = MSK_putbound(mskEnv->task, 1, i, MSK_BK_LO, separation, MSK_INFINITY); assert(mskEnv->r == MSK_RES_OK); } } if (mskEnv->r == MSK_RES_OK) { /* * The lower triangular part of the Q * matrix in the objective is specified. */ mskEnv->r = MSK_putqobj(mskEnv->task, nonzero_lapsize, mskEnv->qsubi, mskEnv->qsubj, mskEnv->qval); assert(mskEnv->r == MSK_RES_OK); } } } return mskEnv; }