12 #include "CoinHelperFunctions.hpp"
13 #include "CbcModel.hpp"
19 #include "OsiCpxSolverInterface.hpp"
22 #include "OsiClpSolverInterface.hpp"
24 #include "OsiAuxInfo.hpp"
26 #include "CoinTime.hpp"
32 #include "CoinHelperFunctions.hpp"
61 howOften_(copy.howOften_),
70 CbcHeuristic::operator=(rhs);
97 if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1)
return 0;
98 if ((model_->getNodeCount()%
howOften_)!=0||model_->getCurrentPassNumber()>1)
105 nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone());
112 double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
113 double primalTolerance = 1.0e-6;
119 Ipopt::TNLP::IndexStyleEnum index_style;
120 minlp->
get_nlp_info(numberColumns, numberRows, nnz_jac_g,
121 nnz_h_lag, index_style);
124 const double* x_sol = minlp->
x_sol();
125 const double* x_l = minlp->
x_l();
126 const double* x_u = minlp->
x_u();
128 const double* g_l = minlp->
g_l();
129 const double* g_u = minlp->
g_u();
137 Ipopt::TNLP::LinearityType* variableLinearNonLinear =
new
138 Ipopt::TNLP::LinearityType [numberColumns];
142 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
144 linearVariable.push_back(iColumn);
146 nonlinearVariable.push_back(iColumn);
148 size_t numberLinearColumns = linearVariable.size();
149 size_t numberNonlinearColumns = nonlinearVariable.size();
155 int* indexRow =
new int[nnz_jac_g];
156 int* indexCol =
new int[nnz_jac_g];
157 minlp->
eval_jac_g(numberColumns, x_sol,
false,
158 numberRows, nnz_jac_g,
159 indexRow, indexCol, 0);
162 CoinIotaN(sortedIndex(), nnz_jac_g, 0);
166 std::sort(sortedIndex.begin(), sortedIndex.end(),
c);
168 int* row =
new int[nnz_jac_g];
169 int* columnStart =
new int[numberColumns];
170 int* columnLength =
new int[numberColumns];
171 CoinZeroN(columnStart, numberColumns);
172 CoinZeroN(columnLength, numberColumns);
179 std::vector<int> numberColumnsLinear(numberRows, 0);
182 int indexCorrection = (index_style == Ipopt::TNLP::C_STYLE) ? 0 : 1;
184 for(
int i=0; i<nnz_jac_g; i++) {
185 int thisIndexCol = indexCol[sortedIndex[i]]-indexCorrection;
186 if(indexCol[sortedIndex[i]] != iniCol) {
187 iniCol = indexCol[sortedIndex[i]];
188 columnStart[thisIndexCol] = i;
189 columnLength[thisIndexCol] = 1;
192 columnLength[thisIndexCol]++;
194 row[i] = indexRow[sortedIndex[i]]-indexCorrection;
195 column[row[i]].push_back(thisIndexCol);
197 columnInt[row[i]].push_back(thisIndexCol);
199 numberColumnsLinear[row[i]]++;
203 double* newSolution =
new double [numberColumns];
204 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
205 double* new_g_sol =
new double [numberRows];
210 int numberFractionalNonlinearVariables = 0;
211 for (
size_t iNLCol=0;iNLCol<numberNonlinearColumns;iNLCol++) {
212 int iColumn = nonlinearVariable[iNLCol];
214 integerNonlinearColumns.push_back(iColumn);
215 double value=newSolution[iColumn];
216 if (fabs(floor(value+0.5)-value)>integerTolerance) {
217 numberFractionalNonlinearVariables++;
225 while(numberFractionalNonlinearVariables) {
232 bestColumn, bestRound);
234 if(bestColumn >= 0) {
249 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
251 numberFractionalNonlinearVariables = 0;
252 for(
int iIntCol=0; iIntCol<(
int)integerNonlinearColumns.size(); iIntCol++) {
253 int iColumn = integerNonlinearColumns[iIntCol];
254 double value=newSolution[iColumn];
255 if (fabs(floor(value+0.5)-value)>integerTolerance)
256 numberFractionalNonlinearVariables++;
259 double newSolutionValue;
260 minlp->
eval_f(numberColumns, newSolution,
true, newSolutionValue);
265 int numberFractionalLinearVariables = 0;
266 for (
size_t iLCol=0;iLCol<numberLinearColumns;iLCol++) {
267 int iColumn = linearVariable[iLCol];
269 double value=newSolution[iColumn];
270 if (fabs(floor(value+0.5)-value)>integerTolerance) {
271 numberFractionalLinearVariables++;
276 bool feasible =
true;
277 if(numberFractionalLinearVariables) {
278 int numberMIPRows = 0;
279 int* mapRows =
new int[numberRows];
280 for(
int iRow=0; iRow<numberRows; iRow++) {
282 if(numberColumnsLinear[iRow] > 0) {
283 mapRows[iRow] = numberMIPRows++;
289 int numberIntegerLinearColumns = 0;
290 for (
size_t iLCol=0;iLCol<numberLinearColumns;iLCol++) {
291 int iColumn = linearVariable[iLCol];
292 newSolution[iColumn] = 0.0;
294 numberIntegerLinearColumns++;
297 double* gradient_f =
new double[numberColumns];
298 minlp->
eval_grad_f(numberColumns,newSolution,
true,gradient_f);
300 minlp->
eval_g(numberColumns, newSolution,
true,
301 numberRows, new_g_sol);
302 double* row_lb =
new double[numberMIPRows];
303 double* row_ub =
new double[numberMIPRows];
304 for(
int iRow=0; iRow<numberRows; iRow++) {
305 if(mapRows[iRow] > -1) {
306 assert(mapRows[iRow] < numberMIPRows);
308 row_lb[mapRows[iRow]] = g_l[iRow];
310 row_lb[mapRows[iRow]] = g_l[iRow] - new_g_sol[iRow];
312 row_ub[mapRows[iRow]] = g_u[iRow];
314 row_ub[mapRows[iRow]] = g_u[iRow] - new_g_sol[iRow];
319 double* jac_g =
new double [nnz_jac_g];
320 minlp->
eval_jac_g(numberColumns, x_sol,
false,
321 numberRows, nnz_jac_g,
326 CoinPackedMatrix* matrix =
new CoinPackedMatrix(
true,0,0);
327 matrix->setDimensions(numberMIPRows,0);
331 double* objective =
new double[numberLinearColumns];
332 double* col_lb =
new double[numberLinearColumns];
333 double* col_ub =
new double[numberLinearColumns];
334 int* indexIntegerColumn =
new int[numberIntegerLinearColumns];
335 int numberIndexIntegerColumn = 0;
336 for (
size_t iLCol=0;iLCol<numberLinearColumns;iLCol++) {
337 int iColumn = linearVariable[iLCol];
338 objective[iLCol] = gradient_f[iColumn];
339 col_lb[iLCol] = x_l[iColumn];
340 col_ub[iLCol] = x_u[iColumn];
341 CoinPackedVector newRow;
342 int end = columnStart[iColumn]+columnLength[iColumn];
343 for (
int j=columnStart[iColumn];
346 newRow.insert(mapRows[iRow], jac_g[sortedIndex[
j]]);
348 matrix->appendCol(newRow);
350 indexIntegerColumn[numberIndexIntegerColumn++] =
static_cast<int>(iLCol);
355 bool delete_si =
false;
357 si =
new OsiClpSolverInterface;
361 CoinMessageHandler * handler = model_->messageHandler()->clone();
362 si->passInMessageHandler(handler);
363 si->messageHandler()->setLogLevel(0);
365 si->loadProblem(*matrix, col_lb, col_ub, objective, row_lb, row_ub);
366 si->setInteger(indexIntegerColumn, numberIndexIntegerColumn);
372 assert(si->getNumCols() ==
static_cast<int>(numberLinearColumns));
373 for (
size_t iLCol=0;iLCol<numberLinearColumns;iLCol++) {
374 int iColumn = linearVariable[iLCol];
375 newSolution[iColumn] = solution[iLCol];
385 delete [] gradient_f;
390 delete [] indexIntegerColumn;
398 bool feasible =
true;
399 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
400 double value=newSolution[iColumn];
401 if(value < x_l[iColumn] || value > x_u[iColumn]) {
406 if (fabs(floor(value+0.5)-value)>integerTolerance) {
412 minlp->
eval_g(numberColumns, newSolution,
true,
413 numberRows, new_g_sol);
414 for(
int iRow=0; iRow<numberRows; iRow++) {
415 if(new_g_sol[iRow]<g_l[iRow]-primalTolerance ||
416 new_g_sol[iRow]>g_u[iRow]+primalTolerance) {
421 #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP
422 cout<<
"It should be infeasible because: "<<endl;
423 cout<<
"g_l["<<iRow<<
"]= "<<g_l[iRow]<<
" "
424 <<
"g_sol["<<iRow<<
"]= "<<new_g_sol[iRow]<<
" "
425 <<
"g_u["<<iRow<<
"]= "<<g_u[iRow]<<endl;
426 cout<<
"primalTolerance= "<<primalTolerance<<endl;
436 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
438 double value=newSolution[iColumn];
439 if (fabs(floor(value+0.5)-value)>integerTolerance) {
440 #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP
441 cout<<
"It should be infeasible because: "<<endl;
442 cout<<
"variable "<<iColumn<<
" is not integer"<<endl;
448 value=floor(newSolution[iColumn]+0.5);
459 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
465 double newSolutionValue;
466 minlp->
eval_f(numberColumns, newSolution,
true, newSolutionValue);
467 if(newSolutionValue < solutionValue) {
468 memcpy(betterSolution,newSolution,numberColumns*
sizeof(
double));
469 solutionValue = newSolutionValue;
474 delete [] variableLinearNonLinear;
478 delete [] columnStart;
479 delete [] columnLength;
480 delete [] newSolution;
484 #ifdef DEBUG_BON_HEURISTIC_DIVE_MIP
485 std::cout<<
"DiveMIP returnCode = "<<returnCode<<std::endl;
Base class for all MINLPs that use a standard triplet matrix form and dense vectors.
virtual void setInternalVariables(TMINLP2TNLP *minlp)=0
sets internal variables
virtual double getInfinity() const
Get solver's value for infinity.
HeuristicDiveMIP & operator=(const HeuristicDiveMIP &rhs)
Assignment operator.
bool isNlpFeasible(TMINLP2TNLP *minlp, const double primalTolerance)
checks if the NLP relaxation of the problem is feasible
const TMINLP2TNLP * problem() const
get pointer to the TMINLP2TNLP adapter
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
void adjustPrimalTolerance(TMINLP2TNLP *minlp, double &primalTolerance)
Adjusts the primalTolerance in case some of the constraints are violated.
OsiSolverInterface * clone(bool copyData=true) const
Virtual copy constructor.
void SetVariableLowerBound(Ipopt::Index var_no, Ipopt::Number x_l)
Change the lower bound on the variable.
BonminSetup * setup_
Setup to use for local searches (will make copies).
Ipopt::SolverReturn optimization_status() const
Get Optimization status.
void SetVariableUpperBound(Ipopt::Index var_no, Ipopt::Number x_u)
Change the upper bound on the variable.
virtual void initialSolve()
Solve initial continuous relaxation.
void Initialize(BonminSetup *setup)
Initialize method.
const double * getLastSolution()
get the solution found in last local search (return NULL if no solution).
virtual int solution(double &solutionValue, double *betterSolution)
Performs heuristic.
SubMipSolver * mip_
A subsolver for MIP.
A very simple class to provide a common interface for solving MIPs with Cplex and Cbc...
virtual void selectVariableToBranch(TMINLP2TNLP *minlp, const vector< int > &integerColumns, const double *newSolution, int &bestColumn, int &bestRound)=0
Selects the next variable to branch on.
Bonmin::Algorithm getAlgorithm()
Get the algorithm used.
const Ipopt::Number * x_l()
Get the current values for the lower bounds.
virtual bool eval_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Number *g)
Returns the vector of constraint values in x.
const Ipopt::Number * x_u()
Get the current values for the upper bounds.
~HeuristicDiveMIP()
Destructor.
virtual bool eval_grad_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number *grad_f)
Returns the vector of the gradient of the objective w.r.t.
OsiSolverInterface * solver()
const Ipopt::Number * g_l()
Get the current values for constraints lower bounds.
const TMINLP * model() const
bool operator()(int i, int j)
Destructor.
const Ipopt::Number * x_sol() const
get the solution values
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
virtual bool eval_f(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Number &obj_value)
Returns the value of the objective function in x.
This is an adapter class that converts a TMINLP to a TNLP to be solved by Ipopt.
virtual bool get_nlp_info(Ipopt::Index &n, Ipopt::Index &m, Ipopt::Index &nnz_jac_g, Ipopt::Index &nnz_h_lag, TNLP::IndexStyleEnum &index_style)
This call is just passed onto the TMINLP object.
HeuristicDiveMIP(BonminSetup *setup)
Constructor with setup.
void optimize(double cutoff, int loglevel, double maxTime)
update cutoff and optimize MIP.
const Ipopt::Number * g_u()
Get the current values for constraints upper bounds.
const char * prefix() const
Get prefix to use for options.
VariableType
Type of the variables.
void setLpSolver(OsiSolverInterface *lp)
Assign lp solver.
const TMINLP::VariableType * var_types()
Get the variable types.
virtual bool eval_jac_g(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index m, Ipopt::Index nele_jac, Ipopt::Index *iRow, Ipopt::Index *jCol, Ipopt::Number *values)
Returns the jacobian of the constraints.
int howOften_
How often to do (code can change)
virtual bool get_variables_linearity(Ipopt::Index n, Ipopt::TNLP::LinearityType *var_types)=0
overload this method to provide the variables linearity.