1 /* $Id$
2  *
3  * Name:    sumStandardize.cpp
4  * Author:  Pietro Belotti
5  * Purpose: check if expr{Group,Sum,Sub} contains a lot of quadratic/bilinear terms
6  *
7  * (C) Carnegie-Mellon University, 2007-10.
8  * This file is licensed under the Eclipse Public License (EPL)
9  */
10 
11 #include <stdio.h>
12 
13 #include "CouenneExprQuad.hpp"
14 
15 #include "CouenneExprSum.hpp"
16 #include "CouenneExprSub.hpp"
17 #include "CouenneExprOpp.hpp"
18 #include "CouenneExprGroup.hpp"
19 #include "CouenneLQelems.hpp"
20 
21 using namespace Couenne;
22 
23 /// translate a sum/difference/exprOpp into:
24 ///
25 /// 1) an exprGroup, if only linear terms are present
26 /// 2) an exprQuad,  if some quadratic/bilinear terms exist
27 
standardize(CouenneProblem * p,bool addAux)28 exprAux *exprSum::standardize (CouenneProblem *p, bool addAux) {
29 
30   // turn all elements of arglist_ and of the linear part into an exprQuad.
31   // count all potential quadratic terms for exprQuad
32 
33   LinMap lmap;
34   QuadMap qmap;
35 
36   int cod = code ();
37 
38   CouNumber c0 = 0; // final constant term
39 
40   ////////////////////////////////////////////////////////////////////////////////
41 
42   // initialize linear/quad maps with the original values/indices of
43   // the linear part
44 
45   if ((cod == COU_EXPRGROUP) ||
46       (cod == COU_EXPRQUAD)) {  // fill linear structure
47 
48     exprGroup *eg = dynamic_cast <exprGroup *> (this);
49     exprGroup::lincoeff &lcoe = eg -> lcoeff ();
50 
51     c0 += eg -> getc0 ();
52 
53     for (exprGroup::lincoeff::iterator el = lcoe.begin (); el != lcoe.end (); ++el)
54       lmap.insert (el -> first -> Index (), el -> second);
55 
56     if (cod == COU_EXPRQUAD) { // fill quadratic structure
57 
58       exprQuad *eq = dynamic_cast <exprQuad *> (this);
59       exprQuad::sparseQ &M = eq -> getQ ();
60 
61       // derive quadratic part (obtain linear part)
62       for (exprQuad::sparseQ::iterator row = M.begin (); row != M.end (); ++row) {
63 
64 	int xind = row -> first -> Index ();
65 
66 	for (exprQuad::sparseQcol::iterator col = row -> second.begin ();
67 	     col != row -> second.end (); ++col)
68 	  qmap.insert (xind, col -> first -> Index (), col -> second);
69       }
70     }
71   }
72 
73   ////////////////////////////////////////////////////////////////////////////////
74   //
75   // standardize all nonlinear arguments and put them into linear or
76   // quadratic form
77 
78   for (int i=0; i<nargs_; i++)
79     p -> decomposeTerm (arglist_ [i], 1, c0, lmap, qmap);
80 
81   ////////////////////////////////////////////////////////////////////////////////
82 
83   if (p -> Jnlst () -> ProduceOutput (Ipopt::J_ALL, J_REFORMULATE)) {
84     printf ("decompTerm: lin [");
85     for (std::map <int, CouNumber>::iterator i = lmap.Map().begin (); i != lmap.Map().end (); ++i)
86       printf ("<%d,%g>", i -> first, i -> second);
87     printf ("] -- quad [");
88     for (std::map <std::pair <int, int>, CouNumber>::iterator i = qmap.Map ().begin (); i != qmap.Map ().end (); ++i)
89       printf ("<%d,%d,%g>", i -> first.first, i -> first.second, i -> second);
90     printf ("] (%g)\n", c0);
91   }
92 
93   return p -> linStandardize (addAux, c0, lmap, qmap);
94 }
95 
96 
97 /// translate an exprOpp into:
98 ///
99 /// 1) an exprGroup, if only linear terms are present
100 /// 2) an exprQuad,  if some quadratic/bilinear terms exist
101 
standardize(CouenneProblem * p,bool addAux)102 exprAux *exprOpp::standardize (CouenneProblem *p, bool addAux) {
103 
104   // turn all elements of arglist_ and of the linear part into an exprQuad.
105   // count all potential quadratic terms for exprQuad
106 
107   LinMap lmap;
108   QuadMap qmap;
109 
110   CouNumber c0 = 0;   // final constant term
111 
112   p -> decomposeTerm (argument_, -1., c0, lmap, qmap);
113 
114   return p -> linStandardize (addAux, c0, lmap, qmap);
115 }
116 
117 
118 /// translate a difference (exprSub) into:
119 ///
120 /// 1) an exprGroup, if only linear terms are present
121 /// 2) an exprQuad,  if some quadratic/bilinear terms exist
122 
standardize(CouenneProblem * p,bool addAux)123 exprAux *exprSub::standardize (CouenneProblem *p, bool addAux) {
124 
125   // turn all elements of arglist_ and of the linear part into an exprQuad.
126   // count all potential quadratic terms for exprQuad
127 
128   LinMap lmap;
129   QuadMap qmap;
130 
131   CouNumber c0 = 0;   // final constant term
132 
133   ////////////////////////////////////////////////////////////////////////////////
134 
135   // standardize all nonlinear arguments and put them into linear or
136   // quadratic form
137 
138   p -> decomposeTerm (arglist_ [0],  1., c0, lmap, qmap);
139   p -> decomposeTerm (arglist_ [1], -1., c0, lmap, qmap);
140 
141   return p -> linStandardize (addAux, c0, lmap, qmap);
142 }
143