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