00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #if defined(_MSC_VER)
00014
00015 # pragma warning(disable:4786)
00016 #endif
00017
00018 #include <iomanip>
00019 #include <fstream>
00020
00021 #include <stdlib.h>
00022
00023 #include "CoinTime.hpp"
00024 #include "CoinError.hpp"
00025 #include "BonCouenneInterface.hpp"
00026
00027 #include "BonCouenneSetup.hpp"
00028
00029 #include "BonCbc.hpp"
00030 #include "CouenneBab.hpp"
00031
00032 #include "CbcCutGenerator.hpp"
00033 #include "CouenneProblem.hpp"
00034 #include "CouenneCutGenerator.hpp"
00035
00036 #include "CouenneRecordBestSol.hpp"
00037
00038 using namespace Couenne;
00039
00040
00041 #define PRINTED_PRECISION 1e-5
00042
00043 #include "CouenneExprVar.hpp"
00044 #include "CouenneExprConst.hpp"
00045 #include "CouenneExprSum.hpp"
00046 #include "CouenneExprClone.hpp"
00047 #include "CouenneProblemElem.hpp"
00048 #include "CouenneProblem.hpp"
00049 #include "CouenneJournalist.hpp"
00050
00051 #ifdef COIN_HAS_NTY
00052
00053 #include "CouenneBranchingObject.hpp"
00054 #endif
00055
00056 #include "CoinSignal.hpp"
00057
00058 #if 0
00059 extern "C" {
00060
00061 static int nInterrupts = 0;
00062 static void signal_handler (int sig) {
00063
00064 if (!nInterrupts) {
00065 std::cerr << "[BREAK]" << std::endl;
00066 abort ();
00067 }
00068 return;
00069 }
00070 }
00071 #endif
00072
00073
00074
00075 int main (int argc, char *argv[]) {
00076
00077
00078
00079
00080 printf ("Couenne %s -- an Open-Source solver for Mixed Integer Nonlinear Optimization\n\
00081 Mailing list: couenne@list.coin-or.org\n\
00082 Instructions: http://www.coin-or.org/Couenne\n",
00083 strcmp (COUENNE_VERSION, "trunk") ? COUENNE_VERSION : "");
00084
00085 WindowsErrorPopupBlocker();
00086 using namespace Ipopt;
00087
00088 char * pbName = NULL;
00089
00090 const int infeasible = 1;
00091
00092 try {
00093
00094 CouenneBab bb;
00095
00096
00097 CouenneProblem *p = NULL;
00098 CouenneInterface *ci = NULL;
00099
00100 #if 0
00101
00102 p = new CouenneProblem;
00103
00104 p -> addVariable (false, p -> domain ());
00105 p -> addVariable (false, p -> domain ());
00106 p -> addVariable (false, p -> domain ());
00107 p -> addVariable (false, p -> domain ());
00108
00109 p -> addObjective (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), "min");
00110 p -> addLEConstraint (new exprSum (new exprClone (p->Var (0)), new exprClone (p->Var (2))), new exprConst (1));
00111 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (2))), new exprConst (1));
00112 p -> addEQConstraint (new exprSum (new exprClone (p->Var (1)), new exprClone (p->Var (3))), new exprConst (1));
00113 p -> addEQConstraint (new exprSum (new exprClone (p->Var (2)), new exprClone (p->Var (3))), new exprConst (1));
00114 #endif
00115
00116 CouenneSetup couenne;
00117
00118 if (!couenne.InitializeCouenne (argv, p, NULL, ci, &bb))
00119 throw infeasible;
00120
00122 CouenneCutGenerator *cg = NULL;
00123
00124
00125
00126
00127 if (couenne. cutGenerators () . size () > 0) {
00128
00129 for (std::list <Bonmin::BabSetupBase::CuttingMethod>::iterator
00130 i = couenne.cutGenerators () . begin ();
00131 !cg && (i != couenne.cutGenerators () . end ());
00132 ++i)
00133
00134 cg = dynamic_cast <CouenneCutGenerator *> (i -> cgl);
00135 }
00136
00137
00138
00139
00140
00141 if (cg)
00142
00143 cg -> setBabPtr (&bb);
00144
00145 else {
00146 printf ("main(): ### ERROR: Can not get CouenneCutGenerator\n");
00147 exit (1);
00148 }
00149
00150
00151
00152 ConstJnlstPtr jnlst = couenne. couennePtr () -> Jnlst ();
00153
00154 CouenneProblem *prob = couenne. couennePtr () -> Problem ();
00155
00156 bb. setProblem (prob);
00157
00158 jnlst -> Printf (J_ERROR, J_COUENNE, "\
00159 Loaded instance \"%s\"\n\
00160 Constraints: %8d\n\
00161 Variables: %8d (%d integer)\n\
00162 Auxiliaries: %8d (%d integer)\n\n",
00163 prob -> problemName ().c_str (),
00164 prob -> nOrigCons (),
00165 prob -> nOrigVars (),
00166 prob -> nOrigIntVars (),
00167 prob -> nVars () - prob -> nOrigVars (),
00168 CoinMax (0, prob -> nIntVars () - prob -> nOrigIntVars ()));
00169
00170 double time_start = CoinCpuTime();
00171
00172 #if 0
00173 CouenneFeasibility feasibility;
00174 bb.model().setProblemFeasibility (feasibility);
00175 #endif
00176
00178 double timeLimit = 0;
00179 couenne.options () -> GetNumericValue ("time_limit", timeLimit, "couenne.");
00180 couenne.setDoubleParameter (Bonmin::BabSetupBase::MaxTime,
00181 CoinMax (1., timeLimit - time_start));
00182
00183
00184
00186
00187 bb (couenne);
00188
00189 #ifdef COIN_HAS_NTY
00190 if (CouenneBranchingObject::nOrbBr)
00191 printf ("%d orbital nontrivial branchings\n", CouenneBranchingObject::nOrbBr);
00192 #endif
00193
00194 std::cout.precision (10);
00195
00196 int nr=-1, nt=-1;
00197 double st=-1;
00198
00199 if (cg) cg -> getStats (nr, nt, st);
00200 else printf ("Warning, could not get pointer to CouenneCutGenerator\n");
00201
00202 CouenneProblem *cp = cg ? cg -> Problem () : NULL;
00203
00204 #if defined (FM_TRACE_OPTSOL) || defined (FM_FRES)
00205 double cbcLb = bb.model ().getBestPossibleObjValue();
00206 double printObj = 0;
00207 bool foundSol = false;
00208 #endif
00209
00210 #ifdef FM_TRACE_OPTSOL
00211
00212
00213
00214
00215
00216
00217
00218
00219 if(cp != NULL) {
00220 double cbcObjVal = bb.model().getObjValue();
00221 int modelNvars = bb.model().getNumCols();
00222
00223 CouenneRecordBestSol *rs = cp->getRecordBestSol();
00224 const double *cbcSol = bb.model().getColSolution();
00225 double *modCbcSol = new double[modelNvars];
00226 double modCbcSolVal= 1e100, modCbcSolMaxViol = 0;
00227 bool cbcSolIsFeas = false;
00228
00229 if(modelNvars != cp->nVars()) {
00230 printf("### ERROR: modelNvars: %d nVars: %d\n",
00231 modelNvars, cp->nVars());
00232 exit(1);
00233 }
00234
00235 if(cbcObjVal < 1e49) {
00236
00237 #ifdef FM_CHECKNLP2
00238 int cMS = rs->getCardModSol();
00239 cbcSolIsFeas = cp->checkNLP2(cbcSol, 0, false,
00240 false,
00241 true,
00242 cp->getFeasTol());
00243 CoinCopyN(rs->getModSol(cMS), cMS, modCbcSol);
00244 modCbcSolVal = rs->getModSolVal();
00245 modCbcSolMaxViol = rs->getModSolMaxViol();
00246 #else
00247 int cMS = cp->nVars();
00248 cbcSolIsFeas = cp->checkNLP(cbcSol, modCbcSolVal, true);
00249 CoinCopyN(cbcSol, cMS, modCbcSol);
00250 modCbcSolMaxViol = cp->getFeasTol();
00251 #endif
00252 foundSol = true;
00253 }
00254
00255 const double *couenneSol = rs->getSol();
00256 double *modCouenneSol = new double[modelNvars];
00257 double modCouenneSolVal= 1e100, modCouenneSolMaxViol = 0;
00258 bool couenneSolIsFeas = false;
00259
00260 if(couenneSol != NULL) {
00261 #ifdef FM_CHECKNLP2
00262 couenneSolIsFeas = cp->checkNLP2(couenneSol, 0, false,
00263 false, true,
00264 cp->getFeasTol());
00265 int cMS = rs->getCardModSol();
00266 CoinCopyN(rs->getModSol(cMS), cMS, modCouenneSol);
00267 modCouenneSolVal = rs->getModSolVal();
00268 modCouenneSolMaxViol = rs->getModSolMaxViol();
00269 #else
00270 couenneSolIsFeas = cp->checkNLP(couenneSol, modCouenneSolVal, true);
00271 int cMS = cp->nVars();
00272 CoinCopyN(couenneSol, cMS, modCouenneSol);
00273 modCouenneSolMaxViol = cp->getFeasTol();
00274 #endif
00275 foundSol = true;
00276 }
00277
00278 int retcomp = rs->compareAndSave(modCbcSol, modCbcSolVal,
00279 modCbcSolMaxViol, cbcSolIsFeas,
00280 modCouenneSol, modCouenneSolVal,
00281 modCouenneSolMaxViol, couenneSolIsFeas,
00282 modelNvars, cp->getFeasTol());
00283 switch (retcomp) {
00284 case -1: printf("No solution found\n"); break;
00285 case 0: printf("Best solution found by Cbc. Value: %10.4f. Tolerance: %10g\n", modCbcSolVal, modCbcSolMaxViol); break;
00286 case 1:
00287 default: break;
00288 }
00289
00290 if(rs->getHasSol()) {
00291 if(cbcLb > rs->getVal()) {
00292
00293 cbcLb = rs->getVal();
00294 }
00295 printObj = rs->getVal();
00296
00297 }
00298 delete[] modCbcSol;
00299 delete[] modCouenneSol;
00300 }
00301
00302 #endif
00303
00304 #ifdef FM_FRES
00305 if(cp != NULL) {
00306 FILE *f_res = NULL;
00307 f_res = fopen("fres.xxx", "r");
00308 if(f_res == NULL) {
00309 f_res = fopen("fres.xxx", "w");
00310 fprintf(f_res, "END_OF_HEADER\n");
00311 }
00312 else {
00313 fclose(f_res);
00314 f_res = fopen("fres.xxx", "a");
00315 }
00316 char *pbName, shortName[256];
00317
00318 pbName = strdup(cp -> problemName ().c_str ());
00319 char *f_name_pos = strrchr(pbName, '/');
00320 if(f_name_pos != NULL) {
00321 strcpy(shortName, &(f_name_pos[1]));
00322 }
00323 else {
00324 strcpy(shortName, pbName);
00325 }
00326
00327
00328 fprintf(f_res, "%20s ", shortName);
00329 if((cbcLb > 1e20) || (cbcLb < -1e20)) {
00330 fprintf(f_res, "%10.4g", cbcLb);
00331 }
00332 else {
00333 fprintf(f_res, "%10.4f", cbcLb);
00334 }
00335 if(foundSol) {
00336 fprintf(f_res, " %10.4f", printObj);
00337 }
00338 else {
00339 fprintf(f_res, " *");
00340 }
00341 fprintf(f_res, " %10d %10.4f\n", bb.numNodes (),
00342 CoinCpuTime () - time_start);
00343 fclose(f_res);
00344 }
00345 #endif
00346
00347
00348 double global_opt;
00349 couenne.options () -> GetNumericValue ("couenne_check", global_opt, "couenne.");
00350
00351 double
00352 ub = bb. model (). getObjValue (),
00353 lb = bb. model (). getBestPossibleObjValue ();
00354
00355 if (cp -> getRecordBestSol () &&
00356 (ub > cp -> getRecordBestSol () -> getVal ())) ub = cp -> getRecordBestSol () -> getVal ();
00357
00358 if ((fabs (lb) > COUENNE_INFINITY / 1e4) ||
00359 (lb > ub)) lb = ub;
00360
00361 char
00362 *gapstr = new char [80],
00363 *lbstr = new char [80],
00364 *ubstr = new char [80];
00365
00366 sprintf (lbstr, "%10g", lb);
00367 sprintf (ubstr, "%10g", ub);
00368 if(ub > COUENNE_INFINITY/1e4) {
00369 sprintf (gapstr, "--");
00370 }
00371 else {
00372 sprintf (gapstr, "%.2f%%", fabs (100. * (ub - lb) / (1. + fabs (lb))));
00373 }
00374
00375 jnlst -> Printf (J_ERROR, J_COUENNE, "\n\
00376 Linearization cuts added at root node: %8d\n\
00377 Linearization cuts added in total: %8d (separation time: %gs)\n\
00378 Total solving time: %8gs (%gs in branch-and-bound)\n\
00379 Lower bound: %s\n\
00380 Upper bound: %s (gap: %s)\n\
00381 Branch-and-bound nodes: %8d\n",
00382 nr, nt, st,
00383 CoinCpuTime () - time_start,
00384 cg ? (CoinCpuTime () - CoinMax (time_start, cg -> rootTime ())) : CoinCpuTime () - time_start,
00385 (lb < -9e12) ||
00386 (lb > COUENNE_INFINITY/1e4) ? " -inf" : lbstr,
00387 (ub > COUENNE_INFINITY/1e4) ? " inf" : ubstr,
00388 (ub > COUENNE_INFINITY/1e4) ? "--" : gapstr,
00389 bb.numNodes ());
00390
00391 if (fabs (ub - bb. model (). getObjValue ()) > COUENNE_EPS * fabs (ub))
00392 jnlst -> Printf (J_ERROR, J_COUENNE,
00393 "Warning: upper bounds differ between Couenne and Cbc. Saving Couenne's (more reliable).\n");
00394
00395 delete [] lbstr;
00396 delete [] ubstr;
00397 delete [] gapstr;
00398
00399 if (global_opt < COUENNE_INFINITY) {
00400
00401 double opt = bb.model (). getBestPossibleObjValue ();
00402
00403 printf ("Global Optimum Test on %-40s %s\n",
00404 cp ? cp -> problemName ().c_str () : "unknown",
00405 (fabs (opt - global_opt) /
00406 (1. + CoinMax (fabs (opt), fabs (global_opt))) < PRINTED_PRECISION) ?
00407 (const char *) "OK" : (const char *) "FAILED");
00408
00409
00410
00411 } else
00412
00413 if (couenne.displayStats ()) {
00414
00415 if (cg && !cp) printf ("Warning, could not get pointer to problem\n");
00416 else
00417 printf ("Stats: %-15s %4d [var] %4d [int] %4d [con] %4d [aux] "
00418 "%6d [root] %8d [tot] %6g [sep] %8g [time] %8g [bb] "
00419 "%20e [lower] %20e [upper] %7d [nodes]\n",
00420 cp ? cp -> problemName (). c_str () : "unknown",
00421 (cp) ? cp -> nOrigVars () : -1,
00422 (cp) ? cp -> nOrigIntVars () : -1,
00423 (cp) ? cp -> nOrigCons () : -1,
00424 (cp) ? (cp -> nVars () -
00425 cp -> nOrigVars ()): -1,
00426 nr, nt, st,
00427 CoinCpuTime () - time_start,
00428 cg ? (CoinCpuTime () - cg -> rootTime ()) : CoinCpuTime (),
00429 lb,
00430 ub,
00431
00432
00433 bb.numNodes ());
00434
00435
00436 }
00437
00438
00439 }
00440 catch(Bonmin::TNLPSolver::UnsolvedError *E) {
00441 E->writeDiffFiles();
00442 E->printError(std::cerr);
00443
00444
00445
00446
00447 }
00448 catch (Bonmin::OsiTMINLPInterface::SimpleError &E) {
00449 std::cerr<<E.className()<<"::"<<E.methodName()
00450 <<std::endl
00451 <<E.message()<<std::endl;
00452 }
00453 catch (CoinError &E) {
00454 std::cerr<<E.className()<<"::"<<E.methodName()
00455 <<std::endl
00456 <<E.message()<<std::endl;
00457 }
00458 catch (Ipopt::OPTION_INVALID &E)
00459 {
00460 std::cerr<<"Ipopt exception : "<<E.Message()<<std::endl;
00461 }
00462 catch (int generic_error) {
00463 if (generic_error == infeasible)
00464 printf ("problem infeasible\n");
00465 }
00466
00467
00468
00469
00470
00471
00472
00473 delete [] pbName;
00474 return 0;
00475 }