Пример #1
0
int main(int argc, char *argv[]) 
{

	try{
		// Set up lp solver
		OsiClpSolverInterface lpSolver;
		lpSolver.getModelPtr()->setDualBound(1.0e10);
		lpSolver.messageHandler()->setLogLevel(0);
	
		// Create BLIS model 
		BlisModel model;
		model.setSolver(&lpSolver);
	
#ifdef  COIN_HAS_MPI
		AlpsKnowledgeBrokerMPI broker(argc, argv, model);
#else
		AlpsKnowledgeBrokerSerial broker(argc, argv, model); 
#endif

		// Search for best solution
		broker.search(&model);
	
		// Report the best solution found and its ojective value
		broker.printBestSolution();
 }	

	catch(CoinError& er) {
 	std::cerr << "\nBLIS ERROR: \"" << er.message() 
		  << "\""<< std::endl
		  << "             from function \"" << er.methodName()
		  << "\""<< std::endl
		  << "             from class \"" << er.className()
		  << "\"" << std::endl;
	}
  catch(...) {
		std::cerr << "Something went wrong!" << std::endl;
  }
    
    
  return 0;
}
Пример #2
0
// inner part of dive
int 
CbcHeuristicDive::solution(double & solutionValue, int & numberNodes,
			   int & numberCuts, OsiRowCut ** cuts,
			   CbcSubProblem ** & nodes,
			   double * newSolution)
{
#ifdef DIVE_DEBUG
    int nRoundInfeasible = 0;
    int nRoundFeasible = 0;
#endif
    int reasonToStop = 0;
    double time1 = CoinCpuTime();
    int numberSimplexIterations = 0;
    int maxSimplexIterations = (model_->getNodeCount()) ? maxSimplexIterations_
                               : maxSimplexIterationsAtRoot_;
    // but can't be exactly coin_int_max
    maxSimplexIterations = CoinMin(maxSimplexIterations,COIN_INT_MAX>>3);
    OsiSolverInterface * solver = cloneBut(6); // was model_->solver()->clone();
# ifdef COIN_HAS_CLP
    OsiClpSolverInterface * clpSolver
    = dynamic_cast<OsiClpSolverInterface *> (solver);
    if (clpSolver) {
      ClpSimplex * clpSimplex = clpSolver->getModelPtr();
      int oneSolveIts = clpSimplex->maximumIterations();
      oneSolveIts = CoinMin(1000+2*(clpSimplex->numberRows()+clpSimplex->numberColumns()),oneSolveIts);
      clpSimplex->setMaximumIterations(oneSolveIts);
      if (!nodes) {
        // say give up easily
        clpSimplex->setMoreSpecialOptions(clpSimplex->moreSpecialOptions() | 64);
      } else {
	// get ray
	int specialOptions = clpSimplex->specialOptions();
	specialOptions &= ~0x3100000;
	specialOptions |= 32;
        clpSimplex->setSpecialOptions(specialOptions);
        clpSolver->setSpecialOptions(clpSolver->specialOptions() | 1048576);
	if ((model_->moreSpecialOptions()&16777216)!=0) {
	  // cutoff is constraint
	  clpSolver->setDblParam(OsiDualObjectiveLimit, COIN_DBL_MAX);
	}
      }
    }
# endif
    const double * lower = solver->getColLower();
    const double * upper = solver->getColUpper();
    const double * rowLower = solver->getRowLower();
    const double * rowUpper = solver->getRowUpper();
    const double * solution = solver->getColSolution();
    const double * objective = solver->getObjCoefficients();
    double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
    double primalTolerance;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance);

    int numberRows = matrix_.getNumRows();
    assert (numberRows <= solver->getNumRows());
    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();
    double direction = solver->getObjSense(); // 1 for min, -1 for max
    double newSolutionValue = direction * solver->getObjValue();
    int returnCode = 0;
    // Column copy
    const double * element = matrix_.getElements();
    const int * row = matrix_.getIndices();
    const CoinBigIndex * columnStart = matrix_.getVectorStarts();
    const int * columnLength = matrix_.getVectorLengths();
#ifdef DIVE_FIX_BINARY_VARIABLES
    // Row copy
    const double * elementByRow = matrixByRow_.getElements();
    const int * column = matrixByRow_.getIndices();
    const CoinBigIndex * rowStart = matrixByRow_.getVectorStarts();
    const int * rowLength = matrixByRow_.getVectorLengths();
#endif

    // Get solution array for heuristic solution
    int numberColumns = solver->getNumCols();
    memcpy(newSolution, solution, numberColumns*sizeof(double));

    // vectors to store the latest variables fixed at their bounds
    int* columnFixed = new int [numberIntegers];
    double* originalBound = new double [numberIntegers+2*numberColumns];
    double * lowerBefore = originalBound+numberIntegers;
    double * upperBefore = lowerBefore+numberColumns;
    memcpy(lowerBefore,lower,numberColumns*sizeof(double));
    memcpy(upperBefore,upper,numberColumns*sizeof(double));
    double * lastDjs=newSolution+numberColumns;
    bool * fixedAtLowerBound = new bool [numberIntegers];
    PseudoReducedCost * candidate = new PseudoReducedCost [numberIntegers];
    double * random = new double [numberIntegers];

    int maxNumberAtBoundToFix = static_cast<int> (floor(percentageToFix_ * numberIntegers));
    assert (!maxNumberAtBoundToFix||!nodes);

    // count how many fractional variables
    int numberFractionalVariables = 0;
    for (int i = 0; i < numberIntegers; i++) {
        random[i] = randomNumberGenerator_.randomDouble() + 0.3;
        int iColumn = integerVariable[i];
        double value = newSolution[iColumn];
        if (fabs(floor(value + 0.5) - value) > integerTolerance) {
            numberFractionalVariables++;
        }
    }

    const double* reducedCost = NULL;
    // See if not NLP
    if (model_->solverCharacteristics()->reducedCostsAccurate())
        reducedCost = solver->getReducedCost();

    int iteration = 0;
    while (numberFractionalVariables) {
        iteration++;

        // initialize any data
        initializeData();

        // select a fractional variable to bound
        int bestColumn = -1;
        int bestRound; // -1 rounds down, +1 rounds up
        bool canRound = selectVariableToBranch(solver, newSolution,
                                               bestColumn, bestRound);
        // if the solution is not trivially roundable, we don't try to round;
        // if the solution is trivially roundable, we try to round. However,
        // if the rounded solution is worse than the current incumbent,
        // then we don't round and proceed normally. In this case, the
        // bestColumn will be a trivially roundable variable
        if (canRound) {
            // check if by rounding all fractional variables
            // we get a solution with an objective value
            // better than the current best integer solution
            double delta = 0.0;
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                double value = newSolution[iColumn];
                if (fabs(floor(value + 0.5) - value) > integerTolerance) {
                    assert(downLocks_[i] == 0 || upLocks_[i] == 0);
                    double obj = objective[iColumn];
                    if (downLocks_[i] == 0 && upLocks_[i] == 0) {
                        if (direction * obj >= 0.0)
                            delta += (floor(value) - value) * obj;
                        else
                            delta += (ceil(value) - value) * obj;
                    } else if (downLocks_[i] == 0)
                        delta += (floor(value) - value) * obj;
                    else
                        delta += (ceil(value) - value) * obj;
                }
            }
            if (direction*(solver->getObjValue() + delta) < solutionValue) {
#ifdef DIVE_DEBUG
                nRoundFeasible++;
#endif
		if (!nodes||bestColumn<0) {
		  // Round all the fractional variables
		  for (int i = 0; i < numberIntegers; i++) {
                    int iColumn = integerVariable[i];
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) > integerTolerance) {
		      assert(downLocks_[i] == 0 || upLocks_[i] == 0);
		      if (downLocks_[i] == 0 && upLocks_[i] == 0) {
			if (direction * objective[iColumn] >= 0.0)
			  newSolution[iColumn] = floor(value);
			else
			  newSolution[iColumn] = ceil(value);
		      } else if (downLocks_[i] == 0)
			newSolution[iColumn] = floor(value);
		      else
			newSolution[iColumn] = ceil(value);
                    }
		  }
		  break;
		} else {
		  // can't round if going to use in branching
		  int i;
		  for (i = 0; i < numberIntegers; i++) {
		    int iColumn = integerVariable[i];
		    double value = newSolution[bestColumn];
		    if (fabs(floor(value + 0.5) - value) > integerTolerance) {
		      if (iColumn==bestColumn) {
			assert(downLocks_[i] == 0 || upLocks_[i] == 0);
			double obj = objective[bestColumn];
			if (downLocks_[i] == 0 && upLocks_[i] == 0) {
			  if (direction * obj >= 0.0)
                            bestRound=-1;
			  else
                            bestRound=1;
			} else if (downLocks_[i] == 0)
			  bestRound=-1;
			else
			  bestRound=1;
			break;
		      }
		    }
		  }
		}
	    }
#ifdef DIVE_DEBUG
            else
                nRoundInfeasible++;
#endif
        }

        // do reduced cost fixing
#ifdef DIVE_DEBUG
        int numberFixed = reducedCostFix(solver);
        std::cout << "numberReducedCostFixed = " << numberFixed << std::endl;
#else
        reducedCostFix(solver);
#endif

        int numberAtBoundFixed = 0;
#ifdef DIVE_FIX_BINARY_VARIABLES
        // fix binary variables based on pseudo reduced cost
        if (binVarIndex_.size()) {
            int cnt = 0;
            int n = static_cast<int>(binVarIndex_.size());
            for (int j = 0; j < n; j++) {
                int iColumn1 = binVarIndex_[j];
                double value = newSolution[iColumn1];
                if (fabs(value) <= integerTolerance &&
                        lower[iColumn1] != upper[iColumn1]) {
                    double maxPseudoReducedCost = 0.0;
#ifdef DIVE_DEBUG
                    std::cout << "iColumn1 = " << iColumn1 << ", value = " << value << std::endl;
#endif
                    int iRow = vbRowIndex_[j];
                    double chosenValue = 0.0;
                    for (int k = rowStart[iRow]; k < rowStart[iRow] + rowLength[iRow]; k++) {
                        int iColumn2 = column[k];
#ifdef DIVE_DEBUG
                        std::cout << "iColumn2 = " << iColumn2 << std::endl;
#endif
                        if (iColumn1 != iColumn2) {
                            double pseudoReducedCost = fabs(reducedCost[iColumn2] *
                                                            elementByRow[k]);
#ifdef DIVE_DEBUG
                            int k2;
                            for (k2 = rowStart[iRow]; k2 < rowStart[iRow] + rowLength[iRow]; k2++) {
                                if (column[k2] == iColumn1)
                                    break;
                            }
                            std::cout << "reducedCost[" << iColumn2 << "] = "
                                      << reducedCost[iColumn2]
                                      << ", elementByRow[" << iColumn2 << "] = " << elementByRow[k]
                                      << ", elementByRow[" << iColumn1 << "] = " << elementByRow[k2]
                                      << ", pseudoRedCost = " << pseudoReducedCost
                                      << std::endl;
#endif
                            if (pseudoReducedCost > maxPseudoReducedCost)
                                maxPseudoReducedCost = pseudoReducedCost;
                        } else {
                            // save value
                            chosenValue = fabs(elementByRow[k]);
                        }
                    }
                    assert (chosenValue);
                    maxPseudoReducedCost /= chosenValue;
#ifdef DIVE_DEBUG
                    std::cout << ", maxPseudoRedCost = " << maxPseudoReducedCost << std::endl;
#endif
                    candidate[cnt].var = iColumn1;
                    candidate[cnt++].pseudoRedCost = maxPseudoReducedCost;
                }
            }
#ifdef DIVE_DEBUG
            std::cout << "candidates for rounding = " << cnt << std::endl;
#endif
            std::sort(candidate, candidate + cnt, compareBinaryVars);
            for (int i = 0; i < cnt; i++) {
                int iColumn = candidate[i].var;
                if (numberAtBoundFixed < maxNumberAtBoundToFix) {
                    columnFixed[numberAtBoundFixed] = iColumn;
                    originalBound[numberAtBoundFixed] = upper[iColumn];
                    fixedAtLowerBound[numberAtBoundFixed] = true;
                    solver->setColUpper(iColumn, lower[iColumn]);
                    numberAtBoundFixed++;
                    if (numberAtBoundFixed == maxNumberAtBoundToFix)
                        break;
                }
            }
        }
#endif

        // fix other integer variables that are at their bounds
        int cnt = 0;
#ifdef GAP
        double gap = 1.0e30;
#endif
        if (reducedCost && true) {
#ifndef JJF_ONE
            cnt = fixOtherVariables(solver, solution, candidate, random);
#else
#ifdef GAP
            double cutoff = model_->getCutoff() ;
            if (cutoff < 1.0e20 && false) {
                double direction = solver->getObjSense() ;
                gap = cutoff - solver->getObjValue() * direction ;
                gap *= 0.1; // Fix more if plausible
                double tolerance;
                solver->getDblParam(OsiDualTolerance, tolerance) ;
                if (gap <= 0.0)
                    gap = tolerance;
                gap += 100.0 * tolerance;
            }
            int nOverGap = 0;
#endif
            int numberFree = 0;
            int numberFixed = 0;
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    numberFree++;
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) <= integerTolerance) {
                        candidate[cnt].var = iColumn;
                        candidate[cnt++].pseudoRedCost =
                            fabs(reducedCost[iColumn] * random[i]);
#ifdef GAP
                        if (fabs(reducedCost[iColumn]) > gap)
                            nOverGap++;
#endif
                    }
                } else {
                    numberFixed++;
                }
            }
#ifdef GAP
            int nLeft = maxNumberAtBoundToFix - numberAtBoundFixed;
#ifdef CLP_INVESTIGATE4
            printf("cutoff %g obj %g nover %d - %d free, %d fixed\n",
                   cutoff, solver->getObjValue(), nOverGap, numberFree, numberFixed);
#endif
            if (nOverGap > nLeft && true) {
                nOverGap = CoinMin(nOverGap, nLeft + maxNumberAtBoundToFix / 2);
                maxNumberAtBoundToFix += nOverGap - nLeft;
            }
#else
#ifdef CLP_INVESTIGATE4
            printf("cutoff %g obj %g - %d free, %d fixed\n",
                   model_->getCutoff(), solver->getObjValue(), numberFree, numberFixed);
#endif
#endif
#endif
        } else {
            for (int i = 0; i < numberIntegers; i++) {
                int iColumn = integerVariable[i];
                if (upper[iColumn] > lower[iColumn]) {
                    double value = newSolution[iColumn];
                    if (fabs(floor(value + 0.5) - value) <= integerTolerance) {
                        candidate[cnt].var = iColumn;
                        candidate[cnt++].pseudoRedCost = numberIntegers - i;
                    }
                }
            }
        }
        std::sort(candidate, candidate + cnt, compareBinaryVars);
        for (int i = 0; i < cnt; i++) {
            int iColumn = candidate[i].var;
            if (upper[iColumn] > lower[iColumn]) {
                double value = newSolution[iColumn];
                if (fabs(floor(value + 0.5) - value) <= integerTolerance &&
                        numberAtBoundFixed < maxNumberAtBoundToFix) {
                    // fix the variable at one of its bounds
                    if (fabs(lower[iColumn] - value) <= integerTolerance) {
                        columnFixed[numberAtBoundFixed] = iColumn;
                        originalBound[numberAtBoundFixed] = upper[iColumn];
                        fixedAtLowerBound[numberAtBoundFixed] = true;
                        solver->setColUpper(iColumn, lower[iColumn]);
                        numberAtBoundFixed++;
                    } else if (fabs(upper[iColumn] - value) <= integerTolerance) {
                        columnFixed[numberAtBoundFixed] = iColumn;
                        originalBound[numberAtBoundFixed] = lower[iColumn];
                        fixedAtLowerBound[numberAtBoundFixed] = false;
                        solver->setColLower(iColumn, upper[iColumn]);
                        numberAtBoundFixed++;
                    }
                    if (numberAtBoundFixed == maxNumberAtBoundToFix)
                        break;
                }
            }
        }
#ifdef DIVE_DEBUG
        std::cout << "numberAtBoundFixed = " << numberAtBoundFixed << std::endl;
#endif

        double originalBoundBestColumn;
        double bestColumnValue;
	int whichWay;
        if (bestColumn >= 0) {
	    bestColumnValue = newSolution[bestColumn];
            if (bestRound < 0) {
                originalBoundBestColumn = upper[bestColumn];
                solver->setColUpper(bestColumn, floor(bestColumnValue));
		whichWay=0;
            } else {
                originalBoundBestColumn = lower[bestColumn];
                solver->setColLower(bestColumn, ceil(bestColumnValue));
		whichWay=1;
            }
        } else {
            break;
        }
        int originalBestRound = bestRound;
        int saveModelOptions = model_->specialOptions();
	
        while (1) {

            model_->setSpecialOptions(saveModelOptions | 2048);
            solver->resolve();
            model_->setSpecialOptions(saveModelOptions);
            if (!solver->isAbandoned()&&!solver->isIterationLimitReached()) {
                numberSimplexIterations += solver->getIterationCount();
            } else {
                numberSimplexIterations = maxSimplexIterations + 1;
		reasonToStop += 100;
                break;
            }

            if (!solver->isProvenOptimal()) {
	        if (nodes) {
		  if (solver->isProvenPrimalInfeasible()) {
		    if (maxSimplexIterationsAtRoot_!=COIN_INT_MAX) {
		      // stop now
		      printf("stopping on first infeasibility\n");
		      break;
		    } else if (cuts) {
		      // can do conflict cut
		      printf("could do intermediate conflict cut\n");
		      bool localCut;
		      OsiRowCut * cut = model_->conflictCut(solver,localCut);
		      if (cut) {
			if (!localCut) {
			  model_->makePartialCut(cut,solver);
			  cuts[numberCuts++]=cut;
			} else {
			  delete cut;
			}
		      }
		    }
		  } else {
		    reasonToStop += 10;
		    break;
		  }
		}
                if (numberAtBoundFixed > 0) {
                    // Remove the bound fix for variables that were at bounds
                    for (int i = 0; i < numberAtBoundFixed; i++) {
                        int iColFixed = columnFixed[i];
                        if (fixedAtLowerBound[i])
                            solver->setColUpper(iColFixed, originalBound[i]);
                        else
                            solver->setColLower(iColFixed, originalBound[i]);
                    }
                    numberAtBoundFixed = 0;
                } else if (bestRound == originalBestRound) {
                    bestRound *= (-1);
		    whichWay |=2;
                    if (bestRound < 0) {
                        solver->setColLower(bestColumn, originalBoundBestColumn);
                        solver->setColUpper(bestColumn, floor(bestColumnValue));
                    } else {
                        solver->setColLower(bestColumn, ceil(bestColumnValue));
                        solver->setColUpper(bestColumn, originalBoundBestColumn);
                    }
                } else
                    break;
            } else
                break;
        }

        if (!solver->isProvenOptimal() ||
                direction*solver->getObjValue() >= solutionValue) {
            reasonToStop += 1;
        } else if (iteration > maxIterations_) {
            reasonToStop += 2;
        } else if (CoinCpuTime() - time1 > maxTime_) {
            reasonToStop += 3;
        } else if (numberSimplexIterations > maxSimplexIterations) {
            reasonToStop += 4;
            // also switch off
#ifdef CLP_INVESTIGATE
            printf("switching off diving as too many iterations %d, %d allowed\n",
                   numberSimplexIterations, maxSimplexIterations);
#endif
            when_ = 0;
        } else if (solver->getIterationCount() > 1000 && iteration > 3 && !nodes) {
            reasonToStop += 5;
            // also switch off
#ifdef CLP_INVESTIGATE
            printf("switching off diving one iteration took %d iterations (total %d)\n",
                   solver->getIterationCount(), numberSimplexIterations);
#endif
            when_ = 0;
        }

        memcpy(newSolution, solution, numberColumns*sizeof(double));
        numberFractionalVariables = 0;
	double sumFractionalVariables=0.0;
        for (int i = 0; i < numberIntegers; i++) {
            int iColumn = integerVariable[i];
            double value = newSolution[iColumn];
	    double away = fabs(floor(value + 0.5) - value);
            if (away > integerTolerance) {
                numberFractionalVariables++;
		sumFractionalVariables += away;
            }
        }
	if (nodes) {
	  // save information
	  //branchValues[numberNodes]=bestColumnValue;
	  //statuses[numberNodes]=whichWay+(bestColumn<<2);
	  //bases[numberNodes]=solver->getWarmStart();
	  ClpSimplex * simplex = clpSolver->getModelPtr();
	  CbcSubProblem * sub =
	    new CbcSubProblem(clpSolver,lowerBefore,upperBefore,
			  simplex->statusArray(),numberNodes);
	  nodes[numberNodes]=sub;
	  // other stuff
	  sub->branchValue_=bestColumnValue;
	  sub->problemStatus_=whichWay;
	  sub->branchVariable_=bestColumn;
	  sub->objectiveValue_ = simplex->objectiveValue();
	  sub->sumInfeasibilities_ = sumFractionalVariables;
	  sub->numberInfeasibilities_ = numberFractionalVariables;
	  printf("DiveNode %d column %d way %d bvalue %g obj %g\n",
		 numberNodes,sub->branchVariable_,sub->problemStatus_,
		 sub->branchValue_,sub->objectiveValue_);
	  numberNodes++;
	  if (solver->isProvenOptimal()) {
	    memcpy(lastDjs,solver->getReducedCost(),numberColumns*sizeof(double));
	    memcpy(lowerBefore,lower,numberColumns*sizeof(double));
	    memcpy(upperBefore,upper,numberColumns*sizeof(double));
	  }
	}
	if (!numberFractionalVariables||reasonToStop)
	  break;
    }
    if (nodes) {
      printf("Exiting dive for reason %d\n",reasonToStop);
      if (reasonToStop>1) {
	printf("problems in diving\n");
	int whichWay=nodes[numberNodes-1]->problemStatus_;
	CbcSubProblem * sub;
	if ((whichWay&2)==0) {
	  // leave both ways
	  sub = new CbcSubProblem(*nodes[numberNodes-1]);
	  nodes[numberNodes++]=sub;
	} else {
	  sub = nodes[numberNodes-1];
	}
	if ((whichWay&1)==0)
	  sub->problemStatus_=whichWay|1;
	else
	  sub->problemStatus_=whichWay&~1;
      }
      if (!numberNodes) {
	// was good at start! - create fake
	clpSolver->resolve();
	ClpSimplex * simplex = clpSolver->getModelPtr();
	CbcSubProblem * sub =
	  new CbcSubProblem(clpSolver,lowerBefore,upperBefore,
			    simplex->statusArray(),numberNodes);
	nodes[numberNodes]=sub;
	// other stuff
	sub->branchValue_=0.0;
	sub->problemStatus_=0;
	sub->branchVariable_=-1;
	sub->objectiveValue_ = simplex->objectiveValue();
	sub->sumInfeasibilities_ = 0.0;
	sub->numberInfeasibilities_ = 0;
	printf("DiveNode %d column %d way %d bvalue %g obj %g\n",
	       numberNodes,sub->branchVariable_,sub->problemStatus_,
	       sub->branchValue_,sub->objectiveValue_);
	numberNodes++;
	assert (solver->isProvenOptimal());
      }
      nodes[numberNodes-1]->problemStatus_ |= 256*reasonToStop;
      // use djs as well
      if (solver->isProvenPrimalInfeasible()&&cuts) {
	// can do conflict cut and re-order
	printf("could do final conflict cut\n");
	bool localCut;
	OsiRowCut * cut = model_->conflictCut(solver,localCut);
	if (cut) {
	  printf("cut - need to use conflict and previous djs\n");
	  if (!localCut) {
	    model_->makePartialCut(cut,solver);
	    cuts[numberCuts++]=cut;
	  } else {
	    delete cut;
	  }
	} else {
	  printf("bad conflict - just use previous djs\n");
	}
      }
    }
    
    // re-compute new solution value
    double objOffset = 0.0;
    solver->getDblParam(OsiObjOffset, objOffset);
    newSolutionValue = -objOffset;
    for (int i = 0 ; i < numberColumns ; i++ )
      newSolutionValue += objective[i] * newSolution[i];
    newSolutionValue *= direction;
    //printf("new solution value %g %g\n",newSolutionValue,solutionValue);
    if (newSolutionValue < solutionValue && !reasonToStop) {
      double * rowActivity = new double[numberRows];
      memset(rowActivity, 0, numberRows*sizeof(double));
      // paranoid check
      memset(rowActivity, 0, numberRows*sizeof(double));
      for (int i = 0; i < numberColumns; i++) {
	int j;
	double value = newSolution[i];
	if (value) {
	  for (j = columnStart[i];
	       j < columnStart[i] + columnLength[i]; j++) {
	    int iRow = row[j];
	    rowActivity[iRow] += value * element[j];
	  }
	}
      }
      // check was approximately feasible
      bool feasible = true;
      for (int i = 0; i < numberRows; i++) {
	if (rowActivity[i] < rowLower[i]) {
	  if (rowActivity[i] < rowLower[i] - 1000.0*primalTolerance)
	    feasible = false;
	} else if (rowActivity[i] > rowUpper[i]) {
	  if (rowActivity[i] > rowUpper[i] + 1000.0*primalTolerance)
	    feasible = false;
	}
      }
      for (int i = 0; i < numberIntegers; i++) {
	int iColumn = integerVariable[i];
	double value = newSolution[iColumn];
	if (fabs(floor(value + 0.5) - value) > integerTolerance) {
	  feasible = false;
	  break;
	}
      }
      if (feasible) {
	// new solution
	solutionValue = newSolutionValue;
	//printf("** Solution of %g found by CbcHeuristicDive\n",newSolutionValue);
	//if (cuts)
	//clpSolver->getModelPtr()->writeMps("good8.mps", 2);
	returnCode = 1;
      } else {
	// Can easily happen
	//printf("Debug CbcHeuristicDive giving bad solution\n");
      }
      delete [] rowActivity;
    }

#ifdef DIVE_DEBUG
    std::cout << "nRoundInfeasible = " << nRoundInfeasible
              << ", nRoundFeasible = " << nRoundFeasible
              << ", returnCode = " << returnCode
              << ", reasonToStop = " << reasonToStop
              << ", simplexIts = " << numberSimplexIterations
              << ", iterations = " << iteration << std::endl;
#endif

    delete [] columnFixed;
    delete [] originalBound;
    delete [] fixedAtLowerBound;
    delete [] candidate;
    delete [] random;
    delete [] downArray_;
    downArray_ = NULL;
    delete [] upArray_;
    upArray_ = NULL;
    delete solver;
    return returnCode;
}
Пример #3
0
int CbcHeuristicDive::reducedCostFix (OsiSolverInterface* solver)

{
    //return 0; // temp
#ifndef JJF_ONE
    if (!model_->solverCharacteristics()->reducedCostsAccurate())
        return 0; //NLP
#endif
    double cutoff = model_->getCutoff() ;
    if (cutoff > 1.0e20)
        return 0;
#ifdef DIVE_DEBUG
    std::cout << "cutoff = " << cutoff << std::endl;
#endif
    double direction = solver->getObjSense() ;
    double gap = cutoff - solver->getObjValue() * direction ;
    gap *= 0.5; // Fix more
    double tolerance;
    solver->getDblParam(OsiDualTolerance, tolerance) ;
    if (gap <= 0.0)
        gap = tolerance; //return 0;
    gap += 100.0 * tolerance;
    double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);

    const double *lower = solver->getColLower() ;
    const double *upper = solver->getColUpper() ;
    const double *solution = solver->getColSolution() ;
    const double *reducedCost = solver->getReducedCost() ;

    int numberIntegers = model_->numberIntegers();
    const int * integerVariable = model_->integerVariable();

    int numberFixed = 0 ;

# ifdef COIN_HAS_CLP
    OsiClpSolverInterface * clpSolver
    = dynamic_cast<OsiClpSolverInterface *> (solver);
    ClpSimplex * clpSimplex = NULL;
    if (clpSolver)
        clpSimplex = clpSolver->getModelPtr();
# endif
    for (int i = 0 ; i < numberIntegers ; i++) {
        int iColumn = integerVariable[i] ;
        double djValue = direction * reducedCost[iColumn] ;
        if (upper[iColumn] - lower[iColumn] > integerTolerance) {
            if (solution[iColumn] < lower[iColumn] + integerTolerance && djValue > gap) {
#ifdef COIN_HAS_CLP
                // may just have been fixed before
                if (clpSimplex) {
                    if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
#ifdef COIN_DEVELOP
                        printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
                               iColumn, clpSimplex->getColumnStatus(iColumn),
                               djValue, gap, lower[iColumn], upper[iColumn]);
#endif
                    } else {
                        assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atLowerBound ||
                               clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
                    }
                }
#endif
                solver->setColUpper(iColumn, lower[iColumn]) ;
                numberFixed++ ;
            } else if (solution[iColumn] > upper[iColumn] - integerTolerance && -djValue > gap) {
#ifdef COIN_HAS_CLP
                // may just have been fixed before
                if (clpSimplex) {
                    if (clpSimplex->getColumnStatus(iColumn) == ClpSimplex::basic) {
#ifdef COIN_DEVELOP
                        printf("DJfix %d has status of %d, dj of %g gap %g, bounds %g %g\n",
                               iColumn, clpSimplex->getColumnStatus(iColumn),
                               djValue, gap, lower[iColumn], upper[iColumn]);
#endif
                    } else {
                        assert(clpSimplex->getColumnStatus(iColumn) == ClpSimplex::atUpperBound ||
                               clpSimplex->getColumnStatus(iColumn) == ClpSimplex::isFixed);
                    }
                }
#endif
                solver->setColLower(iColumn, upper[iColumn]) ;
                numberFixed++ ;
            }
        }
    }
    return numberFixed;
}
Пример #4
0
int main( int argc, char **argv )
{
    if ( argc < 2 )
    {
        printf("Invalid number of parameters!\n");
        exit( EXIT_FAILURE );
    }

    char problemName[ 256 ];
    getFileName( problemName, argv[1] );

    clock_t start = clock();
    OsiClpSolverInterface *realSolver = new OsiClpSolverInterface();
    realSolver->getModelPtr()->setPerturbation(50); /* makes CLP faster for hard instances */
    OsiSolverInterface *solver = (OsiSolverInterface*) realSolver;

    parseParameters( argc, argv );
    readLP( solver, argv[1] );

    FILE *log = NULL;
    if(!output.empty())
    {
        log = fopen(output.c_str(), "a");
        if(!log)
        {
            printf("Could not open the file!\n");
            exit(EXIT_FAILURE);
        }
    }

    const int numCols = solver->getNumCols(), numRows = solver->getNumRows();
    int pass = 0, newCuts = 0, totalCuts = 0;
    double pTime, opt, cgTime;
    CGraph *cgraph = NULL;

    if(sepMethod == Npsep)
    	cgraph = build_cgraph_osi( solver );

    if(!optFile.empty())
    {
        getOptimals();
        if(optimals.find(problemName) == optimals.end())
        {
            fprintf(stderr, "ERROR: optimal value not found!\n");
            exit(EXIT_FAILURE);
        }
        opt = optimals[problemName];
    }

    solver->initialSolve();

    if (!solver->isProvenOptimal())
    {
        if (solver->isAbandoned())
        {
            fprintf( stderr, "LP solver abandoned due to numerical dificulties.\n" );
            exit( EXIT_FAILURE );
        }
        if (solver->isProvenPrimalInfeasible())
        {
            fprintf( stderr, "LP solver says PRIMAL INFEASIBLE.\n" );
            exit( EXIT_FAILURE );
        }
        if (solver->isProvenDualInfeasible())
        {
            fprintf( stderr, "LP solver says DUAL INFEASIBLE.\n" );
            exit( EXIT_FAILURE );
        }
        if (solver->isPrimalObjectiveLimitReached())
        {
            fprintf( stderr, "LP solver says isPrimalObjectiveLimitReached.\n" );
            exit( EXIT_FAILURE );
        }
        if (solver->isDualObjectiveLimitReached())
        {
            fprintf( stderr, "LP solver says isDualObjectiveLimitReached.\n" );
            exit( EXIT_FAILURE );
        }
        if (solver->isIterationLimitReached())
        {
            fprintf( stderr, "LP solver says isIterationLimitReached.\n" );
            exit( EXIT_FAILURE );
        }

        fprintf( stderr, "ERROR: Could not solve LP relaxation to optimality. Checking status...\n" );
        exit( EXIT_FAILURE );
    }

    double initialBound = solver->getObjValue();
    printf("%.2lf %d %d %.7lf", ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC), pass, 0, solver->getObjValue());
    if(!optFile.empty())
    {
        printf(" %.7lf %.7lf", opt, abs_mip_gap(solver->getObjValue(), opt));
    }
    printf("\n");

    do
    {
        clock_t startSep = clock();
        newCuts = 0;

        switch (sepMethod)
        {
            case Npsep:
            {
                CglEClique cliqueGen;
                OsiCuts cuts;
                CglTreeInfo info;
                info.level = 0;
                info.pass = 1;
                vector<string> varNames = getVarNames(solver->getColNames(), numCols);
                cliqueGen.parseParameters( argc, (const char**)argv );
                cliqueGen.setCGraph( cgraph );
                cliqueGen.setGenOddHoles( true ); //allow (or not) inserting odd hole cuts
                cliqueGen.colNames = &varNames;
                cliqueGen.generateCuts( *solver, cuts, info );
                newCuts = cuts.sizeCuts();
                solver->applyCuts( cuts );
            }
            break;

            case CglSepM:
            {
                CglClique cliqueGen;
                OsiCuts cuts;
                CglTreeInfo info;
                info.level = 0;
                info.pass = 1;
                cliqueGen.setMinViolation( MIN_VIOLATION );
                cliqueGen.setStarCliqueReport(false);
                cliqueGen.setRowCliqueReport(false);
                cliqueGen.generateCuts( *solver, cuts, info );
                newCuts = cuts.sizeCuts();
                solver->applyCuts( cuts );
            }
            break;

            Default:
            {
            	fprintf( stderr, "Separation Method does not recognized!\n" );
                exit( EXIT_FAILURE );
            }
        }

        pTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC);
        if(pTime > MAX_TIME) break;

        totalCuts += newCuts;
        ++pass;

        if (newCuts)
        {
            solver->resolve();
            if (!solver->isProvenOptimal())
            {
                if (solver->isAbandoned())
                {
                    fprintf( stderr, "LP solver abandoned due to numerical dificulties.\n" );
                    exit( EXIT_FAILURE );
                }
                if (solver->isProvenPrimalInfeasible())
                {
                    fprintf( stderr, "LP solver says PRIMAL INFEASIBLE.\n" );
                    exit( EXIT_FAILURE );
                }
                if (solver->isProvenDualInfeasible())
                {
                    fprintf( stderr, "LP solver says DUAL INFEASIBLE.\n" );
                    exit( EXIT_FAILURE );
                }
                if (solver->isPrimalObjectiveLimitReached())
                {
                    fprintf( stderr, "LP solver says isPrimalObjectiveLimitReached.\n" );
                    exit( EXIT_FAILURE );
                }
                if (solver->isDualObjectiveLimitReached())
                {
                    fprintf( stderr, "LP solver says isDualObjectiveLimitReached.\n" );
                    exit( EXIT_FAILURE );
                }
                if (solver->isIterationLimitReached())
                {
                    fprintf( stderr, "LP solver says isIterationLimitReached.\n" );
                    exit( EXIT_FAILURE );
                }

                fprintf( stderr, "ERROR: Could not solve LP relaxation. Exiting.\n" );
                exit( EXIT_FAILURE );
            }

            pTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC);
            if(pTime > MAX_TIME) break;

            double sepTime = ((double)(clock()-startSep)) / ((double)CLOCKS_PER_SEC);
            printf("%.2lf %d %d %.7lf", sepTime, pass, newCuts, solver->getObjValue());
            if(!optFile.empty())
                printf(" %.7lf %.7lf", opt, abs_mip_gap(solver->getObjValue(), opt));
            printf("\n");
        }
    }
    while ( (newCuts>0) && (pass<MAX_PASSES) ) ;

    if(log)
    {
        double totalTime = ((double)(clock()-start)) / ((double)CLOCKS_PER_SEC);
        fprintf(log, "%s %.2lf %d %d %.7lf", problemName, totalTime, pass - 1, totalCuts, solver->getObjValue());
        if(!optFile.empty())
            fprintf(log, " %.7lf", abs_mip_gap(solver->getObjValue(), opt));
        fprintf(log, "\n");
    }

    if(cgraph)
    	cgraph_free( &cgraph );

   	delete realSolver;

    return EXIT_SUCCESS;
}
Пример #5
0
CbcBranchingObject *
CbcGeneralDepth::createCbcBranch(OsiSolverInterface * solver, const OsiBranchingInformation * info, int /*way*/)
{
    int numberDo = numberNodes_;
    if (whichSolution_ >= 0 && (model_->moreSpecialOptions()&33554432)==0) 
        numberDo--;
    assert (numberDo > 0);
    // create object
    CbcGeneralBranchingObject * branch = new CbcGeneralBranchingObject(model_);
    // skip solution
    branch->numberSubProblems_ = numberDo;
    // If parentBranch_ back in then will have to be 2*
    branch->numberSubLeft_ = numberDo;
    branch->setNumberBranches(numberDo);
    CbcSubProblem * sub = new CbcSubProblem[numberDo];
    int iProb = 0;
    branch->subProblems_ = sub;
    branch->numberRows_ = model_->solver()->getNumRows();
    int iNode;
    //OsiSolverInterface * solver = model_->solver();
    OsiClpSolverInterface * clpSolver
    = dynamic_cast<OsiClpSolverInterface *> (solver);
    assert (clpSolver);
    ClpSimplex * simplex = clpSolver->getModelPtr();
    int numberColumns = simplex->numberColumns();
    if ((model_->moreSpecialOptions()&33554432)==0) {
      double * lowerBefore = CoinCopyOfArray(simplex->getColLower(),
					     numberColumns);
      double * upperBefore = CoinCopyOfArray(simplex->getColUpper(),
					     numberColumns);
      ClpNodeStuff * info = nodeInfo_;
      double * weight = new double[numberNodes_];
      int * whichNode = new int [numberNodes_];
      // Sort
      for (iNode = 0; iNode < numberNodes_; iNode++) {
        if (iNode != whichSolution_) {
	  double objectiveValue = info->nodeInfo_[iNode]->objectiveValue();
	  double sumInfeasibilities = info->nodeInfo_[iNode]->sumInfeasibilities();
	  int numberInfeasibilities = info->nodeInfo_[iNode]->numberInfeasibilities();
	  double thisWeight = 0.0;
#if 1
	  // just closest
	  thisWeight = 1.0e9 * numberInfeasibilities;
	  thisWeight += sumInfeasibilities;
	  thisWeight += 1.0e-7 * objectiveValue;
	  // Try estimate
	  thisWeight = info->nodeInfo_[iNode]->estimatedSolution();
#else
	  thisWeight = 1.0e-3 * numberInfeasibilities;
	  thisWeight += 1.0e-5 * sumInfeasibilities;
	  thisWeight += objectiveValue;
#endif
	  whichNode[iProb] = iNode;
	  weight[iProb++] = thisWeight;
        }
      }
      assert (iProb == numberDo);
      CoinSort_2(weight, weight + numberDo, whichNode);
      for (iProb = 0; iProb < numberDo; iProb++) {
        iNode = whichNode[iProb];
        ClpNode * node = info->nodeInfo_[iNode];
        // move bounds
        node->applyNode(simplex, 3);
        // create subproblem
        sub[iProb] = CbcSubProblem(clpSolver, lowerBefore, upperBefore,
                                   node->statusArray(), node->depth());
        sub[iProb].objectiveValue_ = node->objectiveValue();
        sub[iProb].sumInfeasibilities_ = node->sumInfeasibilities();
        sub[iProb].numberInfeasibilities_ = node->numberInfeasibilities();
#ifdef CHECK_PATH
        if (simplex->numberColumns() == numberColumns_Z) {
	  bool onOptimal = true;
	  const double * columnLower = simplex->columnLower();
	  const double * columnUpper = simplex->columnUpper();
	  for (int i = 0; i < numberColumns_Z; i++) {
	    if (iNode == gotGoodNode_Z)
	      printf("good %d %d %g %g\n", iNode, i, columnLower[i], columnUpper[i]);
	    if (columnUpper[i] < debuggerSolution_Z[i] || columnLower[i] > debuggerSolution_Z[i] && simplex->isInteger(i)) {
	      onOptimal = false;
	      break;
	    }
	  }
	  if (onOptimal) {
	    printf("adding to node %x as %d - objs\n", this, iProb);
	    for (int j = 0; j <= iProb; j++)
	      printf("%d %g\n", j, sub[j].objectiveValue_);
	  }
        }
#endif
      }
      delete [] weight;
      delete [] whichNode;
      const double * lower = solver->getColLower();
      const double * upper = solver->getColUpper();
      // restore bounds
      for ( int j = 0; j < numberColumns; j++) {
        if (lowerBefore[j] != lower[j])
	  solver->setColLower(j, lowerBefore[j]);
        if (upperBefore[j] != upper[j])
	  solver->setColUpper(j, upperBefore[j]);
      }
      delete [] upperBefore;
      delete [] lowerBefore;
    } else {
      // from diving
      CbcSubProblem ** nodes = reinterpret_cast<CbcSubProblem **>
	(model_->temporaryPointer());
      assert (nodes);
      int adjustDepth=info->depth_;
      assert (numberDo);
      numberNodes_=0;
      for (iProb = 0; iProb < numberDo; iProb++) {
	if ((nodes[iProb]->problemStatus_&2)==0) {
	  // create subproblem (and swap way and/or make inactive)
	  sub[numberNodes_].takeOver(*nodes[iProb],true);
	  // but adjust depth
	  sub[numberNodes_].depth_+=adjustDepth;
	  numberNodes_++;
	}
	delete nodes[iProb];
      }
      branch->numberSubProblems_ = numberNodes_;
      branch->numberSubLeft_ = numberNodes_;
      branch->setNumberBranches(numberNodes_);
      if (!numberNodes_) {
	// infeasible
	delete branch;
	branch=NULL;
      }
      delete [] nodes;
    }
    return branch;
}
Пример #6
0
// Infeasibility - large is 0.5
double
CbcGeneralDepth::infeasibility(const OsiBranchingInformation * /*info*/,
                               int &/*preferredWay*/) const
{
    whichSolution_ = -1;
    // should use genuine OsiBranchingInformation usefulInfo = model_->usefulInformation();
    // for now assume only called when correct
    //if (usefulInfo.depth_>=4&&!model_->parentModel()
    //     &&(usefulInfo.depth_%2)==0) {
    if (true) {
        OsiSolverInterface * solver = model_->solver();
        OsiClpSolverInterface * clpSolver
        = dynamic_cast<OsiClpSolverInterface *> (solver);
        if (clpSolver) {
	  if ((model_->moreSpecialOptions()&33554432)==0) {
            ClpNodeStuff * info = nodeInfo_;
            info->integerTolerance_ = model_->getIntegerTolerance();
            info->integerIncrement_ = model_->getCutoffIncrement();
            info->numberBeforeTrust_ = model_->numberBeforeTrust();
            info->stateOfSearch_ = model_->stateOfSearch();
            // Compute "small" change in branch
            int nBranches = model_->getIntParam(CbcModel::CbcNumberBranches);
            if (nBranches) {
                double average = model_->getDblParam(CbcModel::CbcSumChange) / static_cast<double>(nBranches);
                info->smallChange_ =
                    CoinMax(average * 1.0e-5, model_->getDblParam(CbcModel::CbcSmallestChange));
                info->smallChange_ = CoinMax(info->smallChange_, 1.0e-8);
            } else {
                info->smallChange_ = 1.0e-8;
            }
            int numberIntegers = model_->numberIntegers();
            double * down = new double[numberIntegers];
            double * up = new double[numberIntegers];
            int * priority = new int[numberIntegers];
            int * numberDown = new int[numberIntegers];
            int * numberUp = new int[numberIntegers];
            int * numberDownInfeasible = new int[numberIntegers];
            int * numberUpInfeasible = new int[numberIntegers];
            model_->fillPseudoCosts(down, up, priority, numberDown, numberUp,
                                    numberDownInfeasible, numberUpInfeasible);
            info->fillPseudoCosts(down, up, priority, numberDown, numberUp,
                                  numberDownInfeasible,
                                  numberUpInfeasible, numberIntegers);
            info->presolveType_ = 1;
            delete [] down;
            delete [] up;
            delete [] numberDown;
            delete [] numberUp;
            delete [] numberDownInfeasible;
            delete [] numberUpInfeasible;
            bool takeHint;
            OsiHintStrength strength;
            solver->getHintParam(OsiDoReducePrint, takeHint, strength);
            ClpSimplex * simplex = clpSolver->getModelPtr();
            int saveLevel = simplex->logLevel();
            if (strength != OsiHintIgnore && takeHint && saveLevel == 1)
                simplex->setLogLevel(0);
            clpSolver->setBasis();
            whichSolution_ = simplex->fathomMany(info);
            //printf("FAT %d nodes, %d iterations\n",
            //info->numberNodesExplored_,info->numberIterations_);
            //printf("CbcBranch %d rows, %d columns\n",clpSolver->getNumRows(),
            //     clpSolver->getNumCols());
            model_->incrementExtra(info->numberNodesExplored_,
                                   info->numberIterations_);
            // update pseudo costs
            double smallest = 1.0e50;
            double largest = -1.0;
            OsiObject ** objects = model_->objects();
#ifndef NDEBUG
            const int * integerVariable = model_->integerVariable();
#endif
            for (int i = 0; i < numberIntegers; i++) {
#ifndef NDEBUG
                CbcSimpleIntegerDynamicPseudoCost * obj =
                    dynamic_cast <CbcSimpleIntegerDynamicPseudoCost *>(objects[i]) ;
                assert (obj && obj->columnNumber() == integerVariable[i]);
#else
                CbcSimpleIntegerDynamicPseudoCost * obj =
                    static_cast <CbcSimpleIntegerDynamicPseudoCost *>(objects[i]) ;
#endif
                if (info->numberUp_[i] > 0) {
                    if (info->downPseudo_[i] > largest)
                        largest = info->downPseudo_[i];
                    if (info->downPseudo_[i] < smallest)
                        smallest = info->downPseudo_[i];
                    if (info->upPseudo_[i] > largest)
                        largest = info->upPseudo_[i];
                    if (info->upPseudo_[i] < smallest)
                        smallest = info->upPseudo_[i];
                    obj->updateAfterMini(info->numberDown_[i],
                                         info->numberDownInfeasible_[i],
                                         info->downPseudo_[i],
                                         info->numberUp_[i],
                                         info->numberUpInfeasible_[i],
                                         info->upPseudo_[i]);
                }
            }
            //printf("range of costs %g to %g\n",smallest,largest);
            simplex->setLogLevel(saveLevel);
            numberNodes_ = info->nNodes_;
	  } else {
	    // Try diving
	    // See if any diving heuristics set to do dive+save
	    CbcHeuristicDive * dive=NULL;
	    for (int i = 0; i < model_->numberHeuristics(); i++) {
	      CbcHeuristicDive * possible = dynamic_cast<CbcHeuristicDive *>(model_->heuristic(i));
	      if (possible&&possible->maxSimplexIterations()==COIN_INT_MAX) {
		// if more than one then rotate later?
		//if (possible->canHeuristicRun()) {
		dive=possible;
		break;
	      }
	    }
	    assert (dive); // otherwise moreSpecial should have been turned off
	    CbcSubProblem ** nodes=NULL;
	    int branchState=dive->fathom(model_,numberNodes_,nodes);
	    if (branchState) {
	      printf("new solution\n");
	      whichSolution_=numberNodes_-1;
	    } else {
	      whichSolution_=-1;
	    }
#if 0
	    if (0) {
	      for (int iNode=0;iNode<numberNodes;iNode++) {
		//tree_->push(nodes[iNode]) ;
	      }
	      assert (node->nodeInfo());
	      if (node->nodeInfo()->numberBranchesLeft()) {
		tree_->push(node) ;
	      } else {
		node->setActive(false);
	      }
	    }
#endif
	    //delete [] nodes;
	    model_->setTemporaryPointer(reinterpret_cast<void *>(nodes));
	    // end try diving
	  }
	  int numberDo = numberNodes_;
	  if (numberDo > 0 || whichSolution_ >= 0) {
	    return 0.5;
	  } else {
	    // no solution
	    return COIN_DBL_MAX; // say infeasible
	  }
        } else {
            return -1.0;
        }
    } else {
        return -1.0;
    }
}
Пример #7
0
// Generate cuts
void
CglFakeClique::generateCuts(const OsiSolverInterface& si, OsiCuts & cs,
			const CglTreeInfo info)
{
  if (fakeSolver_) {
    assert (si.getNumCols()==fakeSolver_->getNumCols());
    fakeSolver_->setColLower(si.getColLower());
    const double * solution = si.getColSolution();
    fakeSolver_->setColSolution(solution);
    fakeSolver_->setColUpper(si.getColUpper());
    // get and set branch and bound cutoff
    double cutoff;
    si.getDblParam(OsiDualObjectiveLimit,cutoff);
    fakeSolver_->setDblParam(OsiDualObjectiveLimit,COIN_DBL_MAX);
#ifdef COIN_HAS_CLP
    OsiClpSolverInterface * clpSolver
      = dynamic_cast<OsiClpSolverInterface *> (fakeSolver_);
    if (clpSolver) {
      // fix up fake solver
      const ClpSimplex * siSimplex = clpSolver->getModelPtr();
      // need to set djs
      memcpy(siSimplex->primalColumnSolution(),
	     si.getReducedCost(),si.getNumCols()*sizeof(double));
      fakeSolver_->setDblParam(OsiDualObjectiveLimit,cutoff);
    }
#endif
    const CoinPackedMatrix * matrixByRow = si.getMatrixByRow();
    const double * elementByRow = matrixByRow->getElements();
    const int * column = matrixByRow->getIndices();
    const CoinBigIndex * rowStart = matrixByRow->getVectorStarts();
    const int * rowLength = matrixByRow->getVectorLengths();
    const double * rowUpper = si.getRowUpper();
    const double * rowLower = si.getRowLower();
    
    // Scan all rows looking for possibles
    int numberRows = si.getNumRows();
    double tolerance = 1.0e-3;
    for (int iRow=0;iRow<numberRows;iRow++) {
      CoinBigIndex start = rowStart[iRow];
      CoinBigIndex end = start + rowLength[iRow];
      double upRhs = rowUpper[iRow]; 
      double loRhs = rowLower[iRow]; 
      double sum = 0.0;
      for (CoinBigIndex j=start;j<end;j++) {
	int iColumn=column[j];
	double value = elementByRow[j];
	sum += solution[iColumn]*value;
      }
      if (sum<loRhs-tolerance||sum>upRhs+tolerance) {
	// add as cut
	OsiRowCut rc;
	rc.setLb(loRhs);
	rc.setUb(upRhs);
	rc.setRow(end-start,column+start,elementByRow+start,false);
	CoinAbsFltEq equal(1.0e-12);
	cs.insertIfNotDuplicate(rc,equal);
      }
    }
    CglClique::generateCuts(*fakeSolver_,cs,info);
    if (probing_) {
      probing_->generateCuts(*fakeSolver_,cs,info);
    }
  } else {
    // just use real solver
    CglClique::generateCuts(si,cs,info);
  }
}
Пример #8
0
/*
  Randomized Rounding Heuristic
  Returns 1 if solution, 0 if not
*/
int
CbcHeuristicRandRound::solution(double & solutionValue,
                                double * betterSolution)
{
    // rlh: Todo: Memory Cleanup

    //  std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;

    setWhen(1);  // setWhen(1) didn't have the effect I expected (e.g., run once).

    // Run only once.
    //
    //    See if at root node
    bool atRoot = model_->getNodeCount() == 0;
    int passNumber = model_->getCurrentPassNumber();
    //    Just do once
    if (!atRoot || passNumber > 1) {
        // std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }

    std::cout << "Entering the Randomized Rounding Heuristic" << std::endl;
    typedef struct {
        int numberSolutions;
        int maximumSolutions;
        int numberColumns;
        double ** solution;
        int * numberUnsatisfied;
    } clpSolution;

    double start = CoinCpuTime();
    numCouldRun_++; //
#ifdef HEURISTIC_INFORM
    printf("Entering heuristic %s - nRuns %d numCould %d when %d\n",
	   heuristicName(),numRuns_,numCouldRun_,when_);
#endif
    // Todo: Ask JJHF what "number of times
    // the heuristic could run" means.

    OsiSolverInterface * solver = model_->solver()->clone();
    double primalTolerance ;
    solver->getDblParam(OsiPrimalTolerance, primalTolerance) ;
    OsiClpSolverInterface * clpSolver = dynamic_cast<OsiClpSolverInterface *> (solver);
    assert (clpSolver);
    ClpSimplex * simplex = clpSolver->getModelPtr();

    // Initialize the structure holding the solutions for the Simplex iterations
    clpSolution solutions;
    // Set typeStruct field of ClpTrustedData struct to 1 to indicate
    // desired behavior for  RandRound heuristic (which is what?)
    ClpTrustedData trustedSolutions;
    trustedSolutions.typeStruct = 1;
    trustedSolutions.data = &solutions;
    solutions.numberSolutions = 0;
    solutions.maximumSolutions = 0;
    solutions.numberColumns = simplex->numberColumns();
    solutions.solution = NULL;
    solutions.numberUnsatisfied = NULL;
    simplex->setTrustedUserPointer(&trustedSolutions);

    // Solve from all slack to get some points
    simplex->allSlackBasis();

    // Calling primal() invalidates pointers to some rim vectors,
    // like...row sense (!)
    simplex->primal();

    // 1. Okay - so a workaround would be to copy the data I want BEFORE
    // calling primal.
    // 2. Another approach is to ask the simplex solvers NOT to mess up my
    // rims.
    // 3. See freeCachedResults() for what is getting
    // deleted. Everything else points into the structure.
    // ...or use collower and colupper rather than rowsense.
    // ..store address of where one of these

    // Store the basic problem information
    // -Get the number of columns, rows and rhs vector
    int numCols = clpSolver->getNumCols();
    int numRows = clpSolver->getNumRows();

    // Find the integer variables (use columnType(?))
    // One if not continuous, that is binary or general integer)
    // columnType() = 0 continuous
    //              = 1 binary
    //              = 2 general integer
    bool * varClassInt = new bool[numCols];
    const char* columnType = clpSolver->columnType();
    int numGenInt = 0;
    for (int i = 0; i < numCols; i++) {
        if (clpSolver->isContinuous(i))
            varClassInt[i] = 0;
        else
            varClassInt[i] = 1;
        if (columnType[i] == 2) numGenInt++;
    }

    // Heuristic is for problems with general integer variables.
    // If there are none, quit.
    if (numGenInt++ < 1) {
        delete [] varClassInt ;
        std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
        return 0;
    }


    // -Get the rows sense
    const char * rowSense;
    rowSense = clpSolver->getRowSense();

    // -Get the objective coefficients
    double *originalObjCoeff = CoinCopyOfArray(clpSolver->getObjCoefficients(), numCols);

    // -Get the matrix of the problem
    // rlh: look at using sparse representation
    double ** matrix = new double * [numRows];
    for (int i = 0; i < numRows; i++) {
        matrix[i] = new double[numCols];
        for (int j = 0; j < numCols; j++)
            matrix[i][j] = 0;
    }

    const CoinPackedMatrix* matrixByRow = clpSolver->getMatrixByRow();
    const double * matrixElements = matrixByRow->getElements();
    const int * matrixIndices = matrixByRow->getIndices();
    const int * matrixStarts = matrixByRow->getVectorStarts();
    for (int j = 0; j < numRows; j++) {
        for (int i = matrixStarts[j]; i < matrixStarts[j+1]; i++) {
            matrix[j][matrixIndices[i]] = matrixElements[i];
        }
    }

    double * newObj = new double [numCols];
    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int randNum;

    // Shuffle the rows:
    // Put the rows in a random order
    // so that the optimal solution is a different corner point than the
    // starting point.
    int * index = new int [numRows];
    for (int i = 0; i < numRows; i++)
        index[i] = i;
    for (int i = 0; i < numRows; i++) {
        int temp = index[i];
        int randNumTemp = i + intRand(numRows - i);
        index[i] = index[randNumTemp];
        index[randNumTemp] = temp;
    }

    // Start finding corner points by iteratively doing the following:
    // - contruct a randomly tilted objective
    // - solve
    for (int i = 0; i < numRows; i++) {
        // TODO: that 10,000 could be a param in the member data
        if (solutions.numberSolutions  > 10000)
            break;
        randNum = intRand(2);
        for (int j = 0; j < numCols; j++) {
            // for row i and column j vary the coefficient "a bit"
            if (randNum == 1)
                // if the element is zero, then set the new obj
                // coefficient to 0.1 (i.e., round up)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = 0.1;
                else
                    // if the element is nonzero, then increase the new obj
                    // coefficient "a bit"
                    newObj[j] = matrix[index[i]][j] * 1.1;
            else
                // if randnum is 2, then
                // if the element is zero, then set the new obj coeffient
                // to NEGATIVE 0.1 (i.e., round down)
                if (fabs(matrix[index[i]][j]) < primalTolerance)
                    newObj[j] = -0.1;
                else
                    // if the element is nonzero, then DEcrease the new obj coeffienct "a bit"
                    newObj[j] = matrix[index[i]][j] * 0.9;
        }
        // Use the new "tilted" objective
        clpSolver->setObjective(newObj);

        // Based on the row sense, we decide whether to max or min
        if (rowSense[i] == 'L')
            clpSolver->setObjSense(-1);
        else
            clpSolver->setObjSense(1);

        // Solve with primal simplex
        simplex->primal(1);
        // rlh+ll: This was the original code. But we already have the
        // model pointer (it's in simplex). And, calling getModelPtr()
        // invalidates the cached data in the OsiClpSolverInterface
        // object, which means our precious rowsens is lost. So let's
        // not use the line below...
        /******* clpSolver->getModelPtr()->primal(1); */
        printf("---------------------------------------------------------------- %d\n", i);
    }
    // Iteratively do this process until...
    // either you reach the max number of corner points (aka 10K)
    // or all the rows have been used as an objective.

    // Look at solutions
    int numberSolutions = solutions.numberSolutions;
    //const char * integerInfo = simplex->integerInformation();
    //const double * columnLower = simplex->columnLower();
    //const double * columnUpper = simplex->columnUpper();
    printf("there are %d solutions\n", numberSolutions);

    // Up to here we have all the corner points
    // Now we need to do the random walks and roundings

    double ** cornerPoints = new double * [numberSolutions];
    for (int j = 0; j < numberSolutions; j++)
        cornerPoints[j] = solutions.solution[j];

    bool feasibility = 1;
    // rlh: use some COIN max instead of 1e30 (?)
    double bestObj = 1e30;
    std::vector< std::vector <double> > feasibles;
    int numFeasibles = 0;

    // Check the feasibility of the corner points
    int numCornerPoints = numberSolutions;

    const double * rhs = clpSolver->getRightHandSide();
    // rlh: row sense hasn't changed. why a fresh copy?
    // Delete next line.
    rowSense = clpSolver->getRowSense();

    for (int i = 0; i < numCornerPoints; i++) {
        //get the objective value for this this point
        double objValue = 0;
        for (int k = 0; k < numCols; k++)
            objValue += cornerPoints[i][k] * originalObjCoeff[k];

        if (objValue < bestObj) {
            // check integer feasibility
            feasibility = 1;
            for (int j = 0; j < numCols; j++) {
                if (varClassInt[j]) {
                    double closest = floor(cornerPoints[i][j] + 0.5);
                    if (fabs(cornerPoints[i][j] - closest) > primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                }
            }
            // check all constraints satisfied
            if (feasibility) {
                for (int irow = 0; irow < numRows; irow++) {
                    double lhs = 0;
                    for (int j = 0; j < numCols; j++) {
                        lhs += matrix[irow][j] * cornerPoints[i][j];
                    }
                    if (rowSense[irow] == 'L' && lhs > rhs[irow] + primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'G' && lhs < rhs[irow] - primalTolerance) {
                        feasibility = 0;
                        break;
                    }
                    if (rowSense[irow] == 'E' && (lhs - rhs[irow] > primalTolerance || lhs - rhs[irow] < -primalTolerance)) {
                        feasibility = 0;
                        break;
                    }
                }
            }

            if (feasibility) {
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int k = 0; k < numCols; k++)
                    feasibles[numFeasibles-1][k] = cornerPoints[i][k];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
    }
    int numFeasibleCorners;
    numFeasibleCorners = numFeasibles;
    //find the center of gravity of the corner points as the first random point
    double * rp = new double[numCols];
    for (int i = 0; i < numCols; i++) {
        rp[i] = 0;
        for (int j = 0; j < numCornerPoints; j++) {
            rp[i] += cornerPoints[j][i];
        }
        rp[i] = rp[i] / numCornerPoints;
    }

    //-------------------------------------------
    //main loop:
    // -generate the next random point
    // -round the random point
    // -check the feasibility of the random point
    //-------------------------------------------

    srand ( static_cast<unsigned int>(time(NULL) + 1));
    int numRandomPoints = 0;
    while (numRandomPoints < 50000) {
        numRandomPoints++;
        //generate the next random point
        int randomIndex = intRand(numCornerPoints);
        double random = CoinDrand48();
        for (int i = 0; i < numCols; i++) {
            rp[i] = (random * (cornerPoints[randomIndex][i] - rp[i])) + rp[i];
        }

        //CRISP ROUNDING
        //round the random point just generated
        double * roundRp = new double[numCols];
        for (int i = 0; i < numCols; i++) {
            roundRp[i] = rp[i];
            if (varClassInt[i]) {
                if (rp[i] >= 0) {
                    if (fmod(rp[i], 1) > 0.5)
                        roundRp[i] = floor(rp[i]) + 1;
                    else
                        roundRp[i] = floor(rp[i]);
                } else {
                    if (fabs(fmod(rp[i], 1)) > 0.5)
                        roundRp[i] = floor(rp[i]);
                    else
                        roundRp[i] = floor(rp[i]) + 1;

                }
            }
        }


        //SOFT ROUNDING
        // Look at original files for the "how to" on soft rounding;
        // Soft rounding omitted here.

        //Check the feasibility of the rounded random point
        // -Check the feasibility
        // -Get the rows sense
        rowSense = clpSolver->getRowSense();
        rhs = clpSolver->getRightHandSide();

        //get the objective value for this feasible point
        double objValue = 0;
        for (int i = 0; i < numCols; i++)
            objValue += roundRp[i] * originalObjCoeff[i];

        if (objValue < bestObj) {
            feasibility = 1;
            for (int i = 0; i < numRows; i++) {
                double lhs = 0;
                for (int j = 0; j < numCols; j++) {
                    lhs += matrix[i][j] * roundRp[j];
                }
                if (rowSense[i] == 'L' && lhs > rhs[i] + primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'G' && lhs < rhs[i] - primalTolerance) {
                    feasibility = 0;
                    break;
                }
                if (rowSense[i] == 'E' && (lhs - rhs[i] > primalTolerance || lhs - rhs[i] < -primalTolerance)) {
                    feasibility = 0;
                    break;
                }
            }
            if (feasibility) {
                printf("Feasible Found.\n");
                printf("%.2f\n", CoinCpuTime() - start);
                numFeasibles++;
                feasibles.push_back(std::vector <double> (numCols));
                for (int i = 0; i < numCols; i++)
                    feasibles[numFeasibles-1][i] = roundRp[i];
                printf("obj: %f\n", objValue);
                if (objValue < bestObj)
                    bestObj = objValue;
            }
        }
        delete [] roundRp;
    }
    printf("Number of Feasible Corners: %d\n", numFeasibleCorners);
    printf("Number of Feasibles Found: %d\n", numFeasibles);
    if (numFeasibles > 0)
        printf("Best Objective: %f\n", bestObj);
    printf("time: %.2f\n", CoinCpuTime() - start);

    if (numFeasibles == 0) {
        // cleanup
        delete [] varClassInt;
        for (int i = 0; i < numRows; i++)
            delete matrix[i];
        delete [] matrix;
        delete [] newObj;
        delete [] index;
        for (int i = 0; i < numberSolutions; i++)
            delete cornerPoints[i];
        delete [] cornerPoints;
        delete [] rp;
        return 0;
    }

    // We found something better
    solutionValue = bestObj;
    for (int k = 0; k < numCols; k++) {
        betterSolution[k] =  feasibles[numFeasibles-1][k];
    }
    delete [] varClassInt;
    for (int i = 0; i < numRows; i++)
        delete matrix[i];
    delete [] matrix;
    delete [] newObj;
    delete [] index;
    for (int i = 0; i < numberSolutions; i++)
        delete cornerPoints[i];
    delete [] cornerPoints;
    delete [] rp;
    std::cout << "Leaving the Randomized Rounding Heuristic" << std::endl;
    return 1;

}
Пример #9
0
void
CglLandP::CachedData::getData(const OsiSolverInterface &si)
{
    int nBasics = si.getNumRows();
    int nNonBasics = si.getNumCols();
    if (basis_ != NULL)
        delete basis_;
    basis_ = dynamic_cast<CoinWarmStartBasis *> (si.getWarmStart());
    if (!basis_)
        throw NoBasisError();

    if (nBasics_ > 0 || nBasics != nBasics_)
    {
        delete [] basics_;
        basics_ = NULL;
    }
    if (basics_ == NULL)
    {
        basics_ = new int[nBasics];
        nBasics_ = nBasics;
    }

    if (nNonBasics_ > 0 || nNonBasics != nNonBasics_)
    {
        delete [] nonBasics_;
        nonBasics_ = NULL;
    }
    if (nonBasics_ == NULL)
    {
        nonBasics_ = new int[nNonBasics];
        nNonBasics_ = nNonBasics;
    }
    int n = nBasics + nNonBasics;
    if ( nBasics_ + nNonBasics_ > 0 || nBasics_ + nNonBasics_ != n)
    {
        delete [] colsol_;
        delete [] integers_;
        integers_ = NULL;
        colsol_ = NULL;
        slacks_ = NULL;
    }
    if (colsol_ == NULL)
    {
        colsol_ = new double[n];
        slacks_ = &colsol_[nNonBasics];
    }

    if (integers_ == NULL)
    {
        integers_ = new bool[n];
    }

    const double * rowLower = si.getRowLower();
    const double * rowUpper = si.getRowUpper();
    //determine which slacks are integer
    const CoinPackedMatrix * m = si.getMatrixByCol();
    const double * elems = m->getElements();
    const int * inds = m->getIndices();
    const CoinBigIndex * starts = m->getVectorStarts();
    const int * lengths = m->getVectorLengths();
    //    int numElems = m->getNumElements();
    int numCols = m->getNumCols();
    assert(numCols == nNonBasics_);
    //   int numRows = m->getNumRows();
    CoinFillN(integers_ ,n, true);
    for (int i = 0 ;  i < numCols ; i++)
    {
        if (si.isContinuous(i))
            integers_[i] = false;
    }
    bool * integerSlacks = integers_ + numCols;
    for (int i = 0 ; i < nBasics ; i++)
    {
        if (rowLower[i] > -1e50 && INT_INFEAS(rowLower[i]) > 1e-15)
            integerSlacks[i] = false;
        if (rowUpper[i] < 1e50 && INT_INFEAS(rowUpper[i]) > 1e-15)
            integerSlacks[i] = false;
    }
    for (int i = 0 ;  i < numCols ; i++)
    {
        CoinBigIndex end = starts[i] + lengths[i];
        if (integers_[i])
        {
            for (CoinBigIndex k=starts[i] ; k < end; k++)
            {
                if (integerSlacks[inds[k]] && INT_INFEAS(elems[k])>1e-15 )
                    integerSlacks[inds[k]] = false;
            }
        }
        else
        {
            for (CoinBigIndex k=starts[i] ; k < end; k++)
            {
                if (integerSlacks[inds[k]])
                    integerSlacks[inds[k]] = false;
            }
        }
    }

    CoinCopyN(si.getColSolution(), si.getNumCols(), colsol_);
    CoinCopyN(si.getRowActivity(), si.getNumRows(), slacks_);
    for (int i = 0 ; i < si.getNumRows() ; i++)
    {
        slacks_[i]*=-1;
        if (rowLower[i]>-1e50)
        {
            slacks_[i] += rowLower[i];
        }
        else
        {
            slacks_[i] += rowUpper[i];
        }
    }
    //Now get the fill the arrays;
    nNonBasics = 0;
    nBasics = 0;



    //For having the index variables correctly ordered we need to access to OsiSimplexInterface
    {
        OsiSolverInterface * ncSi = (const_cast<OsiSolverInterface *>(&si));
        ncSi->enableSimplexInterface(0);
        ncSi->getBasics(basics_);
	// Save enabled solver
	solver_ = si.clone();
#ifdef COIN_HAS_OSICLP
	OsiClpSolverInterface * clpSi = dynamic_cast<OsiClpSolverInterface *>(solver_);
	const OsiClpSolverInterface * clpSiRhs = dynamic_cast<const OsiClpSolverInterface *>(&si);
	if (clpSi)
	  clpSi->getModelPtr()->copyEnabledStuff(clpSiRhs->getModelPtr());;
#endif
        ncSi->disableSimplexInterface();
    }

    int numStructural = basis_->getNumStructural();
    for (int i = 0 ; i < numStructural ; i++)
    {
        if (basis_->getStructStatus(i)== CoinWarmStartBasis::basic)
        {
            nBasics++;
            //Basically do nothing
        }
        else
        {
            nonBasics_[nNonBasics++] = i;
        }
    }

    int numArtificial = basis_->getNumArtificial();
    for (int i = 0 ; i < numArtificial ; i++)
    {
        if (basis_->getArtifStatus(i)== CoinWarmStartBasis::basic)
        {
            //Just check number of basics
            nBasics++;
        }
        else
        {
            nonBasics_[nNonBasics++] = i + basis_->getNumStructural();
        }
    }
}