00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CoinHelperFunctions.hpp"
00012 #include "CouenneProblem.hpp"
00013 #include "exprConst.hpp"
00014 #include "exprQuad.hpp"
00015 #include "exprPow.hpp"
00016 #include "exprMul.hpp"
00017 #include "depGraph.hpp"
00018 #include "lqelems.hpp"
00019
00020 class Domain;
00021
00022
00023
00024 struct cmpVar {
00025 bool operator() (const exprVar* v1, const exprVar* v2) const
00026 {return (v1 -> Index () < v2 -> Index ());}
00027 };
00028
00030 exprQuad::exprQuad (CouNumber c0,
00031 std::vector <std::pair <exprVar *, CouNumber> > &lcoeff,
00032 std::vector <quadElem> &qcoeff,
00033 expression **al,
00034 int n):
00035
00036 exprGroup (c0, lcoeff, al, n) {
00037
00038 nqterms_ = 0;
00039
00040 typedef std::map <exprVar *, CouNumber, cmpVar> rowMap;
00041 typedef std::map <exprVar *, rowMap, cmpVar> matrixMap;
00042
00043 matrixMap qMap;
00044
00045 for (std::vector <quadElem>::iterator qel = qcoeff.begin (); qel != qcoeff.end (); ++qel) {
00046
00047 CouNumber coe = qel -> coeff ();
00048
00049 exprVar
00050 *varI = qel -> varI (),
00051 *varJ = qel -> varJ ();
00052
00053 if (varI -> Index () != varJ -> Index ()) {
00054
00055 coe /= 2.;
00056
00057
00058 if (varI -> Index () > varJ -> Index ()) {
00059
00060 exprVar *swap = varJ;
00061 varJ = varI;
00062 varI = swap;
00063 }
00064 }
00065
00066 matrixMap::iterator rowp = qMap.find (varI);
00067
00068 if (rowp == qMap.end ()) {
00069
00070 std::pair <exprVar *, CouNumber> newcell (varJ, coe);
00071 rowMap rmap;
00072 rmap.insert (newcell);
00073
00074 std::pair <exprVar *, rowMap> newrow (varI, rmap);
00075 qMap.insert (newrow);
00076
00077 } else {
00078
00079 rowMap::iterator cell = rowp -> second.find (varJ);
00080
00081 if (cell == rowp -> second.end ()) {
00082
00083 std::pair <exprVar *, CouNumber> newcell (varJ, coe);
00084 rowp -> second.insert (newcell);
00085
00086 } else {
00087
00088 if (fabs (cell -> second += coe) < COUENNE_EPS)
00089
00090 rowp -> second.erase (cell);
00091 }
00092 }
00093 }
00094
00095
00096
00097 for (matrixMap::iterator row = qMap.begin (); row != qMap.end (); ++row) {
00098
00099 sparseQcol line;
00100
00101
00102 if (bounds_.find (row -> first) == bounds_.end ()) {
00103
00104 std::pair <CouNumber, CouNumber> newbound (-DBL_MAX, DBL_MAX);
00105 std::pair <exprVar *, std::pair <CouNumber, CouNumber> > newvar (row -> first, newbound);
00106 bounds_.insert (newvar);
00107 }
00108
00109 for (rowMap::iterator cell = row -> second.begin (); cell != row -> second.end (); ++cell) {
00110
00111 line.push_back (std::pair <exprVar *, CouNumber> (*cell));
00112
00113
00114 if (bounds_.find (cell -> first) == bounds_.end ()) {
00115
00116 std::pair <CouNumber, CouNumber> newbound (-DBL_MAX, DBL_MAX);
00117 std::pair <exprVar *, std::pair <CouNumber, CouNumber> > newvar (cell -> first, newbound);
00118 bounds_.insert (newvar);
00119 }
00120 }
00121
00122 matrix_.push_back (std::pair <exprVar *, sparseQcol> (row -> first, line));
00123 nqterms_ += line.size ();
00124 }
00125 }
00126
00127
00129 exprQuad::exprQuad (const exprQuad &src, Domain *d):
00130 exprGroup (src, d),
00131 bounds_ (src.bounds_),
00132 nqterms_ (src.nqterms_) {
00133
00134 for (sparseQ::iterator row = src.matrix_.begin (); row != src.matrix_ . end (); ++row) {
00135
00136 sparseQcol column;
00137
00138 for (sparseQcol::iterator i = row -> second. begin (); i != row -> second. end (); ++i)
00139 column.push_back (std::pair <exprVar *, CouNumber>
00140
00141 (new exprVar (i -> first -> Index (), d), i -> second));
00142
00143 matrix_.push_back (std::pair <exprVar *, sparseQcol>
00144
00145 (new exprVar (row -> first -> Index (), d), column));
00146 }
00147
00149
00150 std::vector
00151 <std::pair <CouNumber, std::vector
00152 <std::pair <exprVar *, CouNumber> > > >::iterator row;
00153
00154 for (row = src.eigen_ . begin ();
00155 row != src.eigen_ . end (); ++row) {
00156
00157 std::vector <std::pair <exprVar *, CouNumber> > eigVec;
00158
00159 for (std::vector <std::pair <exprVar *, CouNumber> >::iterator
00160 i = row -> second. begin ();
00161 i != row -> second. end (); ++i)
00162 eigVec.push_back (std::pair <exprVar *, CouNumber>
00163 (dynamic_cast <exprVar *> (i -> first -> clone (d)), i -> second));
00164
00165 eigen_.push_back (std::pair <CouNumber, std::vector
00166 <std::pair <exprVar *, CouNumber> > > (row -> first, eigVec));
00167 }
00168 }
00169
00170
00172 void exprQuad::print (std::ostream &out, bool descend) const {
00173
00174
00175 if (matrix_.size () > 0)
00176 out << '(';
00177
00178
00179 exprGroup::print (out, descend);
00180
00181 int noperands = 0;
00182
00183 for (int n = matrix_.size (), i=0; n--; i++) {
00184
00185
00186 int xind = matrix_ [i].first -> Index ();
00187 const sparseQcol row = matrix_ [i].second;
00188
00189 for (int m = row.size (), j=0; m--; j++) {
00190
00191
00192 if (fabs (row [j]. second - 1.) > COUENNE_EPS) {
00193 if (fabs (row [j]. second + 1.) < COUENNE_EPS) out << "- ";
00194 else {
00195 if (row [j]. second > 0.) out << '+';
00196 out << row [j]. second << "*";
00197 }
00198 } else out << '+';
00199
00200 if (row [j].first -> Index () == xind) {
00201 matrix_ [i]. first -> print (out, descend);
00202 out << "^2";
00203 } else {
00204 matrix_ [i]. first -> print (out, descend);
00205 out << '*';
00206 row [j]. first -> print (out, descend);
00207 }
00208
00209 if (!((noperands + 1) % MAX_ARG_LINE))
00210 out << std::endl;
00211 }
00212 }
00213
00214
00215 if (matrix_.size () > 0)
00216 out << ')';
00217 }
00218
00219
00221 expression *exprQuad::differentiate (int index) {
00222
00223 std::map <exprVar *, CouNumber> lmap;
00224
00225 CouNumber c0 = 0;
00226
00227
00228 for (lincoeff::iterator el = lcoeff_.begin (); el != lcoeff_.end (); ++el)
00229 c0 += el -> second;
00230
00231
00232 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00233
00234 int xind = row -> first -> Index ();
00235
00236 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00237
00238 int yind = col -> first -> Index ();
00239
00240 CouNumber coe = col -> second;
00241 exprVar *var = col -> first;
00242
00243 if (xind == index)
00244 if (yind == index) {var = col -> first; coe *= 2;}
00245 else var = col -> first;
00246 else if (yind == index) var = row -> first;
00247 else continue;
00248
00249 std::map <exprVar *, CouNumber>::iterator i = lmap.find (var);
00250
00251 if (i != lmap.end()) {
00252 if (fabs (i -> second += coe) < COUENNE_EPS)
00253 lmap.erase (i);
00254 } else {
00255 std::pair <exprVar *, CouNumber> npair (var, coe);
00256 lmap.insert (npair);
00257 }
00258 }
00259 }
00260
00261
00262 expression **arglist = new expression * [nargs_ + 1];
00263 int nargs = 0;
00264
00265 for (int i = 0; i < nargs_; i++)
00266 if (arglist_ [i] -> dependsOn (index))
00267 arglist [nargs++] = arglist_ [i] -> differentiate (index);
00268
00269
00270
00271
00272 if (lmap.empty ()) {
00273
00274
00275 if (!nargs) {
00276 delete arglist;
00277 return new exprConst (c0);
00278 }
00279
00280 if (fabs (c0) > COUENNE_EPS)
00281 arglist [nargs++] = new exprConst (c0);
00282
00283 return new exprSum (arglist, nargs);
00284 }
00285
00286 lincoeff coe;
00287
00288 for (std::map <exprVar *, CouNumber>::iterator i = lmap.begin (); i != lmap.end (); ++i)
00289 coe.push_back (std::pair <exprVar *, CouNumber> (i -> first, i -> second));
00290
00291 return new exprGroup (c0, coe, arglist, nargs);
00292 }
00293
00294
00296
00297 int exprQuad::compare (exprQuad &e) {
00298
00299 int sum = exprGroup::compare (e);
00300
00301 if (sum != 0)
00302 return sum;
00303
00304 if (matrix_.size() < e.matrix_.size()) return -1;
00305 if (matrix_.size() > e.matrix_.size()) return 1;
00306
00307 for (sparseQ::iterator
00308 row1 = matrix_.begin (),
00309 row2 = e.matrix_.begin ();
00310 row1 != matrix_.end ();
00311 ++row1, ++row2) {
00312
00313 if (row1 -> first -> Index () < row2 -> first -> Index ()) return -1;
00314 if (row1 -> first -> Index () > row2 -> first -> Index ()) return 1;
00315
00316 if (row1 -> second.size () < row2 -> second.size ()) return -1;
00317 if (row1 -> second.size () > row2 -> second.size ()) return 1;
00318
00319
00320
00321
00322
00323 for (sparseQcol::iterator
00324 col1 = row1 -> second.begin (),
00325 col2 = row2 -> second.begin ();
00326 col1 != row1 -> second.end ();
00327 ++col1, ++col2) {
00328
00329 if (col1 -> first -> Index () < col2 -> first -> Index ()) return -1;
00330 if (col1 -> first -> Index () > col2 -> first -> Index ()) return 1;
00331
00332 if (col1 -> second < col2 -> second - COUENNE_EPS) return -1;
00333 if (col1 -> second > col2 -> second + COUENNE_EPS) return 1;
00334 }
00335 }
00336
00337 return 0;
00338 }
00339
00340
00342
00343 int exprQuad::rank () {
00344
00345 int maxrank = exprGroup::rank ();
00346
00347 if (maxrank < 0)
00348 maxrank = 0;
00349
00350 int r;
00351
00352 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00353
00354 if ((r = row -> first -> rank ()) > maxrank) maxrank = r;
00355
00356 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00357 if ((r = col -> first -> rank ()) > maxrank) maxrank = r;
00358 }
00359
00360 return maxrank;
00361 }
00362
00363
00365 void exprQuad::fillDepSet (std::set <DepNode *, compNode> *dep, DepGraph *g) {
00366
00367 exprGroup::fillDepSet (dep, g);
00368
00369 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00370
00371 dep -> insert (g -> lookup (row -> first -> Index ()));
00372
00373 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00374 dep -> insert (g -> lookup (col -> first -> Index ()));
00375 }
00376 }
00377
00378
00381 int exprQuad::DepList (std::set <int> &deplist,
00382 enum dig_type type) {
00383
00384 int deps = exprGroup::DepList (deplist, type);
00385
00386 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00387 deps += row -> first -> DepList (deplist, type);
00388 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00389 deps += col -> first -> DepList (deplist, type);
00390 }
00391
00392 return deps;
00393 }
00394
00395
00397 bool exprQuad::isInteger () {
00398
00399 if (!(exprGroup::isInteger ()))
00400 return false;
00401
00402 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00403
00404 bool intI = row -> first -> isInteger ();
00405
00406 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00407
00408 CouNumber coe = col -> second;
00409
00410 bool
00411 intCoe = ::isInteger (coe),
00412 intJ = row -> first -> isInteger ();
00413
00414 if (intI && intJ && intCoe)
00415 continue;
00416
00417 if (!intCoe
00418 && row -> first -> isFixed ()
00419 && col -> first -> isFixed ()
00420 && ::isInteger (coe *
00421 row -> first -> lb () *
00422 col -> first -> lb ()))
00423 continue;
00424
00425 if (!intI && (row -> first -> isFixed ()) && ::isInteger ((*(row -> first)) ())) continue;
00426 if (!intJ && (col -> first -> isFixed ()) && ::isInteger ((*(col -> first)) ())) continue;
00427
00428
00429
00430
00431
00432 return false;
00433 }
00434 }
00435
00436 return true;
00437 }
00438
00439
00441 void exprQuad::replace (exprVar *x, exprVar *w) {
00442
00443 exprGroup::replace (x, w);
00444 int xind = x -> Index ();
00445 int wind = w -> Index ();
00446
00447 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00448
00449 exprVar * &vr = row -> first;
00450 if ((vr -> Index () == xind)) {
00451
00452
00453
00454 vr = w;
00455 }
00456
00457 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00458
00459 exprVar * &vc = col -> first;
00460 if ((vc -> Index () == wind)) {
00461
00462
00463
00464 vc = w;
00465 }
00466 }
00467 }
00468 }
00469
00470
00472 void exprQuad::realign (const CouenneProblem *p) {
00473
00474 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00475
00476 exprVar * &vr = row -> first;
00477 int indVar;
00478
00479
00480
00481 if (((vr -> Type () == VAR) ||
00482 (vr -> Type () == AUX)) &&
00483 (vr -> Original () != p -> Var (indVar = vr -> Index ()))) {
00484
00485 expression *trash = vr;
00486 row -> first = p -> Var (indVar);
00487 delete trash;
00488 }
00489
00490
00491
00492 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col) {
00493
00494 exprVar * &vc = col -> first;
00495 int indVar;
00496
00497
00498
00499 if (((vc -> Type () == VAR) ||
00500 (vc -> Type () == AUX)) &&
00501 (vc -> Original () != p -> Var (indVar = vc -> Index ()))) {
00502
00503 expression *trash = vc;
00504 col -> first = p -> Var (indVar);
00505 delete trash;
00506 }
00507 }
00508 }
00509 }
00510
00511
00513 void exprQuad::closestFeasible (expression *varind,
00514 expression *vardep,
00515 CouNumber &left,
00516 CouNumber &right) const {
00517
00518 fprintf (stderr, "exprQuad::closestFeasible() not available for VT\n");
00519 exit (-1);
00520 }
00521
00522
00524 CouNumber exprQuad::gradientNorm (const double *x) {
00525
00526 CouNumber grad = 0.;
00527
00528 for (sparseQ::iterator row = matrix_.begin (); row != matrix_.end (); ++row) {
00529
00530 CouNumber gradEl = 0.;
00531 for (sparseQcol::iterator col = row -> second.begin (); col != row -> second.end (); ++col)
00532 gradEl += col -> second * x [col -> first -> Index ()];
00533
00534 grad += gradEl * gradEl;
00535 }
00536
00537 return sqrt (grad);
00538 }
00539
00541 expression *exprQuad::simplify () {
00542 exprOp::simplify ();
00543 return NULL;
00544 }
00545