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

allow cleaning of small sos variables

File:
1 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
Note: See TracChangeset for help on using the changeset viewer.