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

Idiot.cpp

00001 // Copyright (C) 2002, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 
00004 #include "CoinPragma.hpp"
00005 #include <stdio.h>
00006 #include <stdarg.h>
00007 #include <stdlib.h>
00008 #include <math.h>
00009 #include "ClpPresolve.hpp"
00010 #include "Idiot.hpp"
00011 #include "CoinTime.hpp"
00012 #include "CoinMessageHandler.hpp"
00013 // Redefine stuff for Clp
00014 #ifndef OSI_IDIOT
00015 #include "ClpMessage.hpp"
00016 #define OsiObjOffset ClpObjOffset
00017 #endif
00018 /**** strategy 4 - drop, exitDrop and djTolerance all relative:
00019 For first two major iterations these are small.  Then:
00020 
00021 drop - exit a major iteration if drop over 5*checkFrequency < this is
00022 used as info->drop*(10.0+fabs(last weighted objective))
00023 
00024 exitDrop - exit idiot if feasible and drop < this is
00025 used as info->exitDrop*(10.0+fabs(last objective))
00026 
00027 djExit - exit a major iteration if largest dj (averaged over 5 checks)
00028 drops below this - used as info->djTolerance*(10.0+fabs(last weighted objective)
00029 
00030 djFlag - mostly skip variables with bad dj worse than this => 2*djExit
00031 
00032 djTol - only look at variables with dj better than this => 0.01*djExit
00033 ****************/
00034 
00035 #define IDIOT_FIX_TOLERANCE 1e-6
00036 #define SMALL_IDIOT_FIX_TOLERANCE 1e-10
00037 int 
00038 Idiot::dropping(IdiotResult result,
00039                     double tolerance,
00040                     double small,
00041                     int *nbad)
00042 {
00043   if (result.infeas<=small) {
00044     double value=max(fabs(result.objval),fabs(result.dropThis))+1.0;
00045     if (result.dropThis>tolerance*value) {
00046       *nbad=0;
00047       return 1;
00048     } else {
00049       (*nbad)++;
00050       if (*nbad>4) {
00051         return 0;
00052       } else {
00053         return 1;
00054       }
00055     }
00056   } else {
00057     *nbad=0;
00058     return 1;
00059   }
00060 }
00061 
00062 /* returns -1 or start of costed slacks */
00063  static int countCostedSlacks(OsiSolverInterface * model)
00064 {
00065 #ifdef OSI_IDIOT
00066   const CoinPackedMatrix * matrix = model->getMatrixByCol();
00067 #else
00068   ClpMatrixBase * matrix = model->clpMatrix();
00069 #endif
00070   const int * row = matrix->getIndices();
00071   const CoinBigIndex * columnStart = matrix->getVectorStarts();
00072   const int * columnLength = matrix->getVectorLengths(); 
00073   const double * element = matrix->getElements();
00074   const double * rowupper = model->getRowUpper();
00075   int nrows=model->getNumRows();
00076   int ncols=model->getNumCols();
00077   int slackStart = ncols-nrows;
00078   int nSlacks=nrows;
00079   int i;
00080   
00081   if (ncols<=nrows) return -1;
00082   while (1) {
00083     for (i=0;i<nrows;i++) {
00084       int j=i+slackStart;
00085       CoinBigIndex k=columnStart[j];
00086       if (columnLength[j]==1) {
00087         if (row[k]!=i||element[k]!=1.0) {
00088           nSlacks=0;
00089           break;
00090         }
00091       } else {
00092         nSlacks=0;
00093         break;
00094       }
00095       if (rowupper[i]<=0.0) {
00096         nSlacks=0;
00097         break;
00098       }
00099     }
00100     if (nSlacks||!slackStart) break;
00101     slackStart=0;
00102   }
00103   if (!nSlacks) slackStart=-1;
00104   return slackStart;
00105 }
00106 void
00107 Idiot::crash(int numberPass, CoinMessageHandler * handler,const CoinMessages *messages)
00108 {
00109   // lightweight options
00110   int numberColumns = model_->getNumCols();
00111   const double * objective = model_->getObjCoefficients();
00112   int nnzero=0;
00113   double sum=0.0;
00114   int i;
00115   for (i=0;i<numberColumns;i++) {
00116     if (objective[i]) {
00117       sum += fabs(objective[i]);
00118       nnzero++;
00119     }
00120   }
00121   sum /= (double) (nnzero+1);
00122   maxIts_=2;
00123   if (numberPass<=0)
00124     // Cast to double to avoid VACPP complaining
00125     majorIterations_=(int)(2+log10((double)(numberColumns+1)));
00126   else
00127     majorIterations_=numberPass;
00128   // If mu not changed then compute
00129   if (mu_==1e-4)
00130     mu_= max(1.0e-3,sum*1.0e-5);
00131   if (!lightWeight_) {
00132     maxIts2_=105;
00133   } else if (lightWeight_==1) {
00134     mu_ *= 1000.0;
00135     maxIts2_=23;
00136   } else if (lightWeight_==2) {
00137     maxIts2_=11;
00138   } else {
00139     maxIts2_=23;
00140   }
00141   //printf("setting mu to %g and doing %d passes\n",mu_,majorIterations_);
00142   solve2(handler,messages);
00143 #ifndef OSI_IDIOT
00144   double averageInfeas = model_->sumPrimalInfeasibilities()/((double) model_->numberRows());
00145   if (averageInfeas<0.01&&(strategy_&512)!=0) 
00146     crossOver(16+1); 
00147   else
00148     crossOver(3);
00149 #endif
00150 }
00151 void
00152 Idiot::solve()
00153 {
00154   CoinMessages dummy;
00155   solve2(NULL,&dummy);
00156 }
00157 void
00158 Idiot::solve2(CoinMessageHandler * handler,const CoinMessages * messages)
00159 {
00160   int strategy=0;
00161   double d2;
00162   int i,n;
00163   int allOnes=1;
00164   int iteration=0;
00165   int iterationTotal=0;
00166   int nTry=0; /* number of tries at same weight */
00167   double fixTolerance=IDIOT_FIX_TOLERANCE;
00168   int maxBigIts=maxBigIts_;
00169   int maxIts=maxIts_;
00170   int logLevel=logLevel_;
00171   int saveMajorIterations = majorIterations_;
00172   if (handler) {
00173     if (handler->logLevel()>0&&handler->logLevel()<3)
00174       logLevel=1;
00175     else if (!handler->logLevel())
00176       logLevel=0;
00177     else
00178       logLevel=7;
00179   }
00180   double djExit=djTolerance_;
00181   double djFlag=1.0+100.0*djExit;
00182   double djTol=0.00001;
00183   double mu =mu_;
00184   double drop=drop_;
00185   int maxIts2=maxIts2_;
00186   double factor=muFactor_;
00187   double smallInfeas=smallInfeas_;
00188   double reasonableInfeas=reasonableInfeas_;
00189   double stopMu=stopMu_;
00190   double maxmin,offset;
00191   double lastWeighted=1.0e50;
00192   double exitDrop=exitDrop_;
00193   double fakeSmall=smallInfeas;
00194   double firstInfeas;
00195   int badIts=0;
00196   int slackStart,slackEnd,ordStart,ordEnd;
00197   int checkIteration=0;
00198   int lambdaIteration=0;
00199   int belowReasonable=0; /* set if ever gone below reasonable infeas */
00200   double bestWeighted=1.0e60;
00201   double bestFeasible=1.0e60; /* best solution while feasible */
00202   IdiotResult result,lastResult;
00203   int saveStrategy=strategy_;
00204   const int strategies[]={0,2,128};
00205   double saveLambdaScale=0.0;
00206   if ((saveStrategy&128)!=0) {
00207     fixTolerance=SMALL_IDIOT_FIX_TOLERANCE;
00208   }
00209 #ifdef OSI_IDIOT
00210   const CoinPackedMatrix * matrix = model_->getMatrixByCol();
00211 #else
00212   ClpMatrixBase * matrix = model_->clpMatrix();
00213 #endif
00214   const int * row = matrix->getIndices();
00215   const CoinBigIndex * columnStart = matrix->getVectorStarts();
00216   const int * columnLength = matrix->getVectorLengths(); 
00217   const double * element = matrix->getElements();
00218   int nrows=model_->getNumRows();
00219   int ncols=model_->getNumCols();
00220   double * rowsol, * colsol;
00221   double * pi, * dj;
00222 #ifndef OSI_IDIOT
00223   double * cost = model_->objective();
00224   double * lower = model_->columnLower();
00225   double * upper = model_->columnUpper();
00226   double * rowlower= model_->rowLower();
00227 #else
00228   double * cost = new double [ncols];
00229   memcpy( cost, model_->getObjCoefficients(), ncols*sizeof(double));
00230   const double * lower = model_->getColLower();
00231   const double * upper = model_->getColUpper();
00232   const double * rowlower= model_->getRowLower();
00233 #endif
00234   const double *elemXX;
00235   double * saveSol;
00236   double * rowupper= new double[nrows]; // not const as modified
00237   memcpy(rowupper,model_->getRowUpper(),nrows*sizeof(double));
00238   int * whenUsed;
00239   double * lambda;
00240   saveSol=new double[ncols];
00241   lambda=new double [nrows];
00242   rowsol= new double[nrows];
00243   colsol= new double [ncols];
00244   memcpy(colsol,model_->getColSolution(),ncols*sizeof(double));
00245   pi= new double[nrows];
00246   dj=new double[ncols];
00247   delete [] whenUsed_;
00248   whenUsed=whenUsed_=new int[ncols];
00249   if (model_->getObjSense()==-1.0) {
00250     maxmin=-1.0;
00251   } else {
00252     maxmin=1.0;
00253   }
00254   model_->getDblParam(OsiObjOffset,offset);
00255   if (!maxIts2) maxIts2=maxIts;
00256   strategy=strategy_;
00257   strategy &= 3;
00258   memset(lambda,0,nrows*sizeof(double));
00259   slackStart=countCostedSlacks(model_);
00260   if (slackStart>=0) {
00261     printf("This model has costed slacks\n");
00262     slackEnd=slackStart+nrows;
00263     if (slackStart) {
00264       ordStart=0;
00265       ordEnd=slackStart;
00266     } else {
00267       ordStart=nrows;
00268       ordEnd=ncols;
00269     }
00270   } else {
00271     slackEnd=slackStart;
00272     ordStart=0;
00273     ordEnd=ncols;
00274   }
00275   if (offset&&logLevel>2) {
00276     printf("** Objective offset is %g\n",offset);
00277   }
00278   /* compute reasonable solution cost */
00279   for (i=0;i<nrows;i++) {
00280     rowsol[i]=1.0e31;
00281   }
00282   for (i=0;i<ncols;i++) {
00283     CoinBigIndex j;
00284     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00285       if (element[j]!=1.0) {
00286         allOnes=0;
00287         break;
00288       }
00289     }
00290   }
00291   if (allOnes) {
00292     elemXX=NULL;
00293   } else {
00294     elemXX=element;
00295   }
00296   // Do scaling if wanted
00297   bool scaled=false;
00298 #ifndef OSI_IDIOT
00299   if ((strategy_&32)!=0&&!allOnes) {
00300     scaled = model_->clpMatrix()->scale(model_)==0;
00301     if (scaled) {
00302       const double * rowScale = model_->rowScale();
00303       const double * columnScale = model_->columnScale();
00304       double * oldLower = lower;
00305       double * oldUpper = upper;
00306       double * oldCost = cost;
00307       lower = new double[ncols];
00308       upper = new double[ncols];
00309       cost = new double[ncols];
00310       memcpy(lower,oldLower,ncols*sizeof(double));
00311       memcpy(upper,oldUpper,ncols*sizeof(double));
00312       memcpy(cost,oldCost,ncols*sizeof(double));
00313       int icol,irow;
00314       for (icol=0;icol<ncols;icol++) {
00315         double multiplier = 1.0/columnScale[icol];
00316         if (lower[icol]>-1.0e50)
00317           lower[icol] *= multiplier;
00318         if (upper[icol]<1.0e50)
00319           upper[icol] *= multiplier;
00320         colsol[icol] *= multiplier;
00321         cost[icol] *= columnScale[icol];
00322       }
00323       rowlower = new double[nrows];
00324       memcpy(rowlower,model_->rowLower(),nrows*sizeof(double));
00325       for (irow=0;irow<nrows;irow++) {
00326         double multiplier = rowScale[irow];
00327         if (rowlower[irow]>-1.0e50)
00328           rowlower[irow] *= multiplier;
00329         if (rowupper[irow]<1.0e50)
00330           rowupper[irow] *= multiplier;
00331         rowsol[irow] *= multiplier;
00332       }
00333       int length = columnStart[ncols-1]+columnLength[ncols-1];
00334       double * elemYY = new double[length];
00335       for (i=0;i<ncols;i++) {
00336         CoinBigIndex j;
00337         double scale = columnScale[i];
00338         for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00339           int irow=row[j];
00340           elemYY[j] = element[j]*scale*rowScale[irow];
00341         }
00342       }
00343       elemXX=elemYY;
00344     }
00345   }
00346 #endif
00347   for (i=0;i<ncols;i++) {
00348     CoinBigIndex j;
00349     double dd=columnLength[i];
00350     dd=cost[i]/dd;
00351     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00352       int irow=row[j];
00353       if (dd<rowsol[irow]) {
00354         rowsol[irow]=dd;
00355       }
00356     }
00357   }
00358   d2=0.0;
00359   for (i=0;i<nrows;i++) {
00360     d2+=rowsol[i];
00361   }
00362   d2*=2.0; /* for luck */
00363   
00364   d2=d2/((double) (4*nrows+8000));
00365   d2*=0.5; /* halve with more flexible method */
00366   if (d2<5.0) d2=5.0;
00367   if (djExit==0.0) {
00368     djExit=d2;
00369   }
00370   if ((saveStrategy&4)!=0) {
00371     /* go to relative tolerances - first small */
00372     djExit=1.0e-10;
00373     djFlag=1.0e-5;
00374     drop=1.0e-10;
00375   }
00376   memset(whenUsed,0,ncols*sizeof(int));
00377   strategy=strategies[strategy];
00378   if ((saveStrategy&8)!=0) strategy |= 64; /* don't allow large theta */
00379   memcpy(saveSol,colsol,ncols*sizeof(double));
00380   
00381   lastResult=IdiSolve(nrows,ncols,rowsol ,colsol,pi,
00382                        dj,cost,rowlower,rowupper,
00383                        lower,upper,elemXX,row,columnStart,columnLength,lambda,
00384                        0,mu,drop,
00385                        maxmin,offset,strategy,djTol,djExit,djFlag);
00386   n=0;
00387   for (i=ordStart;i<ordEnd;i++) {
00388     if (colsol[i]>lower[i]+fixTolerance) {
00389       if (colsol[i]<upper[i]-fixTolerance) {
00390         n++;
00391       } else {
00392         colsol[i]=upper[i];
00393       }
00394       whenUsed[i]=iteration;
00395     } else {
00396       colsol[i]=lower[i];
00397     }
00398   }
00399   if ((logLevel_&1)!=0) {
00400 #ifndef OSI_IDIOT
00401     if (!handler) {
00402 #endif
00403       printf("Iteration %d infeasibility %g, objective %g - mu %g, its %d, %d interior\n", 
00404              iteration,lastResult.infeas,lastResult.objval,mu,lastResult.iteration,n);
00405 #ifndef OSI_IDIOT
00406     } else {
00407       handler->message(CLP_IDIOT_ITERATION,*messages)
00408         <<iteration<<lastResult.infeas<<lastResult.objval<<mu<<lastResult.iteration<<n
00409         <<CoinMessageEol;
00410     }
00411 #endif
00412   }
00413   int numberAway=-1;
00414   iterationTotal = lastResult.iteration;
00415   firstInfeas=lastResult.infeas;
00416   if ((strategy_&1024)!=0) reasonableInfeas=0.5*firstInfeas;
00417   if (lastResult.infeas<reasonableInfeas) lastResult.infeas=reasonableInfeas;
00418   double keepinfeas=1.0e31;
00419   double lastInfeas=1.0e31;
00420   double bestInfeas=1.0e31;
00421   while ((mu>stopMu&&lastResult.infeas>smallInfeas)||
00422          (lastResult.infeas<=smallInfeas&&
00423          dropping(lastResult,exitDrop,smallInfeas,&badIts))||
00424          checkIteration<2||lambdaIteration<lambdaIterations_) {
00425     if (lastResult.infeas<=exitFeasibility_)
00426       break; 
00427     iteration++;
00428     checkIteration++;
00429     if (lastResult.infeas<=smallInfeas&&lastResult.objval<bestFeasible) {
00430       bestFeasible=lastResult.objval;
00431     }
00432     if ((saveStrategy&4096)) strategy |=256;
00433     if ((saveStrategy&4)!=0&&iteration>2) {
00434       /* go to relative tolerances */
00435       double weighted=10.0+fabs(lastWeighted);
00436       djExit=djTolerance_*weighted;
00437       djFlag=2.0*djExit;
00438       drop=drop_*weighted;
00439       djTol=0.01*djExit;
00440     }
00441     result=IdiSolve(nrows,ncols,rowsol ,colsol,pi,dj,
00442                      cost,rowlower,rowupper,
00443                      lower,upper,elemXX,row,columnStart,columnLength,lambda,
00444                      maxIts,mu,drop,
00445                      maxmin,offset,strategy,djTol,djExit,djFlag);
00446     n=0;
00447     for (i=ordStart;i<ordEnd;i++) {
00448       if (colsol[i]>lower[i]+fixTolerance) {
00449         if (colsol[i]<upper[i]-fixTolerance) {
00450           n++;
00451         } else {
00452           colsol[i]=upper[i];
00453         }
00454         whenUsed[i]=iteration;
00455       } else {
00456         colsol[i]=lower[i];
00457       }
00458     }
00459     if ((logLevel_&1)!=0) {
00460 #ifndef OSI_IDIOT
00461       if (!handler) {
00462 #endif
00463         printf("Iteration %d infeasibility %g, objective %g - mu %g, its %d, %d interior\n", 
00464                iteration,result.infeas,result.objval,mu,result.iteration,n);
00465 #ifndef OSI_IDIOT
00466       } else {
00467         handler->message(CLP_IDIOT_ITERATION,*messages)
00468           <<iteration<<result.infeas<<result.objval<<mu<<result.iteration<<n
00469           <<CoinMessageEol;
00470       }
00471 #endif
00472     }
00473     if (iteration>50&&n==numberAway&&result.infeas<1.0e-4)
00474       break; // not much happening
00475     if (lightWeight_==1&&iteration>10&&result.infeas>1.0&&maxIts!=7) {
00476       if (lastInfeas!=bestInfeas&&min(result.infeas,lastInfeas)>0.95*bestInfeas)
00477         majorIterations_ = min(majorIterations_,iteration); // not getting feasible
00478     }
00479     bestInfeas=min(bestInfeas,result.infeas);
00480     lastInfeas = result.infeas;
00481     numberAway=n;
00482     keepinfeas = result.infeas;
00483     lastWeighted=result.weighted;
00484     iterationTotal += result.iteration;
00485     if (iteration==1) {
00486       if ((strategy_&1024)!=0&&mu<1.0e-10) 
00487         result.infeas=firstInfeas*0.8;
00488       if (result.infeas>firstInfeas*0.9
00489           &&result.infeas>reasonableInfeas) {
00490         iteration--;
00491         memcpy(colsol,saveSol,ncols*sizeof(double));
00492         if (majorIterations_<50)
00493           mu*=1.0e-1;
00494         else
00495           mu*=0.7;
00496         bestFeasible=1.0e31;
00497         bestWeighted=1.0e60;
00498         if (mu<1.0e-30) break;
00499       } else {
00500         delete [] saveSol;
00501         saveSol=0;
00502         maxIts=maxIts2;
00503         checkIteration=0;
00504         if ((strategy_&1024)!=0) mu *= 1.0e-1;
00505       }
00506     }
00507     if (iteration) {
00508       /* this code is in to force it to terminate sometime */
00509       double changeMu=factor;
00510       if ((saveStrategy&64)!=0) {
00511         keepinfeas=0.0; /* switch off ranga's increase */
00512         fakeSmall=smallInfeas;
00513       } else {
00514         fakeSmall=-1.0;
00515       }
00516       saveLambdaScale=0.0;
00517       if (result.infeas>reasonableInfeas||
00518           (nTry+1==maxBigIts&&result.infeas>fakeSmall)) {
00519         if (result.infeas>lastResult.infeas*(1.0-dropEnoughFeasibility_)||
00520             nTry+1==maxBigIts||
00521             (result.infeas>lastResult.infeas*0.9
00522              &&result.weighted>lastResult.weighted
00523              -dropEnoughWeighted_*fabs(lastResult.weighted))) {
00524           mu*=changeMu;
00525           if ((saveStrategy&32)!=0&&result.infeas<reasonableInfeas&&0) {
00526             reasonableInfeas=max(smallInfeas,reasonableInfeas*sqrt(changeMu));
00527             printf("reasonable infeas now %g\n",reasonableInfeas);
00528           }
00529           nTry=0;
00530           bestFeasible=1.0e31;
00531           bestWeighted=1.0e60;
00532           checkIteration=0;
00533           lambdaIteration=0;
00534 #define LAMBDA
00535 #ifdef LAMBDA
00536           if ((saveStrategy&2048)==0) {
00537             memset(lambda,0,nrows*sizeof(double));
00538           }
00539 #else
00540           memset(lambda,0,nrows*sizeof(double));
00541 #endif
00542         } else {
00543           nTry++;
00544         }
00545       } else if (lambdaIterations_>=0) {
00546         /* update lambda  */
00547         double scale=1.0/mu;
00548         int i,nnz=0;
00549         saveLambdaScale=scale;
00550          lambdaIteration++;
00551          if ((saveStrategy&4)==0) drop = drop_/50.0;
00552          if (lambdaIteration>4 && 
00553             (((lambdaIteration%10)==0 && smallInfeas<keepinfeas) ||
00554              (lambdaIteration%5)==0 && 1.5*smallInfeas<keepinfeas)) {
00555            //printf(" Increasing smallInfeas from %f to %f\n",smallInfeas,1.5*smallInfeas);
00556            smallInfeas *= 1.5;
00557          }
00558          if ((saveStrategy&2048)==0) {
00559            for (i=0;i<nrows;i++) {
00560              if (lambda[i]) nnz++;
00561              lambda[i]+= scale*rowsol[i];
00562            }
00563          } else {
00564            nnz=1;
00565 #ifdef LAMBDA
00566            for (i=0;i<nrows;i++) {
00567              lambda[i]+= scale*rowsol[i];
00568            }
00569 #else
00570            for (i=0;i<nrows;i++) {
00571              lambda[i] = scale*rowsol[i];
00572            }
00573            for (i=0;i<ncols;i++) {
00574              CoinBigIndex j;
00575              double value=cost[i]*maxmin;
00576              for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00577                int irow=row[j];
00578                value+=element[j]*lambda[irow];
00579              }
00580              cost[i]=value*maxmin;
00581            }
00582            for (i=0;i<nrows;i++) {
00583              offset+=lambda[i]*rowupper[i];
00584              lambda[i]=0.0;
00585            }
00586 #ifdef DEBUG
00587            printf("offset %g\n",offset);
00588 #endif
00589            model_->setDblParam(OsiObjOffset,offset);
00590 #endif
00591          }
00592         nTry++;
00593         if (!nnz) {
00594           bestFeasible=1.0e32;
00595           bestWeighted=1.0e60;
00596           checkIteration=0;
00597           result.weighted=1.0e31;
00598         }
00599 #ifdef DEBUG
00600         for (i=0;i<ncols;i++) {
00601           int j;
00602           trueCost+=cost[i]*colsol[i];
00603         }
00604         printf("True objective %g\n",trueCost-offset);
00605 #endif
00606       } else {
00607         nTry++;
00608       }
00609       lastResult=result;
00610       if (result.infeas<reasonableInfeas&&!belowReasonable) {
00611         belowReasonable=1;
00612         bestFeasible=1.0e32;
00613         bestWeighted=1.0e60;
00614         checkIteration=0;
00615         result.weighted=1.0e31;
00616       }
00617     }
00618     if (iteration>=majorIterations_) {
00619       // If small and not feasible and crash then dive dive dive
00620       if (0&&result.infeas>1.0&&majorIterations_<30&&(maxIts2_==11||maxIts2_==23)) {
00621         maxIts=7;
00622         majorIterations_=100;
00623       } else {
00624         if (logLevel>2) 
00625           printf("Exiting due to number of major iterations\n");
00626         break;
00627       }
00628     }
00629   }
00630   majorIterations_ = saveMajorIterations;
00631 #ifndef OSI_IDIOT
00632   if (scaled) {
00633     // Scale solution and free arrays
00634     const double * rowScale = model_->rowScale();
00635     const double * columnScale = model_->columnScale();
00636     int icol,irow;
00637     for (icol=0;icol<ncols;icol++) {
00638       colsol[icol] *= columnScale[icol];
00639       dj[icol] /= columnScale[icol];
00640     }
00641     for (irow=0;irow<nrows;irow++) {
00642       rowsol[irow] /= rowScale[irow];
00643       pi[irow] *= rowScale[irow];
00644     }
00645     // Don't know why getting Microsoft problems
00646 #if defined (_MSC_VER)
00647     delete [] ( double *)rowScale;
00648     delete [] ( double *) columnScale;
00649     delete [] ( double *) elemXX;
00650 #else
00651     delete [] rowScale;
00652     delete [] columnScale;
00653     delete [] elemXX;
00654 #endif
00655     model_->setRowScale(NULL);
00656     model_->setColumnScale(NULL);
00657     delete [] lower;
00658     delete [] upper;
00659     delete [] cost;
00660     lower = model_->columnLower();
00661     upper = model_->columnUpper();
00662     cost = model_->objective();
00663     rowlower = model_->rowLower();
00664   }
00665 #endif
00666 #define TRYTHIS
00667 #ifdef TRYTHIS
00668   if ((saveStrategy&2048)!=0) {
00669     double offset;
00670     model_->getDblParam(OsiObjOffset,offset);
00671     for (i=0;i<ncols;i++) {
00672       CoinBigIndex j;
00673       double djval=cost[i]*maxmin;
00674       for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00675         int irow=row[j];
00676         djval -= element[j]*lambda[irow];
00677       }
00678       cost[i]=djval;
00679     }
00680     for (i=0;i<nrows;i++) {
00681       offset+=lambda[i]*rowupper[i];
00682     }
00683     model_->setDblParam(OsiObjOffset,offset);
00684   }
00685 #endif
00686   if (saveLambdaScale) {
00687     /* back off last update */
00688     for (i=0;i<nrows;i++) {
00689       lambda[i]-= saveLambdaScale*rowsol[i];
00690     }
00691   }
00692   muAtExit_=mu;
00693   n=0;
00694   for (i=ordStart;i<ordEnd;i++) {
00695     if (colsol[i]>lower[i]+fixTolerance) {
00696       n++;
00697       whenUsed[i]=iteration;
00698     } else {
00699       colsol[i]=lower[i];
00700     }
00701   }
00702   if ((logLevel&1)==0) {
00703     printf(
00704             "%d - mu %g, infeasibility %g, objective %g, %d interior\n",
00705             iteration,mu,lastResult.infeas,lastResult.objval,n);
00706   }
00707 #ifndef OSI_IDIOT
00708   model_->setSumPrimalInfeasibilities(lastResult.infeas);
00709 #endif
00710   {
00711     double large=0.0;
00712     int i;
00713     memset(rowsol,0,nrows*sizeof(double));
00714     for (i=0;i<ncols;i++) {
00715       CoinBigIndex j;
00716       double value=colsol[i];
00717       for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00718         int irow=row[j];
00719         rowsol[irow] += element[j]*value;
00720       }
00721     }
00722     for (i=0;i<nrows;i++) {
00723       if (rowsol[i] > rowupper[i]) {
00724         double diff=rowsol[i]-rowupper[i];
00725         if (diff>large) 
00726           large=diff;
00727       } else if (rowsol[i] < rowlower[i]) {
00728         double diff=rowlower[i]-rowsol[i];
00729         if (diff>large) 
00730           large=diff;
00731       } 
00732     }
00733     if (logLevel>2)
00734       printf("largest infeasibility is %g\n",large);
00735   }
00736   /* subtract out lambda */
00737   for (i=0;i<nrows;i++) {
00738     pi[i]-=lambda[i];
00739   }
00740   for (i=0;i<ncols;i++) {
00741     CoinBigIndex j;
00742     double djval=cost[i]*maxmin;
00743     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00744       int irow=row[j];
00745       djval -= element[j]*pi[irow];
00746     }
00747     dj[i]=djval;
00748   }
00749   if ((strategy_&1024)!=0) {
00750     double ratio = ((double) ncols)/((double) nrows);
00751     printf("col/row ratio %g infeas ratio %g\n",ratio,lastResult.infeas/firstInfeas);
00752     if (lastResult.infeas>0.01*firstInfeas*ratio) {
00753       strategy_ &= (~1024);
00754       printf(" - layer off\n");
00755     } else {
00756       printf(" - layer on\n");
00757     }
00758   }
00759   delete [] saveSol;
00760   delete [] lambda;
00761   // save solution 
00762   // duals not much use - but save anyway
00763 #ifndef OSI_IDIOT
00764   memcpy(model_->primalRowSolution(),rowsol,nrows*sizeof(double));
00765   memcpy(model_->primalColumnSolution(),colsol,ncols*sizeof(double));
00766   memcpy(model_->dualRowSolution(),pi,nrows*sizeof(double));
00767   memcpy(model_->dualColumnSolution(),dj,ncols*sizeof(double));
00768 #else
00769   model_->setColSolution(colsol);
00770   model_->setRowPrice(pi);
00771   delete [] cost;
00772 #endif
00773   delete [] rowsol;
00774   delete [] colsol;
00775   delete [] pi;
00776   delete [] dj;
00777   return ;
00778 }
00779 #ifndef OSI_IDIOT
00780 void
00781 Idiot::crossOver(int mode)
00782 {
00783   double fixTolerance=IDIOT_FIX_TOLERANCE;
00784   double startTime = CoinCpuTime();
00785   ClpSimplex * saveModel=NULL;
00786   ClpMatrixBase * matrix = model_->clpMatrix();
00787   const int * row = matrix->getIndices();
00788   const CoinBigIndex * columnStart = matrix->getVectorStarts();
00789   const int * columnLength = matrix->getVectorLengths(); 
00790   const double * element = matrix->getElements();
00791   const double * rowupper = model_->getRowUpper();
00792   int nrows=model_->getNumRows();
00793   int ncols=model_->getNumCols();
00794   double * rowsol, * colsol;
00795   // different for Osi
00796   double * lower = model_->columnLower();
00797   double * upper = model_->columnUpper();
00798   const double * rowlower= model_->getRowLower();
00799   int * whenUsed=whenUsed_;
00800   rowsol= model_->primalRowSolution();
00801   colsol= model_->primalColumnSolution();;
00802   double * cost=model_->objective();
00803 
00804   int slackEnd,ordStart,ordEnd;
00805   int slackStart = countCostedSlacks(model_);
00806 
00807   int addAll = mode&7;
00808   int presolve=0;
00809 
00810   double djTolerance = djTolerance_;
00811   if (djTolerance>0.0&&djTolerance<1.0)
00812     djTolerance=1.0;
00813   int iteration;
00814   int i, n=0;
00815   double ratio=1.0;
00816   double objValue=0.0;
00817   if ((strategy_&128)!=0) {
00818     fixTolerance=SMALL_IDIOT_FIX_TOLERANCE;
00819   }
00820   if ((mode&16)!=0&&addAll<3) presolve=1;
00821   double * saveUpper = NULL;
00822   double * saveLower = NULL;
00823   if (addAll<3) {
00824     saveUpper = new double [ncols];
00825     saveLower = new double [ncols];
00826     memcpy(saveUpper,upper,ncols*sizeof(double));
00827     memcpy(saveLower,lower,ncols*sizeof(double));
00828   }
00829   if (slackStart>=0) {
00830     slackEnd=slackStart+nrows;
00831     if (slackStart) {
00832       ordStart=0;
00833       ordEnd=slackStart;
00834     } else {
00835       ordStart=nrows;
00836       ordEnd=ncols;
00837     }
00838   } else {
00839     slackEnd=slackStart;
00840     ordStart=0;
00841     ordEnd=ncols;
00842   }
00843   /* get correct rowsol (without known slacks) */
00844   memset(rowsol,0,nrows*sizeof(double));
00845   for (i=ordStart;i<ordEnd;i++) {
00846     CoinBigIndex j;
00847     double value=colsol[i];
00848     if (value<lower[i]+fixTolerance) {
00849       value=lower[i];
00850       colsol[i]=value;
00851     }
00852     for (j=columnStart[i];j<columnStart[i]+columnLength[i];j++) {
00853       int irow=row[j];
00854       rowsol[irow]+=value*element[j];
00855     }
00856   }
00857   if (slackStart>=0) {
00858     for (i=0;i<nrows;i++) {
00859       if (ratio*rowsol[i]>rowlower[i]&&rowsol[i]>1.0e-8) {
00860         ratio=rowlower[i]/rowsol[i];
00861       }
00862     }
00863     for (i=0;i<nrows;i++) {
00864       rowsol[i]*=ratio;
00865     }
00866     for (i=ordStart;i<ordEnd;i++) {
00867       double value=colsol[i]*ratio;
00868       colsol[i]=value;
00869       objValue+=value*cost[i];
00870     }
00871     for (i=0;i<nrows;i++) {
00872       double value=rowlower[i]-rowsol[i];
00873       colsol[i+slackStart]=value;
00874       objValue+=value*cost[i+slackStart];
00875     }
00876     printf("New objective after scaling %g\n",objValue);
00877   }
00878 #if 0
00879    maybe put back - but just get feasible ?
00880   // If not many fixed then just exit
00881   int numberFixed=0;
00882   for (i=ordStart;i<ordEnd;i++) {
00883     if (colsol[i]<lower[i]+fixTolerance) 
00884       numberFixed++;
00885     else if (colsol[i]>upper[i]-fixTolerance) 
00886       numberFixed++;
00887   }
00888   if (numberFixed<ncols/2) {
00889     addAll=3;
00890     presolve=0;
00891   }
00892 #endif
00893   model_->createStatus();
00894   /* addAll
00895      0 - chosen,all used, all 
00896      1 - chosen, all
00897      2 - all
00898      3 - do not do anything  - maybe basis
00899   */
00900   for (i=ordStart;i<ordEnd;i++) {
00901     if (addAll<2) {
00902       if (colsol[i]<lower[i]+fixTolerance) {
00903         upper[i]=lower[i];
00904         colsol[i]=lower[i];
00905       } else if (colsol[i]>upper[i]-fixTolerance) {
00906         lower[i]=upper[i];
00907         colsol[i]=upper[i];
00908       }
00909     }
00910     model_->setColumnStatus(i,ClpSimplex::superBasic);
00911   }
00912   double maxmin;
00913   if (model_->getObjSense()==-1.0) {
00914     maxmin=-1.0;
00915   } else {
00916     maxmin=1.0;
00917   }
00918   if (slackStart>=0) {
00919     for (i=0;i<nrows;i++) {
00920       model_->setRowStatus(i,ClpSimplex::superBasic);
00921     }
00922     for (i=slackStart;i<slackEnd;i++) {
00923       model_->setColumnStatus(i,ClpSimplex::basic);
00924     }
00925   } else {
00926     /* still try and put singletons rather than artificials in basis */
00927     int ninbas=0;
00928     for (i=0;i<nrows;i++) {
00929       model_->setRowStatus(i,ClpSimplex::basic);
00930     }
00931     for (i=0;i<ncols;i++) {
00932       if (columnLength[i]==1&&upper[i]>lower[i]+1.0e-5) {
00933         CoinBigIndex j =columnStart[i];
00934         double value=element[j];
00935         int irow=row[j];
00936         double rlo=rowlower[irow];
00937         double rup=rowupper[irow];
00938         double clo=lower[i];
00939         double cup=upper[i];
00940         double csol=colsol[i];
00941         /* adjust towards feasibility */
00942         double move=0.0;
00943         if (rowsol[irow]>rup) {
00944           move=(rup-rowsol[irow])/value;
00945           if (value>0.0) {
00946             /* reduce */
00947             if (csol+move<clo) move=min(0.0,clo-csol);
00948           } else {
00949             /* increase */
00950             if (csol+move>cup) move=max(0.0,cup-csol);
00951           }
00952         } else if (rowsol[irow]<rlo) {
00953           move=(rlo-rowsol[irow])/value;
00954           if (value>0.0) {
00955             /* increase */
00956             if (csol+move>cup) move=max(0.0,cup-csol);
00957           } else {
00958             /* reduce */
00959             if (csol+move<clo) move=min(0.0,clo-csol);
00960           }
00961         } else {
00962           /* move to improve objective */
00963           if (cost[i]*maxmin>0.0) {
00964             if (value>0.0) {
00965               move=(rlo-rowsol[irow])/value;
00966               /* reduce */
00967               if (csol+move<clo) move=min(0.0,clo-csol);
00968             } else {
00969               move=(rup-rowsol[irow])/value;
00970               /* increase */
00971               if (csol+move>cup) move=max(0.0,cup-csol);
00972             }
00973           } else if (cost[i]*maxmin<0.0) {
00974             if (value>0.0) {
00975               move=(rup-rowsol[irow])/value;
00976               /* increase */
00977               if (csol+move>cup) move=max(0.0,cup-csol);
00978             } else {
00979               move=(rlo-rowsol[irow])/value;
00980               /* reduce */
00981               if (csol+move<clo) move=min(0.0,clo-csol);
00982             }
00983           }
00984         }
00985         rowsol[irow] +=move*value;
00986         colsol[i]+=move;
00987         /* put in basis if row was artificial */
00988         if (rup-rlo<1.0e-7&&model_->getRowStatus(irow)==ClpSimplex::basic) {
00989           model_->setRowStatus(irow,ClpSimplex::superBasic);
00990           model_->setColumnStatus(i,ClpSimplex::basic);
00991           ninbas++;
00992         }
00993       }
00994     }
00995     /*printf("%d in basis\n",ninbas);*/
00996   }
00997   if (addAll<3) {
00998     ClpPresolve pinfo;
00999     if (presolve) {
01000       saveModel = model_;
01001       model_ = pinfo.presolvedModel(*model_,1.0e-8,false,5);
01002     }
01003     if (model_) {
01004       model_->primal(1);
01005       if (presolve) {
01006         pinfo.postsolve(true);
01007         delete model_;
01008         model_ = saveModel;
01009         saveModel=NULL;
01010       }
01011     } else {
01012       // not feasible
01013       addAll=1;
01014       presolve=0;
01015       model_ = saveModel;
01016       saveModel=NULL;
01017     }
01018     if (addAll<2) {
01019       n=0;
01020       if (!addAll ) {
01021         /* could do scans to get a good number */
01022         iteration=1;
01023         for (i=ordStart;i<ordEnd;i++) {
01024           if (whenUsed[i]>=iteration) {
01025             if (upper[i]-lower[i]<1.0e-5&&saveUpper[i]-saveLower[i]>1.0e-5) {
01026               n++;
01027               upper[i]=saveUpper[i];
01028               lower[i]=saveLower[i];
01029             }
01030           }
01031         }
01032       } else {
01033         for (i=ordStart;i<ordEnd;i++) {
01034           if (upper[i]-lower[i]<1.0e-5&&saveUpper[i]-saveLower[i]>1.0e-5) {
01035             n++;
01036             upper[i]=saveUpper[i];
01037             lower[i]=saveLower[i];
01038           }
01039         }
01040       }
01041       printf("Time so far %g, %d now added from previous iterations\n",
01042              CoinCpuTime()-startTime,n);
01043       if (addAll)
01044         presolve=0;
01045       if (presolve) {
01046         saveModel = model_;
01047         model_ = pinfo.presolvedModel(*model_,1.0e-8,false,5);
01048       } else {
01049         presolve=0;
01050       }
01051       model_->primal(1);
01052       if (presolve) {
01053         pinfo.postsolve(true);
01054         delete model_;
01055         model_ = saveModel;
01056         saveModel=NULL;
01057       }
01058       if (!addAll) {
01059         n=0;
01060         for (i=ordStart;i<ordEnd;i++) {
01061           if (upper[i]-lower[i]<1.0e-5&&saveUpper[i]-saveLower[i]>1.0e-5) {
01062             n++;
01063             upper[i]=saveUpper[i];
01064             lower[i]=saveLower[i];
01065           }
01066         }
01067         printf("Time so far %g, %d now added from previous iterations\n",
01068                CoinCpuTime()-startTime,n);
01069       }
01070       if (presolve) {
01071         saveModel = model_;
01072         model_ = pinfo.presolvedModel(*model_,1.0e-8,false,5);
01073       } else {
01074         presolve=0;
01075       }
01076       model_->primal(1);
01077       if (presolve) {
01078         pinfo.postsolve(true);
01079         delete model_;
01080         model_ = saveModel;
01081         saveModel=NULL;
01082       }
01083     }
01084     printf("Total time in crossover %g\n", CoinCpuTime()-startTime);
01085     delete [] saveUpper;
01086     delete [] saveLower;
01087   }
01088   return ;
01089 }
01090 #endif
01091 /*****************************************************************************/
01092 
01093 // Default contructor
01094 Idiot::Idiot()
01095 {
01096   model_ = NULL;
01097   maxBigIts_ = 3;
01098   maxIts_ = 5;
01099   logLevel_ = 1; 
01100   logFreq_ = 100;
01101   maxIts2_ = 100;
01102   djTolerance_ = 1e-1;
01103   mu_ = 1e-4;
01104   drop_ = 5.0;
01105   exitDrop_=-1.0e20;
01106   muFactor_ = 0.3333;
01107   stopMu_ = 1e-12;
01108   smallInfeas_ = 1e-1;
01109   reasonableInfeas_ = 1e2;
01110   muAtExit_ =1.0e31;
01111   strategy_ =8;
01112   lambdaIterations_ =0;
01113   checkFrequency_ =100;
01114   whenUsed_ = NULL;
01115   majorIterations_ =30;
01116   exitFeasibility_ =-1.0;
01117   dropEnoughFeasibility_ =0.02;
01118   dropEnoughWeighted_ =0.01;
01119   // adjust
01120   double nrows=10000.0;
01121   int baseIts =(int) sqrt((double)nrows);
01122   baseIts =baseIts/10;
01123   baseIts *= 10;
01124   maxIts2_ =200+baseIts+5;
01125   reasonableInfeas_ =((double) nrows)*0.05;
01126   lightWeight_=0;
01127 }
01128 // Constructor from model
01129 Idiot::Idiot(OsiSolverInterface &model)
01130 {
01131   model_ = & model;
01132   maxBigIts_ = 3;
01133   maxIts_ = 5;
01134   logLevel_ = 1; 
01135   logFreq_ = 100;
01136   maxIts2_ = 100;
01137   djTolerance_ = 1e-1;
01138   mu_ = 1e-4;
01139   drop_ = 5.0;
01140   exitDrop_=-1.0e20;
01141   muFactor_ = 0.3333;
01142   stopMu_ = 1e-12;
01143   smallInfeas_ = 1e-1;
01144   reasonableInfeas_ = 1e2;
01145   muAtExit_ =1.0e31;
01146   strategy_ =8;
01147   lambdaIterations_ =0;
01148   checkFrequency_ =100;
01149   whenUsed_ = NULL;
01150   majorIterations_ =30;
01151   exitFeasibility_ =-1.0;
01152   dropEnoughFeasibility_ =0.02;
01153   dropEnoughWeighted_ =0.01;
01154   // adjust
01155   double nrows;
01156   if (model_)
01157     nrows=model_->getNumRows();
01158   else
01159     nrows=10000.0;
01160   int baseIts =(int) sqrt((double)nrows);
01161   baseIts =baseIts/10;
01162   baseIts *= 10;
01163   maxIts2_ =200+baseIts+5;
01164   reasonableInfeas_ =((double) nrows)*0.05;
01165   lightWeight_=0;
01166 }
01167 // Copy constructor. 
01168 Idiot::Idiot(const Idiot &rhs)
01169 {
01170   model_ = rhs.model_;
01171   if (model_&&rhs.whenUsed_) {
01172     int numberColumns = model_->getNumCols();
01173     whenUsed_ = new int [numberColumns];
01174     memcpy(whenUsed_,rhs.whenUsed_,numberColumns*sizeof(int));
01175   } else {
01176     whenUsed_=NULL;
01177   }
01178   djTolerance_ = rhs.djTolerance_;
01179   mu_ = rhs.mu_;
01180   drop_ = rhs.drop_;
01181   muFactor_ = rhs.muFactor_;
01182   stopMu_ = rhs.stopMu_;
01183   smallInfeas_ = rhs.smallInfeas_;
01184   reasonableInfeas_ = rhs.reasonableInfeas_;
01185   exitDrop_ = rhs.exitDrop_;
01186   muAtExit_ = rhs.muAtExit_;
01187   exitFeasibility_ = rhs.exitFeasibility_;
01188   dropEnoughFeasibility_ = rhs.dropEnoughFeasibility_;
01189   dropEnoughWeighted_ = rhs.dropEnoughWeighted_;
01190   maxBigIts_ = rhs.maxBigIts_;
01191   maxIts_ = rhs.maxIts_;
01192   majorIterations_ = rhs.majorIterations_;
01193   logLevel_ = rhs.logLevel_;
01194   logFreq_ = rhs.logFreq_;
01195   checkFrequency_ = rhs.checkFrequency_;
01196   lambdaIterations_ = rhs.lambdaIterations_;
01197   maxIts2_ = rhs.maxIts2_;
01198   strategy_ = rhs.strategy_;
01199   lightWeight_=rhs.lightWeight_;
01200 }
01201 // Assignment operator. This copies the data
01202 Idiot & 
01203 Idiot::operator=(const Idiot & rhs)
01204 {
01205   if (this != &rhs) {
01206     delete [] whenUsed_;
01207     model_ = rhs.model_;
01208     if (model_&&rhs.whenUsed_) {
01209       int numberColumns = model_->getNumCols();
01210       whenUsed_ = new int [numberColumns];
01211       memcpy(whenUsed_,rhs.whenUsed_,numberColumns*sizeof(int));
01212     } else {
01213       whenUsed_=NULL;
01214     }
01215     djTolerance_ = rhs.djTolerance_;
01216     mu_ = rhs.mu_;
01217     drop_ = rhs.drop_;
01218     muFactor_ = rhs.muFactor_;
01219     stopMu_ = rhs.stopMu_;
01220     smallInfeas_ = rhs.smallInfeas_;
01221     reasonableInfeas_ = rhs.reasonableInfeas_;
01222     exitDrop_ = rhs.exitDrop_;
01223     muAtExit_ = rhs.muAtExit_;
01224     exitFeasibility_ = rhs.exitFeasibility_;
01225     dropEnoughFeasibility_ = rhs.dropEnoughFeasibility_;
01226     dropEnoughWeighted_ = rhs.dropEnoughWeighted_;
01227     maxBigIts_ = rhs.maxBigIts_;
01228     maxIts_ = rhs.maxIts_;
01229     majorIterations_ = rhs.majorIterations_;
01230     logLevel_ = rhs.logLevel_;
01231     logFreq_ = rhs.logFreq_;
01232     checkFrequency_ = rhs.checkFrequency_;
01233     lambdaIterations_ = rhs.lambdaIterations_;
01234     maxIts2_ = rhs.maxIts2_;
01235     strategy_ = rhs.strategy_;
01236     lightWeight_=rhs.lightWeight_;
01237   }
01238   return *this;
01239 }
01240 Idiot::~Idiot()
01241 {
01242   delete [] whenUsed_;
01243 }

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