// Copyright (C) 2002, International Business Machines // Corporation and others. All Rights Reserved. #include "CoinPragma.hpp" #include #include #include "CoinIndexedVector.hpp" #include "ClpSimplex.hpp" #include "CoinHelperFunctions.hpp" #include "ClpNonLinearCost.hpp" //############################################################################# // Constructors / Destructor / Assignment //############################################################################# //------------------------------------------------------------------- // Default Constructor //------------------------------------------------------------------- ClpNonLinearCost::ClpNonLinearCost () : changeCost_(0.0), feasibleCost_(0.0), infeasibilityWeight_(-1.0), largestInfeasibility_(0.0), sumInfeasibilities_(0.0), averageTheta_(0.0), numberRows_(0), numberColumns_(0), start_(NULL), whichRange_(NULL), offset_(NULL), lower_(NULL), cost_(NULL), model_(NULL), infeasible_(NULL), numberInfeasibilities_(-1), status_(NULL), bound_(NULL), cost2_(NULL), method_(1), convex_(true), bothWays_(false) { } //#define VALIDATE #ifdef VALIDATE static double * saveLowerV=NULL; static double * saveUpperV=NULL; #ifdef NDEBUG Validate sgould not be set if no debug #endif #endif /* Constructor from simplex. This will just set up wasteful arrays for linear, but later may do dual analysis and even finding duplicate columns */ ClpNonLinearCost::ClpNonLinearCost ( ClpSimplex * model,int method) { method=2; model_ = model; numberRows_ = model_->numberRows(); //if (numberRows_==402) { //model_->setLogLevel(63); //model_->setMaximumIterations(30000); //} numberColumns_ = model_->numberColumns(); // If gub then we need this extra int numberExtra = model_->numberExtraRows(); if (numberExtra) method=1; int numberTotal1 = numberRows_+numberColumns_; int numberTotal = numberTotal1+numberExtra; convex_ = true; bothWays_ = false; method_=method; numberInfeasibilities_=0; changeCost_=0.0; feasibleCost_=0.0; infeasibilityWeight_ = -1.0; double * cost = model_->costRegion(); // check if all 0 int iSequence; bool allZero=true; for (iSequence=0;iSequencesetInfeasibilityCost(1.0); double infeasibilityCost = model_->infeasibilityCost(); sumInfeasibilities_=0.0; averageTheta_=0.0; largestInfeasibility_=0.0; // All arrays NULL to start status_ = NULL; bound_ = NULL; cost2_ = NULL; start_ = NULL; whichRange_ = NULL; offset_ = NULL; lower_ = NULL; cost_= NULL; infeasible_=NULL; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); // See how we are storing things bool always4 = (model_->clpMatrix()-> generalExpanded(model_,10,iSequence)!=0); if (always4) method_=1; if (CLP_METHOD1) { start_ = new int [numberTotal+1]; whichRange_ = new int [numberTotal]; offset_ = new int [numberTotal]; memset(offset_,0,numberTotal*sizeof(int)); // First see how much space we need int put=0; // For quadratic we need -inf,0,0,+inf for (iSequence=0;iSequence-COIN_DBL_MAX) put++; if (upper[iSequence]>5]; memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int)); put=0; start_[0]=0; for (iSequence=0;iSequence-COIN_DBL_MAX) { lower_[put] = -COIN_DBL_MAX; setInfeasible(put,true); cost_[put++] = cost[iSequence]-infeasibilityCost; } whichRange_[iSequence]=put; lower_[put] = lower[iSequence]; cost_[put++] = cost[iSequence]; lower_[put] = upper[iSequence]; cost_[put++] = cost[iSequence]+infeasibilityCost; if (upper[iSequence]clpMatrix()-> generalExpanded(model_,10,iSequence)==0); #endif if (CLP_METHOD2) { assert (!numberExtra); bound_ = new double[numberTotal]; cost2_ = new double[numberTotal]; status_ = new unsigned char[numberTotal]; #ifdef VALIDATE delete [] saveLowerV; saveLowerV = CoinCopyOfArray(model_->lowerRegion(),numberTotal); delete [] saveUpperV; saveUpperV = CoinCopyOfArray(model_->upperRegion(),numberTotal); #endif for (iSequence=0;iSequencecostRegion(); // zero row costs memset(cost+numberColumns_,0,numberRows_*sizeof(double)); // copy column costs memcpy(cost,columnCosts,numberColumns_*sizeof(double)); if ((method_&1)!=0) { for (int iSequence=0;iSequencescalingFlag()); model_ = model; numberRows_ = model_->numberRows(); numberColumns_ = model_->numberColumns(); int numberTotal = numberRows_+numberColumns_; convex_ = true; bothWays_ = true; start_ = new int [numberTotal+1]; whichRange_ = new int [numberTotal]; offset_ = new int [numberTotal]; memset(offset_,0,numberTotal*sizeof(int)); double whichWay = model_->optimizationDirection(); printf("Direction %g\n",whichWay); numberInfeasibilities_=0; changeCost_=0.0; feasibleCost_=0.0; double infeasibilityCost = model_->infeasibilityCost(); infeasibilityWeight_ = infeasibilityCost;; largestInfeasibility_=0.0; sumInfeasibilities_=0.0; int iSequence; assert (!model_->rowObjective()); double * cost = model_->objective(); // First see how much space we need // Also set up feasible bounds int put=starts[numberColumns_]; double * columnUpper = model_->columnUpper(); double * columnLower = model_->columnLower(); for (iSequence=0;iSequence-1.0e20) put++; if (columnUpper[iSequence]<1.0e20) put++; } double * rowUpper = model_->rowUpper(); double * rowLower = model_->rowLower(); for (iSequence=0;iSequence-1.0e20) put++; if (rowUpper[iSequence]<1.0e20) put++; put +=2; } lower_ = new double [put]; cost_ = new double [put]; infeasible_ = new unsigned int[(put+31)>>5]; memset(infeasible_,0,((put+31)>>5)*sizeof(unsigned int)); // now fill in put=0; start_[0]=0; for (iSequence=0;iSequence=numberColumns_) { // rows lowerValue = rowLower[iSequence-numberColumns_]; upperValue = rowUpper[iSequence-numberColumns_]; if (lowerValue>-1.0e30) { setInfeasible(put,true); cost_[put++] = -infeasibilityCost; lower_[put] = lowerValue; } cost_[put++] = 0.0; thisCost = 0.0; } else { // columns - move costs and see if convex lowerValue = columnLower[iSequence]; upperValue = columnUpper[iSequence]; if (lowerValue>-1.0e30) { setInfeasible(put,true); cost_[put++] = whichWay*cost[iSequence]-infeasibilityCost; lower_[put] = lowerValue; } int iIndex = starts[iSequence]; int end = starts[iSequence+1]; assert (fabs(columnLower[iSequence]-lowerNon[iIndex])<1.0e-8); thisCost = -COIN_DBL_MAX; for (;iIndex>5]; memcpy(infeasible_,rhs.infeasible_, ((numberEntries+31)>>5)*sizeof(unsigned int)); } if (CLP_METHOD2) { bound_ = CoinCopyOfArray(rhs.bound_,numberTotal); cost2_ = CoinCopyOfArray(rhs.cost2_,numberTotal); status_ = CoinCopyOfArray(rhs.status_,numberTotal); } } } //------------------------------------------------------------------- // Destructor //------------------------------------------------------------------- ClpNonLinearCost::~ClpNonLinearCost () { delete [] start_; delete [] whichRange_; delete [] offset_; delete [] lower_; delete [] cost_; delete [] infeasible_; delete [] status_; delete [] bound_; delete [] cost2_; } //---------------------------------------------------------------- // Assignment operator //------------------------------------------------------------------- ClpNonLinearCost & ClpNonLinearCost::operator=(const ClpNonLinearCost& rhs) { if (this != &rhs) { numberRows_ = rhs.numberRows_; numberColumns_ = rhs.numberColumns_; delete [] start_; delete [] whichRange_; delete [] offset_; delete [] lower_; delete [] cost_; delete [] infeasible_; delete [] status_; delete [] bound_; delete [] cost2_; start_ = NULL; whichRange_ = NULL; lower_ = NULL; cost_= NULL; infeasible_=NULL; status_ = NULL; bound_ = NULL; cost2_ = NULL; method_=rhs.method_; if (numberRows_) { int numberTotal = numberRows_+numberColumns_; if (CLP_METHOD1) { start_ = new int [numberTotal+1]; memcpy(start_,rhs.start_,(numberTotal+1)*sizeof(int)); whichRange_ = new int [numberTotal]; memcpy(whichRange_,rhs.whichRange_,numberTotal*sizeof(int)); offset_ = new int [numberTotal]; memcpy(offset_,rhs.offset_,numberTotal*sizeof(int)); int numberEntries = start_[numberTotal]; lower_ = new double [numberEntries]; memcpy(lower_,rhs.lower_,numberEntries*sizeof(double)); cost_ = new double [numberEntries]; memcpy(cost_,rhs.cost_,numberEntries*sizeof(double)); infeasible_ = new unsigned int[(numberEntries+31)>>5]; memcpy(infeasible_,rhs.infeasible_, ((numberEntries+31)>>5)*sizeof(unsigned int)); } if (CLP_METHOD2) { bound_ = CoinCopyOfArray(rhs.bound_,numberTotal); cost2_ = CoinCopyOfArray(rhs.cost2_,numberTotal); status_ = CoinCopyOfArray(rhs.status_,numberTotal); } } model_ = rhs.model_; numberInfeasibilities_=rhs.numberInfeasibilities_; changeCost_ = rhs.changeCost_; feasibleCost_ = rhs.feasibleCost_; infeasibilityWeight_ = rhs.infeasibilityWeight_; largestInfeasibility_ = rhs.largestInfeasibility_; sumInfeasibilities_ = rhs.sumInfeasibilities_; averageTheta_ = rhs.averageTheta_; convex_ = rhs.convex_; bothWays_ = rhs.bothWays_; } return *this; } // Changes infeasible costs and computes number and cost of infeas // We will need to re-think objective offsets later // We will also need a 2 bit per variable array for some // purpose which will come to me later void ClpNonLinearCost::checkInfeasibilities(double oldTolerance) { numberInfeasibilities_=0; double infeasibilityCost = model_->infeasibilityCost(); changeCost_=0.0; largestInfeasibility_ = 0.0; sumInfeasibilities_ = 0.0; double primalTolerance = model_->currentPrimalTolerance(); int iSequence; double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); bool toNearest = oldTolerance<=0.0; feasibleCost_=0.0; //bool checkCosts = (infeasibilityWeight_ != infeasibilityCost); infeasibilityWeight_ = infeasibilityCost; int numberTotal = numberColumns_+numberRows_; //#define NONLIN_DEBUG #ifdef NONLIN_DEBUG double * saveSolution=NULL; double * saveLower=NULL; double * saveUpper=NULL; unsigned char * saveStatus=NULL; if (method_==3) { // Save solution as we will be checking saveSolution = CoinCopyOfArray(solution,numberTotal); saveLower = CoinCopyOfArray(lower,numberTotal); saveUpper = CoinCopyOfArray(upper,numberTotal); saveStatus = CoinCopyOfArray(model_->statusArray(),numberTotal); } #else assert (method_!=3); #endif if (CLP_METHOD1) { // nonbasic should be at a valid bound for (iSequence=0;iSequence=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; whichRange_[iSequence]=iRange; break; } } assert(iRangegetStatus(iSequence); if (upperValue==lowerValue && status!=ClpSimplex::isFixed) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence,ClpSimplex::isFixed); status = ClpSimplex::isFixed; } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: // iRange is in correct place // slot in here if (infeasible(iRange)) { if (lower_[iRange]<-1.0e50) { //cost_[iRange] = cost_[iRange+1]-infeasibilityCost; // possibly below lowerValue = lower_[iRange+1]; if (value-lowerValue<-primalTolerance) { value = lowerValue-value-primalTolerance; #ifndef NDEBUG if(value>1.0e15) printf("nonlincostb %d %g %g %g\n", iSequence,lowerValue,solution[iSequence],lower_[iRange+2]); #endif sumInfeasibilities_ += value; largestInfeasibility_ = CoinMax(largestInfeasibility_,value); changeCost_ -= lowerValue* (cost_[iRange]-cost[iSequence]); numberInfeasibilities_++; } } else { //cost_[iRange] = cost_[iRange-1]+infeasibilityCost; // possibly above upperValue = lower_[iRange]; if (value-upperValue>primalTolerance) { value = value-upperValue-primalTolerance; #ifndef NDEBUG if(value>1.0e15) printf("nonlincostu %d %g %g %g\n", iSequence,lower_[iRange-1],solution[iSequence],upperValue); #endif sumInfeasibilities_ += value; largestInfeasibility_ = CoinMax(largestInfeasibility_,value); changeCost_ -= upperValue* (cost_[iRange]-cost[iSequence]); numberInfeasibilities_++; } } } //lower[iSequence] = lower_[iRange]; //upper[iSequence] = lower_[iRange+1]; //cost[iSequence] = cost_[iRange]; break; case ClpSimplex::isFree: //if (toNearest) //solution[iSequence] = 0.0; break; case ClpSimplex::atUpperBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value-upperValue)>oldTolerance*1.0001) { if (fabs(value-lowerValue)<=oldTolerance*1.0001) { if (fabs(value-lowerValue)>primalTolerance) solution[iSequence]=lowerValue; model_->setStatus(iSequence,ClpSimplex::atLowerBound); } else { model_->setStatus(iSequence,ClpSimplex::superBasic); } } else if (fabs(value-upperValue)>primalTolerance) { solution[iSequence]=upperValue; } } else { // Set to nearest and make at upper bound int kRange; iRange=-1; double nearest = COIN_DBL_MAX; for (kRange=start; kRange=0); iRange--; whichRange_[iSequence]=iRange; solution[iSequence]=lower_[iRange+1]; } break; case ClpSimplex::atLowerBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place // below stops compiler error with gcc 3.2!!! if (iSequence==-119) printf("ZZ %g %g %g %g\n",lowerValue,value,upperValue,oldTolerance); if (fabs(value-lowerValue)>oldTolerance*1.0001) { if (fabs(value-upperValue)<=oldTolerance*1.0001) { if (fabs(value-upperValue)>primalTolerance) solution[iSequence]=upperValue; model_->setStatus(iSequence,ClpSimplex::atUpperBound); } else { model_->setStatus(iSequence,ClpSimplex::superBasic); } } else if (fabs(value-lowerValue)>primalTolerance) { solution[iSequence]=lowerValue; } } else { // Set to nearest and make at lower bound int kRange; iRange=-1; double nearest = COIN_DBL_MAX; for (kRange=start; kRange=0); whichRange_[iSequence]=iRange; solution[iSequence]=lower_[iRange]; } break; case ClpSimplex::isFixed: if (toNearest) { // Set to true fixed for (iRange=start; iRange=0); whichRange_[iSequence]=iRange; if (lower_[iRange]!=lower_[iRange+1]) model_->setStatus(iSequence,ClpSimplex::atLowerBound); else model_->setStatus(iSequence,ClpSimplex::atUpperBound); } solution[iSequence]=lower_[iRange]; } break; } lower[iSequence] = lower_[iRange]; upper[iSequence] = lower_[iRange+1]; cost[iSequence] = cost_[iRange]; feasibleCost_ += thisFeasibleCost*solution[iSequence]; //assert (iRange==whichRange_[iSequence]); } } #ifdef NONLIN_DEBUG double saveCost=feasibleCost_; if (method_==3) { feasibleCost_=0.0; // Put back solution as we will be checking unsigned char * statusA = model_->statusArray(); for (iSequence=0;iSequencegetStatus(iSequence); if (upperValue==lowerValue && status!=ClpSimplex::isFixed) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence,ClpSimplex::isFixed); status = ClpSimplex::isFixed; } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: if (value-upperValue<=primalTolerance) { if (value-lowerValue>=-primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere=CLP_BELOW_LOWER; double infeasibility = lowerValue-value-primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_,infeasibility); costValue = trueCost - infeasibilityCost; changeCost_ -= lowerValue*(costValue-cost[iSequence]); numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; double infeasibility = value-upperValue-primalTolerance; sumInfeasibilities_ += infeasibility; largestInfeasibility_ = CoinMax(largestInfeasibility_,infeasibility); costValue = trueCost + infeasibilityCost; changeCost_ -= upperValue*(costValue-cost[iSequence]); numberInfeasibilities_++; } break; case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value-upperValue)>oldTolerance*1.0001) { if (fabs(value-lowerValue)<=oldTolerance*1.0001) { if (fabs(value-lowerValue)>primalTolerance) { solution[iSequence]=lowerValue; value = lowerValue; } model_->setStatus(iSequence,ClpSimplex::atLowerBound); } else { if (valuelowerValue) { model_->setStatus(iSequence,ClpSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence]=lowerValue; value = lowerValue; model_->setStatus(iSequence,ClpSimplex::atLowerBound); } } else { // set to upper bound as infeasible solution[iSequence]=upperValue; value = upperValue; } } } else if (fabs(value-upperValue)>primalTolerance) { solution[iSequence]=upperValue; value = upperValue; } } else { // Set to nearest and make at bound if (fabs(value-lowerValue)setStatus(iSequence,ClpSimplex::atLowerBound); } else { solution[iSequence]=upperValue; value = upperValue; } } break; case ClpSimplex::atLowerBound: if (!toNearest) { // With increasing tolerances - we may be at wrong place if (fabs(value-lowerValue)>oldTolerance*1.0001) { if (fabs(value-upperValue)<=oldTolerance*1.0001) { if (fabs(value-upperValue)>primalTolerance) { solution[iSequence]=upperValue; value = upperValue; } model_->setStatus(iSequence,ClpSimplex::atUpperBound); } else { if (valuelowerValue) { model_->setStatus(iSequence,ClpSimplex::superBasic); } else { // set to lower bound as infeasible solution[iSequence]=lowerValue; value = lowerValue; } } else { // set to upper bound as infeasible solution[iSequence]=upperValue; value = upperValue; model_->setStatus(iSequence,ClpSimplex::atUpperBound); } } } else if (fabs(value-lowerValue)>primalTolerance) { solution[iSequence]=lowerValue; value = lowerValue; } } else { // Set to nearest and make at bound if (fabs(value-lowerValue)setStatus(iSequence,ClpSimplex::atUpperBound); } } break; case ClpSimplex::isFixed: solution[iSequence]=lowerValue; value = lowerValue; break; } #ifdef NONLIN_DEBUG double lo=saveLower[iSequence]; double up=saveUpper[iSequence]; double cc=cost[iSequence]; unsigned char ss=saveStatus[iSequence]; unsigned char snow=model_->statusArray()[iSequence]; #endif if (iWhere!=newWhere) { setOriginalStatus(status_[iSequence],newWhere); if (newWhere==CLP_BELOW_LOWER) { bound_[iSequence]=upperValue; upperValue=lowerValue; lowerValue=-COIN_DBL_MAX; costValue = trueCost - infeasibilityCost; } else if (newWhere==CLP_ABOVE_UPPER) { bound_[iSequence]=lowerValue; lowerValue=upperValue; upperValue=COIN_DBL_MAX; costValue = trueCost + infeasibilityCost; } else { costValue = trueCost; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } // always do as other things may change cost[iSequence] = costValue; #ifdef NONLIN_DEBUG if (method_==3) { assert (ss==snow); assert (cc==cost[iSequence]); assert (lo==lower[iSequence]); assert (up==upper[iSequence]); assert (value==saveSolution[iSequence]); } #endif feasibleCost_ += trueCost*value; } } #ifdef NONLIN_DEBUG if (method_==3) assert (fabs(saveCost-feasibleCost_)<0.001*(1.0+CoinMax(fabs(saveCost),fabs(feasibleCost_)))); delete [] saveSolution; delete [] saveLower; delete [] saveUpper; delete [] saveStatus; #endif //feasibleCost_ /= (model_->rhsScale()*model_->objScale()); } // Puts feasible bounds into lower and upper void ClpNonLinearCost::feasibleBounds() { if (CLP_METHOD2) { int iSequence; double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); int numberTotal = numberColumns_+numberRows_; for (iSequence=0;iSequence0 goes down, otherwise up. The indices are row indices and need converting to sequences */ void ClpNonLinearCost::goThru(int numberInArray, double multiplier, const int * index, const double * array, double * rhs) { assert (model_!=NULL); abort(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i=0;isolution(iSequence); if (alpha>0.0) { // down one iRange--; assert(iRange>=start_[iSequence]); rhs[iRow] = value - lower_[iRange]; } else { // up one iRange++; assert(iRangenumberRows(); saveRhs = CoinCopyOfArray(rhs,numberRows); } #endif if (CLP_METHOD2) { const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); for (int i=0;i0.0) { // going below iWhere=CLP_BELOW_LOWER; rhs[iRow] = value - lower[iSequence]; } else { // going above iWhere=CLP_ABOVE_UPPER; rhs[iRow] = upper[iSequence] - value; } } else if(iWhere==CLP_BELOW_LOWER) { assert (alpha<0); // going feasible iWhere=CLP_FEASIBLE; rhs[iRow] = upper[iSequence] - value; } else { assert (iWhere==CLP_ABOVE_UPPER); // going feasible iWhere=CLP_FEASIBLE; rhs[iRow] = value - lower[iSequence]; } #ifdef NONLIN_DEBUG if (method_==3) assert (rhs[iRow]==saveRhs[iRow]); #endif setCurrentStatus(status_[iSequence],iWhere); } } #ifdef NONLIN_DEBUG delete [] saveRhs; #endif } /* Takes off last iteration (i.e. offsets closer to 0) */ void ClpNonLinearCost::goBack(int numberInArray, const int * index, double * rhs) { assert (model_!=NULL); abort(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i=0;i0) { offset_[iSequence]--; assert (offset_[iSequence]>=0); iRange += offset_[iSequence]; //add temporary bias double value = model_->solution(iSequence); // up one assert(iRangesolution(iSequence); // down one assert(iRange>=start_[iSequence]); rhs[iRow] = value - lower_[iRange]; // was earlier lower_[iRange+1] } } } #ifdef NONLIN_DEBUG double * saveRhs = NULL; if (method_==3) { int numberRows = model_->numberRows(); saveRhs = CoinCopyOfArray(rhs,numberRows); } #endif if (CLP_METHOD2) { const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); for (int i=0;ipivotVariable(); int number = update->getNumElements(); const int * index = update->getIndices(); if (CLP_METHOD1) { for (int i=0;icurrentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); if (CLP_METHOD1) { for (int i=0;isolution(iSequence); int start = start_[iSequence]; int end = start_[iSequence+1]-1; for (iRange=start; iRange=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; break; } } assert(iRangegetStatus(iSequence)==ClpSimplex::basic); double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); whichRange_[iSequence]=iRange; if (iRange!=currentRange) { if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(currentRange)) numberInfeasibilities_--; } lower = lower_[iRange]; upper = lower_[iRange+1]; cost = cost_[iRange]; } } if (CLP_METHOD2) { double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); for (int i=0;i=-primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere=CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere!=newWhere) { setOriginalStatus(status_[iSequence],newWhere); if (newWhere==CLP_BELOW_LOWER) { bound_[iSequence]=upperValue; upperValue=lowerValue; lowerValue=-COIN_DBL_MAX; } else if (newWhere==CLP_ABOVE_UPPER) { bound_[iSequence]=lowerValue; lowerValue=upperValue; upperValue=COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } } } /* Puts back correct infeasible costs for each variable The input indices are row indices and need converting to sequences for costs. On input array is empty (but indices exist). On exit just changed costs will be stored as normal CoinIndexedVector */ void ClpNonLinearCost::checkChanged(int numberInArray, CoinIndexedVector * update) { assert (model_!=NULL); double primalTolerance = model_->currentPrimalTolerance(); const int * pivotVariable = model_->pivotVariable(); int number=0; int * index = update->getIndices(); double * work = update->denseVector(); if (CLP_METHOD1) { for (int i=0;isolution(iSequence); int start = start_[iSequence]; int end = start_[iSequence+1]-1; for (iRange=start; iRange=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; break; } } assert(iRangegetStatus(iSequence)==ClpSimplex::basic); int jRange = whichRange_[iSequence]; if (iRange!=jRange) { // changed work[iRow] = cost_[jRange]-cost_[iRange]; index[number++]=iRow; double & lower = model_->lowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); whichRange_[iSequence]=iRange; if (infeasible(iRange)) numberInfeasibilities_++; if (infeasible(jRange)) numberInfeasibilities_--; lower = lower_[iRange]; upper = lower_[iRange+1]; cost = cost_[iRange]; } } } if (CLP_METHOD2) { double * solution = model_->solutionRegion(); double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); for (int i=0;i=-primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere=CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere!=newWhere) { work[iRow] = cost[iSequence]-costValue; index[number++]=iRow; setOriginalStatus(status_[iSequence],newWhere); if (newWhere==CLP_BELOW_LOWER) { bound_[iSequence]=upperValue; upperValue=lowerValue; lowerValue=-COIN_DBL_MAX; } else if (newWhere==CLP_ABOVE_UPPER) { bound_[iSequence]=lowerValue; lowerValue=upperValue; upperValue=COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } } } update->setNumElements(number); } /* Sets bounds and cost for one variable - returns change in cost*/ double ClpNonLinearCost::setOne(int iSequence, double value) { assert (model_!=NULL); double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference=0.0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int currentRange = whichRange_[iSequence]; int start = start_[iSequence]; int end = start_[iSequence+1]-1; if (!bothWays_) { // If fixed try and get feasible if (lower_[start+1]==lower_[start+2]&&fabs(value-lower_[start+1])<1.001*primalTolerance) { iRange =start+1; } else { for (iRange=start; iRange=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; break; } } } } else { // leave in current if possible iRange = whichRange_[iSequence]; if (valuelower_[iRange+1]+primalTolerance) { for (iRange=start; iRange=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; break; } } } } assert(iRangelowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); lower = lower_[iRange]; upper = lower_[iRange+1]; ClpSimplex::Status status = model_->getStatus(iSequence); if (upper==lower) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence,ClpSimplex::isFixed); status = ClpSimplex::basic; // so will skip } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: case ClpSimplex::atLowerBound: case ClpSimplex::isFixed: // set correctly if (fabs(value-lower)<=primalTolerance*1.001){ model_->setStatus(iSequence,ClpSimplex::atLowerBound); } else if (fabs(value-upper)<=primalTolerance*1.001){ model_->setStatus(iSequence,ClpSimplex::atUpperBound); } else { // set superBasic model_->setStatus(iSequence,ClpSimplex::superBasic); } break; } difference = cost-cost_[iRange]; cost = cost_[iRange]; } if (CLP_METHOD2) { double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); int iStatus = status_[iSequence]; assert (currentStatus(iStatus)==CLP_SAME); double lowerValue=lower[iSequence]; double upperValue=upper[iSequence]; double costValue = cost2_[iSequence]; int iWhere = originalStatus(iStatus); if (iWhere==CLP_BELOW_LOWER) { lowerValue=upperValue; upperValue=bound_[iSequence]; numberInfeasibilities_--; } else if (iWhere==CLP_ABOVE_UPPER) { upperValue=lowerValue; lowerValue=bound_[iSequence]; numberInfeasibilities_--; } // get correct place int newWhere=CLP_FEASIBLE; if (value-upperValue<=primalTolerance) { if (value-lowerValue>=-primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere=CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere!=newWhere) { difference = cost[iSequence]-costValue; setOriginalStatus(status_[iSequence],newWhere); if (newWhere==CLP_BELOW_LOWER) { bound_[iSequence]=upperValue; upperValue=lowerValue; lowerValue=-COIN_DBL_MAX; } else if (newWhere==CLP_ABOVE_UPPER) { bound_[iSequence]=lowerValue; lowerValue=upperValue; upperValue=COIN_DBL_MAX; } lower[iSequence] = lowerValue; upper[iSequence] = upperValue; cost[iSequence] = costValue; } ClpSimplex::Status status = model_->getStatus(iSequence); if (upperValue==lowerValue) { if (status != ClpSimplex::basic) { model_->setStatus(iSequence,ClpSimplex::isFixed); status = ClpSimplex::basic; // so will skip } } switch(status) { case ClpSimplex::basic: case ClpSimplex::superBasic: case ClpSimplex::isFree: break; case ClpSimplex::atUpperBound: case ClpSimplex::atLowerBound: case ClpSimplex::isFixed: // set correctly if (fabs(value-lowerValue)<=primalTolerance*1.001){ model_->setStatus(iSequence,ClpSimplex::atLowerBound); } else if (fabs(value-upperValue)<=primalTolerance*1.001){ model_->setStatus(iSequence,ClpSimplex::atUpperBound); } else { // set superBasic model_->setStatus(iSequence,ClpSimplex::superBasic); } break; } } changeCost_ += value*difference; return difference; } /* Sets bounds and infeasible cost and true cost for one variable This is for gub and column generation etc */ void ClpNonLinearCost::setOne(int sequence, double solutionValue, double lowerValue, double upperValue, double costValue) { if (CLP_METHOD1) { int iRange=-1; int start = start_[sequence]; double infeasibilityCost = model_->infeasibilityCost(); cost_[start] = costValue-infeasibilityCost; lower_[start+1]=lowerValue; cost_[start+1] = costValue; lower_[start+2]=upperValue; cost_[start+2] = costValue+infeasibilityCost; double primalTolerance = model_->currentPrimalTolerance(); if (solutionValue-lowerValue>=-primalTolerance) { if (solutionValue-upperValue<=primalTolerance) { iRange=start+1; } else { iRange=start+2; } } else { iRange = start; } model_->costRegion()[sequence]=cost_[iRange]; whichRange_[sequence]=iRange; } if (CLP_METHOD2) { abort(); // may never work } } /* Sets bounds and cost for outgoing variable may change value Returns direction */ int ClpNonLinearCost::setOneOutgoing(int iSequence, double & value) { assert (model_!=NULL); double primalTolerance = model_->currentPrimalTolerance(); // difference in cost double difference=0.0; int direction=0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int currentRange = whichRange_[iSequence]; int start = start_[iSequence]; int end = start_[iSequence+1]-1; // Set perceived direction out if (value<=lower_[currentRange]+1.001*primalTolerance) { direction=1; } else if (value>=lower_[currentRange+1]-1.001*primalTolerance) { direction=-1; } else { // odd direction=0; } // If fixed try and get feasible if (lower_[start+1]==lower_[start+2]&&fabs(value-lower_[start+1])<1.001*primalTolerance) { iRange =start+1; } else { // See if exact for (iRange=start; iRange=lower_[iRange+1]-primalTolerance&&infeasible(iRange)&&iRange==start) iRange++; break; } } } } assert(iRangelowerAddress(iSequence); double & upper = model_->upperAddress(iSequence); double & cost = model_->costAddress(iSequence); lower = lower_[iRange]; upper = lower_[iRange+1]; if (upper==lower) { value=upper; } else { // set correctly if (fabs(value-lower)<=primalTolerance*1.001){ value = CoinMin(value,lower+primalTolerance); } else if (fabs(value-upper)<=primalTolerance*1.001){ value = CoinMax(value,upper-primalTolerance); } else { //printf("*** variable wandered off bound %g %g %g!\n", // lower,value,upper); if (value-lower<=upper-value) value = lower+primalTolerance; else value = upper-primalTolerance; } } difference = cost-cost_[iRange]; cost = cost_[iRange]; } if (CLP_METHOD2) { double * upper = model_->upperRegion(); double * lower = model_->lowerRegion(); double * cost = model_->costRegion(); int iStatus = status_[iSequence]; assert (currentStatus(iStatus)==CLP_SAME); double lowerValue=lower[iSequence]; double upperValue=upper[iSequence]; double costValue = cost2_[iSequence]; // Set perceived direction out if (value<=lowerValue+1.001*primalTolerance) { direction=1; } else if (value>=upperValue-1.001*primalTolerance) { direction=-1; } else { // odd direction=0; } int iWhere = originalStatus(iStatus); if (iWhere==CLP_BELOW_LOWER) { lowerValue=upperValue; upperValue=bound_[iSequence]; numberInfeasibilities_--; } else if (iWhere==CLP_ABOVE_UPPER) { upperValue=lowerValue; lowerValue=bound_[iSequence]; numberInfeasibilities_--; } // get correct place // If fixed give benefit of doubt if (lowerValue==upperValue) value=lowerValue; int newWhere=CLP_FEASIBLE; if (value-upperValue<=primalTolerance) { if (value-lowerValue>=-primalTolerance) { // feasible //newWhere=CLP_FEASIBLE; } else { // below newWhere=CLP_BELOW_LOWER; costValue -= infeasibilityWeight_; numberInfeasibilities_++; } } else { // above newWhere = CLP_ABOVE_UPPER; costValue += infeasibilityWeight_; numberInfeasibilities_++; } if (iWhere!=newWhere) { difference = cost[iSequence]-costValue; setOriginalStatus(status_[iSequence],newWhere); if (newWhere==CLP_BELOW_LOWER) { bound_[iSequence]=upperValue; upper[iSequence]=lowerValue; lower[iSequence]=-COIN_DBL_MAX; } else if (newWhere==CLP_ABOVE_UPPER) { bound_[iSequence]=lowerValue; lower[iSequence]=upperValue; upper[iSequence]=COIN_DBL_MAX; } else { lower[iSequence] = lowerValue; upper[iSequence] = upperValue; } cost[iSequence] = costValue; } // set correctly if (fabs(value-lowerValue)<=primalTolerance*1.001){ value = CoinMin(value,lowerValue+primalTolerance); } else if (fabs(value-upperValue)<=primalTolerance*1.001){ value = CoinMax(value,upperValue-primalTolerance); } else { //printf("*** variable wandered off bound %g %g %g!\n", // lowerValue,value,upperValue); if (value-lowerValue<=upperValue-value) value = lowerValue+primalTolerance; else value = upperValue-primalTolerance; } } changeCost_ += value*difference; return direction; } // Returns nearest bound double ClpNonLinearCost::nearest(int iSequence, double solutionValue) { assert (model_!=NULL); double nearest=0.0; if (CLP_METHOD1) { // get where in bound sequence int iRange; int start = start_[iSequence]; int end = start_[iSequence+1]; int jRange=-1; nearest=COIN_DBL_MAX; for (iRange=start; iRangeupperRegion(); const double * lower = model_->lowerRegion(); double lowerValue=lower[iSequence]; double upperValue=upper[iSequence]; int iWhere = originalStatus(status_[iSequence]); if (iWhere==CLP_BELOW_LOWER) { lowerValue=upperValue; upperValue=bound_[iSequence]; } else if (iWhere==CLP_ABOVE_UPPER) { upperValue=lowerValue; lowerValue=bound_[iSequence]; } if (fabs(solutionValue-lowerValue)getDblParam(ClpObjOffset,value); return (feasibleCost_+model_->objectiveAsObject()->nonlinearOffset())*model_->optimizationDirection()/ (model_->objectiveScale()*model_->rhsScale())-value; } // Get rid of real costs (just for moment) void ClpNonLinearCost::zapCosts() { int iSequence; double infeasibilityCost = model_->infeasibilityCost(); // zero out all costs int numberTotal = numberColumns_+numberRows_; if (CLP_METHOD1) { int n = start_[numberTotal]; memset(cost_,0,n*sizeof(double)); for (iSequence=0;iSequencecurrentPrimalTolerance(); int iSequence; const double * solution = model_->solutionRegion(); const double * upper = model_->upperRegion(); const double * lower = model_->lowerRegion(); const double * cost = model_->costRegion(); double infeasibilityCost = model_->infeasibilityCost(); int numberTotal = numberRows_+numberColumns_; int numberInfeasibilities=0; double sumInfeasibilities = 0.0; for (iSequence=0;iSequencegetStatus(iSequence)==ClpSimplex::basic); } else if (iWhere==CLP_ABOVE_UPPER) { upperValue=lowerValue; lowerValue=bound_[iSequence]; costValue += infeasibilityCost; assert (value>=upperValue+primalTolerance); numberInfeasibilities++; sumInfeasibilities += value -upperValue-primalTolerance; assert (model_->getStatus(iSequence)==ClpSimplex::basic); } else { assert (value>=lowerValue-primalTolerance&&value<=upperValue+primalTolerance); } assert (lowerValue==saveLowerV[iSequence]); assert (upperValue==saveUpperV[iSequence]); assert (costValue==cost[iSequence]); } if (numberInfeasibilities) printf("JJ %d infeasibilities summing to %g\n", numberInfeasibilities,sumInfeasibilities); } #endif