standardize.cpp
Go to the documentation of this file.
1 /* $Id: standardize.cpp 1147 2015-05-04 14:01:51Z stefan $
2  *
3  * Name: standardize.cpp
4  * Author: Pietro Belotti
5  * Purpose: standardize all expressions in a problem
6  *
7  * (C) Carnegie-Mellon University, 2006-11.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include <vector>
12 
13 #include "CoinHelperFunctions.hpp"
14 
15 #include "BonBabSetupBase.hpp"
16 
17 #include "CouenneTypes.hpp"
18 #include "CouenneExpression.hpp"
19 #include "CouenneExprIVar.hpp"
20 #include "CouenneExprSub.hpp"
21 #include "CouenneExprClone.hpp"
22 #include "CouenneProblem.hpp"
23 #include "CouenneProblemElem.hpp"
24 #include "CouenneDepGraph.hpp"
25 #include "CouenneSdpCuts.hpp"
26 
27 using namespace Ipopt;
28 using namespace Couenne;
29 
30 void replace (CouenneProblem *p, int wind, int xind);
31 
33 
34 bool CouenneProblem::standardize () {
35 
36  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
37  printf ("Reformulation. current point: %d vars -------------------\n",
38  domain_.current () -> Dimension ());
39  for (int i=0; i<domain_.current () -> Dimension (); i++)
40  printf ("%3d %20g [%20g %20g]\n", i, domain_.x (i), domain_.lb (i), domain_.ub (i));
41  }
42 
43  bool retval = true;
44 
45  // create dependence graph to assign an order to the evaluation (and
46  // bound propagation, and -- in reverse direction -- implied bounds)
47  graph_ = new DepGraph;
48 
49  for (std::vector <exprVar *>::iterator i = variables_ . begin ();
50  i != variables_ . end (); ++i)
51  graph_ -> insert (*i);
52 
53  // allocate space in auxiliaries_ from commonexprs_
54 
55  //int initVar = variables_ . size () - commonexprs_ . size ();
56 
57  //std::set <int> DefVarDiffSet;
58 
59  // // DEFINED VARIABLES -----------------------------------------------------------------------
60 
61  // // standardize initial aux variables (aka defined variables, aka
62  // // common expression)
63 
64  // if (commonexprs_.size ()) jnlst_ -> Printf (J_ALL, J_REFORMULATE,
65  // "%d common exprs, initVar = %d = %d - %d\n",
66  // commonexprs_ . size (),
67  // initVar,
68  // variables_ . size (),
69  // commonexprs_ . size ());
70 
71  // for (std::vector <expression *>::iterator i = commonexprs_ . begin ();
72  // i != commonexprs_ . end (); ++i) {
73 
74  // if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
75  // printf ("\n=====> [1] stdz common expr [%d] := ", initVar); fflush (stdout);
76  // (*i) -> print (); printf ("\n");
77  // }
78 
79  // exprAux *naux = (*i) -> standardize (this, false);
80  // expression *img = (*i);
81 
82  // if (naux)
83  // img = naux -> Image ();
84 
85  // if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
86  // printf ("\n=====> [2] "); fflush (stdout);
87  // if (*i) (*i) -> print (); else printf ("(null)"); printf (" [*i] "); fflush (stdout);
88  // if (naux) naux -> print (); else printf ("(null)"); printf (" [naux] "); fflush (stdout);
89  // if (img) img -> print (); else printf ("(null)"); printf (" [img]\n");
90  // }
91 
92  // // trick to obtain same index as common expression: create exprAux
93  // // with index initVar and replace occurrences with address of
94  // // newly created exprAux through auxiliarize()
95 
96  // exprVar *newvar;
97  // //img -> isInteger () ? exprAux::Integer : exprAux::Continuous);
98 
99  // //auxiliarize (newvar); // puts newvar at right position in variables_
100 
101  // if (((*i) -> Type () == VAR) ||
102  // ((*i) -> Type () == AUX)) {
103 
104  // newvar = new exprAux (img, initVar, 1 + img -> rank (), exprAux::Unset, &domain_);
105  // replace (this, initVar, img -> Index ());
106  // //auxiliarize (variables_ [initVar],
107  // //variables_ [img -> Index ()]);
108 
109  // //delete variables_ [initVar];
110 
111  // variables_ [initVar] = newvar;
112  // variables_ [initVar] -> zeroMult ();
113 
114  // } else {
115 
116  // if (img -> dependsOn (&initVar, 1, TAG_AND_RECURSIVE)) {
117 
118  // //printf ("depends! "); img -> print ();
119 
120  // expression *diff = new exprSub (new exprClone (variables_ [initVar]), img);
121 
122  // //printf ("; diff = "); diff -> print ();
123 
124  // exprAux *diffAux = diff -> standardize (this, false);
125 
126  // //printf ("; aux: "); if (diffAux) diffAux -> print ();
127 
128  // //if (diffAux)
129  // exprAux *newAux = addAuxiliary (diff);
130 
131  // //printf ("; real aux: "); if (newAux) newAux -> print (); putchar ('\n');
132 
133  // //Lb (newAux -> Index ()) =
134  // //Ub (newAux -> Index ()) = 0.;
135 
136  // DefVarDiffSet. insert (newAux -> Index ());
137 
138  // } else {
139 
140  // newvar = new exprAux (img, initVar, 1 + img -> rank (), exprAux::Unset, &domain_);
141  // //replace (this, initVar, newvar -> Index ());
142 
143  // auxiliarize (newvar);
144 
145  // //delete variables_ [initVar];
146  // variables_ [initVar] = newvar;
147 
148  // graph_ -> insert (newvar);
149  // //if (naux)
150  // graph_ -> erase (naux);
151  // }
152  // }
153 
154  // //variables_ . erase (variables_ . end () - 1);
155 
156  // if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
157  // if (naux) {
158  // printf ("done: "); fflush (stdout);
159  // naux -> print ();
160  // printf (" := "); fflush (stdout);
161  // naux -> Image () -> print (); printf ("\n..."); fflush (stdout);
162  // } else if (*i) {
163  // (*i) -> print ();
164  // //printf (" := "); fflush (stdout);
165  // //aux -> Image () -> print ();
166  // printf ("\n");
167  // } else printf ("[n]aux NULL!\n");
168  // }
169 
170  // initVar++;
171  // }
172 
173  // OBJECTIVES ------------------------------------------------------------------------------
174 
175  for (std::vector <CouenneObjective *>::iterator i = objectives_.begin ();
176  i != objectives_.end (); ++i) {
177 
178  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
179  printf ("Objective [code: %d]", (*i) -> Body () -> code ());
180  (*i) -> print ();
181  }
182 
183  // check for constant objective
184 
185  std::set <int> deplist;
186 
187  if (0 == (*i) -> Body () -> DepList (deplist, TAG_AND_RECURSIVE)) {
188 
189  // This objective is constant. Store the value and use it in
190  // CouenneSolverInterface.
191 
192  constObjVal_ = (*i) -> Body () -> Value ();
193 
194  } else {
195 
196  exprAux *aux = (*i) -> standardize (this);
197 
198  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
199  printf (" objective "); (*i) -> print ();
200  if (aux) {printf (" admits aux "); aux -> print ();}
201  }
202 
203  if (aux) {
204  //delete ((*i) -> Body ());
205  (*i) -> Body (new exprClone (aux));
206  }
207 
208  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
209  printf (". New obj: "); (*i) -> print (); printf ("\n");
210  }
211  }
212  }
213 
214  // CONSTRAINTS ----------------------------------------------------------------------------
215 
216  // commuted_ is an array with a flag for each original variable,
217  // which is true at position i if initially original variable x_i
218  // became auxiliary (because of constraint
219  //
220  // x_{k+1} + f(x_1,x_2...,x_k} <=/=/>= 0
221  //
222  // becoming
223  //
224  // x_{k+1} <=/=/>= - f(x_1,x_2...,x_k}
225 
226  commuted_ = new bool [nVars ()];
227  CoinFillN (commuted_, nVars (), false);
228 
229  std::vector <std::vector <CouenneConstraint *>::iterator> iters2erase;
230 
231  for (std::vector <CouenneConstraint *>::iterator i = constraints_.begin ();
232  i != constraints_.end (); ++i) {
233 
234  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
235  printf ("\nReformulating constraint: ");
236  (*i) -> print ();
237  }
238 
239  CouNumber
240  conLb = (*((*i) -> Lb ())) (),
241  conUb = (*((*i) -> Ub ())) ();
242 
243  // sanity check: if (due to bad model or redundancies) the
244  // constraint's body is constant, delete it -- check if it's
245  // within bounds.
246 
247  expression *eBody = (*i) -> Body ();
248 
249  if (eBody -> Linearity () <= CONSTANT) {
250 
251  CouNumber bodyVal = (*eBody)();
252 
253  if ((bodyVal < conLb - COUENNE_BOUND_PREC) ||
254  (bodyVal > conUb + COUENNE_BOUND_PREC)) { // all variables eliminated, but out of bounds
255 
256  jnlst_ -> Printf (J_SUMMARY, J_PROBLEM,
257  "Constraint: all variables eliminated, but value %g out of bounds [%g,%g]: ",
258  bodyVal, conLb, conUb);
259 
260  if (jnlst_ -> ProduceOutput (J_SUMMARY, J_PROBLEM))
261  (*i) -> print ();
262 
263  retval = false;
264  break;
265 
266  } else {
267 
268  iters2erase.push_back (i);
269  continue; // all variables eliminated and constraint is redundant
270  }
271  }
272 
273  exprAux *aux = (*i) -> standardize (this);
274 
275  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
276  printf (" reformulated: aux w[%d] ", aux ? (aux -> Index ()) : -2);
277  (*i) -> print ();
278  }
279 
280  if (aux) { // save if standardized
281 
282  // this is a top level auxiliary, i.e., an auxiliary whose node
283  // in the DAG stands at the maximum level -- no other variable
284  // depends on it as it is the lhs of a constraint.
285 
286  aux -> top_level () = true;
287 
288  // this constraint f(x)<=b is therefore replaced by w<=b, where
289  // w is the top-level auxiliary associated with f(x)
290 
291  //printf ("delete %x: ", ((*i) -> Body ())); ((*i) -> Body ()) -> print ();
292  //printf ("\n");
293  //delete ((*i) -> Body ());
294 
295  (*i) -> Body (new exprClone (aux));
296 
297  // con2.push_back (*i);
298  }
299  else {
300 
301  // left-hand side not reformulated, therefore this is probably
302  // an affine expression
303 
304  //CouNumber lb, ub;
305 
306  //printf ("let's see what's left of the body: "); fflush (stdout);
307  //(*i) -> Body () -> print (); printf ("\n");
308 
309  // (*i) -> Body () -> getBounds (lb, ub);
310 
311  // if ((((*((*i) -> Lb ())) ()) > ub + COUENNE_EPS) ||
312  // (((*((*i) -> Ub ())) ()) < lb - COUENNE_EPS)) {
313 
314  // jnlst_ -> Printf (J_SUMMARY, J_PROBLEM, "found infeasible constraint [%g,%g] vs [%g,%g]\n",
315  // lb, ub,
316  // ((*((*i) -> Lb ())) ()),
317  // ((*((*i) -> Ub ())) ()));
318 
319  // if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE))
320  // (*i) -> print ();
321 
322  // retval = false;
323  // }
324 
325  // delete constraint as no aux associated with it. It is a
326  // linear constraint now (after reformulation), so it will be
327  // inserted as a linearization of the aux's definition (an
328  // affine function).
329 
330  iters2erase.push_back (i);
331  }
332 
333  //(*i) -> Body () -> realign (this);
334 
335  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {printf (" --> "); (*i) -> print (); printf ("\n\n");}
336 
337  /*printf ("=== "); fflush (stdout);
338  aux -> print (); printf (" := "); fflush (stdout);
339  aux -> Image () -> print (); printf ("\n");*/
340  }
341 
342  for (unsigned int i = iters2erase.size (); i--;)
343  constraints_. erase (iters2erase [i]);
344 
345  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
346  // Use with caution. Bounds on auxs are not defined yet, so valgrind complains
347  printf ("Done with standardization (careful, bounds below can be nonsense):\n");
348  print ();
349  }
350 
351  // Extra auxiliaries: useless without CouenneSDPcuts
352 
353  if (bonBase_) {
354 
355  int freq;
356 
357  if ((bonBase_ -> options () -> GetIntegerValue ("sdp_cuts", freq, "couenne.")) &&
358  (freq != 0))
359 
360  sdpCutGen_ = new CouenneSdpCuts (this, jnlst_, bonBase_ -> options ());
361  }
362 
363  // TODO: move redundancy elimination here. Then add another round of simplification
364 
365 #define ANTICIPATE_DELETE_REDUND
366 #ifdef ANTICIPATE_DELETE_REDUND
367 
368  bool has_changed;
369 
370  do {
371 
372  has_changed = false;
373 
374  // TODO: resolve duplicate index in exprQuad before restoring this
375 
376  // remove duplicates
377 
378  std::string delete_redund;
379 
380  if (bonBase_) bonBase_ -> options () -> GetStringValue ("delete_redundant", delete_redund, "couenne.");
381  else delete_redund = "yes";
382 
383  if (delete_redund == "yes")
384 
385  // Look for auxiliaries of the form w:=x and replace each occurrence of w with x
386  for (std::vector <exprVar *>::iterator i = variables_.begin ();
387  i != variables_.end (); ++i)
388 
389  if (((*i) -> Multiplicity () > 0) && ((*i) -> Type () == AUX) && ((*i) -> sign () == expression::AUX_EQ)) {
390 
391  int type = (*i) -> Image () -> Type ();
392 
393  if ((type == VAR) || (type == AUX)) {
394 
395  // found w_k = x_h.
396  //
397  // Check if either is integer, the survivor will be integer too
398  // Replace all occurrences of w_k with x_h
399 
400  /*printf ("redundancy: ");
401  (*i) -> print (); printf (" := ");
402  (*i) -> Image () -> print (); printf ("\n");*/
403 
404  // use the info on the variable to be discarded: tighter
405  // bounds and integrality that the replacement might not have.
406 
407  int
408  indStays = (*i) -> Image () -> Index (), // index h
409  indLeaves = (*i) -> Index (); // index k
410 
411  if (indStays == indLeaves) // very strange case, w_h = x_h
412  continue;
413 
414  // do not swap! x_h could be in turn an auxiliary...
415  //
416  //if (indStays > indLeaves)
417  //{int swap = indStays; indStays = indLeaves; indLeaves = swap;} // swap
418 
419  exprVar
420  *varStays = variables_ [indStays],
421  *varLeaves = variables_ [indLeaves];
422 
423  // intersect features of the two variables (integrality, bounds)
424 
425  varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
426  varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
427 
428  if (varStays -> isInteger () ||
429  varLeaves -> isInteger ()) {
430 
431  varStays -> lb () = ceil (varStays -> lb ());
432  varStays -> ub () = floor (varStays -> ub ());
433 
434  if (varStays -> Type () == AUX)
435  varStays -> setInteger (true);
436  else {
437  //expression *old = varStays; // !!! leak
438  variables_ [indStays] = varStays = new exprIVar (indStays, &domain_);
439  auxiliarize (varStays); // replace it everywhere in the problem
440  //delete old;
441  }
442  }
443 
444  auxiliarize (varLeaves, varStays); // now replace occurrences of w_k with x_h
445 
446  //if (varLeaves -> Index () >= nOrigVars_) // why check? It's not there anymore.
447  varLeaves -> zeroMult (); // disable this variable
448  }
449  }
450 
451  // realignment and cleanup of variable might have introduced
452  // variable duplication, e.g. x0*x0. Do one round of
453  // simplification and reformulate what is simplified.
454 
455  for (std::vector <exprVar *>::iterator i = variables_. begin ();
456  i != variables_. end (); ++i)
457 
458  if (((*i) -> Multiplicity () > 0) &&
459  ((*i) -> Type () == AUX)) {
460 
461  expression
462  *image = (*i) -> Image (),
463  *simpl = image -> simplify ();
464 
465  exprVar *subst = NULL;
466 
467  if (simpl &&
468  (subst = simpl -> standardize (this))) {
469  if ((subst -> Type () == VAR) ||
470  (subst -> Type () == AUX))
471  simpl = new exprClone (subst);
472  else simpl = subst;
473  }
474 
475  if (simpl && simpl != subst) {
476 
477  has_changed = true;
478 
479  delete (*i) -> Image ();
480  (*i) -> Image (simpl);
481  }
482  }
483 
484  } while (has_changed); // should repeat this while there have been
485  // simplifications or duplicates have been
486  // cut
487 #endif
488 
489  // delete auxSet_;
490 
491  // Create evaluation order ////////////////////////////////////////////////////
492 
493  // reallocate space for enlarged set of variables
494  domain_.current () -> resize (nVars ());
495 
496  //graph_ -> print ();
497  graph_ -> createOrder ();
498  //graph_ -> print ();
499 
500  assert (graph_ -> checkCycles () == false);
501 
502  // Fill numbering structure /////////////////////////////////////////////////
503 
504  int n = nVars ();
505  numbering_ = new int [n];
506  std::set <DepNode *, compNode> vertices = graph_ -> Vertices ();
507 
508  for (std::set <DepNode *, compNode>::iterator i = vertices.begin ();
509  i != vertices.end (); ++i)
510 
511  numbering_ [(*i) -> Order ()] = (*i) -> Index ();
512 
514 
515  // do initial bound propagation
516 
517  for (int i = 0; i < nVars (); i++) {
518 
519  int ord = numbering_ [i];
520 
521  if (variables_ [ord] -> Multiplicity () <= 0)
522  continue;
523 
524  if (variables_ [ord] -> Type () == AUX) {
525 
526  // initial auxiliary bounds are infinite (they are later changed
527  // through branching)
528 
529  if (variables_ [ord] -> Index () >= nOrigVars_) { // and one that was not an original, originally...
530 
531  domain_.lb (ord) = -COIN_DBL_MAX;
532  domain_.ub (ord) = COIN_DBL_MAX;
533  }
534 
535  //printf ("from "); variables_ [ord] -> Lb () -> print ();
536 
537  // tighten them with propagated bounds
538  variables_ [ord] -> crossBounds ();
539 
540  //printf ("to "); variables_ [ord] -> Lb () -> print (); printf (", now eval\n");
541 
542  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
543  printf (":::: %3d %10g [%10g, %10g]",
544  ord, domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
545  }
546 
547  // and evaluate them
548  domain_.x (ord) = (*(variables_ [ord] -> Image ())) ();
549  domain_.lb (ord) = (*(variables_ [ord] -> Lb ())) ();
550  domain_.ub (ord) = (*(variables_ [ord] -> Ub ())) ();
551 
552  // if (DefVarDiffSet.find (ord) != DefVarDiffSet.end ()) {
553 
554  // domain_.lb (ord) =
555  // domain_.ub (ord) = 0.;
556  // }
557 
558  if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
559  printf (" --> %10g [%10g, %10g] [",
560  domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
561  variables_ [ord] -> Lb () -> print (); printf (",");
562  variables_ [ord] -> Ub () -> print (); printf ("]\n");
563  }
564 
565  bool integer = variables_ [ord] -> isInteger ();
566 
567  if (integer) {
568  domain_.lb (ord) = ceil (domain_.lb (ord) - COUENNE_EPS);
569  domain_.ub (ord) = floor (domain_.ub (ord) + COUENNE_EPS);
570  }
571  }
572  }
573 
574 #ifndef ANTICIPATE_DELETE_REDUND
575 
576  // TODO: resolve duplicate index in exprQuad before restoring this
577 
578  // remove duplicates
579 
580  std::string delete_redund;
581 
582  if (bonBase_) bonBase_ -> options () -> GetStringValue ("delete_redundant", delete_redund, "couenne.");
583  else delete_redund = "yes";
584 
585  if (delete_redund == "yes")
586 
587  // Look for auxiliaries of the form w:=x and replace each occurrence of w with x
588  for (std::vector <exprVar *>::iterator i = variables_.begin ();
589  i != variables_.end (); ++i)
590 
591  if (((*i) -> Type () == AUX) && ((*i) -> sign () == expression::AUX_EQ)) {
592 
593  int type = (*i) -> Image () -> Type ();
594 
595  if ((type == VAR) || (type == AUX)) {
596 
597  // found w_k = x_h.
598  //
599  // Check if either is integer, the survivor will be integer too
600  // Replace all occurrences of w_k with x_h
601 
602  /*printf ("redundancy: ");
603  (*i) -> print (); printf (" := ");
604  (*i) -> Image () -> print (); printf ("\n");*/
605 
606  // use the info on the variable to be discarded: tighter
607  // bounds and integrality that the replacement might not have.
608 
609  int
610  indStays = (*i) -> Image () -> Index (), // index h
611  indLeaves = (*i) -> Index (); // index k
612 
613  if (indStays == indLeaves) // very strange case, w_h = x_h
614  continue;
615 
616  // do not swap! x_h could be in turn an auxiliary...
617  //
618  //if (indStays > indLeaves)
619  //{int swap = indStays; indStays = indLeaves; indLeaves = swap;} // swap
620 
621  exprVar
622  *varStays = variables_ [indStays],
623  *varLeaves = variables_ [indLeaves];
624 
625  // intersect features of the two variables (integrality, bounds)
626 
627  varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
628  varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
629 
630  if (varStays -> isInteger () ||
631  varLeaves -> isInteger ()) {
632 
633  varStays -> lb () = ceil (varStays -> lb ());
634  varStays -> ub () = floor (varStays -> ub ());
635 
636  if (varStays -> Type () == AUX)
637  varStays -> setInteger (true);
638  else {
639  //expression *old = varStays; // !!! leak
640  variables_ [indStays] = varStays = new exprIVar (indStays, &domain_);
641  auxiliarize (varStays); // replace it everywhere in the problem
642  //delete old;
643  }
644  }
645 
646  auxiliarize (varLeaves, varStays); // now replace occurrences of w_k with x_h
647 
648  //if (varLeaves -> Index () >= nOrigVars_) // why check? It's not there anymore.
649  varLeaves -> zeroMult (); // disable this variable
650  }
651  }
652 
653 #endif
654 
660  for (int ii=0; ii < nVars (); ii++) {
661 
662  int i = numbering_ [ii];
663 
664  if ((Var (i) -> Multiplicity () > 0) &&
665  (Var (i) -> Type () == AUX) &&
666  (Var (i) -> Image () -> isInteger ()) &&
667  (Var (i) -> sign () == expression::AUX_EQ))
668  Var (i) -> setInteger (true);
669 
670  //if (Var (i) -> Multiplicity () == 0)
671  //Lb (i) = Ub (i) = 0.;
672  }
673 
674  // check how many multiplications there are
675 
676 // int nmul = 0;
677 // // Look for auxiliaries of the form w:=x and replace each occurrence of w with x
678 // for (std::vector <exprVar *>::iterator i = variables_.begin ();
679 // i != variables_.end (); ++i) {
680 
681 // if ((*i) -> Type () != AUX ||
682 // (*i) -> Multiplicity () <= 0)
683 // continue;
684 
685 // expression *img = (*i) -> Image ();
686 
687 // if (img -> code () != COU_EXPRMUL)
688 // continue;
689 
690 // expression **args = img -> ArgList ();
691 
692 // if ((args [0] -> Type () == AUX ||
693 // args [0] -> Type () == VAR) &&
694 // (args [1] -> Type () == AUX ||
695 // args [1] -> Type () == VAR))
696 // nmul++;
697 // }
698 
699 // printf ("\nMULS: %d/%d\n", nmul, variables_.size());
700 
701 // exit (-1);
702 
703  // TODO: re-compute ranks
704 
705  delete [] commuted_; commuted_ = NULL;
706  delete graph_; graph_ = NULL;
707 
708  return retval;
709 }
#define COUENNE_BOUND_PREC
void replace(CouenneProblem *p, int wind, int xind)
These are cuts of the form.
fint end
Class for MINLP problems with symbolic information.
expression clone (points to another expression)
const Ipopt::EJournalCategory J_REFORMULATE(Ipopt::J_USER7)
#define COUENNE_EPS
double CouNumber
main number type in Couenne
variable-type operator.
Dependence graph.
Auxiliary variable.
variable-type operator
Expression base class.
const Ipopt::EJournalCategory J_PROBLEM(Ipopt::J_USER4)
void fint * n
bool isInteger(CouNumber x)
is this number integer?