00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <queue>
00012
00013 #include "CouenneTypes.hpp"
00014 #include "CouenneExprMul.hpp"
00015 #include "CouenneExprTrilinear.hpp"
00016 #include "CouenneExprBMul.hpp"
00017 #include "CouenneExprConst.hpp"
00018 #include "CouenneExprPow.hpp"
00019 #include "CouenneExprAux.hpp"
00020 #include "CouenneExprClone.hpp"
00021 #include "CouenneProblem.hpp"
00022
00023 using namespace Couenne;
00024
00026
00027 inline bool areSameVariables (expression *v1, expression *v2) {
00028
00029 register int t1 = v1 -> Type (), t2;
00030 return (((t1 == VAR) || (t1 == AUX)) &&
00031 (((t2 = v2 -> Type ()) == VAR) || (t2 == AUX)) &&
00032 (v1 -> Index () == v2 -> Index ()));
00033 }
00034
00035
00037
00038 exprAux *exprMul::standardize (CouenneProblem *p, bool addAux) {
00039
00040
00041
00042 CouNumber coeff = 1.;
00043 std::map <int, CouNumber> indCoe;
00044
00045 p -> flattenMul (this, coeff, indCoe);
00046
00047 int nArgs = 0;
00048
00049 expression **arglist = new expression * [indCoe.size ()];
00050
00051 for (std::map <int, CouNumber>::iterator i = indCoe.begin (); i != indCoe.end (); ++i)
00052 if (i -> second == 1.) arglist [nArgs++] = new exprClone (p -> Var (i -> first));
00053 else arglist [nArgs++] = new exprPow (new exprClone (p -> Var (i -> first)), new exprConst (i -> second));
00054
00055
00056
00057
00058
00059
00060 arglist_ = arglist;
00061 nargs_ = (int) indCoe.size();
00062
00063
00064
00065 exprOp::standardize (p);
00066
00067
00068
00069 if (nargs_ == 1) {
00070
00071 if (coeff != 1.) {
00072
00073
00074
00075 expression *simMul = new exprMul (new exprConst (coeff), new exprClone (arglist_ [0]));
00076 return (addAux ? (p -> addAuxiliary (simMul)) : new exprAux (simMul, p -> domain ()));
00077
00078 } else {
00079
00080
00081
00082
00083
00084 exprAux *var = dynamic_cast <exprAux *> (arglist_ [0] -> Copy ());
00085 return var;
00086 }
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 #if 0
00100
00101 bool isBinProd = true;
00102 for (int i=nargs_; i--;) {
00103
00104 expression *arg = arglist_ [i];
00105 if (arg -> isInteger ()) {
00106
00107 CouNumber lb, ub;
00108 arg -> getBounds (lb, ub);
00109 if ((fabs (ceil (lb - COUENNE_EPS)) > 0.) ||
00110 (fabs (floor (ub + COUENNE_EPS) - 1.) > 0.)) {
00111 isBinProd = false;
00112 break;
00113 }
00114 } else {
00115 isBinProd = false;
00116 break;
00117 }
00118 }
00119
00120 if (isBinProd) {
00121
00122 }
00123 #endif
00124
00125 enum Couenne::TrilinDecompType type = p -> getTrilinDecompType ();
00126
00127 if (nargs_ <= 2)
00128 type = Couenne::rAI;
00129
00130 expression *retExpr;
00131
00132 switch (type) {
00133
00134 case Couenne::treeDecomp: {
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 std::queue <expression *> queue;
00154
00155 for (int i=0; i<nargs_; i++)
00156 queue.push (arglist_ [i]);
00157
00158 expression *aux;
00159
00160 while (queue.size() > 1) {
00161
00162 expression *arg1 = queue.front (); queue.pop ();
00163 expression *arg2 = queue.front (); queue.pop ();
00164
00165
00166
00167
00168 if (areSameVariables (arg1, arg2)) aux = new exprPow (new exprClone (arg1), new exprConst (2.));
00169 else aux = new exprMul (new exprClone (arg1), new exprClone (arg2));
00170
00171
00172
00173 if (!(queue.empty ()))
00174 aux = p -> addAuxiliary (aux);
00175
00176 queue.push (aux);
00177 }
00178
00179 aux = queue.front (); queue.pop ();
00180
00181 retExpr = aux;
00182 } break;
00183
00184
00185
00186 case Couenne::tri_bi:
00187 case Couenne::bi_tri: {
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 expression *aux = arglist_ [0];
00201
00202 for (int i = 1; i < nargs_;) {
00203
00204 if (i < nargs_ - 1 && ((type==tri_bi) || (i!=1))) {
00205
00206
00207 if (areSameVariables (aux, arglist_ [i])) {
00208
00209 if (areSameVariables (aux, arglist_ [i+1]))
00210
00211 if (i == nargs_ - 2) aux = new exprPow (new exprClone (aux), new exprConst (3.));
00212 else aux = p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (3.)));
00213
00214 else {
00215
00216 aux = p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (2.)));
00217
00218 if (i == nargs_ - 2) aux = new exprMul (new exprClone (aux), new exprClone (arglist_ [i+1]));
00219 else aux = p -> addAuxiliary (new exprMul (new exprClone (aux), new exprClone (arglist_ [i+1])));
00220 }
00221
00222 } else
00223 if (areSameVariables (aux, arglist_ [i+1])) {
00224
00225 printf ("Couenne, exprTrilinear: bad ordering of factors in product, aborting\n");
00226 exit (-1);
00227
00228 } else {
00229
00230 aux = new exprTrilinear (new exprClone (aux),
00231 new exprClone (arglist_ [i]),
00232 new exprClone (arglist_ [i+1]));
00233
00234 if (i != nargs_ - 2)
00235 aux = p -> addAuxiliary (aux);
00236 }
00237
00238
00239
00240 i += 2;
00241
00242 } else {
00243
00244 if (areSameVariables (aux, arglist_ [i])) aux = new exprPow (new exprClone (aux), new exprConst (2.));
00245 else aux = new exprMul (new exprClone (aux), new exprClone (arglist_ [i]));
00246
00247 if (i==1)
00248 aux = p -> addAuxiliary (aux);
00249
00250
00251
00252 i++;
00253 }
00254 }
00255
00256
00257
00258 retExpr = aux;
00259 } break;
00260
00261
00262
00263 case Couenne::rAI:
00264 default:
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 expression *aux = arglist_ [0];
00276
00277 for (int i = 1; i < nargs_ - 1; i++)
00278 aux = (areSameVariables (aux, arglist_ [i])) ?
00279 (p -> addAuxiliary (new exprPow (new exprClone (aux), new exprConst (2.)))) :
00280 (p -> addAuxiliary (new exprMul (new exprClone (aux), new exprClone (arglist_ [i]))));
00281
00282 if (areSameVariables (aux, arglist_ [nargs_ - 1]))
00283 aux = new exprPow (new exprClone (aux), new exprConst (2.));
00284 else aux = new exprMul (new exprClone (aux), new exprClone (arglist_ [nargs_ - 1]));
00285
00286 retExpr = aux;
00287 }
00288
00289 if (coeff != 1.) {
00290
00291 retExpr = p -> addAuxiliary (retExpr);
00292 retExpr = new exprMul (new exprConst (coeff), new exprClone (retExpr));
00293 }
00294
00295 return (addAux ? (p -> addAuxiliary (retExpr)) : new exprAux (retExpr, p -> domain ()));
00296 }