14 #include "CoinHelperFunctions.hpp"
15 #include "CbcModel.hpp"
20 #include "OsiCpxSolverInterface.hpp"
23 #include "OsiClpSolverInterface.hpp"
25 #include "OsiAuxInfo.hpp"
27 #include "CoinTime.hpp"
33 #include "CoinHelperFunctions.hpp"
35 #define DEBUG_BON_HEURISTIC
41 HeuristicInnerApproximation::HeuristicInnerApproximation(
BonminSetup * setup) :
42 CbcHeuristic(), setup_(setup), howOften_(100), mip_(NULL),
51 howOften_(copy.howOften_),
59 CbcHeuristic::operator=(rhs);
72 roptions->SetRegisteringCategory(
"Initial Approximations descriptions",
74 roptions->AddStringOption2(
"heuristic_inner_approximation",
75 "if yes runs the InnerApproximation heuristic",
"yes",
"no",
76 "don't run it",
"yes",
"runs the heuristic",
"");
78 roptions->setOptionExtraInfo(
"heuristic_inner_approximation", 63);
86 b->
options()->GetIntegerValue(
"number_approximations_initial_outer",
100 if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1)
return 0;
101 if ((model_->getNodeCount()%
howOften_)!=0||model_->getCurrentPassNumber()>1)
108 nlp = dynamic_cast<OsiTMINLPInterface *>(model_->solver()->clone());
114 double integerTolerance = model_->getDblParam(CbcModel::CbcIntegerTolerance);
120 Ipopt::TNLP::IndexStyleEnum index_style;
121 minlp->
get_nlp_info(numberColumns, numberRows, nnz_jac_g,
122 nnz_h_lag, index_style);
126 const double* x_sol = minlp->
x_sol();
128 double* newSolution =
new double [numberColumns];
129 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
130 double* new_g_sol =
new double [numberRows];
132 bool feasible =
true;
134 #ifdef DEBUG_BON_HEURISTIC
135 cout <<
"Loading the problem to OSI\n";
139 bool delete_si =
false;
141 si =
new OsiClpSolverInterface;
145 CoinMessageHandler * handler = model_->messageHandler()->clone();
146 si->passInMessageHandler(handler);
147 si->messageHandler()->setLogLevel(2);
148 #ifdef DEBUG_BON_HEURISTIC
149 cout <<
"Loading problem into si\n";
152 #ifdef DEBUG_BON_HEURISTIC
153 cout <<
"problem loaded\n";
154 cout <<
"**** Running optimization ****\n";
157 #ifdef DEBUG_BON_HEURISTIC
158 cout <<
"Optimization finished\n";
162 for (
size_t iLCol=0;iLCol<numberColumns;iLCol++) {
163 newSolution[iLCol] = solution[iLCol];
174 const double* x_l = minlp->
x_l();
175 const double* x_u = minlp->
x_u();
176 const double* g_l = minlp->
g_l();
177 const double* g_u = minlp->
g_u();
178 double primalTolerance = 1.0e-6;
182 std::vector<double> memLow(numberColumns);
183 std::vector<double> memUpp(numberColumns);
184 std::copy(minlp->
x_l(), minlp->
x_l() + numberColumns, memLow.begin());
185 std::copy(minlp->
x_u(), minlp->
x_u() + numberColumns, memUpp.begin());
187 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
189 double value=floor(newSolution[iColumn]+0.5);
199 memcpy(newSolution,minlp->
x_sol(),numberColumns*
sizeof(double));
203 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
214 double newSolutionValue;
215 minlp->
eval_f(numberColumns, newSolution,
true, newSolutionValue);
216 if(newSolutionValue < solutionValue) {
217 memcpy(betterSolution,newSolution,numberColumns*
sizeof(
double));
218 solutionValue = newSolutionValue;
223 delete [] newSolution;
228 #ifdef DEBUG_BON_HEURISTIC
229 std::cout<<
"Inner approximation returnCode = "<<returnCode<<std::endl;
238 const double *
x,
const double *
x2) {
240 int n,
m, nnz_jac_g, nnz_h_lag;
241 Ipopt::TNLP::IndexStyleEnum index_style;
243 problem->
get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
246 CoinPackedVector cut;
258 problem->
eval_gi(n, x, 1, ind, g);
259 problem->
eval_gi(n, x2, 1, ind, g2);
262 problem->
eval_grad_gi(n, x2, 0, ind, nnz, jCol(), NULL);
264 problem->
eval_grad_gi(n, x2, 0, ind, nnz, NULL, jValues());
266 for (
int i = 0; i <
nnz; i++) {
267 const int &colIdx = jCol[i];
268 if(index_style == Ipopt::TNLP::FORTRAN_STYLE) jCol[i]--;
269 diff = x[colIdx] - x2[colIdx];
271 if (fabs(diff) >= 1
e-8) {
273 cut.insert(colIdx, a);
274 ub = a * x[colIdx] -
g;
277 cut.insert(colIdx, jValues[i]);
283 newCut.setGloballyValidAsInteger(1);
288 int binary_id = (ids == NULL) ? -1 : ids[ind];
290 cut.insert(binary_id, -ub);
305 const double *
x,
bool getObj) {
310 Ipopt::TNLP::IndexStyleEnum index_style;
313 problem->
get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
318 problem->
eval_jac_g(n, NULL, 0, m, nnz_jac_g, jRow(), jCol(), NULL);
319 if(index_style == Ipopt::TNLP::FORTRAN_STYLE)
321 for(
int i = 0 ; i < nnz_jac_g ; i++){
328 problem->
eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL,
332 problem->
eval_g(n, x, 1, m,
g());
336 int numNonLinear = 0;
342 double infty = si.getInfinity();
346 for (
int i = 0; i <
m; i++) {
347 if (constTypes[i] == Ipopt::TNLP::NON_LINEAR) {
348 nonLinear[numNonLinear++] = i;
354 for (
int i = 0; i <
m; i++) {
355 if (constTypes[i] != Ipopt::TNLP::NON_LINEAR) {
356 if (rowLower[i] > -nlp_infty) {
358 rowLow[ind] = (rowLower[i]);
360 rowLow[ind] = -
infty;
361 if (rowUpper[i] < nlp_infty) {
363 rowUp[ind] = (rowUpper[i]);
371 CoinPackedMatrix mat(
true, jRow(), jCol(), jValues(), nnz_jac_g);
372 mat.setDimensions(m, n);
375 mat.deleteRows(numNonLinear, nonLinear());
379 for (
int i = 0; i < numcols; i++)
383 obj(), rowLow(), rowUp());
385 for (
int i = 0; i <
n; i++) {
391 bool addObjVar =
false;
396 si.setDblParam(OsiObjOffset, -zero);
399 si.setObjective(obj());
411 if (InnerDesc == 1) {
414 double * p = CoinCopyOfArray(colLower, n);
415 double * pp = CoinCopyOfArray(colLower, n);
416 double *
up = CoinCopyOfArray(colUpper, n);
418 const int& nbAp =
nbAp_;
419 std::vector<int> nbG(m, 0);
421 std::vector<double> step(n);
423 for (
int i = 0; i <
n; i++) {
425 if (colUpper[i] > 1e08) {
429 if (colUpper[i] > 1e08 || colLower[i] < -1e08 || (variableType[i]
433 step[i] = (up[i] - colLower[i]) / (nbAp);
435 if (colLower[i] < -1e08) {
444 for (
int j = 1;
j <= nbAp;
j++) {
446 for (
int i = 0; i <
n; i++) {
450 problem->
eval_g(n, p, 1, m, g_p());
451 problem->
eval_g(n, pp, 1, m, g_pp());
454 for (
int i = 0; (i < m && constTypes[i] == Ipopt::TNLP::NON_LINEAR); i++) {
457 diff = std::abs(g_p[i] - g_pp[i]);
458 if (nbG[i] < nbAp - 1) {
460 p[varInd] = pp[varInd];
467 for(
int i = 0; (i< m && constTypes[i] == Ipopt::TNLP::NON_LINEAR); i++) {
bool getMyInnerApproximation(OsiTMINLPInterface &si, OsiCuts &cs, int ind, const double *x, const double *x2)
Get an inner-approximation constraint obtained by drawing a chord linking the two given points x and ...
For undocumented options.
virtual double getInfinity() const
Get solver's value for infinity.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register the options common to all local search based heuristics.
static Bigint * diff(Bigint *a, Bigint *b)
BonminSetup * setup_
Setup to use for local searches (will make copies).
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
const TMINLP2TNLP * problem() const
get pointer to the TMINLP2TNLP adapter
int nbAp_
Number of Approximation points.
This is class provides an Osi interface for a Mixed Integer Linear Program expressed as a TMINLP (so ...
void extractInnerApproximation(OsiTMINLPInterface &nlp, OsiSolverInterface &si, const double *x, bool getObj)
virtual bool eval_grad_gi(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index i, Ipopt::Index &nele_grad_gi, Ipopt::Index *jCol, Ipopt::Number *values)
compute the structure or values of the gradient for one constraint
void fint fint fint real * a
OsiSolverInterface * clone(bool copyData=true) const
Virtual copy constructor.
virtual bool eval_gi(Ipopt::Index n, const Ipopt::Number *x, bool new_x, Ipopt::Index i, Ipopt::Number &gi)
compute the value of a single constraint
void SetVariableLowerBound(Ipopt::Index var_no, Ipopt::Number x_l)
Change the lower bound on the variable.
SubMipSolver * mip_
A subsolver for MIP.
virtual int getNumRows() const
Get number of rows.
Ipopt::SolverReturn optimization_status() const
Get Optimization status.
virtual int getNumCols() const
Get number of columns.
void SetVariableUpperBound(Ipopt::Index var_no, Ipopt::Number x_u)
Change the upper bound on the variable.
virtual void initialSolve()
Solve initial continuous relaxation.
const double * getLastSolution()
get the solution found in last local search (return NULL if no solution).
void fint fint fint real fint real real real real real real real real real * e
virtual bool get_constraints_linearity(Ipopt::Index m, LinearityType *const_types)
Returns the constraint linearity.
A very simple class to provide a common interface for solving MIPs with Cplex and Cbc...
Bonmin::Algorithm getAlgorithm()
Get the algorithm used.
const Ipopt::Number * x_l()
Get the current values for the lower bounds.
~HeuristicInnerApproximation()
Destructor.
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.
HeuristicInnerApproximation & operator=(const HeuristicInnerApproximation &rhs)
Assignment operator.
const Ipopt::Number * x_u()
Get the current values for the upper bounds.
virtual int solution(double &solutionValue, double *betterSolution)
Performs heuristic.
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.
virtual const double * getRowUpper() const
Get pointer to array[getNumRows()] of row upper bounds.
OsiSolverInterface * solver()
const Ipopt::Number * g_l()
Get the current values for constraints lower bounds.
void Initialize(BonminSetup *setup)
Initialize method.
HeuristicInnerApproximation(BonminSetup *setup)
Constructor with setup.
const Ipopt::Number * x_sol() const
get the solution values
virtual const double * getColUpper() const
Get pointer to array[getNumCols()] of column upper bounds.
OsiTMINLPInterface * nonlinearSolver()
Pointer to the non-linear solver used.
virtual void addObjectiveFunction(OsiSolverInterface &si, const double *x)
Add constraint corresponding to objective function.
Ipopt::SmartPtr< Ipopt::OptionsList > options()
Acces list of Options.
void fint fint fint real fint real real real real real real * g
virtual const double * getRowLower() const
Get pointer to array[getNumRows()] of row lower bounds.
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.
int howOften_
How often to do (code can change)
int nnz
ATTENTION: Filter expect the jacobian to be ordered by row.
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.
virtual const int * get_const_xtra_id() const
Access array describing constraint to which perspectives should be applied.
virtual bool hasLinearObjective()
returns true if objective is linear.
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.
void fint fint fint real fint real * x
Class to add a few more information to Ipopt::RegisteredOptions.