reformulate.cpp
Go to the documentation of this file.
1 /* $Id: reformulate.cpp 818 2012-02-08 04:16:35Z pbelotti $
2  *
3  * Name: reformulate.cpp
4  * Author: Pietro Belotti
5  * Purpose: apply reformulation
6  *
7  * This file is licensed under the Eclipse Public License (EPL)
8  */
9 
10 #include <vector>
11 
12 #include "CoinHelperFunctions.hpp"
13 #include "CoinTime.hpp"
14 
15 #include "BonBabSetupBase.hpp"
16 
17 #include "CouenneTypes.hpp"
18 
19 #include "CouenneExprVar.hpp"
20 
21 #include "CouenneProblem.hpp"
22 #include "CouenneDepGraph.hpp"
23 #include "CouenneLQelems.hpp"
24 
25 #include "CouenneRecordBestSol.hpp"
26 
27 #define THRESHOLD_OUTPUT_REFORMULATE 1000
28 
29 using namespace Couenne;
30 
33 
34  double now = CoinCpuTime ();
35 
37  jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "Reformulating problem: ");
38  fflush (stdout);
39  }
40 
41  if (domain_.current () == NULL) {
42 
43  // create room for problem's variables and bounds, if no domain exists
44  CouNumber
45  *x = (CouNumber *) malloc (nVars() * sizeof (CouNumber)),
46  *lb = (CouNumber *) malloc (nVars() * sizeof (CouNumber)),
47  *ub = (CouNumber *) malloc (nVars() * sizeof (CouNumber));
48 
49  for (int i = nVars(); i--;) {
50  x [i] = 0.;
51  lb [i] = -COUENNE_INFINITY;
52  ub [i] = COUENNE_INFINITY;
53  }
54 
55  domain_.push (nVars (), x, lb, ub);
56  }
57 
58  // link initial variables to problem's domain
59  for (std::vector <exprVar *>::iterator i = variables_.begin ();
60  i != variables_.end (); ++i)
61  (*i) -> linkDomain (&domain_);
62 
63  if (jnlst_ -> ProduceOutput(Ipopt::J_SUMMARY, J_PROBLEM))
64  print (std::cout);
65 
66  // save -- for statistic purposes -- number of original
67  // constraints. Some of them will be deleted as definition of
68  // auxiliary variables.
69  nOrigCons_ = constraints_. size ();
71 
72  jnlst_->Printf (Ipopt::J_ERROR, J_PROBLEM,
73  "Problem size before reformulation: %d variables (%d integer), %d constraints.\n",
75 
76  // reformulation
77  if (!standardize ()) { // problem is infeasible if standardize returns false
78 
79  jnlst_->Printf(Ipopt::J_ERROR, J_COUENNE,
80  "Problem infeasible after reformulation\n");
81  // fake infeasible bounds for Couenne to bail out
82  for (int i = nVars (); i--;)
83  Ub (i) = - (Lb (i) = 1.);
84 
85  return;
86  }
87 
88  // clear all spurious variable pointers not referring to the variables_ vector
89  realign ();
90 
91  // give a value to all auxiliary variables. Do it now to be able to
92  // recognize complementarity constraints in fillDependence()
93  initAuxs ();
94 
95  bool *isInt = new bool[nVars()];
96  for(int i=0; i<nVars(); i++) {
97  if(variables_[i]->isInteger()) {
98  isInt[i] = true;
99  }
100  else {
101  isInt[i] = false;
102  }
103  }
104  recBSol->setInitIsInt(isInt, nVars());
105  recBSol->setInitDomLb(domain()->lb(), nVars());
106  recBSol->setInitDomUb(domain()->ub(), nVars());
107  delete[] isInt;
108 
109  CouNumber cutoff;
110  // check for initial solution given to Couenne. If feasible, set cutoff
111 
112 #ifdef FM_CHECKNLP2
113  int objind = objectives_ [0] -> Body () -> Index ();
114  cutoff = objind >= 0 ? X (objind) : objectives_ [0] -> Body () -> Value ();
115  if(checkNLP2(X(), cutoff, false, // do not care about obj value
116  true, // stop at first viol
117  true, // checkAll
118  getFeasTol())) {
119 
120  jnlst_ -> Printf (Ipopt::J_ERROR, J_PROBLEM,
121  "Couenne: initial solution (value %g) is MINLP feasible\n",
122  cutoff);
123 
124 #ifdef FM_TRACE_OPTSOL
126  setCutOff(getRecordBestSol()->getVal());
127 #else /* not FM_TRACE_OPTSOL */
128 
129 #ifdef FM_UP_BND
130  setCutOff(getRecordBestSol()->getModSolVal());
131 #else
132  setCutOff(getRecordBestSol()->getModSolVal(),
133  getRecordBestSol()->getModSol(nVars()));
134 #endif
135 #endif /* not FM_TRACE_OPTSOL */
136 
137  }
138 #else /* not FM_CHECKNLP2 */
139  int objind = objectives_ [0] -> Body () -> Index ();
140  cutoff = objind >= 0 ? X (objind) : objectives_ [0] -> Body () -> Value ();
141 
142  if (checkNLP (X (), cutoff, true)) {
143  jnlst_ -> Printf (Ipopt::J_ERROR, J_PROBLEM,
144  "Couenne: initial solution (value %g) is MINLP feasible\n",
145  cutoff);
146 
147 #ifdef FM_TRACE_OPTSOL
148  getRecordBestSol()->update(X(), nVars(), cutoff, getFeasTol());
149  setCutOff(getRecordBestSol()->getVal());
150 #else /* not FM_TRACE_OPTSOL */
151 
152 #ifdef FM_UP_BND
153  setCutOff (cutoff);
154 #else
155  setCutOff (cutoff, X ());
156 #endif
157 #endif /* not FM_TRACE_OPTSOL */
158 
159  }
160 #endif /* not FM_CHECKNLP2 */
161 
162  // fill dependence_ structure
163  fillDependence (bonBase_, cg);
164 
165  // quadratic handling
166  fillQuadIndices ();
167 
168  // if ((now = (CoinCpuTime () - now)) > 10.)
169  // jnlst_->Printf(Ipopt::J_ERROR, J_PROBLEM,
170  // "reformulation time %.3fs\n", now);
171 
172  jnlst_->Printf (Ipopt::J_WARNING, J_PROBLEM, "Initializing auxiliaries\n");
173 
174  // give a value to all auxiliary variables
175  initAuxs ();
176 
177  int nActualVars = nIntVars_ = 0;
178 
179  // check how many integer variables we have now (including aux)
180  for (int i=0; i<nVars(); i++)
181  if (variables_ [i] -> Multiplicity () > 0) {
182 
183  nActualVars++;
184  if (variables_ [i] -> isDefinedInteger ())
185  nIntVars_++;
186  }
187 
188  jnlst_->Printf(Ipopt::J_ERROR, J_PROBLEM,
189  "Problem size after reformulation: %d variables (%d integer), %d constraints.\n",
190  nActualVars, nIntVars_, nCons());
191 
192  // check if optimal solution is available (for debug purposes)
193  readOptimum ();
194 
195  if (bonBase_) {
196 
197  CouNumber
198  art_cutoff = COIN_DBL_MAX,
199  art_lower = -COIN_DBL_MAX;
200 
201  bonBase_ -> options() -> GetNumericValue ("art_cutoff", art_cutoff, "couenne.");
202  bonBase_ -> options() -> GetNumericValue ("art_lower", art_lower, "couenne.");
203 
204  if (art_cutoff < 1.e50) setCutOff (art_cutoff);
205  if (art_lower > -1.e50) {
206  int indobj = objectives_ [0] -> Body () -> Index ();
207  if (indobj >= 0)
208  domain_.lb (indobj) = art_lower;
209  }
210  }
211 
212  if (jnlst_->ProduceOutput(Ipopt::J_DETAILED, J_PROBLEM)) {
213  // We should route that also through the journalist
214  print (std::cout);
215  }
216 
218 
220  jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "%.1f seconds\n", CoinCpuTime () - now);
221  else if (nVars () > 2*THRESHOLD_OUTPUT_REFORMULATE)
222  jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "Reformulation: %.1f seconds\n", CoinCpuTime () - now);
223 
224  if (orbitalBranching_)
225  setupSymmetry ();
226 
227  //writeAMPL ("extended-aw.mod", true);
228  //writeAMPL ("original.mod", false);
229 }
Cut Generator for linear convexifications.
void realign()
clear all spurious variables pointers not referring to the variables_ vector
Definition: problem.cpp:392
int nVars() const
Total number of variables.
void update(const double *givenSol, const int givenCard, const double givenVal, const double givenMaxViol)
std::vector< CouenneObjective * > objectives_
Objectives.
int nIntVars_
Number of discrete variables.
int nOrigCons_
Number of original constraints (disregarding those that turned into auxiliary variable definition) ...
CouNumber & lb(register int index)
current lower bound
void print(std::ostream &=std::cout)
Display current representation of problem: objective, linear and nonlinear constraints, and auxiliary variables.
Definition: problemIO.cpp:24
void setCutOff(CouNumber cutoff, const CouNumber *sol=NULL) const
Set cutoff.
Definition: problem.cpp:326
int nOrigIntVars_
Number of original integer variables.
bool checkNLP2(const double *solution, const double obj, const bool careAboutObj, const bool stopAtFirstViol, const bool checkAll, const double precision) const
Return true if either solution or recomputed_solution obtained using getAuxs() from the original vari...
Definition: checkNLP.cpp:571
Domain * domain() const
return current point &amp; bounds
int nIntVars() const
Number of integer variables.
void setInitIsInt(const bool *givenIsInt, const int givenCard)
CouenneRecordBestSol * getRecordBestSol() const
returns recorded best solution
void setupSymmetry()
empty if no NTY, symmetry data structure setup otherwise
Bonmin::BabSetupBase * bonBase_
options
std::vector< CouenneConstraint * > constraints_
Constraints.
void setInitDomUb(const CouNumber *givenUb, const int givenCard)
std::vector< exprVar * > variables_
Variables (original, auxiliary, and defined)
CouenneRecordBestSol * recBSol
Domain domain_
current point and bounds;
CouNumber * Ub() const
Return vector of upper bounds.
bool standardize()
Break problem&#39;s nonlinear constraints in simple expressions to be convexified later.
Definition: standardize.cpp:34
bool orbitalBranching_
use orbital branching?
void fillQuadIndices()
Look for quadratic terms to be used with SDP cuts.
void initAuxs() const
Initialize auxiliary variables and their bounds from original variables.
Definition: problem.cpp:51
double CouNumber
main number type in Couenne
void reformulate(CouenneCutGenerator *=NULL)
preprocess problem in order to extract linear relaxations etc.
Definition: reformulate.cpp:32
int nOrigVars_
Number of original variables.
#define COUENNE_INFINITY
CouNumber * X() const
Return vector of variables.
bool readOptimum(std::string *fname=NULL)
Read best known solution from file given in argument.
Definition: problemIO.cpp:107
void createUnusedOriginals()
Some originals may be unused due to their zero multiplicity (that happens when they are duplicates)...
void push(int dim, CouNumber *x, CouNumber *lb, CouNumber *ub, bool copy=true)
save current point and start using another
Definition: domain.cpp:166
int nCons() const
Get number of constraints.
double getFeasTol()
returns feasibility tolerance
JnlstPtr jnlst_
SmartPointer to the Journalist.
bool checkNLP(const double *solution, double &obj, bool recompute=false) const
Check if solution is MINLP feasible.
Definition: checkNLP.cpp:23
#define THRESHOLD_OUTPUT_REFORMULATE
Definition: reformulate.cpp:27
DomainPoint * current()
return current point
const Ipopt::EJournalCategory J_COUENNE(Ipopt::J_USER8)
const Ipopt::EJournalCategory J_PROBLEM(Ipopt::J_USER4)
void fillDependence(Bonmin::BabSetupBase *base, CouenneCutGenerator *=NULL)
fill dependence_ structure
void setInitDomLb(const CouNumber *givenLb, const int givenCard)
void fint fint fint real fint real * x
CouNumber * Lb() const
Return vector of lower bounds.
bool isInteger(CouNumber x)
is this number integer?