Changeset 2469 for trunk/Cbc/examples/allCuts.cpp
 Timestamp:
 Jan 6, 2019 6:17:46 PM (9 months ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

trunk/Cbc/examples/allCuts.cpp
r1898 r2469 6 6 #include <cassert> 7 7 #include <iomanip> 8 9 8 10 9 #include "CoinPragma.hpp" … … 45 44 /** Stored Cut Generator Class */ 46 45 class CglStoredUser : public CglStored { 47 46 48 47 public: 49 50 51 48 /**@name Generate Cuts */ 52 49 //@{ … … 59 56 and inserts any that are violated by enough 60 57 */ 61 virtual void generateCuts( const OsiSolverInterface & si, OsiCuts &cs,62 58 virtual void generateCuts(const OsiSolverInterface &si, OsiCuts &cs, 59 const CglTreeInfo info = CglTreeInfo()) const; 63 60 //@} 64 61 65 62 /**@name Cut stuff */ 66 63 //@{ 67 OsiRowCut * mutableRowCutPointer(int index) 68 { return cuts_.rowCutPtr(index);} 64 OsiRowCut *mutableRowCutPointer(int index) 65 { 66 return cuts_.rowCutPtr(index); 67 } 69 68 //@} 70 69 71 70 /**@name Constructors and destructors */ 72 71 //@{ 73 /// Default constructor 74 CglStoredUser 75 76 /// Copy constructor 77 CglStoredUser (const CglStoredUser &rhs);72 /// Default constructor 73 CglStoredUser(); 74 75 /// Copy constructor 76 CglStoredUser(const CglStoredUser &rhs); 78 77 79 78 /// Clone 80 virtual CglCutGenerator * 81 82 /// Assignment operator 79 virtual CglCutGenerator *clone() const; 80 81 /// Assignment operator 83 82 CglStoredUser & 84 operator=(const CglStoredUser& rhs); 85 86 /// Destructor 87 virtual 88 ~CglStoredUser (); 83 operator=(const CglStoredUser &rhs); 84 85 /// Destructor 86 virtual ~CglStoredUser(); 89 87 //@} 90 88 91 89 protected: 92 93 // Protected member methods 90 // Protected member methods 94 91 95 92 // Protected member data … … 105 102 // 106 103 // Generate Stored cuts 107 // 108 void 109 CglStoredUser::generateCuts(const OsiSolverInterface & si, OsiCuts & cs, 110 const CglTreeInfo info) const 104 // 105 void CglStoredUser::generateCuts(const OsiSolverInterface &si, OsiCuts &cs, 106 const CglTreeInfo info) const 111 107 { 112 108 // Get basic problem information 113 const double * 114 if (info.inTree &&info.pass>numberPasses_) {109 const double *solution = si.getColSolution(); 110 if (info.inTree && info.pass > numberPasses_) { 115 111 // only continue if integer feasible 116 int numberColumns =si.getNumCols();112 int numberColumns = si.getNumCols(); 117 113 int i; 118 const double * 119 const double * 120 int numberAway =0;121 for (i =0;i<numberColumns;i++) {114 const double *colUpper = si.getColUpper(); 115 const double *colLower = si.getColLower(); 116 int numberAway = 0; 117 for (i = 0; i < numberColumns; i++) { 122 118 double value = solution[i]; 123 119 // In case slightly away from bounds 124 value = CoinMax(colLower[i], value);125 value = CoinMin(colUpper[i], value);126 if (si.isInteger(i) &&fabs(valuefabs(value+0.5))>1.0e5)127 120 value = CoinMax(colLower[i], value); 121 value = CoinMin(colUpper[i], value); 122 if (si.isInteger(i) && fabs(value  fabs(value + 0.5)) > 1.0e5) 123 numberAway++; 128 124 } 129 125 if (numberAway) … … 131 127 } 132 128 int numberRowCuts = cuts_.sizeRowCuts(); 133 for (int i =0;i<numberRowCuts;i++) {134 const OsiRowCut * 129 for (int i = 0; i < numberRowCuts; i++) { 130 const OsiRowCut *rowCutPointer = cuts_.rowCutPtr(i); 135 131 double violation = rowCutPointer>violated(solution); 136 if (violation >=requiredViolation_)132 if (violation >= requiredViolation_) 137 133 cs.insert(*rowCutPointer); 138 134 } … … 140 136 141 137 // 142 // Default Constructor 143 // 144 CglStoredUser::CglStoredUser () 145 : 146 CglStored(), 147 numberPasses_(5) 148 { 149 } 150 151 // 152 // Copy constructor 153 // 154 CglStoredUser::CglStoredUser (const CglStoredUser & source) : 155 CglStored(source), 156 numberPasses_(source.numberPasses_) 157 { 138 // Default Constructor 139 // 140 CglStoredUser::CglStoredUser() 141 : CglStored() 142 , numberPasses_(5) 143 { 144 } 145 146 // 147 // Copy constructor 148 // 149 CglStoredUser::CglStoredUser(const CglStoredUser &source) 150 : CglStored(source) 151 , numberPasses_(source.numberPasses_) 152 { 158 153 } 159 154 … … 168 163 169 164 // 170 // Destructor 171 // 172 CglStoredUser::~CglStoredUser 165 // Destructor 166 // 167 CglStoredUser::~CglStoredUser() 173 168 { 174 169 } 175 170 176 171 // 177 // Assignment operator 172 // Assignment operator 178 173 // 179 174 CglStoredUser & 180 CglStoredUser::operator=(const CglStoredUser &rhs)175 CglStoredUser::operator=(const CglStoredUser &rhs) 181 176 { 182 177 if (this != &rhs) { 183 178 CglStored::operator=(rhs); 184 numberPasses_ =rhs.numberPasses_;179 numberPasses_ = rhs.numberPasses_; 185 180 } 186 181 return *this; … … 188 183 // Class to disallow strong branching solutions 189 184 #include "CbcFeasibilityBase.hpp" 190 class CbcFeasibilityNoStrong : public CbcFeasibilityBase {185 class CbcFeasibilityNoStrong : public CbcFeasibilityBase { 191 186 public: 192 // Default Constructor 193 CbcFeasibilityNoStrong 187 // Default Constructor 188 CbcFeasibilityNoStrong() {}; 194 189 195 190 virtual ~CbcFeasibilityNoStrong() {}; 196 // Copy constructor 197 CbcFeasibilityNoStrong ( const CbcFeasibilityNoStrong &rhs) {}; 198 199 // Assignment operator 200 CbcFeasibilityNoStrong & operator=( const CbcFeasibilityNoStrong& rhs) 201 { return * this;}; 191 // Copy constructor 192 CbcFeasibilityNoStrong(const CbcFeasibilityNoStrong &rhs) {}; 193 194 // Assignment operator 195 CbcFeasibilityNoStrong &operator=(const CbcFeasibilityNoStrong &rhs) 196 { 197 return *this; 198 }; 202 199 203 200 /// Clone 204 virtual CbcFeasibilityBase * clone() const 205 { return new CbcFeasibilityNoStrong();}; 201 virtual CbcFeasibilityBase *clone() const 202 { 203 return new CbcFeasibilityNoStrong(); 204 }; 206 205 207 206 /** … … 214 213 1 pretend integer solution 215 214 */ 216 virtual int feasible(CbcModel * model, int mode) 217 {return mode;}; 215 virtual int feasible(CbcModel *model, int mode) 216 { 217 return mode; 218 }; 218 219 }; 219 220 220 221 221 //############################################################################# 222 222 223 224 223 /************************************************************************ 225 224 … … 230 229 ************************************************************************/ 231 230 232 int main 231 int main(int argc, const char *argv[]) 233 232 { 234 233 235 234 // Define your favorite OsiSolver 236 235 237 236 OsiClpSolverInterface solver1; 238 237 … … 248 247 } 249 248 #endif 250 if (argc >=2) mpsFileName = argv[1];251 int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(),"");252 i f( numMpsReadErrors != 0 )253 {254 255 249 if (argc >= 2) 250 mpsFileName = argv[1]; 251 int numMpsReadErrors = solver1.readMps(mpsFileName.c_str(), ""); 252 if (numMpsReadErrors != 0) { 253 printf("%d errors reading MPS file\n", numMpsReadErrors); 254 return numMpsReadErrors; 256 255 } 257 256 double time1 = CoinCpuTime(); … … 263 262 if 2 parameters and numeric taken as time 264 263 */ 265 bool preProcess =false;266 double minutes =1.0;267 int nGoodParam =0;268 for (int iParam =2; iParam<argc;iParam++) {269 if (!strcmp(argv[iParam], "preprocess")) {270 preProcess =true;264 bool preProcess = false; 265 double minutes = 1.0; 266 int nGoodParam = 0; 267 for (int iParam = 2; iParam < argc; iParam++) { 268 if (!strcmp(argv[iParam], "preprocess")) { 269 preProcess = true; 271 270 nGoodParam++; 272 } else if (!strcmp(argv[iParam], "time")) {273 if (iParam +1<argc&&isdigit(argv[iParam+1][0])) {274 minutes =atof(argv[iParam+1]);275 if (minutes >=0.0) {276 nGoodParam +=2;271 } else if (!strcmp(argv[iParam], "time")) { 272 if (iParam + 1 < argc && isdigit(argv[iParam + 1][0])) { 273 minutes = atof(argv[iParam + 1]); 274 if (minutes >= 0.0) { 275 nGoodParam += 2; 277 276 iParam++; // skip time 278 277 } … … 280 279 } 281 280 } 282 if (nGoodParam ==0&&argc==3&&isdigit(argv[2][0])) {281 if (nGoodParam == 0 && argc == 3 && isdigit(argv[2][0])) { 283 282 // If time is given then stop after that number of minutes 284 283 minutes = atof(argv[2]); 285 if (minutes >=0.0)286 nGoodParam =1;287 } 288 if (nGoodParam !=argc2&&argc>=2) {284 if (minutes >= 0.0) 285 nGoodParam = 1; 286 } 287 if (nGoodParam != argc  2 && argc >= 2) { 289 288 printf("Usage <file> [preprocess] [time <minutes>] or <file> <minutes>\n"); 290 289 exit(1); 291 290 } 292 291 // Reduce printout 293 solver1.setHintParam(OsiDoReducePrint, true,OsiHintTry);292 solver1.setHintParam(OsiDoReducePrint, true, OsiHintTry); 294 293 // See if we want preprocessing 295 OsiSolverInterface * solver2=&solver1;294 OsiSolverInterface *solver2 = &solver1; 296 295 CglPreProcess process; 297 296 // Never do preprocessing until dual tests out as can fix incorrectly 298 preProcess =false;297 preProcess = false; 299 298 if (preProcess) { 300 299 /* Do not try and produce equality cliques and 301 300 do up to 5 passes */ 302 solver2 = process.preProcess(solver1, false,5);301 solver2 = process.preProcess(solver1, false, 5); 303 302 if (!solver2) { 304 303 printf("Preprocessing says infeasible\n"); … … 309 308 // Turn L rows into cuts 310 309 CglStoredUser stored; 311 {312 int numberRows = solver2>getNumRows();313 314 int *whichRow = new int[numberRows];315 // get row copy316 const CoinPackedMatrix *rowCopy = solver2>getMatrixByRow();317 const int *column = rowCopy>getIndices();318 const int *rowLength = rowCopy>getVectorLengths();319 const CoinBigIndex *rowStart = rowCopy>getVectorStarts();320 const double *rowLower = solver2>getRowLower();321 const double *rowUpper = solver2>getRowUpper();322 const double *element = rowCopy>getElements();323 int iRow,nDelete=0;324 for (iRow=0;iRow<numberRows;iRow++) {325 if (rowLower[iRow]<1.0e20rowUpper[iRow]>1.0e20) {326 // take out327 whichRow[nDelete++]=iRow;328 }329 }330 // leave some rows to avoid empty problem (Gomory does not like)331 nDelete = CoinMax(CoinMin(nDelete,numberRows5),0);332 for (int jRow=0;jRow<nDelete;jRow++) {333 iRow=whichRow[jRow];334 int start = rowStart[iRow];335 stored.addCut(rowLower[iRow],rowUpper[iRow],rowLength[iRow],336 column+start,element+start);337 }338 /* The following is problem specific.310 { 311 int numberRows = solver2>getNumRows(); 312 313 int *whichRow = new int[numberRows]; 314 // get row copy 315 const CoinPackedMatrix *rowCopy = solver2>getMatrixByRow(); 316 const int *column = rowCopy>getIndices(); 317 const int *rowLength = rowCopy>getVectorLengths(); 318 const CoinBigIndex *rowStart = rowCopy>getVectorStarts(); 319 const double *rowLower = solver2>getRowLower(); 320 const double *rowUpper = solver2>getRowUpper(); 321 const double *element = rowCopy>getElements(); 322 int iRow, nDelete = 0; 323 for (iRow = 0; iRow < numberRows; iRow++) { 324 if (rowLower[iRow] < 1.0e20  rowUpper[iRow] > 1.0e20) { 325 // take out 326 whichRow[nDelete++] = iRow; 327 } 328 } 329 // leave some rows to avoid empty problem (Gomory does not like) 330 nDelete = CoinMax(CoinMin(nDelete, numberRows  5), 0); 331 for (int jRow = 0; jRow < nDelete; jRow++) { 332 iRow = whichRow[jRow]; 333 int start = rowStart[iRow]; 334 stored.addCut(rowLower[iRow], rowUpper[iRow], rowLength[iRow], 335 column + start, element + start); 336 } 337 /* The following is problem specific. 339 338 Normally cuts are deleted if slack on cut basic. 340 339 On some problems you may wish to leave cuts in as long 341 340 as slack value zero 342 341 */ 343 int numberCuts=stored.sizeRowCuts();344 for (int iCut=0;iCut<numberCuts;iCut++) {345 //stored.mutableRowCutPointer(iCut)>setEffectiveness(1.0e50);346 }347 solver2>deleteRows(nDelete,whichRow);348 delete[] whichRow;349 }342 int numberCuts = stored.sizeRowCuts(); 343 for (int iCut = 0; iCut < numberCuts; iCut++) { 344 //stored.mutableRowCutPointer(iCut)>setEffectiveness(1.0e50); 345 } 346 solver2>deleteRows(nDelete, whichRow); 347 delete[] whichRow; 348 } 350 349 CbcModel model(*solver2); 351 model.solver()>setHintParam(OsiDoReducePrint, true,OsiHintTry);350 model.solver()>setHintParam(OsiDoReducePrint, true, OsiHintTry); 352 351 // Set up some cut generators and defaults 353 352 // Probing first as gets tight bounds on continuous … … 383 382 CglMixedIntegerRounding2 mixedGen; 384 383 CglFlowCover flowGen; 385 384 386 385 // Add in generators 387 386 // Experiment with 1 and 99 etc 388 387 // This is just for one particular model 389 model.addCutGenerator(&generator1, 1,"Probing");388 model.addCutGenerator(&generator1, 1, "Probing"); 390 389 //model.addCutGenerator(&generator2,1,"Gomory"); 391 model.addCutGenerator(&generator2, 1,"Gomory");392 model.addCutGenerator(&generator3, 1,"Knapsack");390 model.addCutGenerator(&generator2, 1, "Gomory"); 391 model.addCutGenerator(&generator3, 1, "Knapsack"); 393 392 // model.addCutGenerator(&generator4,1,"RedSplit"); 394 393 //model.addCutGenerator(&generator5,1,"Clique"); 395 model.addCutGenerator(&generator5, 1,"Clique");396 model.addCutGenerator(&flowGen, 1,"FlowCover");397 model.addCutGenerator(&mixedGen, 1,"MixedIntegerRounding");394 model.addCutGenerator(&generator5, 1, "Clique"); 395 model.addCutGenerator(&flowGen, 1, "FlowCover"); 396 model.addCutGenerator(&mixedGen, 1, "MixedIntegerRounding"); 398 397 // Add stored cuts (making sure at all depths) 399 model.addCutGenerator(&stored, 1,"Stored",true,false,false,100,1,1);400 398 model.addCutGenerator(&stored, 1, "Stored", true, false, false, 100, 1, 1); 399 401 400 int numberGenerators = model.numberCutGenerators(); 402 401 int iGenerator; 403 402 // Say we want timings 404 for (iGenerator =0;iGenerator<numberGenerators;iGenerator++) {405 CbcCutGenerator * 403 for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { 404 CbcCutGenerator *generator = model.cutGenerator(iGenerator); 406 405 generator>setTiming(true); 407 406 } 408 OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*>(model.solver());407 OsiClpSolverInterface *osiclp = dynamic_cast< OsiClpSolverInterface * >(model.solver()); 409 408 // go faster stripes 410 if (osiclp) { 411 if (osiclp>getNumRows()<300&&osiclp>getNumCols()<500) {409 if (osiclp) { 410 if (osiclp>getNumRows() < 300 && osiclp>getNumCols() < 500) { 412 411 //osiclp>setupForRepeatedUse(2,0); 413 osiclp>setupForRepeatedUse(0, 0);412 osiclp>setupForRepeatedUse(0, 0); 414 413 } 415 414 // Don't allow dual stuff 416 osiclp>setSpecialOptions(osiclp>specialOptions() 262144);417 } 415 osiclp>setSpecialOptions(osiclp>specialOptions()  262144); 416 } 418 417 // Uncommenting this should switch off all CBC messages 419 418 // model.messagesPointer()>setDetailMessages(10,10000,NULL); … … 429 428 */ 430 429 // Make sure cut generator called correctly (a) 431 iGenerator =numberGenerators1;430 iGenerator = numberGenerators  1; 432 431 model.cutGenerator(iGenerator)>setMustCallAgain(true); 433 432 // Say cuts needed at continuous (b) … … 443 442 444 443 // Could tune more 445 double objValue = model.solver()>getObjSense() *model.solver()>getObjValue();446 double minimumDropA =CoinMin(1.0,fabs(objValue)*1.0e3+1.0e4);447 double minimumDrop = fabs(objValue)*1.0e4+1.0e4;448 printf("min drop %g (A %g)\n", minimumDrop,minimumDropA);444 double objValue = model.solver()>getObjSense() * model.solver()>getObjValue(); 445 double minimumDropA = CoinMin(1.0, fabs(objValue) * 1.0e3 + 1.0e4); 446 double minimumDrop = fabs(objValue) * 1.0e4 + 1.0e4; 447 printf("min drop %g (A %g)\n", minimumDrop, minimumDropA); 449 448 model.setMinimumDrop(minimumDrop); 450 449 451 if (model.getNumCols() <500)450 if (model.getNumCols() < 500) 452 451 model.setMaximumCutPassesAtRoot(100); // always do 100 if possible 453 else if (model.getNumCols() <5000)452 else if (model.getNumCols() < 5000) 454 453 model.setMaximumCutPassesAtRoot(100); // use minimum drop 455 454 else … … 461 460 // model.setNumberStrong(0); 462 461 // Do more strong branching if small 463 if (model.getNumCols() <5000)462 if (model.getNumCols() < 5000) 464 463 model.setNumberStrong(10); 465 464 model.setNumberStrong(20); … … 467 466 model.setNumberBeforeTrust(5); 468 467 469 model.solver()>setIntParam(OsiMaxNumIterationHotStart, 100);468 model.solver()>setIntParam(OsiMaxNumIterationHotStart, 100); 470 469 471 470 // If time is given then stop after that number of minutes 472 if (minutes >=0.0) {473 std::cout <<"Stopping after "<<minutes<<" minutes"<<std::endl;474 model.setDblParam(CbcModel::CbcMaximumSeconds, 60.0*minutes);471 if (minutes >= 0.0) { 472 std::cout << "Stopping after " << minutes << " minutes" << std::endl; 473 model.setDblParam(CbcModel::CbcMaximumSeconds, 60.0 * minutes); 475 474 } 476 475 // Switch off most output 477 if (model.getNumCols() <30000) {476 if (model.getNumCols() < 30000) { 478 477 model.messageHandler()>setLogLevel(1); 479 478 //model.solver()>messageHandler()>setLogLevel(0); … … 489 488 // Set up debugger by name (only if no preprocesing) 490 489 if (!preProcess) { 491 std::string problemName 492 model.solver()>getStrParam(OsiProbName, problemName);493 model.solver()>activateRowCutDebugger(problemName.c_str()) 490 std::string problemName; 491 model.solver()>getStrParam(OsiProbName, problemName); 492 model.solver()>activateRowCutDebugger(problemName.c_str()); 494 493 } 495 494 #endif 496 495 // Do complete search 497 496 498 497 model.branchAndBound(); 499 498 500 std::cout <<mpsFileName<<" took "<<CoinCpuTime()time1<<" seconds, "501 <<model.getNodeCount()<<" nodes with objective "502 <<model.getObjValue()503 <<(!model.status() ? " Finished" : " Not finished")504 <<std::endl;499 std::cout << mpsFileName << " took " << CoinCpuTime()  time1 << " seconds, " 500 << model.getNodeCount() << " nodes with objective " 501 << model.getObjValue() 502 << (!model.status() ? " Finished" : " Not finished") 503 << std::endl; 505 504 506 505 // Print more statistics 507 std::cout <<"Cuts at root node changed objective from "<<model.getContinuousObjective()508 <<" to "<<model.rootObjectiveAfterCuts()<<std::endl;509 510 for (iGenerator =0;iGenerator<numberGenerators;iGenerator++) {511 CbcCutGenerator * 512 std::cout <<generator>cutGeneratorName()<<" was tried "513 <<generator>numberTimesEntered()<<" times and created "514 <<generator>numberCutsInTotal()<<" cuts of which "515 <<generator>numberCutsActive()<<" were active after adding rounds of cuts";506 std::cout << "Cuts at root node changed objective from " << model.getContinuousObjective() 507 << " to " << model.rootObjectiveAfterCuts() << std::endl; 508 509 for (iGenerator = 0; iGenerator < numberGenerators; iGenerator++) { 510 CbcCutGenerator *generator = model.cutGenerator(iGenerator); 511 std::cout << generator>cutGeneratorName() << " was tried " 512 << generator>numberTimesEntered() << " times and created " 513 << generator>numberCutsInTotal() << " cuts of which " 514 << generator>numberCutsActive() << " were active after adding rounds of cuts"; 516 515 if (generator>timing()) 517 std::cout <<" ( "<<generator>timeInCutGenerator()<<" seconds)"<<std::endl;516 std::cout << " ( " << generator>timeInCutGenerator() << " seconds)" << std::endl; 518 517 else 519 std::cout <<std::endl;518 std::cout << std::endl; 520 519 } 521 520 // Print solution if finished  we can't get names from Osi!  so get from OsiClp 522 521 523 if (model.getMinimizationObjValue() <1.0e50) {522 if (model.getMinimizationObjValue() < 1.0e50) { 524 523 // post process 525 OsiSolverInterface * 524 OsiSolverInterface *solver; 526 525 if (preProcess) { 527 526 process.postProcess(*model.solver()); 528 527 // Solution now back in solver1 529 solver = & 528 solver = &solver1; 530 529 } else { 531 530 solver = model.solver(); 532 531 } 533 532 int numberColumns = solver>getNumCols(); 534 535 const double * 533 534 const double *solution = solver>getColSolution(); 536 535 537 536 // Get names from solver1 (as OsiSolverInterface may lose) 538 std::vector< std::string> columnNames = *solver1.getModelPtr()>columnNames();539 537 std::vector< std::string > columnNames = *solver1.getModelPtr()>columnNames(); 538 540 539 int iColumn; 541 std::cout <<std::setiosflags(std::ios::fixedstd::ios::showpoint)<<std::setw(14);542 543 std::cout <<""<<std::endl;544 for (iColumn =0;iColumn<numberColumns;iColumn++) {545 double value =solution[iColumn];546 if (fabs(value) >1.0e7&&solver>isInteger(iColumn)) {547 std::cout<<std::setw(6)<<iColumn<<" "548 <<columnNames[iColumn]<<" "549 <<value<<std::endl;550 solverSave.setColLower(iColumn,value);551 solverSave.setColUpper(iColumn,value);540 std::cout << std::setiosflags(std::ios::fixed  std::ios::showpoint) << std::setw(14); 541 542 std::cout << "" << std::endl; 543 for (iColumn = 0; iColumn < numberColumns; iColumn++) { 544 double value = solution[iColumn]; 545 if (fabs(value) > 1.0e7 && solver>isInteger(iColumn)) { 546 std::cout << std::setw(6) << iColumn << " " 547 << columnNames[iColumn] << " " 548 << value << std::endl; 549 solverSave.setColLower(iColumn, value); 550 solverSave.setColUpper(iColumn, value); 552 551 } 553 552 } 554 std::cout <<""<<std::endl;555 556 std::cout <<std::resetiosflags(std::ios::fixedstd::ios::showpointstd::ios::scientific);553 std::cout << "" << std::endl; 554 555 std::cout << std::resetiosflags(std::ios::fixed  std::ios::showpoint  std::ios::scientific); 557 556 solverSave.initialSolve(); 558 557 } 559 558 return 0; 560 } 559 }
Note: See TracChangeset
for help on using the changeset viewer.