00001
00002
00003 #if defined(_MSC_VER)
00004
00005 # pragma warning(disable:4786)
00006 #endif
00007
00008 #include <cassert>
00009 #include <typeinfo>
00010 #include <cstdio>
00011 #include <cmath>
00012 #include <cfloat>
00013 #include <string>
00014 #include <iostream>
00015
00016 #define SBBVERSION "0.60"
00017
00018 #include "CoinMpsIO.hpp"
00019 #include "CoinPackedMatrix.hpp"
00020 #include "CoinPackedVector.hpp"
00021 #include "CoinWarmStartBasis.hpp"
00022 #include "CoinTime.hpp"
00023
00024 #include "OsiSolverInterface.hpp"
00025 #include "OsiCuts.hpp"
00026 #include "OsiRowCut.hpp"
00027 #include "OsiColCut.hpp"
00028
00029 #include "CglCutGenerator.hpp"
00030 #include "CglGomory.hpp"
00031 #include "CglProbing.hpp"
00032 #include "CglKnapsackCover.hpp"
00033 #include "CglOddHole.hpp"
00034
00035 #include "SbbModel.hpp"
00036 #include "SbbHeuristic.hpp"
00037 #include "SbbCompareBase.hpp"
00038 #include "SbbParam.hpp"
00039
00040 #ifdef COIN_USE_CLP
00041 #include "OsiClpSolverInterface.hpp"
00042 #endif
00043 #ifdef COIN_USE_DYLP
00044 #include "OsiDylpSolverInterface.hpp"
00045 #endif
00046
00047
00048
00049
00050
00051
00052
00053 class SbbCompareUser : public SbbCompareBase {
00054 public:
00055
00056 double weight_;
00057
00058 int numberSolutions_;
00059
00060 SbbCompareUser () : weight_(-1.0), numberSolutions_(0) {test_=this;};
00061
00062 ~SbbCompareUser() {};
00063
00064
00065
00066
00067
00068
00069 virtual bool test (SbbNode * x, SbbNode * y) {
00070 if (weight_<0.0) {
00071
00072
00073
00074
00075 if (x->numberUnsatisfied() > y->numberUnsatisfied())
00076 return true;
00077 else if (x->numberUnsatisfied() < y->numberUnsatisfied())
00078 return false;
00079 else
00080 return x->depth() < y->depth();
00081 } else {
00082
00083 return x->objectiveValue()+ weight_*x->numberUnsatisfied() >
00084 y->objectiveValue() + weight_*y->numberUnsatisfied();
00085 }
00086 }
00087
00088
00089 virtual void newSolution(SbbModel * model,
00090 double objectiveAtContinuous,
00091 int numberInfeasibilitiesAtContinuous)
00092 {
00093 if (model->getSolutionCount()==model->getNumberHeuristicSolutions())
00094 return;
00095
00096 double costPerInteger =
00097 (model->getObjValue()-objectiveAtContinuous)/
00098 ((double) numberInfeasibilitiesAtContinuous);
00099 weight_ = 0.98*costPerInteger;
00100 numberSolutions_++;
00101 if (numberSolutions_>5)
00102 weight_ =0.0;
00103 }
00104
00105 virtual void every1000Nodes(SbbModel * model, int numberNodes)
00106 {
00107 if (numberNodes>10000)
00108 weight_ =0.0;
00109 }
00110 };
00111
00112
00113 #define MAXPARAMETERS 100
00114
00115 namespace {
00116
00117 void establishParams (int &numberParameters, SbbParam *const parameters)
00118
00119
00120
00121
00122 { numberParameters = 0 ;
00123
00124 parameters[numberParameters++]=
00125 SbbParam("?","For help",GENERALQUERY);
00126 parameters[numberParameters++]=
00127 SbbParam("dualT!olerance",
00128 "For an optimal solution no dual infeasibility may "
00129 "exceed this value",
00130 1.0e-20,1.0e12,DUALTOLERANCE);
00131 parameters[numberParameters++]=
00132 SbbParam("primalT!olerance",
00133 "For an optimal solution no primal infeasibility may "
00134 " exceed this value",
00135 1.0e-20,1.0e12,PRIMALTOLERANCE);
00136 parameters[numberParameters++]=
00137 SbbParam("inf!easibilityWeight","Each integer infeasibility is expected \
00138 to cost this much",
00139 0.0,1.0e20,INFEASIBILITYWEIGHT);
00140 parameters[numberParameters++]=
00141 SbbParam("integerT!olerance","For an optimal solution \
00142 no integer variable may be this away from an integer value",
00143 1.0e-20,0.5,INTEGERTOLERANCE);
00144 parameters[numberParameters++]=
00145 SbbParam("inc!rement","A valid solution must be at least this \
00146 much better than last integer solution",
00147 -1.0e20,1.0e20,INCREMENT);
00148 parameters[numberParameters++]=
00149 SbbParam("allow!ableGap","Stop when gap between best possible and \
00150 best less than this",
00151 0.0,1.0e20,ALLOWABLEGAP);
00152 parameters[numberParameters++]=
00153 SbbParam("ratio!Gap","Stop when gap between best possible and \
00154 best less than this fraction of continuous optimum",
00155 0.0,1.0e20,GAPRATIO);
00156 parameters[numberParameters++]=
00157 SbbParam("fix!OnDj","Try heuristic based on fixing variables with \
00158 reduced costs greater than this",
00159 -1.0e20,1.0e20,DJFIX);
00160 parameters[numberParameters++]=
00161 SbbParam("tighten!Factor","Tighten bounds using this times largest \
00162 activity at continuous solution",
00163 1.0,1.0e20,TIGHTENFACTOR);
00164 parameters[numberParameters++]=
00165 SbbParam("log!Level","Level of detail in BAB output",
00166 0,63,LOGLEVEL);
00167 parameters[numberParameters++]=
00168 SbbParam("slog!Level","Level of detail in Solver output",
00169 0,63,SOLVERLOGLEVEL);
00170 parameters[numberParameters++]=
00171 SbbParam("maxN!odes","Maximum number of nodes to do",
00172 1,999999,MAXNODES);
00173 parameters[numberParameters++]=
00174 SbbParam("strong!Branching","Number of variables to look at in strong branching",
00175 0,999999,STRONGBRANCHING);
00176 parameters[numberParameters++]=
00177 SbbParam("direction","Minimize or Maximize",
00178 "min!imize",DIRECTION);
00179 parameters[numberParameters-1].append("max!imize");
00180 parameters[numberParameters++]=
00181 SbbParam("error!sAllowed","Whether to allow import errors",
00182 "off",ERRORSALLOWED);
00183 parameters[numberParameters-1].append("on");
00184 parameters[numberParameters++]=
00185 SbbParam("gomory!Cuts","Whether to use Gomory cuts",
00186 "off",GOMORYCUTS);
00187 parameters[numberParameters-1].append("on");
00188 parameters[numberParameters++]=
00189 SbbParam("probing!Cuts","Whether to use Probing cuts",
00190 "off",PROBINGCUTS);
00191 parameters[numberParameters-1].append("on");
00192 parameters[numberParameters++]=
00193 SbbParam("knapsack!Cuts","Whether to use Knapsack cuts",
00194 "off",KNAPSACKCUTS);
00195 parameters[numberParameters-1].append("on");
00196 parameters[numberParameters++]=
00197 SbbParam("oddhole!Cuts","Whether to use Oddhole cuts",
00198 "off",ODDHOLECUTS);
00199 parameters[numberParameters-1].append("on");
00200 parameters[numberParameters++]=
00201 SbbParam("round!ingHeuristic","Whether to use Rounding heuristic",
00202 "off",ROUNDING);
00203 parameters[numberParameters-1].append("on");
00204 parameters[numberParameters++]=
00205 SbbParam("keepN!ames","Whether to keep names from import",
00206 "on",KEEPNAMES);
00207 parameters[numberParameters-1].append("off");
00208 parameters[numberParameters++]=
00209 SbbParam("scaling","Whether to do scaling",
00210 "on",SCALING);
00211 parameters[numberParameters-1].append("off");
00212 parameters[numberParameters++]=
00213 SbbParam("directory","Set Default import directory",
00214 DIRECTORY);
00215 parameters[numberParameters++]=
00216 SbbParam("solver!","Set the solver used by sbb",
00217 SOLVER) ;
00218 parameters[numberParameters++]=
00219 SbbParam("import","Import model from mps file",
00220 IMPORT);
00221 parameters[numberParameters++]=
00222 SbbParam("export","Export model as mps file",
00223 EXPORT);
00224 parameters[numberParameters++]=
00225 SbbParam("save!Model","Save model to binary file",
00226 SAVE);
00227 parameters[numberParameters++]=
00228 SbbParam("restore!Model","Restore model from binary file",
00229 RESTORE);
00230 parameters[numberParameters++]=
00231 SbbParam("presolve","Whether to use integer presolve - be careful",
00232 "off",PRESOLVE);
00233 parameters[numberParameters-1].append("on");
00234 parameters[numberParameters++]=
00235 SbbParam("initialS!olve","Solve to continuous",
00236 SOLVECONTINUOUS);
00237 parameters[numberParameters++]=
00238 SbbParam("branch!AndBound","Do Branch and Bound",
00239 BAB);
00240 parameters[numberParameters++]=
00241 SbbParam("sol!ution","Prints solution to file",
00242 SOLUTION);
00243 parameters[numberParameters++]=
00244 SbbParam("max!imize","Set optimization direction to maximize",
00245 MAXIMIZE);
00246 parameters[numberParameters++]=
00247 SbbParam("min!imize","Set optimization direction to minimize",
00248 MINIMIZE);
00249 parameters[numberParameters++] =
00250 SbbParam("time!Limit","Set a time limit for solving this problem",
00251 1.0,(double)(60*60*24*365*10),TIMELIMIT) ;
00252 parameters[numberParameters++]=
00253 SbbParam("exit","Stops sbb execution",
00254 EXIT);
00255 parameters[numberParameters++]=
00256 SbbParam("stop","Stops sbb execution",
00257 EXIT);
00258 parameters[numberParameters++]=
00259 SbbParam("quit","Stops sbb execution",
00260 EXIT);
00261 parameters[numberParameters++]=
00262 SbbParam("-","From stdin",
00263 STDIN);
00264 parameters[numberParameters++]=
00265 SbbParam("stdin","From stdin",
00266 STDIN);
00267 parameters[numberParameters++]=
00268 SbbParam("unitTest","Do unit test",
00269 UNITTEST);
00270 parameters[numberParameters++]=
00271 SbbParam("miplib","Do some of miplib test set",
00272 MIPLIB);
00273 parameters[numberParameters++]=
00274 SbbParam("ver!sion","Print out version",
00275 VERSION);
00276
00277 assert(numberParameters<MAXPARAMETERS);
00278
00279 return ; }
00280
00281 #ifdef READLINE
00282 #include <readline/readline.h>
00283 #include <readline/history.h>
00284 #endif
00285
00286
00287
00288 int read_mode=1;
00289 char line[1000];
00290 char * where=NULL;
00291
00292 std::string
00293 nextField()
00294 {
00295 std::string field;
00296 if (!where) {
00297
00298 #ifdef READLINE
00299
00300 where = readline ("Sbb:");
00301
00302
00303 if (where) {
00304 if ( *where)
00305 add_history (where);
00306 strcpy(line,where);
00307 }
00308 #else
00309 fprintf(stdout,"Sbb:");
00310 fflush(stdout);
00311 where = fgets(line,1000,stdin);
00312 #endif
00313 if (!where)
00314 return field;
00315 where = line;
00316
00317 char * lastNonBlank = line-1;
00318 while ( *where != '\0' ) {
00319 if ( *where != '\t' && *where < ' ' ) {
00320 break;
00321 } else if ( *where != '\t' && *where != ' ') {
00322 lastNonBlank = where;
00323 }
00324 where++;
00325 }
00326 where=line;
00327 *(lastNonBlank+1)='\0';
00328 }
00329
00330 while(*where==' '||*where=='\t')
00331 where++;
00332 char * saveWhere = where;
00333 while (*where!=' '&&*where!='\t'&&*where!='\0')
00334 where++;
00335 if (where!=saveWhere) {
00336 char save = *where;
00337 *where='\0';
00338
00339 field=saveWhere;
00340 *where=save;
00341 } else {
00342 where=NULL;
00343 field="EOL";
00344 }
00345 return field;
00346 }
00347
00348 std::string
00349 getCommand(int argc, const char *argv[])
00350 {
00351 std::string field="EOL";
00352 while (field=="EOL") {
00353 if (read_mode>0) {
00354 if (read_mode<argc) {
00355 field = argv[read_mode++];
00356 if (field=="-") {
00357 std::cout<<"Switching to line mode"<<std::endl;
00358 read_mode=-1;
00359 field=nextField();
00360 } else if (field[0]!='-') {
00361 if (read_mode!=2) {
00362 std::cout<<"skipping non-command "<<field<<std::endl;
00363 field="EOL";
00364 } else {
00365
00366 read_mode--;
00367 field="import";
00368 }
00369 } else {
00370 if (field!="--") {
00371
00372 field = field.substr(1);
00373 } else {
00374
00375 read_mode--;
00376 field="import";
00377 }
00378 }
00379 } else {
00380 field="";
00381 }
00382 } else {
00383 field=nextField();
00384 }
00385 }
00386
00387 return field;
00388 }
00389 std::string
00390 getString(int argc, const char *argv[])
00391 {
00392 std::string field="EOL";
00393 if (read_mode>0) {
00394 if (read_mode<argc) {
00395 if (argv[read_mode][0]!='-') {
00396 field = argv[read_mode++];
00397 } else if (!strcmp(argv[read_mode],"--")) {
00398 field = argv[read_mode++];
00399
00400 field = "-";
00401 }
00402 }
00403 } else {
00404 field=nextField();
00405 }
00406
00407 return field;
00408 }
00409
00410
00411 int
00412 getIntField(int argc, const char *argv[],int * valid)
00413 {
00414 std::string field="EOL";
00415 if (read_mode>0) {
00416 if (read_mode<argc) {
00417
00418 field = argv[read_mode++];
00419 }
00420 } else {
00421 field=nextField();
00422 }
00423 int value=0;
00424
00425 if (field!="EOL") {
00426
00427 value = atoi(field.c_str());
00428 *valid=0;
00429 } else {
00430 *valid=2;
00431 }
00432 return value;
00433 }
00434
00435
00436
00437 double
00438 getDoubleField(int argc, const char *argv[],int * valid)
00439 {
00440 std::string field="EOL";
00441 if (read_mode>0) {
00442 if (read_mode<argc) {
00443
00444 field = argv[read_mode++];
00445 }
00446 } else {
00447 field=nextField();
00448 }
00449 double value=0.0;
00450
00451 if (field!="EOL") {
00452
00453 value = atof(field.c_str());
00454 *valid=0;
00455 } else {
00456 *valid=2;
00457 }
00458 return value;
00459 }
00460
00462
00463 double totalTime=0.0;
00464
00465 }
00466
00467
00468 int main (int argc, const char *argv[])
00469 {
00470
00471 {
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 typedef std::map<std::string,OsiSolverInterface*> solverMap_t ;
00482 typedef solverMap_t::const_iterator solverMapIter_t ;
00483
00484 solverMap_t solvers ;
00485
00486 # ifdef COIN_USE_CLP
00487 # ifndef SBB_DEFAULT_SOLVER
00488 # define SBB_DEFAULT_SOLVER "clp"
00489 # endif
00490 solvers["clp"] = new OsiClpSolverInterface ;
00491 # else
00492 solvers["clp"] = 0 ;
00493 # endif
00494 # ifdef COIN_USE_DYLP
00495 # ifndef SBB_DEFAULT_SOLVER
00496 # define SBB_DEFAULT_SOLVER "dylp"
00497 # endif
00498 solvers["dylp"] = new OsiDylpSolverInterface ;
00499 # else
00500 solvers["dylp"] = 0 ;
00501 # endif
00502
00503
00504
00505 OsiSolverInterface *dflt_solver = solvers[SBB_DEFAULT_SOLVER] ;
00506 if (dflt_solver)
00507 { std::cout << "Default solver is " << SBB_DEFAULT_SOLVER << std::endl ; }
00508 else
00509 { std::cerr << "No solvers! Aborting." << std::endl ;
00510 return (1) ; }
00511
00512
00513
00514 double time1 = CoinCpuTime() ;
00515 double time2;
00516
00517
00518
00519
00520
00521 SbbParam parameters[MAXPARAMETERS];
00522 int numberParameters ;
00523 establishParams(numberParameters,parameters) ;
00524
00525 { int iSolver = 0 ;
00526 for ( ; iSolver < numberParameters ; iSolver++)
00527 { int match = parameters[iSolver].matches("solver") ;
00528 if (match==1) break ; }
00529 for (solverMapIter_t solverIter = solvers.begin() ;
00530 solverIter != solvers.end() ;
00531 solverIter++)
00532 { if (solverIter->second)
00533 parameters[iSolver].append(solverIter->first) ; }
00534 int iKwd = parameters[iSolver].parameterOption(SBB_DEFAULT_SOLVER) ;
00535 parameters[iSolver].setCurrentOption(iKwd) ; }
00536
00537
00538
00539
00540 dflt_solver->messageHandler()->setLogLevel(0) ;
00541 SbbModel *model = new SbbModel(*dflt_solver) ;
00542 model->messageHandler()->setLogLevel(1);
00543 bool goodModel=false;
00544
00545
00546
00547 CglGomory gomoryGen;
00548
00549 CglProbing probingGen;
00550 probingGen.setUsingObjective(true);
00551 probingGen.setMaxPass(3);
00552 probingGen.setMaxProbe(100);
00553 probingGen.setMaxLook(50);
00554 probingGen.setRowCuts(3);
00555
00556 CglKnapsackCover knapsackGen;
00557
00558 CglOddHole oddholeGen;
00559 oddholeGen.setMinimumViolation(0.005);
00560 oddholeGen.setMinimumViolationPer(0.0002);
00561 oddholeGen.setMaximumEntries(100);
00562
00563 bool useRounding=false;
00564
00565 int allowImportErrors=0;
00566 int keepImportNames=1;
00567 int doScaling=1;
00568 int preSolve=0;
00569 double djFix=1.0e100;
00570 double gapRatio=1.0e100;
00571 double tightenFactor=0.0;
00572
00573 std::string directory ="./";
00574 std::string field;
00575
00576
00577
00578
00579 int numberGoodCommands=0;
00580
00581 while (1) {
00582
00583 field=getCommand(argc,argv);
00584
00585
00586 if (!field.length()) {
00587 if (numberGoodCommands==1&&goodModel) {
00588
00589 model->initialSolve();
00590 model->solver()->messageHandler()->setLogLevel(0);
00591 model->branchAndBound();
00592 time2 = CoinCpuTime();
00593 totalTime += time2-time1;
00594 std::cout<<"Result "<<model->getObjValue()<<
00595 " iterations "<<model->getIterationCount()<<
00596 " nodes "<<model->getNodeCount()<<
00597 " took "<<time2-time1<<" seconds - total "<<totalTime<<std::endl;
00598 } else if (!numberGoodCommands) {
00599
00600 std::cout
00601 <<"Sbb takes input from arguments ( - switches to stdin)"
00602 <<std::endl
00603 <<"Enter ? for list of commands or (-)unitTest or -miplib"
00604 <<" for tests"<<std::endl;
00605 }
00606 break;
00607 }
00608
00609
00610 int numberQuery=0;
00611 if (field!="?") {
00612 int length = field.length();
00613 int i;
00614 for (i=length-1;i>0;i--) {
00615 if (field[i]=='?')
00616 numberQuery++;
00617 else
00618 break;
00619 }
00620 field=field.substr(0,length-numberQuery);
00621 }
00622
00623 int iParam;
00624 int numberMatches=0;
00625 for ( iParam=0; iParam<numberParameters; iParam++ ) {
00626 int match = parameters[iParam].matches(field);
00627 if (match==1) {
00628 numberMatches = 1;
00629 break;
00630 } else {
00631 numberMatches += match>>1;
00632 }
00633 }
00634 if (iParam<numberParameters&&!numberQuery) {
00635
00636 SbbParam found = parameters[iParam];
00637 SbbParameterType type = found.type();
00638 int valid;
00639 numberGoodCommands++;
00640 if (type==GENERALQUERY) {
00641 std::cout<<"In argument list keywords have leading - "
00642 ", -stdin or just - switches to stdin"<<std::endl;
00643 std::cout<<"One command per line (and no -)"<<std::endl;
00644 std::cout<<"abcd? gives list of possibilities, if only one + explanation"<<std::endl;
00645 std::cout<<"abcd?? adds explanation, if only one fuller help(LATER)"<<std::endl;
00646 std::cout<<"abcd without value (where expected) gives current value"<<std::endl;
00647 std::cout<<"abcd value or abcd = value sets value"<<std::endl;
00648 std::cout<<"Commands are:"<<std::endl;
00649 for ( iParam=0; iParam<numberParameters; iParam+=4 ) {
00650 int i;
00651 for (i=iParam;i<min(numberParameters,iParam+4);i++)
00652 std::cout<<parameters[i].matchName()<<" ";
00653 std::cout<<std::endl;
00654 }
00655 } else if (type<81) {
00656
00657 double value = getDoubleField(argc,argv,&valid);
00658 if (!valid) {
00659 parameters[iParam].setDoubleParameter(*model,value);
00660 } else if (valid==1) {
00661 abort();
00662 } else {
00663 std::cout<<parameters[iParam].name()<<" has value "<<
00664 parameters[iParam].doubleParameter(*model)<<std::endl;
00665 }
00666 } else if (type<101) {
00667
00668 double value = getDoubleField(argc,argv,&valid);
00669 if (!valid) {
00670 if (!parameters[iParam].checkDoubleParameter(value)) {
00671 switch(type) {
00672 case DJFIX:
00673 djFix=value;
00674 preSolve=5;
00675 break;
00676 case GAPRATIO:
00677 gapRatio=value;
00678 break;
00679 case TIGHTENFACTOR:
00680 tightenFactor=value;
00681 break;
00682 default:
00683 abort();
00684 }
00685 }
00686 } else if (valid==1) {
00687 abort();
00688 } else {
00689 switch(type) {
00690 case DJFIX:
00691 value = djFix ;
00692 break;
00693 case GAPRATIO:
00694 value = gapRatio ;
00695 break;
00696 case TIGHTENFACTOR:
00697 value = tightenFactor ;
00698 break;
00699 default:
00700 abort();
00701 }
00702 std::cout << parameters[iParam].name() << " has value " <<
00703 value << std::endl ;
00704 }
00705 } else if (type<201) {
00706
00707 int value = getIntField(argc,argv,&valid);
00708 if (!valid) {
00709 parameters[iParam].setIntParameter(*model,value);
00710 } else if (valid==1) {
00711 abort();
00712 } else {
00713 std::cout<<parameters[iParam].name()<<" has value "<<
00714 parameters[iParam].intParameter(*model)<<std::endl;
00715 }
00716 } else if (type<301) {
00717
00718 std::string value = getString(argc,argv);
00719 int action = parameters[iParam].parameterOption(value);
00720 if (action<0) {
00721 if (value!="EOL") {
00722
00723 parameters[iParam].printOptions();
00724 } else {
00725
00726 std::cout<<parameters[iParam].name()<<" has value "<<
00727 parameters[iParam].currentOption()<<std::endl;
00728 }
00729 } else {
00730 parameters[iParam].setCurrentOption(action);
00731
00732 switch (type) {
00733 case DIRECTION:
00734 if (action==0)
00735 model->solver()->setObjSense(1);
00736 else
00737 model->solver()->setObjSense(-1);
00738 break;
00739 case ERRORSALLOWED:
00740 allowImportErrors = action;
00741 break;
00742 case KEEPNAMES:
00743 keepImportNames = 1-action;
00744 break;
00745 case SCALING:
00746 doScaling = 1-action;
00747 break;
00748 case GOMORYCUTS:
00749 model->addCutGenerator(&gomoryGen,-1,"Gomory");
00750 break;
00751 case PROBINGCUTS:
00752 model->addCutGenerator(&probingGen,-1,"Probing");
00753 break;
00754 case KNAPSACKCUTS:
00755 model->addCutGenerator(&knapsackGen,-1,"Knapsack");
00756 break;
00757 case ODDHOLECUTS:
00758 model->addCutGenerator(&oddholeGen,-1,"OddHole");
00759 break;
00760 case ROUNDING:
00761 useRounding = action;
00762 break;
00763 case PRESOLVE:
00764 preSolve = action*5;
00765 break;
00766 case SOLVER:
00767 { OsiSolverInterface *newSolver = solvers[value]->clone() ;
00768 model->assignSolver(newSolver) ;
00769 break ; }
00770 default:
00771 { std::cerr << "Unrecognized action. Aborting." << std::endl ;
00772 abort(); }
00773 }
00774 }
00775 } else {
00776
00777 if (type==EXIT)
00778 break;
00779 switch (type) {
00780 case SOLVECONTINUOUS:
00781 if (goodModel) {
00782 model->initialSolve();
00783 time2 = CoinCpuTime();
00784 totalTime += time2-time1;
00785 std::cout<<"Result "<<model->solver()->getObjValue()<<
00786 " iterations "<<model->solver()->getIterationCount()<<
00787 " took "<<time2-time1<<" seconds - total "<<totalTime<<std::endl;
00788 time1=time2;
00789 } else {
00790 std::cout<<"** Current model not valid"<<std::endl;
00791 }
00792 break;
00793
00794
00795
00796
00797
00798
00799 case BAB:
00800 { if (goodModel)
00801 { SbbCompareUser compare;
00802 model->setNodeComparison(compare);
00803 OsiSolverInterface * solver = model->solver();
00804 if (!doScaling)
00805 solver->setHintParam(OsiDoScale,false,OsiHintTry);
00806 #ifdef COIN_USE_CLP
00807 OsiClpSolverInterface * si =
00808 dynamic_cast<OsiClpSolverInterface *>(solver) ;
00809 if (preSolve&&si != NULL) {
00810
00811 ClpSimplex * modelC = si->getModelPtr();
00812 if (si->messageHandler()->logLevel())
00813 si->messageHandler()->setLogLevel(1);
00814 assert (modelC->tightenPrimalBounds()==0);
00815 model->initialSolve();
00816
00817 if (tightenFactor)
00818 assert (modelC->tightenPrimalBounds(tightenFactor)==0);
00819 if (gapRatio<1.0e100) {
00820 double value = si->getObjValue();
00821 double value2 = gapRatio*(1.0e-5+fabs(value));
00822 model->setAllowableGap(value2);
00823 std::cout<<"Continuous "<<value
00824 <<", so allowable gap set to "<<value2<<std::endl;
00825 }
00826 if (djFix<1.0e20) {
00827
00828 int numberColumns = modelC->numberColumns();
00829 int i;
00830 const char * type = modelC->integerInformation();
00831 double * lower = modelC->columnLower();
00832 double * upper = modelC->columnUpper();
00833 double * solution = modelC->primalColumnSolution();
00834 double * dj = modelC->dualColumnSolution();
00835 for (i=0;i<numberColumns;i++) {
00836 if (type[i]) {
00837 double value = solution[i];
00838 if (value<lower[i]+1.0e-5&&dj[i]>djFix) {
00839 solution[i]=lower[i];
00840 upper[i]=lower[i];
00841 } else if (value>upper[i]-1.0e-5&&dj[i]<-djFix) {
00842 solution[i]=upper[i];
00843 lower[i]=upper[i];
00844 }
00845 }
00846 }
00847 }
00848 {
00849
00850 SbbModel * model2 = model->integerPresolve();
00851 if (model2) {
00852
00853
00854 SbbRounding heuristic1(*model2);
00855 if (useRounding)
00856 model2->addHeuristic(&heuristic1);
00857 model2->branchAndBound();
00858
00859 model->originalModel(model2,false);
00860 } else {
00861
00862 exit(1);
00863 }
00864 }
00865 } else
00866 #endif
00867 { if (model->solver()->messageHandler()->logLevel())
00868 model->solver()->messageHandler()->setLogLevel(1) ;
00869 model->initialSolve() ;
00870 if (gapRatio < 1.0e100)
00871 { double value = model->solver()->getObjValue() ;
00872 double value2 = gapRatio*(1.0e-5+fabs(value)) ;
00873 model->setAllowableGap(value2) ;
00874 std::cout << "Continuous " << value
00875 << ", so allowable gap set to "
00876 << value2 << std::endl ; }
00877 SbbRounding heuristic1(*model) ;
00878 if (useRounding)
00879 model->addHeuristic(&heuristic1) ;
00880 model->branchAndBound() ; }
00881 if (model->bestSolution())
00882 { std::cout << "Optimal solution "
00883 << model->solver()->getObjValue() << std::endl ; }
00884 else
00885 { std::cout << "No integer solution found." << std::endl ; }
00886
00887 time2 = CoinCpuTime() ;
00888 totalTime += time2-time1 ;
00889 std::cout << "Result " << model->solver()->getObjValue()
00890 << " took " << time2-time1 << " seconds - total "
00891 << totalTime << std::endl ;
00892 time1 = time2 ; }
00893 else
00894 { std::cout << "** Current model not valid" << std::endl ; }
00895 break ; }
00896 case IMPORT:
00897 {
00898
00899 field = getString(argc,argv);
00900 std::string fileName;
00901 bool canOpen=false;
00902 if (field=="-") {
00903
00904 canOpen=true;
00905 fileName = "-";
00906 } else {
00907 if (field[0]=='/'||field[0]=='~')
00908 fileName = field;
00909 else
00910 fileName = directory+field;
00911 FILE *fp=fopen(fileName.c_str(),"r");
00912 if (fp) {
00913
00914 fclose(fp);
00915 canOpen=true;
00916 } else {
00917 std::cout<<"Unable to open file "<<fileName<<std::endl;
00918 }
00919 }
00920 if (canOpen) {
00921 model->gutsOfDestructor();
00922 int status =model->solver()->readMps(fileName.c_str(),"");
00923 if (!status||(status>0&&allowImportErrors)) {
00924
00925
00926 goodModel=true;
00927
00928 time2 = CoinCpuTime();
00929 totalTime += time2-time1;
00930 time1=time2;
00931 } else {
00932
00933 std::cout<<"There were "<<status<<
00934 " errors on input"<<std::endl;
00935 }
00936 }
00937 }
00938 break;
00939 case EXPORT:
00940 {
00941
00942 field = getString(argc,argv);
00943 std::string fileName;
00944 bool canOpen=false;
00945 if (field[0]=='/'||field[0]=='~')
00946 fileName = field;
00947 else
00948 fileName = directory+field;
00949 FILE *fp=fopen(fileName.c_str(),"w");
00950 if (fp) {
00951
00952 fclose(fp);
00953 canOpen=true;
00954 } else {
00955 std::cout<<"Unable to open file "<<fileName<<std::endl;
00956 }
00957 if (canOpen) {
00958 model->solver()->writeMps(fileName.c_str(),"");
00959 time2 = CoinCpuTime();
00960 totalTime += time2-time1;
00961 time1=time2;
00962 }
00963 }
00964 break;
00965 case MAXIMIZE:
00966 model->solver()->setObjSense(-1);
00967 break;
00968 case MINIMIZE:
00969 model->solver()->setObjSense(1);
00970 break;
00971 case DIRECTORY:
00972 { directory = getString(argc,argv);
00973 if (directory[directory.length()-1] != '/')
00974 directory += '/' ;
00975 break ; }
00976 case STDIN:
00977 read_mode=-1;
00978 break;
00979 case VERSION:
00980 std::cout<<"Coin LP version "<<SBBVERSION
00981 <<", build "<<__DATE__<<std::endl;
00982 break;
00983 case UNITTEST:
00984 {
00985
00986
00987 int status =model->solver()->readMps("../Mps/Sample/p0033.mps",
00988 "");
00989 assert(!status);
00990 model->branchAndBound();
00991 model->solver()->resolve();
00992 std::cout<<"Optimal solution "<<model->solver()->getObjValue()<<std::endl;
00993 assert(fabs(model->solver()->getObjValue()-3089.0)<1.0e-5);
00994 fprintf(stderr,"Test was okay\n");
00995 status =model->solver()->readMps("../Mps/Sample/p0033.mps",
00996 "");
00997 assert(!status);
00998 model->setCutoff(1.0e20);
00999 model->setMaximumSolutions(1);
01000 model->setSolutionCount(0);
01001 model->branchAndBound();
01002 model->solver()->resolve();
01003 std::cout<<"partial solution "<<model->solver()->getObjValue()<<std::endl;
01004 assert(model->solver()->getObjValue()>3090.0);
01005 }
01006 break;
01007 case MIPLIB:
01008 {
01009 int mainTest (int argc, const char *argv[]);
01010
01011 const char * fields[3];
01012 int nFields=1;
01013 fields[0]="fake main for miplib";
01014 if (directory!="./") {
01015 fields[1]=("-miplibDir="+directory).c_str();
01016 nFields=2;
01017 }
01018 mainTest(nFields,fields);
01019 }
01020 break;
01021 case SOLUTION:
01022 if (goodModel) {
01023
01024 field = getString(argc,argv);
01025 std::string fileName;
01026 FILE *fp=NULL;
01027 if (field=="-"||field=="EOL") {
01028
01029 fp=stdout;
01030 } else {
01031 if (field[0]=='/'||field[0]=='~')
01032 fileName = field;
01033 else
01034 fileName = directory+field;
01035 fp=fopen(fileName.c_str(),"w");
01036 }
01037 if (fp) {
01038
01039 int iRow;
01040 int numberRows=model->solver()->getNumRows();
01041 const double * dualRowSolution = model->getRowPrice();
01042 const double * primalRowSolution = model->getRowActivity();
01043 for (iRow=0;iRow<numberRows;iRow++) {
01044 fprintf(fp,"%7d ",iRow);
01045 fprintf(fp,"%15.8g %15.8g\n",primalRowSolution[iRow],
01046 dualRowSolution[iRow]);
01047 }
01048 int iColumn;
01049 int numberColumns=model->solver()->getNumCols();
01050 const double * dualColumnSolution =
01051 model->getReducedCost();
01052 const double * primalColumnSolution =
01053 model->getColSolution();
01054 for (iColumn=0;iColumn<numberColumns;iColumn++) {
01055 fprintf(fp,"%7d ",iColumn);
01056 fprintf(fp,"%15.8g %15.8g\n",
01057 primalColumnSolution[iColumn],
01058 dualColumnSolution[iColumn]);
01059 }
01060 if (fp!=stdout)
01061 fclose(fp);
01062 } else {
01063 std::cout<<"Unable to open file "<<fileName<<std::endl;
01064 }
01065 } else {
01066 std::cout<<"** Current model not valid"<<std::endl;
01067
01068 }
01069 break;
01070 default:
01071 abort();
01072 }
01073 }
01074 } else if (!numberMatches) {
01075 std::cout<<"No match for "<<field<<" - ? for list of commands"
01076 <<std::endl;
01077 } else if (numberMatches==1) {
01078 if (!numberQuery) {
01079 std::cout<<"Short match for "<<field<<" possible completion:"
01080 <<std::endl;
01081 for ( iParam=0; iParam<numberParameters; iParam++ ) {
01082 int match = parameters[iParam].matches(field);
01083 if (match)
01084 std::cout<<parameters[iParam].matchName()<<std::endl;
01085 }
01086 } else if (numberQuery) {
01087 std::cout<<"Short match for "<<field<<" completion:"
01088 <<std::endl;
01089 for ( iParam=0; iParam<numberParameters; iParam++ ) {
01090 int match = parameters[iParam].matches(field);
01091 if (match) {
01092 std::cout<<parameters[iParam].matchName()<<" : ";
01093 std::cout<<parameters[iParam].shortHelp()<<std::endl;
01094 }
01095 }
01096 }
01097 } else {
01098 if (!numberQuery)
01099 std::cout<<"Multiple matches for "<<field<<" - possible completions:"
01100 <<std::endl;
01101 else
01102 std::cout<<"Completions of "<<field<<":"<<std::endl;
01103 for ( iParam=0; iParam<numberParameters; iParam++ ) {
01104 int match = parameters[iParam].matches(field);
01105 if (match) {
01106 std::cout<<parameters[iParam].matchName();
01107 if (numberQuery>=2)
01108 std::cout<<" : "<<parameters[iParam].shortHelp();
01109 std::cout<<std::endl;
01110 }
01111 }
01112 }
01113 }
01114
01115
01116
01117 delete model;
01118
01119 for (solverMapIter_t solverIter = solvers.begin() ;
01120 solverIter != solvers.end() ;
01121 solverIter++)
01122 { if (solverIter->second) delete solverIter->second ; }
01123 }
01124 return 0;
01125 }