Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

ClpSolve.cpp

00001 // Copyright (C) 2003, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 // This file has higher level solve functions
00005 
00006 
00007 #include "CoinPragma.hpp"
00008 
00009 #include <math.h>
00010 
00011 #include "CoinHelperFunctions.hpp"
00012 #include "ClpHelperFunctions.hpp"
00013 #include "CoinSort.hpp"
00014 #include "ClpFactorization.hpp"
00015 #include "ClpSimplex.hpp"
00016 #include "ClpInterior.hpp"
00017 #include "ClpSolve.hpp"
00018 #include "ClpPackedMatrix.hpp"
00019 #include "ClpPlusMinusOneMatrix.hpp"
00020 #include "ClpNetworkMatrix.hpp"
00021 #include "ClpMessage.hpp"
00022 #include "CoinTime.hpp"
00023 
00024 #include "ClpPresolve.hpp"
00025 #include "Idiot.hpp"
00026 
00027 //#############################################################################
00028 // Allow for interrupts
00029 // But is this threadsafe ? (so switched off by option)
00030 
00031 #include "CoinSignal.hpp"
00032 static ClpSimplex * currentModel = NULL;
00033 
00034 extern "C" {
00035    static void signal_handler(int whichSignal)
00036    {
00037       if (currentModel!=NULL) 
00038          currentModel->setMaximumIterations(0); // stop at next iterations
00039       return;
00040    }
00041 }
00042 
00052 int 
00053 ClpSimplex::initialSolve(ClpSolve & options)
00054 {
00055   ClpSolve::SolveType method=options.getSolveType();
00056   ClpSolve::PresolveType presolve = options.getPresolveType();
00057   int saveMaxIterations = maximumIterations();
00058   int finalStatus=-1;
00059   int numberIterations=0;
00060   double time1 = CoinCpuTime();
00061   double timeX = time1;
00062   double time2;
00063   ClpMatrixBase * saveMatrix=NULL;
00064   ClpSimplex * model2 = this;
00065   bool interrupt = (options.getSpecialOption(2)==0);
00066   CoinSighandler_t saveSignal=SIG_DFL;
00067   if (interrupt) {
00068     currentModel = model2;
00069     // register signal handler
00070     saveSignal = signal(SIGINT,signal_handler);
00071   }
00072   ClpPresolve pinfo;
00073   double timePresolve=0.0;
00074   double timeIdiot=0.0;
00075   double timeCore=0.0;
00076   int savePerturbation=perturbation_;
00077   int saveScaling = scalingFlag_;
00078   if (dynamic_cast< ClpNetworkMatrix*>(matrix_)) {
00079     // network - switch off stuff
00080     presolve = ClpSolve::presolveOff;
00081   }
00082   // For below >0 overrides
00083   // 0 means no, -1 means maybe
00084   int doIdiot=0;
00085   int doCrash=0;
00086   int doSprint=0;
00087   if (method!=ClpSolve::useDual) {
00088     switch (options.getSpecialOption(1)) {
00089     case 0:
00090       doIdiot=-1;
00091       doCrash=-1;
00092       doSprint=-1;
00093       break;
00094     case 1:
00095       doIdiot=0;
00096       doCrash=1;
00097       doSprint=0;
00098       break;
00099     case 2:
00100       doIdiot=1;
00101       doCrash=0;
00102       doSprint=0;
00103       break;
00104     case 3:
00105       doIdiot=0;
00106       doCrash=0;
00107       doSprint=1;
00108       break;
00109     case 4:
00110       doIdiot=0;
00111       doCrash=0;
00112       doSprint=0;
00113       break;
00114     case 5:
00115       doIdiot=0;
00116       doCrash=-1;
00117       doSprint=-1;
00118       break;
00119     case 6:
00120       doIdiot=-1;
00121       doCrash=-1;
00122       doSprint=0;
00123       break;
00124     case 7:
00125       doIdiot=-1;
00126       doCrash=0;
00127       doSprint=-1;
00128       break;
00129     case 8:
00130       doIdiot=-1;
00131       doCrash=0;
00132       doSprint=0;
00133       break;
00134     case 9:
00135       doIdiot=0;
00136       doCrash=0;
00137       doSprint=-1;
00138       break;
00139     default:
00140       abort();
00141     }
00142   } else {
00143     // Dual
00144     switch (options.getSpecialOption(0)) {
00145     case 0:
00146       doIdiot=0;
00147       doCrash=0;
00148       doSprint=0;
00149       break;
00150     case 1:
00151       doIdiot=0;
00152       doCrash=1;
00153       doSprint=0;
00154       break;
00155     case 2:
00156       doIdiot=-1;
00157       if (options.getExtraInfo(0)>0)
00158         doIdiot = options.getExtraInfo(0);
00159       doCrash=0;
00160       doSprint=0;
00161       break;
00162     default:
00163       abort();
00164     }
00165   }
00166   // Just do this number of passes in Sprint
00167   int maxSprintPass=100;
00168   // PreSolve to file - not fully tested
00169   bool presolveToFile=false;
00170 
00171   if (presolve!=ClpSolve::presolveOff) {
00172     int numberPasses=5;
00173     if (presolve==ClpSolve::presolveNumber) {
00174       numberPasses=options.getPresolvePasses();
00175       presolve = ClpSolve::presolveOn;
00176     }
00177     if (presolveToFile) {
00178       printf("***** temp test\n");
00179       pinfo.presolvedModelToFile(*this,"ss.sav",1.0e-8,
00180                            false,numberPasses);
00181       model2=this;
00182     } else {
00183       model2 = pinfo.presolvedModel(*this,1.0e-8,
00184                                     false,numberPasses,true);
00185     }
00186     time2 = CoinCpuTime();
00187     timePresolve = time2-timeX;
00188     handler_->message(CLP_INTERVAL_TIMING,messages_)
00189       <<"Presolve"<<timePresolve<<time2-time1
00190       <<CoinMessageEol;
00191     timeX=time2;
00192     if (model2) {
00193     } else {
00194       handler_->message(CLP_INFEASIBLE,messages_)
00195         <<CoinMessageEol;
00196       model2 = this;
00197       presolve=ClpSolve::presolveOff;
00198     }
00199     // We may be better off using original (but if dual leave because of bounds)
00200     if (presolve!=ClpSolve::presolveOff&&
00201         numberRows_<1.01*model2->numberRows_&&numberColumns_<1.01*model2->numberColumns_
00202         &&method!=ClpSolve::useDual&&model2!=this) {
00203       delete model2;
00204       model2 = this;
00205       presolve=ClpSolve::presolveOff;
00206     }
00207   }
00208   if (interrupt)
00209     currentModel = model2;
00210   // See if worth trying +- one matrix
00211   bool plusMinus=false;
00212   int numberElements=model2->getNumElements();
00213   if (dynamic_cast< ClpNetworkMatrix*>(matrix_)) {
00214     // network - switch off stuff
00215     doIdiot=0;
00216     doSprint=0;
00217   }
00218   int numberColumns = model2->numberColumns();
00219   int numberRows = model2->numberRows();
00220   // If not all slack basis - switch off all
00221   int number=0;
00222   int iRow;
00223   for (iRow=0;iRow<numberRows;iRow++)
00224     if (model2->getRowStatus(iRow)==basic)
00225       number++;
00226   if (number<numberRows) {
00227     doIdiot=0;
00228     doCrash=0;
00229     doSprint=0;
00230   }
00231   if (options.getSpecialOption(3)==0) {
00232     if(numberElements>100000)
00233       plusMinus=true;
00234     if(numberElements>10000&&(doIdiot||doSprint)) 
00235       plusMinus=true;
00236   }
00237   if (plusMinus) {
00238     saveMatrix = model2->clpMatrix();
00239     ClpPackedMatrix* clpMatrix =
00240       dynamic_cast< ClpPackedMatrix*>(saveMatrix);
00241     if (clpMatrix) {
00242       ClpPlusMinusOneMatrix * newMatrix = new ClpPlusMinusOneMatrix(*(clpMatrix->matrix()));
00243       if (newMatrix->getIndices()) {
00244         model2->replaceMatrix(newMatrix);
00245       } else {
00246         handler_->message(CLP_MATRIX_CHANGE,messages_)
00247           <<"+- 1"
00248           <<CoinMessageEol;
00249         saveMatrix=NULL;
00250         plusMinus=false;
00251         delete newMatrix;
00252       }
00253     } else {
00254       saveMatrix=NULL;
00255       plusMinus=false;
00256     }
00257   }
00258   if (model2->factorizationFrequency()==200) {
00259     // User did not touch preset
00260     model2->setFactorizationFrequency(min(2000,100+model2->numberRows()/200));
00261   }
00262   if (method==ClpSolve::usePrimalorSprint) {
00263     if (doSprint<0) { 
00264       if (numberElements<500000) {
00265         // Small problem
00266         if(numberRows*10>numberColumns||numberColumns<6000
00267            ||(numberRows*20>numberColumns&&!plusMinus))
00268           method=ClpSolve::usePrimal; // switch off sprint
00269       } else {
00270         // larger problem
00271         if(numberRows*8>numberColumns)
00272           method=ClpSolve::usePrimal; // switch off sprint
00273         // but make lightweight
00274         if(numberRows*10>numberColumns||numberColumns<6000
00275            ||(numberRows*20>numberColumns&&!plusMinus))
00276           maxSprintPass=5;
00277       }
00278     } else if (doSprint==0) {
00279       method=ClpSolve::usePrimal; // switch off sprint
00280     }
00281   }
00282   if (method==ClpSolve::useDual) {
00283     // pick up number passes
00284     int nPasses=0;
00285     int numberNotE=0;
00286     if ((doIdiot<0&&plusMinus)||doIdiot>0) {
00287       // See if candidate for idiot
00288       nPasses=0;
00289       Idiot info(*model2);
00290       // Get average number of elements per column
00291       double ratio  = ((double) numberElements/(double) numberColumns);
00292       // look at rhs
00293       int iRow;
00294       double largest=0.0;
00295       double smallest = 1.0e30;
00296       double largestGap=0.0;
00297       for (iRow=0;iRow<numberRows;iRow++) {
00298         double value1 = model2->rowLower_[iRow];
00299         if (value1&&value1>-1.0e31) {
00300           largest = max(largest,fabs(value1));
00301           smallest=min(smallest,fabs(value1));
00302         }
00303         double value2 = model2->rowUpper_[iRow];
00304         if (value2&&value2<1.0e31) {
00305           largest = max(largest,fabs(value2));
00306           smallest=min(smallest,fabs(value2));
00307         }
00308         if (value2>value1) {
00309           numberNotE++;
00310           if (value2>1.0e31||value1<-1.0e31)
00311             largestGap = COIN_DBL_MAX;
00312           else
00313             largestGap = value2-value1;
00314         }
00315       }
00316       if (doIdiot<0) {
00317         if (numberRows>200&&numberColumns>5000&&ratio>=3.0&&
00318             largest/smallest<1.1&&!numberNotE) {
00319           nPasses = 71;
00320         }
00321       } 
00322       if (doIdiot>0) {
00323         nPasses=max(nPasses,doIdiot);
00324         if (nPasses>70) 
00325           info.setStartingWeight(1.0e3);
00326       }
00327       if (nPasses) {
00328         info.setReduceIterations(5);
00329         doCrash=0;
00330         info.crash(nPasses,model2->messageHandler(),model2->messagesPointer());
00331         time2 = CoinCpuTime();
00332         timeIdiot = time2-timeX;
00333         handler_->message(CLP_INTERVAL_TIMING,messages_)
00334           <<"Idiot Crash"<<timeIdiot<<time2-time1
00335           <<CoinMessageEol;
00336         timeX=time2;
00337       }
00338     }
00339     if (presolve==ClpSolve::presolveOn) {
00340       int numberInfeasibilities = model2->tightenPrimalBounds();
00341       if (numberInfeasibilities) {
00342         handler_->message(CLP_INFEASIBLE,messages_)
00343           <<CoinMessageEol;
00344         model2 = this;
00345         presolve=ClpSolve::presolveOff;
00346       }
00347     }
00348     if (options.getSpecialOption(0)==1)
00349       model2->crash(1000,1);
00350     if (!nPasses) {
00351       model2->dual(0);
00352     } else if (!numberNotE&&0) {
00353       // E so we can do in another way
00354       double * pi = model2->dualRowSolution();
00355       int i;
00356       int numberColumns = model2->numberColumns();
00357       int numberRows = model2->numberRows();
00358       double * saveObj = new double[numberColumns];
00359       memcpy(saveObj,model2->objective(),numberColumns*sizeof(double));
00360       memcpy(model2->dualColumnSolution(),model2->objective(),
00361              numberColumns*sizeof(double));
00362       model2->clpMatrix()->transposeTimes(-1.0,pi,model2->dualColumnSolution());
00363       memcpy(model2->objective(),model2->dualColumnSolution(),
00364              numberColumns*sizeof(double));
00365       const double * rowsol = model2->primalRowSolution();
00366       double offset=0.0;
00367       for (i=0;i<numberRows;i++) {
00368         offset += pi[i]*rowsol[i];
00369       }
00370       double value2;
00371       model2->getDblParam(ClpObjOffset,value2);
00372       printf("Offset %g %g\n",offset,value2);
00373       model2->setRowObjective(pi);
00374       // zero out pi
00375       memset(pi,0,numberRows*sizeof(double));
00376       // Could put some in basis - only partially tested
00377       model2->allSlackBasis(); 
00378       model2->factorization()->maximumPivots(200);
00379       //model2->setLogLevel(63);
00380       // solve
00381       model2->dual(1);
00382       memcpy(model2->objective(),saveObj,numberColumns*sizeof(double));
00383       // zero out pi
00384       memset(pi,0,numberRows*sizeof(double));
00385       model2->setRowObjective(pi);
00386       delete [] saveObj;
00387       model2->primal();
00388     } else {
00389       // solve
00390       model2->dual(1);
00391     }
00392     time2 = CoinCpuTime();
00393     timeCore = time2-timeX;
00394     handler_->message(CLP_INTERVAL_TIMING,messages_)
00395       <<"Dual"<<timeCore<<time2-time1
00396       <<CoinMessageEol;
00397     timeX=time2;
00398   } else if (method==ClpSolve::usePrimal) {
00399     if (doIdiot) {
00400       int nPasses=0;
00401       Idiot info(*model2);
00402       // Get average number of elements per column
00403       double ratio  = ((double) numberElements/(double) numberColumns);
00404       // look at rhs
00405       int iRow;
00406       double largest=0.0;
00407       double smallest = 1.0e30;
00408       double largestGap=0.0;
00409       int numberNotE=0;
00410       for (iRow=0;iRow<numberRows;iRow++) {
00411         double value1 = model2->rowLower_[iRow];
00412         if (value1&&value1>-1.0e31) {
00413           largest = max(largest,fabs(value1));
00414           smallest=min(smallest,fabs(value1));
00415         }
00416         double value2 = model2->rowUpper_[iRow];
00417         if (value2&&value2<1.0e31) {
00418           largest = max(largest,fabs(value2));
00419           smallest=min(smallest,fabs(value2));
00420         }
00421         if (value2>value1) {
00422           numberNotE++;
00423           if (value2>1.0e31||value1<-1.0e31)
00424             largestGap = COIN_DBL_MAX;
00425           else
00426             largestGap = value2-value1;
00427         }
00428       }
00429       if (numberRows>200&&numberColumns>5000&&numberColumns>2*numberRows) {
00430         if (plusMinus) {
00431           if (largest/smallest>2.0) {
00432             nPasses = 10+numberColumns/100000;
00433             nPasses = min(nPasses,50);
00434             nPasses = max(nPasses,15);
00435             if (numberRows>25000&&nPasses>5) {
00436               // Might as well go for it
00437               nPasses = max(nPasses,71);
00438             } else if (numberElements<3*numberColumns) {
00439               nPasses=min(nPasses,10); // probably not worh it
00440             }
00441             if (doIdiot<0)
00442               info.setLightweight(1); // say lightweight idiot
00443           } else if (largest/smallest>1.01||numberElements<=3*numberColumns) {
00444             nPasses = 10+numberColumns/1000;
00445             nPasses = min(nPasses,100);
00446             nPasses = max(nPasses,30);
00447             if (numberRows>25000) {
00448               // Might as well go for it
00449               nPasses = max(nPasses,71);
00450             }
00451             if (!largestGap)
00452               nPasses *= 2;
00453           } else {
00454             nPasses = 10+numberColumns/1000;
00455             nPasses = min(nPasses,200);
00456             nPasses = max(nPasses,100);
00457             info.setStartingWeight(1.0e-1);
00458             info.setReduceIterations(6);
00459             if (!largestGap)
00460               nPasses *= 2;
00461             //info.setFeasibilityTolerance(1.0e-7);
00462           }
00463           // If few passes - don't bother
00464           if (nPasses<=5)
00465             nPasses=0;
00466         } else {
00467           if (doIdiot<0)
00468             info.setLightweight(1); // say lightweight idiot
00469           if (largest/smallest>1.01||numberNotE) {
00470             if (numberRows>25000||numberColumns>5*numberRows) {
00471               nPasses = 50;
00472             } else if (numberColumns>4*numberRows) {
00473               nPasses = 20;
00474             } else {
00475               nPasses=5;
00476             }
00477           } else {
00478             if (numberRows>25000||numberColumns>5*numberRows) {
00479               nPasses = 50;
00480               info.setLightweight(0); // say not lightweight idiot
00481             } else if (numberColumns>4*numberRows) {
00482               nPasses = 20;
00483             } else {
00484               nPasses=15;
00485             }
00486           }
00487           if (numberElements<3*numberColumns) { 
00488             nPasses=(int) ((2.0*(double) nPasses)/ratio); // probably not worh it
00489           } else {
00490             nPasses = max(nPasses,5);
00491             nPasses = (int) (((double) nPasses)*5.0/ratio); // reduce if lots of elements per column
00492           }
00493           if (numberRows>25000&&nPasses>5) {
00494             // Might as well go for it
00495             nPasses = max(nPasses,71);
00496           } else if (plusMinus) {
00497             nPasses *= 2;
00498             nPasses=min(nPasses,71);
00499           }
00500           if (nPasses<=5)
00501             nPasses=0;
00502           //info.setStartingWeight(1.0e-1);
00503         }
00504       }
00505       if (doIdiot>0) {
00506         // pick up number passes
00507         nPasses=options.getExtraInfo(1);
00508         if (nPasses>70) {
00509           info.setStartingWeight(1.0e3);
00510           info.setReduceIterations(6);
00511           // also be more lenient on infeasibilities
00512           info.setDropEnoughFeasibility(0.5*info.getDropEnoughFeasibility());
00513           info.setDropEnoughWeighted(-2.0);
00514         } else if (nPasses>=50) {
00515           info.setStartingWeight(1.0e3);
00516           //info.setReduceIterations(6);
00517         } 
00518         // For experimenting
00519         if (nPasses<70&&(nPasses%10)>0&&(nPasses%10)<4) {
00520           info.setStartingWeight(1.0e3);
00521           info.setLightweight(nPasses%10); // special testing
00522           //info.setReduceIterations(6);
00523         }
00524       }
00525       if (nPasses) {
00526         doCrash=0;
00527 #if 0
00528         double * solution = model2->primalColumnSolution();
00529         int iColumn;
00530         double * saveLower = new double[numberColumns];
00531         memcpy(saveLower,model2->columnLower(),numberColumns*sizeof(double));
00532         double * saveUpper = new double[numberColumns];
00533         memcpy(saveUpper,model2->columnUpper(),numberColumns*sizeof(double));
00534         printf("doing tighten before idiot\n");
00535         model2->tightenPrimalBounds();
00536         // Move solution
00537         double * columnLower = model2->columnLower();
00538         double * columnUpper = model2->columnUpper();
00539         for (iColumn=0;iColumn<numberColumns;iColumn++) {
00540           if (columnLower[iColumn]>0.0)
00541             solution[iColumn]=columnLower[iColumn];
00542           else if (columnUpper[iColumn]<0.0)
00543             solution[iColumn]=columnUpper[iColumn];
00544           else
00545             solution[iColumn]=0.0;
00546         }
00547         memcpy(columnLower,saveLower,numberColumns*sizeof(double));
00548         memcpy(columnUpper,saveUpper,numberColumns*sizeof(double));
00549         delete [] saveLower;
00550         delete [] saveUpper;
00551 #else
00552         // Allow for crossover
00553         info.setStrategy(512|info.getStrategy());
00554         // Allow for scaling
00555         info.setStrategy(32|info.getStrategy());
00556         info.crash(nPasses,model2->messageHandler(),model2->messagesPointer());
00557 #endif
00558         time2 = CoinCpuTime();
00559         timeIdiot = time2-timeX;
00560         handler_->message(CLP_INTERVAL_TIMING,messages_)
00561           <<"Idiot Crash"<<timeIdiot<<time2-time1
00562           <<CoinMessageEol;
00563         timeX=time2;
00564       }
00565     }
00566     // ?
00567     if (doCrash)
00568       model2->crash(1000,1);
00569     model2->primal(1);
00570     time2 = CoinCpuTime();
00571     timeCore = time2-timeX;
00572     handler_->message(CLP_INTERVAL_TIMING,messages_)
00573       <<"Primal"<<timeCore<<time2-time1
00574       <<CoinMessageEol;
00575     timeX=time2;
00576   } else if (method==ClpSolve::usePrimalorSprint) {
00577     // Sprint
00578     /*
00579       This driver implements what I called Sprint when I introduced the idea
00580       many years ago.  Cplex calls it "sifting" which I think is just as silly.
00581       When I thought of this trivial idea
00582       it reminded me of an LP code of the 60's called sprint which after
00583       every factorization took a subset of the matrix into memory (all
00584       64K words!) and then iterated very fast on that subset.  On the
00585       problems of those days it did not work very well, but it worked very
00586       well on aircrew scheduling problems where there were very large numbers
00587       of columns all with the same flavor.
00588     */
00589     
00590     /* The idea works best if you can get feasible easily.  To make it
00591        more general we can add in costed slacks */
00592     
00593     int originalNumberColumns = model2->numberColumns();
00594     int numberRows = model2->numberRows();
00595     
00596     // We will need arrays to choose variables.  These are too big but ..
00597     double * weight = new double [numberRows+originalNumberColumns];
00598     int * sort = new int [numberRows+originalNumberColumns];
00599     int numberSort=0;
00600     // We are going to add slacks to get feasible.
00601     // initial list will just be artificials
00602     // first we will set all variables as close to zero as possible
00603     int iColumn;
00604     const double * columnLower = model2->columnLower();
00605     const double * columnUpper = model2->columnUpper();
00606     double * columnSolution = model2->primalColumnSolution();
00607     
00608     for (iColumn=0;iColumn<originalNumberColumns;iColumn++) {
00609       double value =0.0;
00610       if (columnLower[iColumn]>0.0)
00611         value = columnLower[iColumn];
00612       else if (columnUpper[iColumn]<0.0)
00613         value = columnUpper[iColumn];
00614       columnSolution[iColumn]=value;
00615     }
00616     // now see what that does to row solution
00617     double * rowSolution = model2->primalRowSolution();
00618     memset (rowSolution,0,numberRows*sizeof(double));
00619     model2->times(1.0,columnSolution,rowSolution);
00620     
00621     int * addStarts = new int [numberRows+1];
00622     int * addRow = new int[numberRows];
00623     double * addElement = new double[numberRows];
00624     const double * lower = model2->rowLower();
00625     const double * upper = model2->rowUpper();
00626     addStarts[0]=0;
00627     int numberArtificials=0;
00628     double * addCost = new double [numberRows];
00629     const double penalty=1.0e8;
00630     int iRow;
00631     for (iRow=0;iRow<numberRows;iRow++) {
00632       if (lower[iRow]>rowSolution[iRow]) {
00633         addRow[numberArtificials]=iRow;
00634         addElement[numberArtificials]=1.0;
00635         addCost[numberArtificials]=penalty;
00636         numberArtificials++;
00637         addStarts[numberArtificials]=numberArtificials;
00638       } else if (upper[iRow]<rowSolution[iRow]) {
00639         addRow[numberArtificials]=iRow;
00640         addElement[numberArtificials]=-1.0;
00641         addCost[numberArtificials]=penalty;
00642         numberArtificials++;
00643         addStarts[numberArtificials]=numberArtificials;
00644       }
00645     }
00646     model2->addColumns(numberArtificials,NULL,NULL,addCost,
00647                        addStarts,addRow,addElement);
00648     delete [] addStarts;
00649     delete [] addRow;
00650     delete [] addElement;
00651     delete [] addCost;
00652     // look at rhs to see if to perturb
00653     double largest=0.0;
00654     double smallest = 1.0e30;
00655     for (iRow=0;iRow<numberRows;iRow++) {
00656       double value;
00657       value = fabs(model2->rowLower_[iRow]);
00658       if (value&&value<1.0e30) {
00659         largest = max(largest,value);
00660         smallest=min(smallest,value);
00661       }
00662       value = fabs(model2->rowUpper_[iRow]);
00663       if (value&&value<1.0e30) {
00664         largest = max(largest,value);
00665         smallest=min(smallest,value);
00666       }
00667     }
00668     double * saveLower = NULL;
00669     double * saveUpper = NULL;
00670     if (largest<2.01*smallest) {
00671       // perturb - so switch off standard
00672       model2->setPerturbation(100);
00673       saveLower = new double[numberRows];
00674       memcpy(saveLower,model2->rowLower_,numberRows*sizeof(double));
00675       saveUpper = new double[numberRows];
00676       memcpy(saveUpper,model2->rowUpper_,numberRows*sizeof(double));
00677       double * lower = model2->rowLower();
00678       double * upper = model2->rowUpper();
00679       for (iRow=0;iRow<numberRows;iRow++) {
00680         double lowerValue=lower[iRow], upperValue=upper[iRow];
00681         double value = CoinDrand48();
00682         if (upperValue>lowerValue+primalTolerance_) {
00683           if (lowerValue>-1.0e20&&lowerValue)
00684             lowerValue -= value * 1.0e-4*fabs(lowerValue); 
00685           if (upperValue<1.0e20&&upperValue)
00686             upperValue += value * 1.0e-4*fabs(upperValue); 
00687         } else if (upperValue>0.0) {
00688           upperValue -= value * 1.0e-4*fabs(lowerValue); 
00689           lowerValue -= value * 1.0e-4*fabs(lowerValue); 
00690         } else if (upperValue<0.0) {
00691           upperValue += value * 1.0e-4*fabs(lowerValue); 
00692           lowerValue += value * 1.0e-4*fabs(lowerValue); 
00693         } else {
00694         }
00695         lower[iRow]=lowerValue;
00696         upper[iRow]=upperValue;
00697       }
00698     }
00699     int i;
00700     // Set up initial list
00701     if (numberArtificials) {
00702       numberSort=numberArtificials;
00703       for (i=0;i<numberSort;i++)
00704         sort[i] = i+originalNumberColumns;
00705     } else {
00706       numberSort = min(numberRows_,numberColumns_);
00707       for (i=0;i<numberSort;i++)
00708         sort[i] = i;
00709     }
00710     
00711     // redo as will have changed
00712     columnLower = model2->columnLower();
00713     columnUpper = model2->columnUpper();
00714     int numberColumns = model2->numberColumns();
00715     double * fullSolution = model2->primalColumnSolution();
00716     
00717     // Just do this number of passes in Sprint
00718     if (doSprint>0)
00719       maxSprintPass=options.getExtraInfo(1);
00720     int iPass;
00721     double lastObjective=1.0e31;
00722     // It will be safe to allow dense
00723     model2->setInitialDenseFactorization(true);
00724     
00725     // Just take this number of columns in small problem
00726     int smallNumberColumns = min(3*numberRows,numberColumns);
00727     smallNumberColumns = max(smallNumberColumns,3000);
00728     //int smallNumberColumns = min(12*numberRows/10,numberColumns);
00729     //smallNumberColumns = max(smallNumberColumns,3000);
00730     //smallNumberColumns = max(smallNumberColumns,numberRows+1000);
00731     // We will be using all rows
00732     int * whichRows = new int [numberRows];
00733     for (iRow=0;iRow<numberRows;iRow++)
00734       whichRows[iRow]=iRow;
00735     double originalOffset;
00736     model2->getDblParam(ClpObjOffset,originalOffset);
00737     int totalIterations=0;
00738     for (iPass=0;iPass<maxSprintPass;iPass++) {
00739       //printf("Bug until submodel new version\n");
00740       //CoinSort_2(sort,sort+numberSort,weight);
00741       // Create small problem
00742       ClpSimplex small(model2,numberRows,whichRows,numberSort,sort);
00743       small.setPerturbation(model2->perturbation());
00744       // now see what variables left out do to row solution
00745       double * rowSolution = model2->primalRowSolution();
00746       double * sumFixed = new double[numberRows];
00747       memset (sumFixed,0,numberRows*sizeof(double));
00748       int iRow,iColumn;
00749       // zero out ones in small problem
00750       for (iColumn=0;iColumn<numberSort;iColumn++) {
00751         int kColumn = sort[iColumn];
00752         fullSolution[kColumn]=0.0;
00753       }
00754       // Get objective offset
00755       double offset=0.0;
00756       const double * objective = model2->objective();
00757       for (iColumn=0;iColumn<numberColumns;iColumn++) 
00758         offset += fullSolution[iColumn]*objective[iColumn];
00759       small.setDblParam(ClpObjOffset,originalOffset-offset);
00760       model2->times(1.0,fullSolution,sumFixed);
00761       
00762       double * lower = small.rowLower();
00763       double * upper = small.rowUpper();
00764       for (iRow=0;iRow<numberRows;iRow++) {
00765         if (lower[iRow]>-1.0e50) 
00766           lower[iRow] -= sumFixed[iRow];
00767         if (upper[iRow]<1.0e50)
00768           upper[iRow] -= sumFixed[iRow];
00769         rowSolution[iRow] -= sumFixed[iRow];
00770       }
00771       delete [] sumFixed;
00772       // Solve 
00773       if (interrupt)
00774         currentModel = &small;
00775       small.primal();
00776       totalIterations += small.numberIterations();
00777       // move solution back
00778       const double * solution = small.primalColumnSolution();
00779       for (iColumn=0;iColumn<numberSort;iColumn++) {
00780         int kColumn = sort[iColumn];
00781         model2->setColumnStatus(kColumn,small.getColumnStatus(iColumn));
00782         fullSolution[kColumn]=solution[iColumn];
00783       }
00784       for (iRow=0;iRow<numberRows;iRow++) 
00785         model2->setRowStatus(iRow,small.getRowStatus(iRow));
00786       memcpy(model2->primalRowSolution(),small.primalRowSolution(),
00787              numberRows*sizeof(double));
00788       // get reduced cost for large problem
00789       memcpy(weight,model2->objective(),numberColumns*sizeof(double));
00790       model2->transposeTimes(-1.0,small.dualRowSolution(),weight);
00791       int numberNegative=0;
00792       double sumNegative = 0.0;
00793       // now massage weight so all basic in plus good djs
00794       for (iColumn=0;iColumn<numberColumns;iColumn++) {
00795         double dj = weight[iColumn]*optimizationDirection_;
00796         double value = fullSolution[iColumn];
00797         if (model2->getColumnStatus(iColumn)==ClpSimplex::basic) 
00798           dj = -1.0e50;
00799         else if (dj<0.0&&value<columnUpper[iColumn])
00800           dj = dj;
00801         else if (dj>0.0&&value>columnLower[iColumn])
00802           dj = -dj;
00803         else if (columnUpper[iColumn]>columnLower[iColumn])
00804           dj = fabs(dj);
00805         else
00806           dj = 1.0e50;
00807         weight[iColumn] = dj;
00808         if (dj<-dualTolerance_&&dj>-1.0e50) {
00809           numberNegative++;
00810           sumNegative -= dj;
00811         }
00812         sort[iColumn] = iColumn;
00813       }
00814       handler_->message(CLP_SPRINT,messages_)
00815         <<iPass+1<<small.numberIterations()<<small.objectiveValue()<<sumNegative
00816         <<numberNegative
00817         <<CoinMessageEol;
00818       if ((small.objectiveValue()*optimizationDirection_>lastObjective-1.0e-7&&iPass>5)||
00819           !small.numberIterations()||
00820           iPass==maxSprintPass-1||small.status()==3) {
00821         
00822         break; // finished
00823       } else {
00824         lastObjective = small.objectiveValue()*optimizationDirection_;
00825         // sort
00826         CoinSort_2(weight,weight+numberColumns,sort);
00827         numberSort = smallNumberColumns;
00828       }
00829     }
00830     if (interrupt) 
00831       currentModel = model2;
00832     for (i=0;i<numberArtificials;i++)
00833       sort[i] = i + originalNumberColumns;
00834     model2->deleteColumns(numberArtificials,sort);
00835     delete [] weight;
00836     delete [] sort;
00837     delete [] whichRows;
00838     if (saveLower) {
00839       // unperturb and clean
00840       for (iRow=0;iRow<numberRows;iRow++) {
00841         double diffLower = saveLower[iRow]-model2->rowLower_[iRow];
00842         double diffUpper = saveUpper[iRow]-model2->rowUpper_[iRow];
00843         model2->rowLower_[iRow]=saveLower[iRow];
00844         model2->rowUpper_[iRow]=saveUpper[iRow];
00845         if (diffLower) 
00846           assert (!diffUpper||fabs(diffLower-diffUpper)<1.0e-5);
00847         else
00848           diffLower = diffUpper;
00849         model2->rowActivity_[iRow] += diffLower;
00850       }
00851       delete [] saveLower;
00852       delete [] saveUpper;
00853     }
00854     model2->primal(0);
00855     model2->setPerturbation(savePerturbation);
00856     time2 = CoinCpuTime();
00857     timeCore = time2-timeX;
00858     handler_->message(CLP_INTERVAL_TIMING,messages_)
00859       <<"Sprint"<<timeCore<<time2-time1
00860       <<CoinMessageEol;
00861     timeX=time2;
00862     model2->setNumberIterations(model2->numberIterations()+totalIterations);
00863   } else if (method==ClpSolve::useBarrier) {
00864     printf("***** experimental pretty crude barrier\n");
00865     ClpInterior barrier(*model2);
00866     barrier.primalDual();
00867     time2 = CoinCpuTime();
00868     timeCore = time2-timeX;
00869     handler_->message(CLP_INTERVAL_TIMING,messages_)
00870       <<"Barrier"<<timeCore<<time2-time1
00871       <<CoinMessageEol;
00872     timeX=time2;
00873     printf("***** crude crossover - I will improve\n");
00874     // move solutions
00875     CoinMemcpyN(barrier.primalRowSolution(),
00876                 model2->numberRows(),model2->primalRowSolution());
00877     CoinMemcpyN(barrier.dualRowSolution(),
00878                 model2->numberRows(),model2->dualRowSolution());
00879     CoinMemcpyN(barrier.primalColumnSolution(),
00880                 model2->numberColumns(),model2->primalColumnSolution());
00881     CoinMemcpyN(barrier.dualColumnSolution(),
00882                 model2->numberColumns(),model2->dualColumnSolution());
00883     // make sure no status left
00884     model2->createStatus();
00885     // solve
00886     model2->setPerturbation(100);
00887     model2->primal(1);
00888     model2->setPerturbation(savePerturbation);
00889     time2 = CoinCpuTime();
00890     timeCore = time2-timeX;
00891     handler_->message(CLP_INTERVAL_TIMING,messages_)
00892       <<"Crossover"<<timeCore<<time2-time1
00893       <<CoinMessageEol;
00894     timeX=time2;
00895   } else {
00896     assert (method!=ClpSolve::automatic); // later
00897     time2=0.0;
00898   }
00899   if (saveMatrix) {
00900     // delete and replace
00901     delete model2->clpMatrix();
00902     model2->replaceMatrix(saveMatrix);
00903   }
00904   numberIterations = model2->numberIterations();
00905   finalStatus=model2->status();
00906   if (presolve==ClpSolve::presolveOn) {
00907     int saveLevel = logLevel();
00908     setLogLevel(1);
00909     pinfo.postsolve(true);
00910     time2 = CoinCpuTime();
00911     timePresolve += time2-timeX;
00912     handler_->message(CLP_INTERVAL_TIMING,messages_)
00913       <<"Postsolve"<<time2-timeX<<time2-time1
00914       <<CoinMessageEol;
00915     timeX=time2;
00916     if (!presolveToFile)
00917       delete model2;
00918     if (interrupt)
00919       currentModel = this;
00920     checkSolution();
00921     setLogLevel(saveLevel);
00922     if (finalStatus!=3&&(finalStatus||status()==-1)) {
00923       int savePerturbation = perturbation();
00924       setPerturbation(100);
00925       primal(1);
00926       setPerturbation(savePerturbation);
00927       numberIterations += this->numberIterations();
00928       finalStatus=status();
00929       time2 = CoinCpuTime();
00930       handler_->message(CLP_INTERVAL_TIMING,messages_)
00931       <<"Cleanup"<<time2-timeX<<time2-time1
00932       <<CoinMessageEol;
00933       timeX=time2;
00934     }
00935   }
00936   setMaximumIterations(saveMaxIterations);
00937   std::string statusMessage[]={"Unknown","Optimal","PrimalInfeasible","DualInfeasible","Stopped"};
00938   assert (finalStatus>=-1&&finalStatus<=3);
00939   handler_->message(CLP_TIMING,messages_)
00940     <<statusMessage[finalStatus+1]<<objectiveValue()<<numberIterations<<time2-time1;
00941   handler_->printing(presolve==ClpSolve::presolveOn)
00942     <<timePresolve;
00943   handler_->printing(timeIdiot)
00944     <<timeIdiot;
00945   handler_->message()<<CoinMessageEol;
00946   if (interrupt) 
00947     signal(SIGINT,saveSignal);
00948   perturbation_=savePerturbation;
00949   scalingFlag_=saveScaling;
00950   return finalStatus;
00951 }
00952 // General solve
00953 int 
00954 ClpSimplex::initialSolve()
00955 {
00956   // Default so use dual
00957   ClpSolve options;
00958   return initialSolve(options);
00959 }
00960 // General dual solve
00961 int 
00962 ClpSimplex::initialDualSolve()
00963 {
00964   ClpSolve options;
00965   // Use dual
00966   options.setSolveType(ClpSolve::useDual);
00967   return initialSolve(options);
00968 }
00969 // General dual solve
00970 int 
00971 ClpSimplex::initialPrimalSolve()
00972 {
00973   ClpSolve options;
00974   // Use primal
00975   options.setSolveType(ClpSolve::usePrimal);
00976   return initialSolve(options);
00977 }
00978 // Default constructor
00979 ClpSolve::ClpSolve (  )
00980 {
00981   method_ = useDual;
00982   presolveType_=presolveOn;
00983   numberPasses_=5;
00984   int i;
00985   for (i=0;i<4;i++)
00986     options_[i]=0;
00987   for (i=0;i<4;i++)
00988     extraInfo_[i]=-1;
00989 }
00990 
00991 // Copy constructor. 
00992 ClpSolve::ClpSolve(const ClpSolve & rhs)
00993 {
00994   method_ = rhs.method_;
00995   presolveType_=rhs.presolveType_;
00996   numberPasses_=rhs.numberPasses_;
00997   int i;
00998   for ( i=0;i<4;i++)
00999     options_[i]=rhs.options_[i];
01000   for ( i=0;i<4;i++)
01001     extraInfo_[i]=rhs.extraInfo_[i];
01002 }
01003 // Assignment operator. This copies the data
01004 ClpSolve & 
01005 ClpSolve::operator=(const ClpSolve & rhs)
01006 {
01007   if (this != &rhs) {
01008     method_ = rhs.method_;
01009     presolveType_=rhs.presolveType_;
01010     numberPasses_=rhs.numberPasses_;
01011     int i;
01012     for (i=0;i<4;i++)
01013       options_[i]=rhs.options_[i];
01014     for (i=0;i<4;i++)
01015       extraInfo_[i]=rhs.extraInfo_[i];
01016   }
01017   return *this;
01018 
01019 }
01020 // Destructor
01021 ClpSolve::~ClpSolve (  )
01022 {
01023 }
01024 /*   which translation is:
01025      which:
01026      0 - startup in Dual  (nothing if basis exists).:
01027              0 - no basis, 1 crash
01028      1 - startup in Primal (nothing if basis exists):
01029         0 - use initiative
01030         1 - use crash
01031         2 - use idiot and look at further info
01032         3 - use sprint and look at further info
01033         4 - use all slack
01034         5 - use initiative but no idiot
01035         6 - use initiative but no sprint
01036         7 - use initiative but no crash
01037         8 - do allslack or idiot
01038         9 - do allslack or sprint
01039      2 - interrupt handling - 0 yes, 1 no (for threadsafe)
01040      3 - whether to make +- 1matrix - 0 yes, 1 no
01041 */
01042 void 
01043 ClpSolve::setSpecialOption(int which,int value,int extraInfo)
01044 {
01045   options_[which]=value;
01046   extraInfo_[which]=extraInfo;
01047 }
01048 int 
01049 ClpSolve::getSpecialOption(int which) const
01050 {
01051   return options_[which];
01052 }
01053 
01054 // Solve types
01055 void 
01056 ClpSolve::setSolveType(SolveType method, int extraInfo)
01057 {
01058   method_=method;
01059 }
01060 
01061 ClpSolve::SolveType 
01062 ClpSolve::getSolveType()
01063 {
01064   return method_;
01065 }
01066 
01067 // Presolve types
01068 void 
01069 ClpSolve::setPresolveType(PresolveType amount, int extraInfo)
01070 {
01071   presolveType_=amount;
01072   numberPasses_=extraInfo;
01073 }
01074 ClpSolve::PresolveType 
01075 ClpSolve::getPresolveType()
01076 {
01077   return presolveType_;
01078 }
01079 // Extra info for idiot (or sprint)
01080 int 
01081 ClpSolve::getExtraInfo(int which) const
01082 {
01083   return extraInfo_[which];
01084 }
01085 int 
01086 ClpSolve::getPresolvePasses() const
01087 {
01088   return numberPasses_;
01089 }

Generated on Wed Dec 3 14:37:35 2003 for CLP by doxygen 1.3.5