00001
00019 #include <iostream>
00020
00021
00022
00023 #include "OSDataStructures.h"
00024 #include "OSParameters.h"
00025 #include "OSMathUtil.h"
00026 #include "OSCouenneSolver.h"
00027 #include "BonBonminSetup.hpp"
00028 # include <cppad/cppad.hpp>
00029
00030
00031
00032
00033
00034 #include "CouenneTypes.hpp"
00035 #include "exprClone.hpp"
00036 #include "exprGroup.hpp"
00037 #include "exprAbs.hpp"
00038 #include "exprConst.hpp"
00039 #include "exprCos.hpp"
00040 #include "exprDiv.hpp"
00041 #include "exprExp.hpp"
00042 #include "exprInv.hpp"
00043 #include "exprLog.hpp"
00044 #include "exprMax.hpp"
00045 #include "exprMin.hpp"
00046 #include "exprMul.hpp"
00047 #include "exprOpp.hpp"
00048 #include "exprPow.hpp"
00049 #include "exprSin.hpp"
00050 #include "exprSub.hpp"
00051 #include "exprSum.hpp"
00052 #include "exprVar.hpp"
00053 #include "CouenneJournalist.hpp"
00054
00055
00056
00057
00058
00059 #include "BonOsiTMINLPInterface.hpp"
00060 #include "BonIpoptSolver.hpp"
00061
00062
00063 #include "CoinTime.hpp"
00064 #include "BonminConfig.h"
00065 #include "BonCouenneInterface.hpp"
00066
00067
00068 #include "BonCouenneSetup.hpp"
00069
00070
00071 #ifdef COIN_HAS_FILTERSQP
00072 #include "BonFilterSolver.hpp"
00073 #endif
00074
00075 #include "CbcCutGenerator.hpp"
00076 #include "CouenneProblem.hpp"
00077 #include "CouenneCutGenerator.hpp"
00078
00079
00080 # include <cstddef>
00081 # include <cstdlib>
00082 # include <cctype>
00083 # include <cassert>
00084 # include <stack>
00085 #include <string>
00086 #include<iostream>
00087
00088
00089
00090 using namespace Bonmin;
00091 using std::cout;
00092 using std::endl;
00093 using std::ostringstream;
00094
00095
00096 CouenneSolver::CouenneSolver() {
00097 using namespace Ipopt;
00098 osrlwriter = new OSrLWriter();
00099 osresult = new OSResult();
00100 m_osilreader = NULL;
00101 m_osolreader = NULL;
00102 couenneErrorMsg = "";
00103 couenne = NULL;
00104 con_body = NULL;
00105 obj_body = NULL;
00106 }
00107
00108 CouenneSolver::~CouenneSolver() {
00109 #ifdef DEBUG
00110 cout << "inside CouenneSolver destructor" << endl;
00111 #endif
00112
00113 if(couenne != NULL){
00114
00116
00117 }
00118 if(con_body != NULL){
00119
00120 }
00121 if(obj_body != NULL){
00122
00123 }
00124 if(m_osilreader != NULL) {
00125
00126 delete m_osilreader;
00127
00128 }
00129 m_osilreader = NULL;
00130 if(m_osolreader != NULL) delete m_osolreader;
00131 m_osolreader = NULL;
00132 delete osresult;
00133 osresult = NULL;
00134 delete osrlwriter;
00135 osrlwriter = NULL;
00136
00137
00138 #ifdef DEBUG
00139 cout << "leaving CouenneSolver destructor" << endl;
00140 #endif
00141
00142 }
00143
00144
00145 void CouenneSolver::buildSolverInstance() throw (ErrorClass) {
00146
00147 try{
00148 this->bCallbuildSolverInstance = true;
00149
00150
00151
00152
00153
00154 int i, j;
00155
00156 if(osil.length() == 0 && osinstance == NULL) throw ErrorClass("there is no instance");
00157 if(osinstance == NULL){
00158 m_osilreader = new OSiLReader();
00159 osinstance = m_osilreader->readOSiL( osil);
00160 }
00161
00162
00163
00164
00165 osinstance->initForAlgDiff( );
00166
00167
00168
00169 couenne = new CouenneProblem(NULL, NULL, NULL);
00170 int n_allvars = osinstance->getVariableNumber();
00171 if( n_allvars <= 0 )throw ErrorClass("Couenne solver Needs Variables");
00172 #ifdef DEBUG
00173 std::cout << "NUMBER OF VARIABLES = " << n_allvars << std::endl;
00174 #endif
00175
00176
00177 CouNumber *x_ = (CouNumber *) malloc ((n_allvars) * sizeof (CouNumber));
00178 CouNumber *lb = NULL, *ub = NULL;
00179
00180
00181 ub = osinstance->getVariableUpperBounds();
00182 lb = osinstance->getVariableLowerBounds();
00183
00184
00185 char *varType;
00186 varType = osinstance->getVariableTypes();
00187 for (i = 0; i < n_allvars; ++i) {
00188 if( (varType[i] == 'B') || (varType[i]) == 'I' ) {
00189 couenne->addVariable(true, couenne->domain() );
00190 }
00191 else{
00192
00193 couenne->addVariable(false, couenne->domain() );
00194
00195 }
00196
00197 x_[i] = 0.;
00198 }
00199
00200 couenne->domain()->push(n_allvars, x_, lb, ub);
00201 free(x_);
00202
00203
00204
00205
00206 if(osinstance->getObjectiveNumber() <= 0) throw ErrorClass("Couenne NEEDS AN OBJECTIVE FUNCTION");
00207 SparseVector* sv = osinstance->getObjectiveCoefficients()[ 0];
00208
00209 int nterms = sv->number;
00210 exprGroup::lincoeff lin( nterms);
00211 for ( i = 0; i < nterms; ++i){
00212 lin[i].first = couenne->Var( sv->indexes[ i] );
00213 if( osinstance->getObjectiveMaxOrMins()[0] == "min"){
00214 lin[i].second = sv->values[ i];
00215 }else{
00216 lin[i].second = -sv->values[ i];
00217
00218 }
00219 }
00220
00221 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( -1);
00222 if (exptree != NULL) {
00223 expression** nl = new expression*[1];
00224 if( osinstance->getObjectiveMaxOrMins()[0] == "min"){
00225 nl[0] = createCouenneExpression( exptree->m_treeRoot );
00226 }else{
00227 nl[ 0] = new exprOpp(createCouenneExpression( exptree->m_treeRoot) );
00228
00229 }
00230 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, nl, 1);
00231 } else {
00232 obj_body = new exprGroup(osinstance->getObjectiveConstants()[0], lin, NULL, 0);
00233
00234 }
00235
00236
00237 couenne->addObjective(obj_body, "min");
00238
00239
00240
00241 SparseMatrix* sm = osinstance->getLinearConstraintCoefficientsInRowMajor();
00242
00243 int nconss = osinstance->getConstraintNumber();
00244 int row_nonz = 0;
00245 int kount = 0;
00246
00247 double *rowlb = osinstance->getConstraintLowerBounds();
00248 double *rowub = osinstance->getConstraintUpperBounds();
00249
00250 for (i = 0; i < nconss; ++i) {
00251
00252 row_nonz = 0;
00253 if( sm) row_nonz = sm->starts[ i +1] - sm->starts[ i];
00254 exprGroup::lincoeff con_lin( row_nonz);
00255 for (j = 0; j < row_nonz; ++j){
00256 con_lin[j].first = couenne->Var( sm->indexes[ kount] );
00257 con_lin[j].second = sm->values[ kount];
00258 kount++;
00259 }
00260
00261 OSExpressionTree* exptree = osinstance->getNonlinearExpressionTree( i);
00262 if (exptree != NULL) {
00263 expression** nl = new expression*[1];
00264 nl[0] = createCouenneExpression(exptree->m_treeRoot);
00265 con_body = new exprGroup(0., con_lin, nl, 1);
00266 } else {
00267 con_body = new exprGroup(0., con_lin, NULL, 0);
00268 }
00269
00270 if (rowlb[ i] == rowub[ i])
00271 {
00272 couenne->addEQConstraint(con_body, new exprConst( rowub[ i] ));
00273 }
00274 else if (rowlb[ i] == -OSDBL_MAX)
00275 {
00276 assert(rowub[ i] != -OSDBL_MAX);
00277 couenne->addLEConstraint(con_body, new exprConst( rowub[ i] ));
00278 }
00279 else if (rowub[ i] == OSDBL_MAX)
00280 {
00281 assert(rowlb[ i] != OSDBL_MAX);
00282 couenne->addGEConstraint(con_body, new exprConst( rowlb[ i] ));
00283 }
00284 else
00285 couenne->addRNGConstraint(con_body, new exprConst( rowlb[ i]), new
00286 exprConst( rowub[ i] ));
00287
00288 }
00289 }
00290 catch(const ErrorClass& eclass){
00291 std::cout << "THERE IS AN ERROR" << std::endl;
00292 osresult->setGeneralMessage( eclass.errormsg);
00293 osresult->setGeneralStatusType( "error");
00294 osrl = osrlwriter->writeOSrL( osresult);
00295 throw ErrorClass( osrl) ;
00296 }
00297 }
00298
00299
00300 expression* CouenneSolver::createCouenneExpression(OSnLNode* node) {
00301
00302 unsigned int i;
00303 switch (node->inodeInt) {
00304 case OS_PLUS :
00305 return new exprSum(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00306 case OS_SUM :
00307
00308
00309
00310 switch ( node->inumberOfChildren ) {
00311 case 0:
00312
00313 return new exprConst(0.);
00314 case 1:
00315
00316 return createCouenneExpression(node->m_mChildren[0]);
00317 default:
00318
00319 expression** sumargs = new expression*[node->inumberOfChildren];
00320 for(i = 0; i< node->inumberOfChildren; i++)
00321 sumargs[i] = createCouenneExpression(node->m_mChildren[i]);
00322
00323
00324
00325 return new exprSum(sumargs, node->inumberOfChildren);
00326 }
00327 case OS_MINUS :
00328 return new exprSub(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00329 case OS_NEGATE :
00330 return new exprOpp(createCouenneExpression(node->m_mChildren[0]));
00331 case OS_TIMES :
00332 return new exprMul(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00333 case OS_DIVIDE :
00334
00335 if (node->m_mChildren[0]->inodeInt == OS_NUMBER)
00336 return new exprMul(createCouenneExpression(node->m_mChildren[0]), new exprInv(createCouenneExpression(node->m_mChildren[1])));
00337 else
00338 return new exprDiv(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00339 case OS_POWER :
00340
00341 if (node->m_mChildren[1]->inodeInt != OS_NUMBER)
00342 return new exprExp(new exprMul(new exprLog(createCouenneExpression(node->m_mChildren[0])), createCouenneExpression(node->m_mChildren[1])));
00343 else
00344 return new exprPow(createCouenneExpression(node->m_mChildren[0]), createCouenneExpression(node->m_mChildren[1]));
00345 case OS_PRODUCT:
00346 switch ( node->inumberOfChildren ) {
00347 case 0:
00348 return new exprConst(1.);
00349 case 1:
00350 return createCouenneExpression(node->m_mChildren[0]);
00351 default:
00352 expression** args = new expression*[node->inumberOfChildren];
00353 for( i = 0; i < node->inumberOfChildren;i++)
00354 args[i] = createCouenneExpression(node->m_mChildren[i]);
00355 expression* base = new exprMul(args, node->inumberOfChildren);
00356
00357 return base;
00358 }
00359 case OS_ABS :
00360 return new exprAbs(createCouenneExpression(node->m_mChildren[0]));
00361 case OS_SQUARE :
00362 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(2.));
00363 case OS_SQRT :
00364 return new exprPow(createCouenneExpression(node->m_mChildren[0]), new exprConst(0.5));
00365 case OS_LN :
00366 return new exprLog(createCouenneExpression(node->m_mChildren[0]));
00367 case OS_EXP :
00368 return new exprExp(createCouenneExpression(node->m_mChildren[0]));
00369 case OS_SIN :
00370 return new exprSin(createCouenneExpression(node->m_mChildren[0]));
00371 case OS_COS :
00372 return new exprCos(createCouenneExpression(node->m_mChildren[0]));
00373 case OS_MIN :
00374 switch (node->inumberOfChildren==0) {
00375 case 0:
00376 return new exprConst(0.);
00377 case 1:
00378 return createCouenneExpression(node->m_mChildren[0]);
00379 default:
00380 expression** args = new expression*[node->inumberOfChildren];
00381 for( i = 0; i <node->inumberOfChildren;i++)
00382 args[i] = createCouenneExpression(node->m_mChildren[i]);
00383 expression* base = new exprMin(args, node->inumberOfChildren);
00384
00385 return base;
00386 }
00387 case OS_MAX :
00388 switch (node->inumberOfChildren==0) {
00389 case 0:
00390 return new exprConst(0.);
00391 case 1:
00392 return createCouenneExpression(node->m_mChildren[0]);
00393 default:
00394 expression** args = new expression*[node->inumberOfChildren];
00395 for(i = 0; i < node->inumberOfChildren;i++)
00396 args[i] = createCouenneExpression(node->m_mChildren[i]);
00397 expression* base = new exprMax(args, node->inumberOfChildren);
00398
00399 return base;
00400 }
00401 case OS_NUMBER :
00402 return new exprConst(((OSnLNodeNumber*)node)->value);
00403 case OS_PI :
00404 assert(false);
00405
00406
00407 case OS_VARIABLE : {
00408 OSnLNodeVariable* varnode = (OSnLNodeVariable*)node;
00409 if (varnode->coef == 0.)
00410 return new exprConst(0.);
00411 if (varnode->coef == 1.)
00412 return new exprClone(couenne->Variables()[varnode->idx]);
00413 if (varnode->coef == -1.)
00414 return new exprOpp(new exprClone(couenne->Variables()[varnode->idx]));
00415 return new exprMul(new exprConst(varnode->coef), new exprClone(couenne->Variables()[varnode->idx]));
00416 }
00417 default:
00418 cout << node->snodeName << " NOT IMPLEMENTED!!" << endl;
00419 break;
00420 }
00421
00422 return NULL;
00423 }
00424
00425
00426 void CouenneSolver::setSolverOptions() throw (ErrorClass) {
00427 try{
00428
00429 char *pEnd;
00430 bSetSolverOptions = true;
00431 couenneSetup.initializeOptionsAndJournalist();
00432
00433 couenneSetup.options()->SetIntegerValue("bonmin.bb_log_level", 0);
00434 couenneSetup.options()->SetIntegerValue("bonmin.nlp_log_level", 0 );
00435 if(osoption == NULL && osol.length() > 0)
00436 {
00437 m_osolreader = new OSoLReader();
00438 osoption = m_osolreader->readOSoL( osol);
00439 }
00440
00441 if(osoption != NULL && osoption->getNumberOfSolverOptions() > 0 ){
00442
00443 int i;
00444 std::vector<SolverOption*> optionsVector;
00445 optionsVector = osoption->getSolverOptions( "couenne");
00446 int num_bonmin_options = optionsVector.size();
00447 for(i = 0; i < num_bonmin_options; i++){
00448 if(optionsVector[ i]->type == "numeric" ){
00449
00450 if(optionsVector[ i]->category == "ipopt"){
00451 couenneSetup.options()->SetNumericValue(optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00452 }else{
00453 if(optionsVector[ i]->category == "bonmin" ){
00454 couenneSetup.options()->SetNumericValue("bonmin."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00455 }
00456 else{
00457 couenneSetup.options()->SetNumericValue("couenne."+optionsVector[ i]->name, os_strtod( optionsVector[ i]->value.c_str(), &pEnd ) );
00458 }
00459 }
00460 }
00461 else if(optionsVector[ i]->type == "integer" ){
00462
00463 if(optionsVector[ i]->category == "ipopt"){
00464 couenneSetup.options()->SetIntegerValue(optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00465 }else{
00466 if(optionsVector[ i]->category == "bonmin" ){
00467 couenneSetup.options()->SetIntegerValue("bonmin."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ));
00468 }
00469 else{
00470 couenneSetup.options()->SetIntegerValue("couenne."+optionsVector[ i]->name, atoi( optionsVector[ i]->value.c_str() ) );
00471 }
00472 }
00473 }
00474 else if(optionsVector[ i]->type == "string" ){
00475
00476 if(optionsVector[ i]->category == "ipopt"){
00477 couenneSetup.options()->SetStringValue(optionsVector[ i]->name, optionsVector[ i]->value );
00478 }else{
00479 if(optionsVector[ i]->category == "bonmin" ){
00480 couenneSetup.options()->SetStringValue("bonmin."+optionsVector[ i]->name, optionsVector[ i]->value);
00481 }
00482 else{
00483 couenneSetup.options()->SetStringValue("couenne."+optionsVector[ i]->name, optionsVector[ i]->value);
00484 }
00485 }
00486
00487 }
00488 }
00489 }
00490 }
00491
00492 catch(const ErrorClass& eclass){
00493 std::cout << "THERE IS AN ERROR" << std::endl;
00494 osresult->setGeneralMessage( eclass.errormsg);
00495 osresult->setGeneralStatusType( "error");
00496 osrl = osrlwriter->writeOSrL( osresult);
00497 throw ErrorClass( osrl) ;
00498 }
00499
00500 }
00501
00502
00503 using namespace Ipopt;
00504
00505
00506 void CouenneSolver::solve() throw (ErrorClass) {
00507 #define PRINTED_PRECISION 1e-5
00508 const int infeasible = 1;
00509
00510 if( this->bCallbuildSolverInstance == false) buildSolverInstance();
00511 if(this->bSetSolverOptions == false) setSolverOptions() ;
00512 try{
00513
00514
00515
00516 char **argv = NULL;
00517
00518 bb.setUsingCouenne (true);
00519
00520
00521
00522 if(osoption == NULL && osol.length() > 0){
00523 m_osolreader = new OSoLReader();
00524 osoption = m_osolreader->readOSoL( osol);
00525 }
00526
00527
00528 tminlp = new BonminProblem( osinstance, osoption);
00529
00530 CouenneInterface *ci = NULL;
00531
00532 ci = new CouenneInterface();
00533
00534
00535
00536
00537 ci->initialize (couenneSetup.roptions(),
00538 couenneSetup.options(),
00539 couenneSetup.journalist(),
00540 GetRawPtr( tminlp) );
00541
00542
00543 app_ = new Bonmin::IpoptSolver(couenneSetup.roptions(),
00544 couenneSetup.options(),
00545 couenneSetup.journalist()
00546 );
00547
00548
00549
00550
00551 ci->setModel( GetRawPtr( tminlp) );
00552
00553 ci->setSolver( GetRawPtr( app_) );
00554
00555
00556
00557
00558 bool setupInit = false;
00559 setupInit = couenneSetup.InitializeCouenne(argv, couenne, ci);
00560
00561
00562
00563 if(setupInit == false){
00564 std::string solutionDescription = "";
00565 std::string message = "Couenne solver finishes to the end.";
00566 int solIdx = 0;
00567 if(osresult->setServiceName( "Couenne solver service") != true)
00568 throw ErrorClass("OSResult error: setServiceName");
00569 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00570 throw ErrorClass("OSResult error: setInstanceName");
00571 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00572 throw ErrorClass("OSResult error: setVariableNumer");
00573 if(osresult->setObjectiveNumber( 1) != true)
00574 throw ErrorClass("OSResult error: setObjectiveNumber");
00575 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00576 throw ErrorClass("OSResult error: setConstraintNumber");
00577 if(osresult->setSolutionNumber( 1) != true)
00578 throw ErrorClass("OSResult error: setSolutionNumer");
00579 if(osresult->setGeneralMessage( message) != true)
00580 throw ErrorClass("OSResult error: setGeneralMessage");
00581 solutionDescription = "COUENNE INITIALIZE PROBLEM: There was a problem with Couenne Initialize -- the problem could be infeasible";
00582 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00583 osresult->setGeneralStatusType("normal");
00584 osrl = osrlwriter->writeOSrL( osresult);
00585 return;
00586
00587 }
00588
00589 std::cout << std::endl << std::endl;
00590
00591
00592 if(( ci->isProvenPrimalInfeasible() == false) && (ci -> isProvenOptimal () == false)
00593 && (osinstance->getNumberOfIntegerVariables() + osinstance->getNumberOfBinaryVariables() <= 0) ){
00594 std::string solutionDescription = "";
00595 std::string message = "Success";
00596 int solIdx = 0;
00597 if(osresult->setServiceName( "Couenne solver service") != true)
00598 throw ErrorClass("OSResult error: setServiceName");
00599 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00600 throw ErrorClass("OSResult error: setInstanceName");
00601 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00602 throw ErrorClass("OSResult error: setVariableNumer");
00603 if(osresult->setObjectiveNumber( 1) != true)
00604 throw ErrorClass("OSResult error: setObjectiveNumber");
00605 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00606 throw ErrorClass("OSResult error: setConstraintNumber");
00607 if(osresult->setSolutionNumber( 1) != true)
00608 throw ErrorClass("OSResult error: setSolutionNumer");
00609 if(osresult->setGeneralMessage( message) != true)
00610 throw ErrorClass("OSResult error: setGeneralMessage");
00611 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00612 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00613 osresult->setGeneralStatusType("normal");
00614 osrl = osrlwriter->writeOSrL( osresult);
00615 return;
00616 }
00617
00618
00619
00620
00621
00622
00623 bb ( couenneSetup);
00624
00625
00626
00627
00628
00629 std::cout.precision (10);
00630
00631 CouenneCutGenerator *cg = NULL;
00632
00633 if (bb.model (). cutGenerators ())
00634 cg = dynamic_cast <CouenneCutGenerator *>
00635 (bb.model (). cutGenerators () [0] -> generator ());
00636
00637
00638 double global_opt;
00639 couenneSetup.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00640
00641
00642
00643
00644 double timeLimit = 0;
00645 couenneSetup.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00646
00647
00648
00649
00650
00651
00652 status = tminlp->status;
00653 writeResult();
00654
00655 }
00656
00657 catch(const ErrorClass& eclass){
00658 osresult->setGeneralMessage( eclass.errormsg);
00659 osresult->setGeneralStatusType( "error");
00660 osrl = osrlwriter->writeOSrL( osresult);
00661 throw ErrorClass( osrl) ;
00662 }
00663
00664
00665
00666 catch(TNLPSolver::UnsolvedError *E) {
00667 E->writeDiffFiles();
00668 E->printError(std::cerr);
00669
00670
00671
00672
00673 }
00674
00675 catch(OsiTMINLPInterface::SimpleError &E) {
00676 std::cerr<<E.className()<<"::"<<E.methodName()
00677 <<std::endl
00678 <<E.message()<<std::endl;
00679 }
00680
00681 catch(CoinError &E) {
00682 std::cerr<<E.className()<<"::"<<E.methodName()
00683 <<std::endl
00684 <<E.message()<<std::endl;
00685 }
00686
00687 catch (Ipopt::OPTION_INVALID &E)
00688 {
00689 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00690 }
00691 catch (int generic_error) {
00692 if (generic_error == infeasible)
00693 printf ("problem infeasible\n");
00694 }
00695
00696 }
00697
00698
00699 void CouenneSolver::writeResult(){
00700 double *x = NULL;
00701 double *z = NULL;
00702 int i = 0;
00703 int solIdx = 0;
00704 std::string solutionDescription = "";
00705 std::string message = "Couenne solver finishes to the end.";
00706
00707
00708 try{
00709 x = new double[osinstance->getVariableNumber() ];
00710 z = new double[1];
00711
00712 if(osresult->setServiceName( "Couenne solver service") != true)
00713 throw ErrorClass("OSResult error: setServiceName");
00714 if(osresult->setInstanceName( osinstance->getInstanceName()) != true)
00715 throw ErrorClass("OSResult error: setInstanceName");
00716
00717
00718
00719
00720 if(osresult->setVariableNumber( osinstance->getVariableNumber()) != true)
00721 throw ErrorClass("OSResult error: setVariableNumer");
00722 if(osresult->setObjectiveNumber( 1) != true)
00723 throw ErrorClass("OSResult error: setObjectiveNumber");
00724 if(osresult->setConstraintNumber( osinstance->getConstraintNumber()) != true)
00725 throw ErrorClass("OSResult error: setConstraintNumber");
00726 if(osresult->setSolutionNumber( 1) != true)
00727 throw ErrorClass("OSResult error: setSolutionNumer");
00728 if(osresult->setGeneralMessage( message) != true)
00729 throw ErrorClass("OSResult error: setGeneralMessage");
00730
00731 switch( status){
00732 case TMINLP::SUCCESS:
00733 solutionDescription = "SUCCESS[COUENNE]: Algorithm terminated normally at a locally optimal point, satisfying the convergence tolerances.";
00734
00735 osresult->setSolutionStatus(solIdx, "locallyOptimal", solutionDescription);
00736
00737 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.bestSolution()), true)[ 0];
00738
00739 if(fabs(*(z + 0)) == 9.999e+12){
00740 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: Continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00741
00742 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00743 break;
00744 }
00745 osresult->setObjectiveValuesDense(solIdx, z);
00746 for(i=0; i < osinstance->getVariableNumber(); i++){
00747 *(x + i) = bb.bestSolution()[i];
00748
00749 }
00750 osresult->setPrimalVariableValuesDense(solIdx, x);
00751 break;
00752
00753 case TMINLP::LIMIT_EXCEEDED:
00754 solutionDescription = "LIMIT_EXCEEDED[COUENNE]: A resource limit was exceeded, we provide the current solution.";
00755
00756 osresult->setSolutionStatus(solIdx, "stoppedByLimit", solutionDescription);
00757
00758
00759
00760 *(z + 0) = osinstance->calculateAllObjectiveFunctionValues( const_cast<double*>(bb.model().getColSolution()), true)[ 0];
00761 osresult->setObjectiveValuesDense(solIdx, z);
00762 for(i=0; i < osinstance->getVariableNumber(); i++){
00763 *(x + i) = bb.model().getColSolution()[i];
00764
00765 }
00766 osresult->setPrimalVariableValuesDense(solIdx, x);
00767 break;
00768
00769 case TMINLP::MINLP_ERROR:
00770 solutionDescription = "MINLP_ERROR [COUENNE]: Algorithm stopped with unspecified error.";
00771
00772 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00773
00774 break;
00775
00776 case TMINLP::CONTINUOUS_UNBOUNDED:
00777 solutionDescription = "CONTINUOUS_UNBOUNDED [COUENNE]: The continuous relaxation is unbounded, the MINLP may or may not be unbounded.";
00778
00779 osresult->setSolutionStatus(solIdx, "error", solutionDescription);
00780
00781 break;
00782
00783
00784 case TMINLP::INFEASIBLE:
00785 solutionDescription = "INFEASIBLE [COUENNE]: Problem may be infeasible.";
00786
00787 osresult->setSolutionStatus(solIdx, "infeasible", solutionDescription);
00788 break;
00789
00790 default:
00791 solutionDescription = "OTHER[COUENNE]: other unknown solution status from Couenne solver";
00792 osresult->setSolutionStatus(solIdx, "other", solutionDescription);
00793 }
00794 osresult->setGeneralStatusType("normal");
00795 osrl = osrlwriter->writeOSrL( osresult);
00796 delete[] x;
00797 x = NULL;
00798 delete[] z;
00799 z = NULL;
00800 }
00801
00802
00803 catch(const ErrorClass& eclass){
00804 delete[] x;
00805 x = NULL;
00806 delete[] z;
00807 z = NULL;
00808 osresult->setGeneralMessage( eclass.errormsg);
00809 osresult->setGeneralStatusType( "error");
00810 osrl = osrlwriter->writeOSrL( osresult);
00811 throw ErrorClass( osrl) ;
00812 }
00813
00814
00815 }
00816
00817
00818