Changeset 2373 for trunk


Ignore:
Timestamp:
May 18, 2018 5:45:54 AM (14 months ago)
Author:
forrest
Message:

allow cleaning of small sos variables

Location:
trunk/Cbc/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Cbc/src/CbcModel.cpp

    r2371 r2373  
    53615361        setBestSolution(CBC_END_SOLUTION, bestObjective_, bestSolution_, 1) ;
    53625362        continuousSolver_->resolve() ;
     5363        // Deal with funny variables
     5364        if ((moreSpecialOptions2_&32768)!=0)
     5365          cleanBounds(continuousSolver_,NULL);
    53635366        if (!continuousSolver_->isProvenOptimal()) {
    53645367            continuousSolver_->messageHandler()->setLogLevel(2) ;
     
    1259212595            }
    1259312596#endif
    12594             return objectiveValue;
     12597            return 1.0e50;
    1259512598          }
    1259612599        }
     
    1527515278#endif
    1527615279#ifdef COIN_HAS_CLP
     15280            // Deal with funny variables
     15281            if ((moreSpecialOptions2_&32768)!=0)
     15282              cleanBounds(solver_,NULL);
    1527715283            int save=0;
    1527815284            OsiClpSolverInterface * clpSolver
     
    1969319699#endif
    1969419700}
    19695 
     19701/*
     19702  Clean model i.e. make SOS/integer variables exactly at bound if needed
     19703  Only if moreSpecialOptions2_ 32768
     19704  Returns number of variables forced out
     19705  cleanVariables array will be used if exists
     19706*/
     19707int
     19708CbcModel::cleanBounds(OsiSolverInterface * solver, char * cleanIn)
     19709{
     19710  int numberBad=0;
     19711# ifdef COIN_HAS_CLP
     19712#ifndef ZERO_ODD_TOLERANCE
     19713#define ZERO_ODD_TOLERANCE 1.0e-14
     19714#endif
     19715  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
     19716  if (osiclp&&osiclp->isProvenOptimal()) {
     19717    int numberColumns = osiclp->getNumCols();
     19718    char * cleanVariables;
     19719    if (!cleanIn) {
     19720      cleanVariables = setupCleanVariables();
     19721    } else {
     19722      cleanVariables = cleanIn;
     19723    }
     19724    // If any small values re-do
     19725    ClpSimplex * clp = osiclp->getModelPtr();
     19726    double * solution = clp->primalColumnSolution();
     19727    const double * columnLower = clp->columnLower();
     19728    const double * columnUpper = clp->columnUpper();
     19729    //#define SHOW_BAD
     19730#ifdef SHOW_BAD
     19731    double sumBadLow=0.0;
     19732    double sumBadHigh=0.0;
     19733    double maxBadLow=0.0;
     19734    double maxBadHigh=0.0;
     19735#endif
     19736    for (int i=0;i<numberColumns;i++) {
     19737      if (cleanVariables[i]) {
     19738        if (solution[i]>columnUpper[i]+ZERO_ODD_TOLERANCE) {
     19739          numberBad++;
     19740#ifdef SHOW_BAD
     19741          sumBadHigh += solution[i]-columnUpper[i];
     19742          maxBadHigh = CoinMax(maxBadHigh,solution[i]-columnUpper[i]);
     19743#endif
     19744        } else if (solution[i]<columnLower[i]-ZERO_ODD_TOLERANCE) {
     19745          numberBad++;
     19746#ifdef SHOW_BAD
     19747          sumBadLow += columnLower[i]-solution[i];
     19748          maxBadLow = CoinMax(maxBadLow,columnLower[i]-solution[i]);
     19749#endif
     19750        }
     19751      }
     19752    }
     19753    if (numberBad) {
     19754#ifdef SHOW_BAD
     19755      printf("%d small variables low (%g max %g), high (%g max %g)\n",numberBad,sumBadLow,maxBadLow,sumBadHigh,maxBadHigh);
     19756#endif
     19757      for (int i=0;i<numberColumns;i++) {
     19758        if (cleanVariables[i]) {
     19759          if (solution[i]>columnUpper[i]+ZERO_ODD_TOLERANCE) {
     19760            solution[i]=columnUpper[i];
     19761            clp->setColumnStatus(i,ClpSimplex::atUpperBound);
     19762          } else if (solution[i]<columnLower[i]-ZERO_ODD_TOLERANCE) {
     19763            solution[i]=columnLower[i];
     19764            clp->setColumnStatus(i,ClpSimplex::atLowerBound);
     19765          }
     19766        }
     19767      }
     19768      int saveLevel=clp->logLevel();
     19769      clp->setLogLevel(0);
     19770      clp->dual();
     19771      clp->setLogLevel(saveLevel);
     19772    }
     19773    if (!cleanIn)
     19774      delete [] cleanVariables;
     19775  }
     19776#endif
     19777  return numberBad;
     19778}
     19779// Sets up cleanVariables array (i.e. ones to be careful about)
     19780char *
     19781CbcModel::setupCleanVariables()
     19782{
     19783  OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver_);
     19784  int numberColumns = osiclp->getNumCols();
     19785  char * cleanVariables = NULL;
     19786  if (osiclp) {
     19787    cleanVariables = new char[numberColumns];
     19788    memset(cleanVariables,0,numberColumns);
     19789    for (int i = 0; i < numberObjects_; i++) {
     19790      const CbcSimpleInteger * intvar = dynamic_cast<const CbcSimpleInteger *>(object_[i]);
     19791      const CbcSOS * sos = dynamic_cast<const CbcSOS *>(object_[i]);
     19792      if (intvar) {
     19793#ifdef CLEAN_INTEGER_VARIABLES
     19794        cleanVariables[intvar->columnNumber()]=1;
     19795#endif
     19796      } else if (sos) {
     19797        int n = sos->numberMembers();
     19798        const int * members = sos->members();
     19799        for (int j=0;j<n;j++)
     19800          cleanVariables[members[j]]=2;
     19801      }
     19802    }
     19803  }
     19804  return cleanVariables;
     19805}
     19806
     19807
  • trunk/Cbc/src/CbcModel.hpp

    r2365 r2373  
    451451    */
    452452    void flipModel();
    453 
     453    /**
     454       Clean model i.e. make SOS/integer variables exactly at bound if needed.
     455       Only if moreSpecialOptions2_ 15 bit set (32768) as there is a small
     456       overhead (more2 in standalone cbc).
     457       Fine tuning can be done in configure with -DCLEAN_INTEGER_VARIABLES
     458       and -DZERO_ODD_TOLERANCE=1.0e-nn
     459       If CLEAN_INTEGER_VARIABLES not defined then cleaning is only done for
     460       SOS variables.
     461       If ZERO_ODD_TOLERANCE not defined then 1.0e-14 used.  You can define as
     462       0.0 if you are paranoid.
     463       Returns number of variables forced out
     464       cleanVariables array will be used if exists
     465     */
     466     int cleanBounds(OsiSolverInterface * solver, char * cleanVariables);
     467     /// Sets up cleanVariables array (i.e. ones to be careful about)
     468     char * setupCleanVariables();
    454469    //@}
    455470
     
    18781893        11/12 bit 2048 - intermittent cuts
    18791894        13/14 bit 8192 - go to bitter end in strong branching (first time)
     1895        15 bit 32768 - take care of very very small values for Integer/SOS variables
    18801896    */
    18811897    inline void setMoreSpecialOptions2(int value) {
  • trunk/Cbc/src/CbcNode.cpp

    r2366 r2373  
    543543    branch_ = NULL;
    544544    OsiSolverInterface * solver = model->solver();
     545    // Mark variables which need to be clean
     546    char * cleanVariables = NULL;
    545547# ifdef COIN_HAS_CLP
    546548    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
    547549    int saveClpOptions = 0;
    548550    if (osiclp) {
    549         // for faster hot start
    550         saveClpOptions = osiclp->specialOptions();
    551         osiclp->setSpecialOptions(saveClpOptions | 8192);
     551      // for faster hot start
     552      saveClpOptions = osiclp->specialOptions();
     553      osiclp->setSpecialOptions(saveClpOptions | 8192);
     554      if ((model->moreSpecialOptions2()&32768)!=0) {
     555        cleanVariables = model->setupCleanVariables(); // for odd ints/sos etc
     556      }
    552557    }
    553558# else
     
    11351140                    if (feasible) {
    11361141                        solver->solveFromHotStart() ;
     1142                        if ((model->moreSpecialOptions2()&32768)!=0&&solver->isProvenOptimal()) {
     1143                          // If any small values re-do
     1144                          model->cleanBounds(solver,cleanVariables);
     1145                        }
    11371146                        numberStrongDone++;
    11381147                        numberStrongIterations += solver->getIterationCount();
     
    12381247                    if (feasible) {
    12391248                        solver->solveFromHotStart() ;
     1249                        if ((model->moreSpecialOptions2()&32768)!=0&&solver->isProvenOptimal()) {
     1250                          // If any small values re-do
     1251                          model->cleanBounds(solver,cleanVariables);
     1252                        }
    12401253                        numberStrongDone++;
    12411254                        numberStrongIterations += solver->getIterationCount();
     
    15751588    delete [] saveSolution;
    15761589# ifdef COIN_HAS_CLP
     1590    delete [] cleanVariables;
    15771591    if (osiclp)
    15781592        osiclp->setSpecialOptions(saveClpOptions);
     
    18521866    bool finished = false;
    18531867    int numberToFix = 0;
     1868    // Mark variables which need to be clean
     1869    char * cleanVariables = NULL;
    18541870# ifdef COIN_HAS_CLP
    18551871    OsiClpSolverInterface * osiclp = dynamic_cast< OsiClpSolverInterface*> (solver);
    18561872    int saveClpOptions = 0;
    18571873    if (osiclp) {
     1874        if ((model->moreSpecialOptions2()&32768)!=0) {
     1875          cleanVariables = model->setupCleanVariables(); // for odd ints/sos etc
     1876        }
    18581877        // for faster hot start
    18591878        saveClpOptions = osiclp->specialOptions();
     
    31173136#endif
    31183137                    solver->solveFromHotStart() ;
     3138                    if ((model->moreSpecialOptions2()&32768)!=0&&solver->isProvenOptimal()) {
     3139                      // If any small values re-do
     3140                      model->cleanBounds(solver,cleanVariables);
     3141                    }
    31193142                    bool needHotStartUpdate = false;
    31203143                    numberStrongDone++;
     
    33383361                    }
    33393362#endif
     3363                    if ((model->moreSpecialOptions2()&32768)!=0&&solver->isProvenOptimal()) {
     3364                      // If any small values re-do
     3365                      model->cleanBounds(solver,cleanVariables);
     3366                    }
    33403367                    numberStrongDone++;
    33413368                    numberStrongIterations += solver->getIterationCount();
     
    40584085    }
    40594086#endif
     4087    delete [] cleanVariables;
    40604088    /*
    40614089      Cleanup, then we're finished
     
    61456173    return objectiveValue_;
    61466174}
    6147 
  • trunk/Cbc/src/CbcSOS.cpp

    r2367 r2373  
    204204    const double * upper = solver->getColUpper();
    205205    //double largestValue=0.0;
     206#ifndef ZERO_ODD_TOLERANCE
    206207#define ZERO_SOS_TOLERANCE 1.0e-14
    207 #ifndef ZERO_SOS_TOLERANCE
    208     double integerTolerance =
    209         model_->getDblParam(CbcModel::CbcIntegerTolerance);
    210208#else
     209#define ZERO_SOS_TOLERANCE ZERO_ODD_TOLERANCE
     210#endif
     211    //double integerTolerance =
     212    //  model_->getDblParam(CbcModel::CbcIntegerTolerance);
    211213    double integerTolerance = ZERO_SOS_TOLERANCE;
    212 #endif
    213214    double weight = 0.0;
    214215    double sum = 0.0;
Note: See TracChangeset for help on using the changeset viewer.