My Project
OSBonminSolver.cpp
Go to the documentation of this file.
1
18#include <iostream>
19
20
21#include "OSBonminSolver.h"
22#include "OSDataStructures.h"
23#include "OSParameters.h"
24#include "OSCommonUtil.h"
25#include "OSMathUtil.h"
26
27#include "BonOsiTMINLPInterface.hpp"
28#include "BonCbc.hpp"
29
30#include "CoinTime.hpp"
31
32using std::cout;
33using std::endl;
34using std::ostringstream;
35
36
38 osrlwriter = new OSrLWriter();
39 osresult = new OSResult();
40 m_osilreader = NULL;
41 m_osolreader = NULL;
42 bonminErrorMsg = "";
43
44}
45
47 #ifdef DEBUG
48 cout << "inside BonminSolver destructor" << endl;
49 #endif
50 if(m_osilreader != NULL) delete m_osilreader;
51 m_osilreader = NULL;
52 if(m_osolreader != NULL) delete m_osolreader;
53 m_osolreader = NULL;
54 delete osresult;
55 osresult = NULL;
56 delete osrlwriter;
57 osrlwriter = NULL;
58 //delete osinstance;
59 //osinstance = NULL;
60 #ifdef DEBUG
61 cout << "leaving BonminSolver destructor" << endl;
62 #endif
63}
64
65
66
67
68
69
70bool BonminProblem::get_variables_types(Index n, VariableType* var_types){
71 int i = 0;
72 char *varType;
73 varType = osinstance->getVariableTypes();
74 n = osinstance->getVariableNumber();
75 for(i = 0; i < n; i++){
76 if( varType[i] == 'B') {
77 var_types[i] = BINARY;
78 }
79 else{
80 if( varType[i] == 'I') {
81 var_types[i] = INTEGER;
82 }
83 else{
84 var_types[i] = CONTINUOUS;
85 }
86 }
87 }
88 return true;
89}
90
91bool BonminProblem::get_variables_linearity(Index n, Ipopt::TNLP::LinearityType* var_types){
92
93
94
95 std::cout << "Initialize Nonlinear Structures" << std::endl;
96 try{
97 osinstance->initForAlgDiff( );
98 }
99 catch(const ErrorClass& eclass){
100 bonminErrorMsg = eclass.errormsg;
101 throw;
102 }
108 std::map<int, int> varIndexMap;
109 std::map<int, int>::iterator posVarIndexMap;
110 varIndexMap = osinstance->getAllNonlinearVariablesIndexMap( );
111 /* first make all continuous */
112
113 int i;
114
115 for(i = 0; i < n; i++){
116 var_types[ i] = Ipopt::TNLP::LINEAR;
117 }
122 for(posVarIndexMap = varIndexMap.begin(); posVarIndexMap != varIndexMap.end(); ++posVarIndexMap){
123 std::cout << "Variable Index = " << posVarIndexMap->first << std::endl ;
124 var_types[ posVarIndexMap->first] = Ipopt::TNLP::NON_LINEAR;
125 }
126 std::cout << "Number of nonlinear variables = " << varIndexMap.size() << std::endl;
127
128 return true;
129}
130
131bool BonminProblem::get_constraints_linearity(Index m, Ipopt::TNLP::LinearityType* const_types){
132
133 int i;
134
135 for(i = 0; i < m; i++){
136 const_types[ i] = Ipopt::TNLP::LINEAR;
137 }
138
139
140 int mm = osinstance->getNumberOfNonlinearExpressionTreeModIndexes();
141
142
143
144 for(i = 0; i < mm; i++){
145 if(osinstance->getNonlinearExpressionTreeModIndexes()[ i] >= 0){
146 std::cout << osinstance->getNonlinearExpressionTreeModIndexes()[ i] << std::endl;
147 const_types[ osinstance->getNonlinearExpressionTreeModIndexes()[ i] ] = Ipopt::TNLP::NON_LINEAR;
148
149 }
150
151 }
152
153 return true;
154}
155
156// returns the size of the problem
157bool BonminProblem::get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
158 Index& nnz_h_lag, TNLP::IndexStyleEnum& index_style)
159{
160 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Bonmin NEEDS AN OBJECTIVE FUNCTION");
161 // number of variables
162 n = osinstance->getVariableNumber();
163 // number of constraints
164 m = osinstance->getConstraintNumber();
165 cout << "Bonmin number variables !!!!!!!!!!!!!!!!!!!!!!!!!!!" << n << endl;
166 cout << "Bonmin number constraints !!!!!!!!!!!!!!!!!!!!!!!!!!!" << m << endl;
167 try{
168 osinstance->initForAlgDiff( );
169 }
170 catch(const ErrorClass& eclass){
171 bonminErrorMsg = eclass.errormsg;
172 throw;
173 }
174 // use the OS Expression tree for function evaluations instead of CppAD
175 osinstance->bUseExpTreeForFunEval = true;
176 //std::cout << "Call sparse jacobian" << std::endl;
177 SparseJacobianMatrix *sparseJacobian = NULL;
178 try{
179 sparseJacobian = osinstance->getJacobianSparsityPattern();
180 }
181 catch(const ErrorClass& eclass){
182 bonminErrorMsg = eclass.errormsg;
183 throw;
184 }
185 //std::cout << "Done calling sparse jacobian" << std::endl;
186 nnz_jac_g = sparseJacobian->valueSize;
187 cout << "nnz_jac_g !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_jac_g << endl;
188 // nonzeros in upper hessian
189
190 if( (osinstance->getNumberOfNonlinearExpressions() == 0) && (osinstance->getNumberOfQuadraticTerms() == 0) ) {
191 cout << "This is a linear program" << endl;
192 nnz_h_lag = 0;
193 }
194 else{
195 //std::cout << "Get Lagrangian Hessian Sparsity Pattern " << std::endl;
196 SparseHessianMatrix *sparseHessian = osinstance->getLagrangianHessianSparsityPattern();
197 //std::cout << "Done Getting Lagrangian Hessian Sparsity Pattern " << std::endl;
198 nnz_h_lag = sparseHessian->hessDimension;
199 }
200 cout << "print nnz_h_lag (OSBonminSolver.cpp)" << endl;
201 cout << "nnz_h_lag !!!!!!!!!!!!!!!!!!!!!!!!!!!" << nnz_h_lag << endl;
202 cout << "set index_style (OSBonminSolver.cpp)" << endl;
203 // use the C style indexing (0-based)
204 index_style = TNLP::C_STYLE;
205 cout << "return from get_nlp_info (OSBonminSolver.cpp)" << endl;
206
208
209 return true;
210}//get_nlp_info
211
212
213bool BonminProblem::get_bounds_info(Index n, Number* x_l, Number* x_u,
214 Index m, Number* g_l, Number* g_u){
215 int i;
216
217 double * mdVarLB = osinstance->getVariableLowerBounds();
218 //std::cout << "GET BOUNDS INFORMATION FOR BONMIN !!!!!!!!!!!!!!!!!" << std::endl;
219 // variables upper bounds
220 double * mdVarUB = osinstance->getVariableUpperBounds();
221
222 for(i = 0; i < n; i++){
223 x_l[ i] = mdVarLB[ i];
224 x_u[ i] = mdVarUB[ i];
225 cout << "x_l !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_l[i] << endl;
226 cout << "x_u !!!!!!!!!!!!!!!!!!!!!!!!!!!" << x_u[i] << endl;
227 }
228 // Bonmin interprets any number greater than nlp_upper_bound_inf as
229 // infinity. The default value of nlp_upper_bound_inf and nlp_lower_bound_inf
230 // is 1e19 and can be changed through bonmin options.
231 // e.g. g_u[0] = 2e19;
232
233 //constraint lower bounds
234 double * mdConLB = osinstance->getConstraintLowerBounds();
235 //constraint upper bounds
236 double * mdConUB = osinstance->getConstraintUpperBounds();
237
238 for(int i = 0; i < m; i++){
239 g_l[ i] = mdConLB[ i];
240 g_u[ i] = mdConUB[ i];
241 cout << "lower !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_l[i] << endl;
242 cout << "upper !!!!!!!!!!!!!!!!!!!!!!!!!!!" << g_u[i] << endl;
243 }
244 return true;
245}//get_bounds_info
246
247
248// returns the initial point for the problem
249bool BonminProblem::get_starting_point(Index n, bool init_x, Number* x,
250 bool init_z, Number* z_L, Number* z_U, Index m, bool init_lambda,
251 Number* lambda) {
252 // Here, we assume we only have starting values for x, if you code
253 // your own NLP, you can provide starting values for the dual variables
254 // if you wish
255 assert(init_x == true);
256 assert(init_z == false);
257 assert(init_lambda == false);
258 int i, m1, n1;
259
260#ifdef DEBUG
261 cout << "get initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
262#endif
263
264 //now set initial values
265#ifdef DEBUG
266 cout << "get number of initial values !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
267 cout << "Is osoption = NULL? " << (osoption == NULL) << endl;
268#endif
269 int k;
270 if (osoption != NULL)
271 m1 = osoption->getNumberOfInitVarValues();
272 else
273 m1 = 0;
274#ifdef DEBUG
275 cout << "number of variables initialed: " << m1 << endl;
276#endif
277
278 n1 = osinstance->getVariableNumber();
279 bool* initialed;
280 initialed = new bool[n1];
281#ifdef DEBUG
282 cout << "number of variables in total: " << n1 << endl;
283#endif
284
285
286 for(k = 0; k < n1; k++)
287 initialed[k] = false;
288
289 if (m1 > 0)
290 {
291#ifdef DEBUG
292 cout << "get initial values " << endl;
293#endif
294
295 InitVarValue** initVarVector = osoption->getInitVarValuesSparse();
296#ifdef DEBUG
297 cout << "done " << endl;
298#endif
299
300 double initval;
301 try
302 {
303 for(k = 0; k < m1; k++)
304 {
305 i = initVarVector[k]->idx;
306 if (initVarVector[k]->idx > n1)
307 throw ErrorClass ("Illegal index value in variable initialization");
308
309 initval = initVarVector[k]->value;
310 if (osinstance->instanceData->variables->var[i]->ub == OSDBL_MAX)
311 { if (osinstance->instanceData->variables->var[i]->lb > initval)
312 throw ErrorClass ("Initial value outside of bounds");
313 }
314 else
315 if (osinstance->instanceData->variables->var[i]->lb == -OSDBL_MAX)
316 { if (osinstance->instanceData->variables->var[i]->ub < initval)
317 throw ErrorClass ("Initial value outside of bounds");
318 }
319 else
320 { if ((osinstance->instanceData->variables->var[i]->lb > initval) ||
321 (osinstance->instanceData->variables->var[i]->ub < initval))
322 throw ErrorClass ("Initial value outside of bounds");
323 }
324
325 x[initVarVector[k]->idx] = initval;
326 initialed[initVarVector[k]->idx] = true;
327 }
328 }
329 catch(const ErrorClass& eclass)
330 { cout << "Error in BonminProblem::get_starting_point (OSBonminSolver.cpp)";
331 cout << endl << endl << endl;
332 }
333 } // end if (m1 > 0)
334
335 double default_initval;
336 default_initval = 1.7171;
337
338 for(k = 0; k < n1; k++)
339 {
340 if (!initialed[k])
341 if (osinstance->instanceData->variables->var[k]->ub == OSDBL_MAX)
342 if (osinstance->instanceData->variables->var[k]->lb <= default_initval)
343 x[k] = default_initval;
344 else
345 x[k] = osinstance->instanceData->variables->var[k]->lb;
346 else
347 if (osinstance->instanceData->variables->var[k]->lb == -OSDBL_MAX)
348 if (osinstance->instanceData->variables->var[k]->ub >= default_initval)
349 x[k] = default_initval;
350 else
351 x[k] = osinstance->instanceData->variables->var[k]->ub;
352 else
353 if ((osinstance->instanceData->variables->var[k]->lb <= default_initval) &&
354 (osinstance->instanceData->variables->var[k]->ub >= default_initval))
355 x[k] = default_initval;
356 else
357 if (osinstance->instanceData->variables->var[k]->lb > default_initval)
358 x[k] = osinstance->instanceData->variables->var[k]->lb;
359 else
360 x[k] = osinstance->instanceData->variables->var[k]->ub;
361 }
362 for(i = 0; i < n1; i++){
363 std::cout << "INITIAL VALUE !!!!!!!!!!!!!!!!!!!! " << x[ i] << std::endl;
364 }
365
366
367 delete[] initialed;
368
369 return true;
370}//get_starting_point
371
372
373// returns the value of the objective function
374bool BonminProblem::eval_f(Index n, const Number* x, bool new_x, Number& obj_value){
375 try{
376 obj_value = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 )[ 0];
377 }
378 catch(const ErrorClass& eclass){
379 bonminErrorMsg = eclass.errormsg;
380 throw;
381 }
382 if( CommonUtil::ISOSNAN( (double)obj_value) ) return false;
383 return true;
384}
385
386bool BonminProblem::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f){
387 int i;
388 double *objGrad;
389 try{
390 //objGrad = osinstance->calculateAllObjectiveFunctionGradients( const_cast<double*>(x), NULL, NULL, new_x, 1)[ 0];
391 //std::cout << "Calculate Objective function gradient " << std::endl;
392 // we assume we are doing the objective function indexed by -1
393 objGrad = osinstance->calculateObjectiveFunctionGradient( const_cast<double*>(x), NULL, NULL, -1, new_x, 1);
394 }
395 catch(const ErrorClass& eclass){
396 bonminErrorMsg = eclass.errormsg;
397 throw;
398 }
399 for(i = 0; i < n; i++){
400 grad_f[ i] = objGrad[ i];
401 //std::cout << grad_f[ i] << std::endl;
402 }
403 std::cout << "DONE WITH Calculate Objective function gradient " << std::endl;
404 return true;
405}//eval_grad_f
406
407// return the value of the constraints: g(x)
408bool BonminProblem::eval_g(Index n, const Number* x, bool new_x, Index m, Number* g) {
409 try{
410 double *conVals = osinstance->calculateAllConstraintFunctionValues( const_cast<double*>(x), NULL, NULL, new_x, 0 );
411 int i;
412 for(i = 0; i < m; i++){
413 if( CommonUtil::ISOSNAN( (double)conVals[ i] ) ) return false;
414 g[i] = conVals[ i] ;
415 }
416 return true;
417 }
418 catch(const ErrorClass& eclass){
419 bonminErrorMsg = eclass.errormsg;
420 throw;
421 }
422}//eval_g
423
424
425// return the structure or values of the jacobian
426bool BonminProblem::eval_jac_g(Index n, const Number* x, bool new_x,
427 Index m, Index nele_jac, Index* iRow, Index *jCol,
428 Number* values){
429 SparseJacobianMatrix *sparseJacobian;
430 if (values == NULL) {
431 // return the values of the jacobian of the constraints
432 //cout << "n: " << n << endl;
433 //cout << "m: " << m << endl;
434 //cout << "nele_jac: " << nele_jac << endl;
435 // return the structure of the jacobian
436 try{
437 sparseJacobian = osinstance->getJacobianSparsityPattern();
438 }
439 catch(const ErrorClass& eclass){
440 bonminErrorMsg = eclass.errormsg;
441 throw;
442 }
443 int i = 0;
444 int k, idx;
445 for(idx = 0; idx < m; idx++){
446 for(k = *(sparseJacobian->starts + idx); k < *(sparseJacobian->starts + idx + 1); k++){
447 iRow[i] = idx;
448 jCol[i] = *(sparseJacobian->indexes + k);
449 //cout << "ROW IDX !!!!!!!!!!!!!!!!!!!!!!!!!!!" << iRow[i] << endl;
450 //cout << "COL IDX !!!!!!!!!!!!!!!!!!!!!!!!!!!" << jCol[i] << endl;
451 i++;
452 }
453 }
454 }
455 else {
456 //std::cout << "EVALUATING JACOBIAN" << std::endl;
457 try{
458 sparseJacobian = osinstance->calculateAllConstraintFunctionGradients( const_cast<double*>(x), NULL, NULL, new_x, 1);
459 }
460 catch(const ErrorClass& eclass){
461 bonminErrorMsg = eclass.errormsg;
462 throw;
463 }
464 //osinstance->getIterateResults( (double*)x, 0.0, NULL, -1, new_x, 1);
465 for(int i = 0; i < nele_jac; i++){
466 values[ i] = sparseJacobian->values[i];
467 //values[ i] = osinstance->m_mdJacValue[ i];
468 //cout << "values[i]:!!!!!!!!!!!! " << values[ i] << endl;
469 //cout << "m_mdJacValue[ i]:!!!!!!!!!!!! " << osinstance->m_mdJacValue[ i] << endl;
470 }
471 }
472 return true;
473}//eval_jac_g
474
475//return the structure or values of the hessian
476bool BonminProblem::eval_h(Index n, const Number* x, bool new_x,
477 Number obj_factor, Index m, const Number* lambda,
478 bool new_lambda, Index nele_hess, Index* iRow,
479 Index* jCol, Number* values){
480
482 SparseHessianMatrix *sparseHessian;
483
484 int i;
485 if (values == NULL) {
486 // return the structure. This is a symmetric matrix, fill the lower left triangle only.
487 //cout << "get structure of HESSIAN !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
488 try{
489 sparseHessian = osinstance->getLagrangianHessianSparsityPattern( );
490 }
491 catch(const ErrorClass& eclass){
492 bonminErrorMsg = eclass.errormsg;
493 throw;
494 }
495 //cout << "got structure of HESSIAN !!!!!!!!!!!!!!!!!!!!!!!!!! " << endl;
496 for(i = 0; i < nele_hess; i++){
497 iRow[i] = *(sparseHessian->hessColIdx + i);
498 jCol[i] = *(sparseHessian->hessRowIdx + i);
499 //cout << "ROW HESS IDX !!!!!!!!!!!!!!!!!!!!!!!!!!!" << iRow[i] << endl;
500 //cout << "COL HESS IDX !!!!!!!!!!!!!!!!!!!!!!!!!!!" << jCol[i] << endl;
501 }
502 }
503 else {
504 //std::cout << "EVALUATING HESSIAN" << std::endl;
505 // return the values. This is a symmetric matrix, fill the lower left triangle only
506 double* objMultipliers = new double[1];
507 objMultipliers[0] = obj_factor;
508 try{
509 sparseHessian = osinstance->calculateLagrangianHessian( const_cast<double*>(x), objMultipliers, const_cast<double*>(lambda) , new_x, 2);
510 delete[] objMultipliers;
511 }
512 catch(const ErrorClass& eclass){
513 bonminErrorMsg = eclass.errormsg;
514 delete[] objMultipliers;
515 throw;
516 }
517 for(i = 0; i < nele_hess; i++){
518 values[ i] = *(sparseHessian->hessValues + i);
519 }
520 }
522 return true;
523}//eval_h
524
525bool BonminProblem::get_scaling_parameters(Number& obj_scaling,
526 bool& use_x_scaling, Index n,
527 Number* x_scaling,
528 bool& use_g_scaling, Index m,
529 Number* g_scaling){
530 /*
531 * Bonmin assumes problems cast as a min
532 * if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") != 0){
533 obj_scaling = -1;
534 }
535 else obj_scaling = 1;
536 use_x_scaling = false;
537 use_g_scaling = false;
538 */
539 return true;
540}//get_scaling_parameters
541
542
543
544
545void
546BonminProblem::finalize_solution(TMINLP::SolverReturn status,
547 Index n, const Number* x, Number obj_value)
548{
549 OSrLWriter *osrlwriter ;
550 osrlwriter = new OSrLWriter();
551 std::cout<<"Problem status: "<<status<<std::endl;
552 std::cout<<"Objective value: "<<obj_value<<std::endl;
553 if(printSol_ && x != NULL){
554 std::cout<<"Solution:"<<std::endl;
555 for(int i = 0 ; i < n ; i++){
556 std::cout<<"x["<<i<<"] = "<<x[i];
557 if(i < n-1) std::cout<<", ";
558 }
559 std::cout<<std::endl;
560 }
561
562 printf("\n\nObjective value\n");
563 printf("f(x*) = %e\n", obj_value);
564 int solIdx = 0;
565 ostringstream outStr;
566 double* mdObjValues = new double[1];
567 std::string message = "Bonmin solver finishes to the end.";
568 std::string solutionDescription = "";
569
570 try{
571
572 // resultHeader information
573 if(osresult->setServiceName( "Bonmin solver service") != true)
574 throw ErrorClass("OSResult error: setServiceName");
575 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
576 throw ErrorClass("OSResult error: setInstanceName");
577
578 //if(osresult->setJobID( osoption->jobID) != true)
579 // throw ErrorClass("OSResult error: setJobID");
580
581 // set basic problem parameters
582 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
583 throw ErrorClass("OSResult error: setVariableNumer");
584 if(osresult->setObjectiveNumber( 1) != true)
585 throw ErrorClass("OSResult error: setObjectiveNumber");
586 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
587 throw ErrorClass("OSResult error: setConstraintNumber");
588 if(osresult->setSolutionNumber( 1) != true)
589 throw ErrorClass("OSResult error: setSolutionNumer");
590
591
592 if(osresult->setGeneralMessage( message) != true)
593 throw ErrorClass("OSResult error: setGeneralMessage");
594
595 switch( status){
596 case SUCCESS:
597 solutionDescription = "SUCCESS[BONMIN]: Algorithm terminated successfully at a locally optimal point, satisfying the convergence tolerances.";
598 osresult->setSolutionStatus(solIdx, "locallyOptimal", solutionDescription);
599 osresult->setPrimalVariableValues(solIdx, const_cast<double*>(x), osinstance->getVariableNumber());
600 //osresult->setDualVariableValues(solIdx, const_cast<double*>( lambda));
601 mdObjValues[0] = obj_value;
602 osresult->setObjectiveValues(solIdx, mdObjValues, 1);
603 break;
604 case MAXITER_EXCEEDED:
605 solutionDescription = "MAXITER_EXCEEDED[BONMIN]: Maximum number of iterations exceeded.";
606 osresult->setSolutionStatus(solIdx, "stoppedByLimit", solutionDescription);
607 osresult->setPrimalVariableValues(solIdx, const_cast<double*>(x), osinstance->getVariableNumber());
608 //osresult->setDualVariableValues(solIdx, const_cast<double*>( lambda));
609 mdObjValues[0] = obj_value;
610 osresult->setObjectiveValues(solIdx, mdObjValues, 1);
611 break;
612 case STOP_AT_TINY_STEP:
613 solutionDescription = "STOP_AT_TINY_STEP[BONMIN]: Algorithm proceeds with very little progress.";
614 osresult->setSolutionStatus(solIdx, "stoppedByLimit", solutionDescription);
615 osresult->setPrimalVariableValues(solIdx, const_cast<double*>( x), osinstance->getVariableNumber());
616 //osresult->setDualVariableValues(solIdx, const_cast<double*>( lambda));
617 mdObjValues[0] = obj_value;
618 osresult->setObjectiveValues(solIdx, mdObjValues, 1);
619 break;
620 case STOP_AT_ACCEPTABLE_POINT:
621 solutionDescription = "STOP_AT_ACCEPTABLE_POINT[BONMIN]: Algorithm stopped at a point that was converged, not to _desired_ tolerances, but to _acceptable_ tolerances";
622 osresult->setSolutionStatus(solIdx, "BonminAccetable", solutionDescription);
623 osresult->setPrimalVariableValues(solIdx, const_cast<double*>(x), osinstance->getVariableNumber());
624 //osresult->setDualVariableValues(solIdx, const_cast<double*>( lambda));
625 mdObjValues[0] = obj_value;
626 osresult->setObjectiveValues(solIdx, mdObjValues, 1);
627 break;
628 case LOCAL_INFEASIBILITY:
629 solutionDescription = "LOCAL_INFEASIBILITY[BONMIN]: Algorithm converged to a point of local infeasibility. Problem may be infeasible.";
630 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
631 break;
632 case USER_REQUESTED_STOP:
633 solutionDescription = "USER_REQUESTED_STOP[BONMIN]: The user call-back function intermediate_callback returned false, i.e., the user code requested a premature termination of the optimization.";
634 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
635 break;
636 case DIVERGING_ITERATES:
637 solutionDescription = "DIVERGING_ITERATES[BONMIN]: It seems that the iterates diverge.";
638 osresult->setSolutionStatus(solIdx, "unbounded", solutionDescription);
639 break;
640 case RESTORATION_FAILURE:
641 solutionDescription = "RESTORATION_FAILURE[BONMIN]: Restoration phase failed, algorithm doesn't know how to proceed.";
642 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
643 break;
644 case ERROR_IN_STEP_COMPUTATION:
645 solutionDescription = "ERROR_IN_STEP_COMPUTATION[BONMIN]: An unrecoverable error occurred while IPOPT tried to compute the search direction.";
646 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
647 break;
648 case INVALID_NUMBER_DETECTED:
649 solutionDescription = "INVALID_NUMcatBER_DETECTED[BONMIN]: Algorithm received an invalid number (such as NaN or Inf) from the NLP; see also option check_derivatives_for_naninf.";
650 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
651 break;
652 case INTERNAL_ERROR:
653 solutionDescription = "INTERNAL_ERROR[BONMIN]: An unknown internal error occurred. Please contact the IPOPT authors through the mailing list.";
654 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
655 break;
656 default:
657 solutionDescription = "OTHER[BONMIN]: other unknown solution status from Bonmin solver";
658 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
659 }
661 delete osrlwriter;
662 delete[] mdObjValues;
663 osrlwriter = NULL;
664
665 }
666
667 catch(const ErrorClass& eclass){
670 std::string osrl = osrlwriter->writeOSrL( osresult);
671 delete osrlwriter;
672 osrlwriter = NULL;
673 throw ErrorClass( osrl) ;
674 delete[] mdObjValues;
675 mdObjValues = NULL;
676 }
677}
678
679
680
681
683 try{
684 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
685 if(osinstance == NULL){
686 m_osilreader = new OSiLReader();
687 osinstance = m_osilreader->readOSiL( osil);
688 }
689 // Create a new instance of your nlp
690 tminlp = new BonminProblem( osinstance, osoption, osresult);
691 this->bCallbuildSolverInstance = true;
692 //Now initialize from tminlp
693 bonmin.initialize( GetRawPtr(tminlp) );
694 }
695 catch(const ErrorClass& eclass){
696 std::cout << "THERE IS AN ERROR" << std::endl;
697 osresult->setGeneralMessage( eclass.errormsg);
698 osresult->setGeneralStatusType( "error");
699 osrl = osrlwriter->writeOSrL( osresult);
700 throw ErrorClass( osrl) ;
701 }
702}//end buildSolverInstance()
703
704
705
707 try{
708
709 this->bSetSolverOptions = true;
710 bonmin.initializeOptionsAndJournalist();
711 //Register an additional option
712 bonmin.roptions()->AddStringOption2("print_solution","Do we print the solution or not?",
713 "yes",
714 "no", "No, we don't.",
715 "yes", "Yes, we do.",
716 "A longer comment can be put here");
717
718 // Here we can change the default value of some Bonmin or Ipopt option
719 bonmin.options()->SetNumericValue("bonmin.time_limit", 1000); //changes bonmin's time limit
720 bonmin.options()->SetStringValue("mu_oracle","loqo");
721
722 //Here we read several option files
723 bonmin.readOptionsFile("Mybonmin.opt");
724 bonmin.readOptionsFile();// This reads the default file "bonmin.opt"
725
726 // Options can also be set by using a string with a format similar to the bonmin.opt file
727 bonmin.readOptionsString("bonmin.algorithm B-BB\n");
728
729 // Now we can obtain the value of the new option
730 int printSolution;
731 bonmin.options()->GetEnumValue("print_solution", printSolution,"");
732 if(printSolution == 1){
733 tminlp->printSolutionAtEndOfAlgorithm();
734 }
735
736 if(osoption == NULL && osol.length() > 0)
737 {
738 m_osolreader = new OSoLReader();
739 osoption = m_osolreader->readOSoL( osol);
740 }
741
742 if(osoption != NULL){
743 std::cout << "number of solver options " << osoption->getNumberOfSolverOptions() << std::endl;
744 std::vector<SolverOption*> optionsVector;
745 optionsVector = osoption->getSolverOptions( "bonmin");
746 char *pEnd;
747 int i;
748 int num_bonmin_options = optionsVector.size();
749 for(i = 0; i < num_bonmin_options; i++){
750 std::cout << "bonmin solver option " << optionsVector[ i]->name << std::endl;
751 if(optionsVector[ i]->type == "numeric" ){
752 std::cout << "FOUND A NUMERIC OPTION " << os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) << std::endl;
753 bonmin.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
754 }
755 else if(optionsVector[ i]->type == "integer" ){
756 std::cout << "FOUND AN INTEGER OPTION " << atoi( optionsVector[ i]->value.c_str() ) << std::endl;
757 bonmin.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
758 }
759 else if(optionsVector[ i]->type == "string" ){
760 bonmin.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value);
761 }
762 }
763 }
764
765 }
766
767 catch(const ErrorClass& eclass){
768 std::cout << "THERE IS AN ERROR" << std::endl;
769 osresult->setGeneralMessage( eclass.errormsg);
770 osresult->setGeneralStatusType( "error");
771 osrl = osrlwriter->writeOSrL( osresult);
772 throw ErrorClass( osrl) ;
773 }
774}//end setSolverOptions()
775
776
777//void BonminSolver::solve() throw (ErrorClass) {
778void BonminSolver::solve() throw (ErrorClass) {
779 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
780 std::cout << "set Solver Options for Gus" << std::endl;
781 if( this->bSetSolverOptions == false) setSolverOptions();
782 std::cout << "done setting set Solver Options for Gus" << std::endl;
783
784 try{
785 double start = CoinCpuTime();
786 //OSiLWriter osilwriter;
787 //cout << osilwriter.writeOSiL( osinstance) << endl;
788 if(osinstance->getVariableNumber() <= 0)throw ErrorClass("Bonmin requires decision variables");
789
790// The next line should come out eventually...
791 if(osinstance->getConstraintNumber() <= 0)throw ErrorClass("Bonmin cannot handle unconstrained problems");
792
793 double duration = CoinCpuTime() - start;
794 cout << "Parsing took (seconds): "<< duration << endl;
795
796 try {
797 Bab bb;
798 bb( bonmin); //process parameter file using Ipopt and do branch and bound using Cbc
799
800
801 }
802 catch(TNLPSolver::UnsolvedError *E) {
803 //There has been a failure to solve a problem with Ipopt.
804 std::cerr<<"Ipopt has failed to solve a problem"<<std::endl;
805 }
806 catch(OsiTMINLPInterface::SimpleError &E) {
807 std::cerr<<E.className()<<"::"<<E.methodName()
808 <<std::endl
809 <<E.message()<<std::endl;
810 }
811 catch(CoinError &E) {
812 std::cerr<<E.className()<<"::"<<E.methodName()
813 <<std::endl
814 <<E.message()<<std::endl;
815 }
816
817
818 // see if we have a linear program
819 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Bonmin NEEDS AN OBJECTIVE FUNCTION");
820 if( (osinstance->getNumberOfNonlinearExpressions() == 0) && (osinstance->getNumberOfQuadraticTerms() == 0) )
821 //app->Options()->SetStringValue("hessian_approximation", "limited-memory");
822 // if it is a max problem call scaling and set to -1
823 if( osinstance->instanceData->objectives->obj[ 0]->maxOrMin.compare("min") != 0){
824 //app->Options()->SetStringValue("nlp_scaling_method", "user-scaling");
825 }
826
827 std::cout << "Finish Bonmin Optimize" << std::endl;
828 osrl = osrlwriter->writeOSrL( osresult);
829 std::cout << "Finish writing the osrl" << std::endl;
830
831
832 }
833 catch(const ErrorClass& eclass){
834 osresult->setGeneralMessage( eclass.errormsg);
835 osresult->setGeneralStatusType( "error");
836 osrl = osrlwriter->writeOSrL( osresult);
837 throw ErrorClass( osrl) ;
838 }
839}//solve
840
841
843
844 int i;
845
846 // print out problem parameters
847 cout << "This is problem: " << osinstance->getInstanceName() << endl;
848 cout << "The problem source is: " << osinstance->getInstanceSource() << endl;
849 cout << "The problem description is: " << osinstance->getInstanceDescription() << endl;
850 cout << "number of variables = " << osinstance->getVariableNumber() << endl;
851 cout << "number of Rows = " << osinstance->getConstraintNumber() << endl;
852
853 // print out the variable information
854 if(osinstance->getVariableNumber() > 0){
855 for(i = 0; i < osinstance->getVariableNumber(); i++){
856 if(osinstance->getVariableNames() != NULL) cout << "variable Names " << osinstance->getVariableNames()[ i] << endl;
857 if(osinstance->getVariableTypes() != NULL) cout << "variable Types " << osinstance->getVariableTypes()[ i] << endl;
858 if(osinstance->getVariableLowerBounds() != NULL) cout << "variable Lower Bounds " << osinstance->getVariableLowerBounds()[ i] << endl;
859 if(osinstance->getVariableUpperBounds() != NULL) cout << "variable Upper Bounds " << osinstance->getVariableUpperBounds()[i] << endl;
860 }
861 }
862
863 // print out objective function information
864 if(osinstance->getVariableNumber() > 0 || osinstance->instanceData->objectives->obj != NULL || osinstance->instanceData->objectives->numberOfObjectives > 0){
865 if( osinstance->getObjectiveMaxOrMins()[0] == "min") cout << "problem is a minimization" << endl;
866 else cout << "problem is a maximization" << endl;
867 for(i = 0; i < osinstance->getVariableNumber(); i++){
868 cout << "OBJ COEFFICIENT = " << osinstance->getDenseObjectiveCoefficients()[0][i] << endl;
869 }
870 }
871 // print out constraint information
872 if(osinstance->getConstraintNumber() > 0){
873 for(i = 0; i < osinstance->getConstraintNumber(); i++){
874 if(osinstance->getConstraintNames() != NULL) cout << "row name = " << osinstance->getConstraintNames()[i] << endl;
875 if(osinstance->getConstraintLowerBounds() != NULL) cout << "row lower bound = " << osinstance->getConstraintLowerBounds()[i] << endl;
876 if(osinstance->getConstraintUpperBounds() != NULL) cout << "row upper bound = " << osinstance->getConstraintUpperBounds()[i] << endl;
877 }
878 }
879
880 // print out linear constraint data
881 cout << endl;
882 cout << "number of nonzeros = " << osinstance->getLinearConstraintCoefficientNumber() << endl;
883 for(i = 0; i <= osinstance->getVariableNumber(); i++){
884 cout << "Start Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->starts[ i] << endl;
885 }
886 cout << endl;
887 for(i = 0; i < osinstance->getLinearConstraintCoefficientNumber(); i++){
888 cout << "Index Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->indexes[i] << endl;
889 cout << "Nonzero Value = " << osinstance->getLinearConstraintCoefficientsInColumnMajor()->values[i] << endl;
890 }
891
892 // print out quadratic data
893 cout << "number of qterms = " << osinstance->getNumberOfQuadraticTerms() << endl;
894 for(int i = 0; i < osinstance->getNumberOfQuadraticTerms(); i++){
895 cout << "Row Index = " << osinstance->getQuadraticTerms()->rowIndexes[i] << endl;
896 cout << "Var Index 1 = " << osinstance->getQuadraticTerms()->varOneIndexes[ i] << endl;
897 cout << "Var Index 2 = " << osinstance->getQuadraticTerms()->varTwoIndexes[ i] << endl;
898 cout << "Coefficient = " << osinstance->getQuadraticTerms()->coefficients[ i] << endl;
899 }
900} // end dataEchoCheck
901
902
903BonminProblem::BonminProblem(OSInstance *osinstance_, OSOption *osoption_, OSResult *osresult_) {
904 osinstance = osinstance_;
905 osoption = osoption_;
906 osresult = osresult_;
907 printSol_ = false;
908}
909
911
912}
913
914
915
#define INTEGER
U * GetRawPtr(const OSSmartPtr< U > &smart_ptr)
double os_strtod(const char *s00, char **se)
Definition OSdtoa.cpp:2541
bool printSol_
Method called by Ipopt at the end of optimization.
virtual ~BonminProblem()
the BonminProblem class destructor
virtual bool get_constraints_linearity(Ipopt::Index m, Ipopt::TNLP::LinearityType *const_types)
Pass the type of the constraints (LINEAR, NON_LINEAR) to the optimizer.
virtual bool eval_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Number *g)
Method to return the constraint residuals.
virtual void finalize_solution(Bonmin::TMINLP::SolverReturn status_, Ipopt::Index n, const Ipopt::Number *x, Ipopt::Number obj_value)
Method called by Ipopt at the end of optimization.
virtual bool get_nlp_info(Ipopt::Index &n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g, Ipopt::Index &nnz_h_lag, Ipopt::TNLP::IndexStyleEnum &index_style)
Method to pass the main dimensions of the problem to Ipopt.
OSOption * osoption
virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number *grad_f)
Method to return the gradient of the objective.
OSInstance * osinstance
virtual bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number *x, bool init_z, Ipopt::Number *z_L, Ipopt::Number *z_U, Ipopt::Index m, bool init_lambda, Ipopt::Number *lambda)
Method to return the starting point for the algorithm.
virtual bool get_variables_types(Ipopt::Index n, VariableType *var_types)
Pass the type of the variables (INTEGER, BINARY, CONTINUOUS) to the optimizer.
virtual bool eval_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number &obj_value)
Method to return the objective value.
virtual bool get_variables_linearity(Ipopt::Index n, Ipopt::TNLP::LinearityType *var_types)
Pass info about linear and nonlinear variables.
virtual bool get_bounds_info(Ipopt::Index n, Ipopt::Number *x_l, Ipopt::Number *x_u, Ipopt::Index m, Ipopt::Number *g_l, Ipopt::Number *g_u)
Bonmin specific methods for defining the nlp problem.
std::string bonminErrorMsg
Bonmin::TMINLP::SolverReturn status
BonminProblem(OSInstance *osinstance_, OSOption *osoption_)
the BonminProblemclass constructor
virtual bool eval_h(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number obj_factor, Ipopt::Index m, const Ipopt::Number *lambda, bool new_lambda, Ipopt::Index nele_hess, Ipopt::Index *iRow, Ipopt::Index *jCol, Ipopt::Number *values)
Method to return: 1) The structure of the hessian of the lagrangian (if "values" is NULL) 2) The valu...
virtual bool get_scaling_parameters(Ipopt::Number &obj_scaling, bool &use_x_scaling, Ipopt::Index n, Ipopt::Number *x_scaling, bool &use_g_scaling, Ipopt::Index m, Ipopt::Number *g_scaling)
Method to pass the main dimensions of the problem to Ipopt.
virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index *iRow, Ipopt::Index *jCol, Ipopt::Number *values)
Method to return: 1) The structure of the jacobian (if "values" is NULL) 2) The values of the jacobia...
std::string bonminErrorMsg
Ipopt::SmartPtr< BonminProblem > tminlp
Bonmin::Bab bb
virtual void setSolverOptions()
The implementation of the virtual functions.
virtual void buildSolverInstance()
buildSolverInstance is a virtual function – the actual solvers will implement their own buildSolverIn...
void dataEchoCheck()
use this for debugging, print out the instance that the solver thinks it has and compare this with th...
OSiLReader * m_osilreader
m_osilreader is an OSiLReader object used to create an osinstance from an osil string if needed
OSoLReader * m_osolreader
m_osolreader is an OSoLReader object used to create an osoption from an osol string if needed
~BonminSolver()
the IpoptSolver class destructor
virtual void solve()
solve results in an instance being read into the Bonmin data structrues and optimized
OSrLWriter * osrlwriter
BonminSolver()
the BonminSolver class constructor
std::string osol
osol holds the options for the solver
bool bSetSolverOptions
bSetSolverOptions is set to true if setSolverOptions has been called, false otherwise
std::string osrl
osrl holds the solution or result of the model
OSInstance * osinstance
osinstance holds the problem instance in-memory as an OSInstance object
bool bCallbuildSolverInstance
bCallbuildSolverInstance is set to true if buildSolverService has been called
std::string osil
osil holds the problem instance as a std::string
OSOption * osoption
osoption holds the solver options in-memory as an OSOption object
OSResult * osresult
osresult holds the solution or result of the model in-memory as an OSResult object
used for throwing exceptions.
std::string errormsg
errormsg is the error that is causing the exception to be thrown
double value
initial value
Definition OSOption.h:1170
int idx
variable index
Definition OSOption.h:1164
The in-memory representation of an OSiL instance..
The Option Class.
Definition OSOption.h:3565
The Result Class.
Definition OSResult.h:2549
bool setGeneralMessage(std::string message)
Set the general message.
bool setPrimalVariableValues(int solIdx, double *x, int n)
Set the [i]th optimization solution's primal variable values, where i equals the given solution index...
bool setSolutionNumber(int number)
set the number of solutions.
bool setInstanceName(std::string instanceName)
Set instance name.
bool setGeneralStatusType(std::string type)
Set the general status type, which can be: success, error, warning.
bool setObjectiveNumber(int objectiveNumber)
Set the objective number.
bool setObjectiveValues(int solIdx, double *objectiveValues, int n)
Set the [i]th optimization solution's objective values, where i equals the given solution index.
bool setServiceName(std::string serviceName)
Set service name.
bool setVariableNumber(int variableNumber)
Set the variable number.
bool setSolutionStatus(int solIdx, std::string type, std::string description)
Set the [i]th optimization solution status, where i equals the given solution index.
bool setConstraintNumber(int constraintNumber)
Set the constraint number.
std::string writeOSrL(OSResult *theosresult)
create an osrl string from an OSResult object
int * hessRowIdx
hessRowIdx is an integer array of row indices in the range 0, ..., n - 1.
Definition OSGeneral.h:394
int hessDimension
hessDimension is the number of nonzeros in each array.
Definition OSGeneral.h:389
double * hessValues
hessValues is a double array of the Hessian values.
Definition OSGeneral.h:404
int * hessColIdx
hessColIdx is an integer array of column indices in the range 0, ..., n - 1.
Definition OSGeneral.h:399
int * indexes
indexes holds an integer array of variable indices.
Definition OSGeneral.h:335
int valueSize
valueSize is the dimension of the values array
Definition OSGeneral.h:318
int * starts
starts holds an integer array of start elements, each start element points to the start of partials f...
Definition OSGeneral.h:324
double * values
values holds a double array of nonzero partial derivatives
Definition OSGeneral.h:340
#define OSDBL_MAX
OSResult * osresult