11 #include "CoinHelperFunctions.hpp"
12 #include "CbcModel.hpp"
14 #include "OsiAuxInfo.hpp"
16 #include "CoinTime.hpp"
34 bool operator() (
const int x,
const int y)
const {
35 return score_[
x]>score_[y];
43 HeuristicFPump::HeuristicFPump()
48 enableAdvanced_(false)
56 enableAdvanced_(false)
65 objective_norm_(copy.objective_norm_),
66 enableAdvanced_(copy.enableAdvanced_)
73 CbcHeuristic::operator=(rhs);
84 if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1)
return 0;
86 bool integerSolutionAlreadyExists =
false;
87 if(model_->getSolutionCount()) {
89 integerSolutionAlreadyExists =
true;
92 assert(solutionValue < 1.0e50);
95 const int maxNumberIterations = 200;
96 const double toleranceObjectiveFP = 1.0e-5;
102 nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone());
109 double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
110 double primalTolerance;
112 OsiSolverInterface * solver = model_->solver();
113 solver->getDblParam(OsiPrimalTolerance,primalTolerance);
115 primalTolerance=1.0e-6;
121 Ipopt::TNLP::IndexStyleEnum index_style;
122 minlp->
get_nlp_info(numberColumns, numberRows, nnz_jac_g,
123 nnz_h_lag, index_style);
126 const double* x_sol = minlp->
x_sol();
127 const double* x_l = minlp->
x_l();
128 const double* x_u = minlp->
x_u();
130 #ifdef DEBUG_BON_HEURISTIC_FPUMP
131 const double* g_sol = minlp->
g_sol();
132 const double* g_l = minlp->
g_l();
133 const double* g_u = minlp->
g_u();
135 for(
int i=0; i<numberColumns; i++)
136 cout<<
"x_l["<<i<<
"]= "<<x_l[i]<<
" "
137 <<
"x_sol["<<i<<
"]= "<<x_sol[i]<<
" "
138 <<
"x_u["<<i<<
"]= "<<x_u[i]<<
" "
139 <<
"variableType = "<<variableType[i]<<endl;
140 for(
int i=0; i<numberRows; i++)
141 cout<<
"g_l["<<i<<
"]= "<<g_l[i]<<
" "
142 <<
"g_sol["<<i<<
"]= "<<g_sol[i]<<
" "
143 <<
"g_u["<<i<<
"]= "<<g_u[i]<<endl;
145 cout<<
"obj_value = "<<minlp->
obj_value()<<endl;
158 double* newSolution =
new double [numberColumns];
159 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
160 double* new_g_sol =
new double [numberRows];
164 int numberFractionalVariables = 0;
165 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
167 integerColumns.push_back(iColumn);
168 double value=newSolution[iColumn];
169 if (fabs(floor(value+0.5)-value)>integerTolerance) {
170 numberFractionalVariables++;
174 int numberIntegerColumns = (
int) integerColumns.size();
177 const int numberOldSolutionsStored = 4;
178 double ** oldSolution =
new double * [numberOldSolutionsStored];
179 for (
int j=0;
j<numberOldSolutionsStored;
j++) {
180 oldSolution[
j]=
new double[numberIntegerColumns];
181 for (
int i=0;i<numberIntegerColumns;i++)
182 oldSolution[
j][i]=-COIN_DBL_MAX;
188 double* x_bar =
new double[numberIntegerColumns];
189 int* indexes_x_bar =
new int[numberIntegerColumns];
190 double* copy_newSolution =
new double[numberColumns];
192 while(numberFractionalVariables) {
194 if(iteration > maxNumberIterations) {
197 memcpy(copy_newSolution, newSolution, numberColumns*
sizeof(
double));
198 roundObj.
round(integerTolerance, primalTolerance, copy_newSolution);
200 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
201 int iColumn = integerColumns[iIntCol];
202 double value=copy_newSolution[iColumn];
204 double value=newSolution[iColumn];
205 if (fabs(floor(value+0.5)-value)>integerTolerance) {
206 value = floor(value+0.5);
208 if(value < x_l[iColumn]-primalTolerance)
210 else if(value > x_u[iColumn]+primalTolerance)
214 x_bar[iIntCol]=value;
215 indexes_x_bar[iIntCol]=iColumn;
217 fabs(x_bar[iIntCol]-oldSolution[0][iIntCol])>integerTolerance)
221 #ifdef DEBUG_BON_HEURISTIC_FPUMP
222 cout<<
"iteration= "<<iteration<<
", flip= "<<flip<<endl;
228 vector<int> sortedIntegerColumns(numberIntegerColumns);
230 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
231 int iColumn = integerColumns[iIntCol];
232 sortedIntegerColumns[iIntCol] = iIntCol;
233 double value=newSolution[iColumn];
234 score[iIntCol] = fabs(value-oldSolution[0][iIntCol]);
236 sort(sortedIntegerColumns.begin(),sortedIntegerColumns.end(),
239 int maxNumberToMove = 1;
241 for(
int i=0; i<numberIntegerColumns; i++) {
242 int iIntCol = sortedIntegerColumns[i];
243 if(score[iIntCol] > 0.00) {
244 int iColumn = integerColumns[iIntCol];
245 double value=newSolution[iColumn];
246 if(value-oldSolution[0][iIntCol]>0.0)
247 value = oldSolution[0][iIntCol]+1.0;
249 value = oldSolution[0][iIntCol]-1.0;
251 if(value < x_l[iColumn]-primalTolerance)
253 else if(value > x_u[iColumn]+primalTolerance)
255 assert(fabs(floor(value+0.5)-value)<=integerTolerance);
256 x_bar[iIntCol]=value;
260 if(numberMoved >= maxNumberToMove)
268 for (
int k = numberOldSolutionsStored-1;
k > 0;
k--) {
269 double *
b = oldSolution[
k];
271 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
272 if (fabs(x_bar[iIntCol]-b[iIntCol])>integerTolerance) {
280 #ifdef DEBUG_BON_HEURISTIC_FPUMP
281 cout<<
"matched= "<<matched<<endl;
286 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
287 int iColumn = integerColumns[iIntCol];
288 double value=newSolution[iColumn];
289 double random = max(0.0,CoinDrand48()-0.3);
290 double difference = fabs(value-oldSolution[0][iIntCol]);
291 if(difference+random>0.5) {
292 if(value-oldSolution[0][iIntCol]>0.0)
293 value = oldSolution[0][iIntCol]+1.0;
295 value = oldSolution[0][iIntCol]-1.0;
297 if(value < x_l[iColumn]-primalTolerance)
299 else if(value > x_u[iColumn]+primalTolerance)
301 assert(fabs(floor(value+0.5)-value)<=integerTolerance);
304 value = oldSolution[0][iIntCol];
306 x_bar[iIntCol]=value;
311 for (
int j=numberOldSolutionsStored-1;
j>0;
j--) {
312 for (
int i = 0; i < numberIntegerColumns; i++)
313 oldSolution[
j][i]=oldSolution[
j-1][i];
315 for (
int j = 0;
j < numberIntegerColumns;
j++)
316 oldSolution[0][
j] = x_bar[
j];
321 if(integerSolutionAlreadyExists)
332 #ifdef DEBUG_BON_HEURISTIC_FPUMP
333 cout<<
"obj_nlp= "<<obj_nlp<<endl;
336 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
338 if(obj_nlp < toleranceObjectiveFP) {
344 numberFractionalVariables = 0;
345 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
346 int iColumn = integerColumns[iIntCol];
347 double value=newSolution[iColumn];
348 if (fabs(floor(value+0.5)-value)>integerTolerance)
349 numberFractionalVariables++;
354 for (
int j=0;
j<numberOldSolutionsStored;
j++)
355 delete [] oldSolution[
j];
356 delete [] oldSolution;
358 delete [] indexes_x_bar;
362 for(
int iIntCol=0; iIntCol<numberIntegerColumns; iIntCol++) {
363 int iColumn = integerColumns[iIntCol];
364 double value=floor(newSolution[iColumn]+0.5);
369 bool feasible =
true;
375 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
378 double newSolutionValue;
379 minlp->
eval_f(numberColumns, newSolution,
true, newSolutionValue);
380 if(newSolutionValue < solutionValue) {
381 memcpy(betterSolution,newSolution,numberColumns*
sizeof(
double));
382 solutionValue = newSolutionValue;
387 #ifdef DEBUG_BON_HEURISTIC_FPUMP
388 cout<<
"returnCode= "<<returnCode<<endl;
395 delete [] columnStart;
396 delete [] columnLength;
398 delete [] newSolution;
400 delete [] copy_newSolution;
409 roptions->AddBoundedIntegerOption(
"feasibility_pump_objective_norm",
"Norm of feasibility pump objective function",
411 roptions->setOptionExtraInfo(
"feasibility_pump_objective_norm", 63);
412 roptions->AddStringOption2(
"heuristic_feasibility_pump",
"whether the heuristic feasibility pump should be used",
413 "no",
"no",
"",
"yes",
"",
"");
414 roptions->setOptionExtraInfo(
"heuristic_feasibility_pump", 63);
417 roptions->AddStringOption2(
"unstable_fp",
"use at your own risks",
421 roptions->setOptionExtraInfo(
"unstable_fp", 63);
426 options->GetIntegerValue(
"feasibility_pump_objective_norm",
objective_norm_,
"bonmin.");
448 Ipopt::TNLP::IndexStyleEnum index_style;
450 nnz_h_lag, index_style);
457 int* indexRow =
new int[nnz_jac_g];
458 int* indexCol =
new int[nnz_jac_g];
461 indexRow, indexCol, 0);
464 double* jac_g =
new double [nnz_jac_g];
474 int indexCorrection = (index_style == Ipopt::TNLP::C_STYLE) ? 0 : 1;
475 for(
int i=0; i<nnz_jac_g; i++) {
476 int thisIndexRow = indexRow[i]-indexCorrection;
477 int thisIndexCol = indexCol[i]-indexCorrection;
478 pair<int, int> value(thisIndexCol, static_cast<int>(jac_g[i]));
490 const double primalTolerance,
501 if(g_l[iRow] == 1.0 && g_u[iRow] == 1.0) {
502 bool sosConstraint =
true;
503 double weightedSum = 0.0;
506 for (
unsigned int j=0;
j<jac_g.size();
j++) {
507 int iColumn = jac_g[
j].first;
508 if (solution[iColumn]>=1.0-integerTolerance ||
509 jac_g[
j].second != 1.0 ||
511 sosConstraint =
false;
515 weightedSum += counter * solution[iColumn];
519 #ifdef DEBUG_BON_HEURISTIC_FPUMP
521 cout<<
"weightedSum= "<<weightedSum
527 double fl = floor(weightedSum + 0.5);
528 int indexColumnSelected =
static_cast<int>(fl) - 1;
529 if(indexColumnSelected < 0){
532 assert(indexColumnSelected < jac_g.size());
533 for (
size_t j=0;
j<jac_g.size();
j++) {
534 int iColumn = jac_g[
j].first;
535 if((
int)
j == indexColumnSelected)
536 solution[iColumn] = 1.0;
538 solution[iColumn] = 0.0;
546 double value=solution[iColumn];
547 if (fabs(floor(value+0.5)-value)>integerTolerance) {
548 value = floor(value+0.5);
550 if(value < x_l[iColumn]-primalTolerance)
552 else if(value > x_u[iColumn]+primalTolerance)
554 solution[iColumn] = value;
int numberRows_
Number of rows.
std::vector< std::pair< int, int > > * col_and_jac_g_
Jacobian of g.
score_sorter(const vector< double > &score)
Constructor.
For undocumented options.
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 ...
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.
~RoundingFPump()
Destructor.
const vector< double > & score_
Ipopt::SolverReturn optimization_status() const
Get Optimization status.
int enableAdvanced_
To enable advanced unstable stuff.
void SetVariableUpperBound(Ipopt::Index var_no, Ipopt::Number x_u)
Change the upper bound on the variable.
virtual void initialSolve()
Solve initial continuous relaxation.
HeuristicFPump()
Default constructor.
int objective_norm_
Norm of the objective function - either 1 or 2.
Ipopt::Number obj_value() const
Get the objective value.
double solveFeasibilityProblem(size_t n, const double *x_bar, const int *ind, double a, double s, int L)
Given a point x_bar this solves the problem of finding the point which minimize a convex combination ...
Bonmin::Algorithm getAlgorithm()
Get the algorithm used.
const Ipopt::Number * x_l()
Get the current values for the lower bounds.
int numberColumns_
Number of columns.
const Ipopt::Number * g_sol() const
get the g solution (activities)
void round(const double integerTolerance, const double primalTolerance, double *solution)
Rounds the solution.
TMINLP2TNLP * minlp_
Pointer to problem.
HeuristicFPump & operator=(const HeuristicFPump &rhs)
Assignment operator.
const Ipopt::Number * x_u()
Get the current values for the upper bounds.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register the options for this heuristic.
const Ipopt::Number * g_l()
Get the current values for constraints lower bounds.
void Initialize(Ipopt::SmartPtr< Ipopt::OptionsList > options)
Initiaize using passed options.
void gutsOfConstructor()
gutsOfConstructor
const Ipopt::Number * x_sol() const
get the solution values
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
virtual int solution(double &solutionValue, double *betterSolution)
Performs heuristic.
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.
const Ipopt::Number * g_u()
Get the current values for constraints upper bounds.
VariableType
Type of the variables.
BonminSetup * setup_
Setup to use for local searches (will make copies).
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.
virtual bool get_starting_point(Ipopt::Index n, bool init_x, Ipopt::Number *x, bool init_z, Ipopt::Number *z_L, Ipopt::Number *z_U, Ipopt::Index m, bool init_lambda, Ipopt::Number *lambda)
Method called by Ipopt to get the starting point.
void fint fint fint real fint real * x
RoundingFPump(TMINLP2TNLP *minlp)
Default constructor.