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"
40 CbcHeuristic(), setup_(setup), howOften_(100), mip_(NULL),
41 nbAp_(50), time_limit_(10.) {
49 howOften_(copy.howOften_),
50 mip_(new Bonmin::SubMipSolver(*copy.mip_)),
52 time_limit_(copy.time_limit_)
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);
80 roptions->AddLowerBoundedIntegerOption(
"number_inner_approximation_points",
81 "Set the number of points to use for linear inner approximation of nonlinear functions in heuristic",
83 roptions->setOptionExtraInfo(
"number_inner_approximation_points", 63);
85 roptions->AddLowerBoundedNumberOption(
"inner_time_limit",
86 "Time limit for inner approximation",
88 roptions->setOptionExtraInfo(
"number_inner_approximation_points", 63);
96 b->
options()->GetIntegerValue(
"number_inner_approximation_points",
98 b->
options()->GetNumericValue(
"inner_time_limit",
112 if(model_->getNodeCount() || model_->getCurrentPassNumber() > 1)
return 0;
113 if ((model_->getNodeCount()%
howOften_)!=0||model_->getCurrentPassNumber()>1)
120 nlp = dynamic_cast<Bonmin::OsiTMINLPInterface *>(model_->solver()->clone());
133 Ipopt::TNLP::IndexStyleEnum index_style;
134 minlp->
get_nlp_info(numberColumns, numberRows, nnz_jac_g,
135 nnz_h_lag, index_style);
139 const double* x_sol = minlp->
x_sol();
141 double* newSolution =
new double [numberColumns];
142 memcpy(newSolution,x_sol,numberColumns*
sizeof(
double));
143 double* new_g_sol =
new double [numberRows];
145 bool feasible =
true;
147 #ifdef DEBUG_BON_HEURISTIC
148 std::cout <<
"Loading the problem to OSI\n";
152 bool delete_si =
false;
154 si =
new OsiClpSolverInterface;
158 CoinMessageHandler * handler = model_->messageHandler()->clone();
159 si->passInMessageHandler(handler);
160 si->messageHandler()->setLogLevel(2);
161 #ifdef DEBUG_BON_HEURISTIC
162 std::cout <<
"Loading problem into si\n";
165 #ifdef DEBUG_BON_HEURISTIC
166 std::cout <<
"problem loaded\n";
167 std::cout <<
"**** Running optimization ****\n";
170 #ifdef DEBUG_BON_HEURISTIC
171 std::cout <<
"Optimization finished\n";
175 std::copy(solution, solution + numberColumns, newSolution);
186 #if 0 // Set to 1 if you need to test the feasibility of the returned solution
187 const double* x_l = minlp->
x_l();
188 const double* x_u = minlp->
x_u();
189 const double* g_l = minlp->
g_l();
190 const double* g_u = minlp->
g_u();
191 double primalTolerance = 1.0e-6;
196 for (
int iColumn=0;iColumn<numberColumns;iColumn++) {
197 double value=newSolution[iColumn];
198 if(value - x_l[iColumn] < -1
e-8|| value - x_u[iColumn] > 1
e-8) {
199 std::cout<<
"Solution found infeasible because: "<<std::endl;
200 std::cout<<
"x_l["<<iColumn<<
"]= "<<x_l[iColumn]<<
" "
201 <<
"x_sol["<<iColumn<<
"]= "<<value<<
" "
202 <<
"x_u["<<iColumn<<
"]= "<<x_u[iColumn]<<std::endl;
207 minlp->
eval_g(numberColumns, newSolution,
true,
208 numberRows, new_g_sol);
209 for(
int iRow=0; iRow<numberRows; iRow++) {
210 if(new_g_sol[iRow]<g_l[iRow]-primalTolerance ||
211 new_g_sol[iRow]>g_u[iRow]+primalTolerance) {
212 std::cout<<
"It should be infeasible because: "<<std::endl;
213 std::cout<<
"g_l["<<iRow<<
"]= "<<g_l[iRow]<<
" "
214 <<
"g_sol["<<iRow<<
"]= "<<new_g_sol[iRow]<<
" "
215 <<
"g_u["<<iRow<<
"]= "<<g_u[iRow]<<std::endl;
216 std::cout<<
"primalTolerance= "<<primalTolerance<<std::endl;
217 if(constTypes[iRow] == Ipopt::TNLP::NON_LINEAR)
218 std::cout<<
"nonLinear constraint number "<<iRow<<std::endl;
222 std::cout<<
"Every thing is feasible"<<std::endl;
226 double newSolutionValue;
227 minlp->
eval_f(numberColumns, newSolution,
true, newSolutionValue);
228 if(newSolutionValue < solutionValue) {
229 memcpy(betterSolution,newSolution,numberColumns*
sizeof(
double));
230 solutionValue = newSolutionValue;
235 delete [] newSolution;
240 #ifdef DEBUG_BON_HEURISTIC
241 std::cout<<
"Inner approximation returnCode = "<<returnCode<<std::endl;
250 const double *
x,
const double *
x2) {
252 int n,
m, nnz_jac_g, nnz_h_lag;
253 Ipopt::TNLP::IndexStyleEnum index_style;
255 problem->
get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
259 CoinPackedVector cut;
268 problem->
eval_gi(n, x, 1, ind, g);
269 problem->
eval_gi(n, x2, 1, ind, g2);
272 problem->
eval_grad_gi(n, x2, 0, ind, nnz, jCol(), NULL);
274 problem->
eval_grad_gi(n, x2, 0, ind, nnz, NULL, jValues());
277 for (
int i = 0; i <
nnz; i++) {
278 const int &colIdx = jCol[i];
279 if(index_style == Ipopt::TNLP::FORTRAN_STYLE) jCol[i]--;
280 diff = x[colIdx] - x2[colIdx];
282 if (fabs(diff) >= 1
e-8) {
284 cut.insert(colIdx, a);
285 ub = (a * x[colIdx] -
g) - fabs(a * x[colIdx] - g)*1
e-6;
289 cut.insert(colIdx, jValues[i]);
297 newCut.setGloballyValidAsInteger(1);
304 binary_id = (ids == NULL) ? -1 : ids[ind];
306 cut.insert(binary_id, -ub);
323 const double *
x,
bool getObj) {
324 printf(
"************ Start extracting inner approx");
329 Ipopt::TNLP::IndexStyleEnum index_style;
332 problem->
get_nlp_info(n, m, nnz_jac_g, nnz_h_lag, index_style);
337 problem->
eval_jac_g(n, NULL, 0, m, nnz_jac_g, jRow(), jCol(), NULL);
338 if(index_style == Ipopt::TNLP::FORTRAN_STYLE)
340 for(
int i = 0 ; i < nnz_jac_g ; i++){
347 problem->
eval_jac_g(n, x, 1, m, nnz_jac_g, NULL, NULL,
351 problem->
eval_g(n, x, 1, m,
g());
355 int numNonLinear = 0;
361 double infty = si.getInfinity();
367 for (
int i = 0; i <
m; i++) {
368 if (constTypes[i] == Ipopt::TNLP::NON_LINEAR) {
369 nonLinear[numNonLinear++] = i;
375 for (
int i = 0; i <
m; i++) {
376 if (constTypes[i] != Ipopt::TNLP::NON_LINEAR) {
377 if (rowLower[i] > -nlp_infty) {
379 rowLow[ind] = (rowLower[i]);
381 rowLow[ind] = -
infty;
382 if (rowUpper[i] < nlp_infty) {
384 rowUp[ind] = (rowUpper[i]);
392 CoinPackedMatrix mat(
true, jRow(), jCol(), jValues(), nnz_jac_g);
393 mat.setDimensions(m, n);
396 mat.deleteRows(numNonLinear, nonLinear());
400 for (
int i = 0; i < numcols; i++)
404 obj(), rowLow(), rowUp());
406 for (
int i = 0; i <
n; i++) {
411 bool addObjVar =
false;
416 si.setDblParam(OsiObjOffset, -zero);
419 si.setObjective(obj());
431 if (InnerDesc == 1) {
434 double * p = CoinCopyOfArray(colLower, n);
435 double * pp = CoinCopyOfArray(colLower, n);
436 double *
up = CoinCopyOfArray(colUpper, n);
438 for (
int i = 0; i <
n; i++) {
447 const int& nbAp =
nbAp_;
448 printf(
"Generating approximation with %i points.\n", nbAp);
450 std::vector<double> step(n);
453 for (
int i = 0; i <
n; i++) {
458 p[i] = pp[i] = up[i] = 0;
461 step[i] = (up[i] - p[i]) / (nbAp);
464 printf(
"Number of linears %i\n", n_lin);
466 for (
int j = 1;
j < nbAp;
j++) {
468 for (
int i = 0; i <
n; i++) {
472 for (
int i = 0; (i <
m ); i++) {
476 printf(
"Error in generating inner approximation\n");
480 std::copy(pp, pp+n, p);
484 for(
int i = 0; (i<
m); i++) {
494 printf(
"************ Done extracting inner approx ********");
For undocumented options.
virtual double getInfinity() const
Get solver's value for infinity.
static Bigint * diff(Bigint *a, Bigint *b)
virtual const double * getColLower() const
Get pointer to array[getNumCols()] of column lower bounds.
~HeuristicInnerApproximation()
Destructor.
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 ...
int howOften_
How often to do (code can change)
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
int nbAp_
Number of Approximation points.
OsiSolverInterface * clone(bool copyData=true) const
Virtual copy constructor.
void Initialize(Bonmin::BonminSetup *setup)
Initialize method.
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
virtual int getNumRows() const
Get number of rows.
double time_limit_
Time limit for mip.
virtual int getNumCols() const
Get number of columns.
static void registerOptions(Ipopt::SmartPtr< Bonmin::RegisteredOptions > roptions)
Register the options common to all local search based heuristics.
HeuristicInnerApproximation(Bonmin::BonminSetup *setup)
Constructor with setup.
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.
virtual bool get_variables_linearity(Ipopt::Index n, LinearityType *var_types)
Returns the variables 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.
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.
bool getMyInnerApproximation(Bonmin::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 ...
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.
Bonmin::BonminSetup * setup_
Setup to use for local searches (will make copies).
virtual int solution(double &solutionValue, double *betterSolution)
Performs heuristic.
Bonmin::SubMipSolver * mip_
A subsolver for MIP.
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 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.
HeuristicInnerApproximation & operator=(const HeuristicInnerApproximation &rhs)
Assignment operator.
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.
void extractInnerApproximation(Bonmin::OsiTMINLPInterface &nlp, OsiSolverInterface &si, const double *x, bool getObj)
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.