00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include <vector>
00012
00013 #include "CoinHelperFunctions.hpp"
00014
00015 #include "BonBabSetupBase.hpp"
00016
00017 #include "CouenneTypes.hpp"
00018 #include "CouenneExpression.hpp"
00019 #include "CouenneExprIVar.hpp"
00020 #include "CouenneExprSub.hpp"
00021 #include "CouenneExprClone.hpp"
00022 #include "CouenneProblem.hpp"
00023 #include "CouenneProblemElem.hpp"
00024 #include "CouenneDepGraph.hpp"
00025 #include "CouenneSdpCuts.hpp"
00026
00027 using namespace Ipopt;
00028 using namespace Couenne;
00029
00030 void replace (CouenneProblem *p, int wind, int xind);
00031
00033
00034 bool CouenneProblem::standardize () {
00035
00036 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00037 printf ("Reformulation. current point: %d vars -------------------\n",
00038 domain_.current () -> Dimension ());
00039 for (int i=0; i<domain_.current () -> Dimension (); i++)
00040 printf ("%3d %20g [%20g %20g]\n", i, domain_.x (i), domain_.lb (i), domain_.ub (i));
00041 }
00042
00043 bool retval = true;
00044
00045
00046
00047 graph_ = new DepGraph;
00048
00049 for (std::vector <exprVar *>::iterator i = variables_ . begin ();
00050 i != variables_ . end (); ++i)
00051 graph_ -> insert (*i);
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 for (std::vector <CouenneObjective *>::iterator i = objectives_.begin ();
00176 i != objectives_.end (); ++i) {
00177
00178 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00179 printf ("Objective [code: %d]", (*i) -> Body () -> code ());
00180 (*i) -> print ();
00181 }
00182
00183
00184
00185 std::set <int> deplist;
00186
00187 if (0 == (*i) -> Body () -> DepList (deplist, TAG_AND_RECURSIVE)) {
00188
00189
00190
00191
00192 constObjVal_ = (*i) -> Body () -> Value ();
00193
00194 } else {
00195
00196 exprAux *aux = (*i) -> standardize (this);
00197
00198 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00199 printf (" objective "); (*i) -> print ();
00200 if (aux) {printf (" admits aux "); aux -> print ();}
00201 }
00202
00203 if (aux) {
00204
00205 (*i) -> Body (new exprClone (aux));
00206 }
00207
00208 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00209 printf (". New obj: "); (*i) -> print (); printf ("\n");
00210 }
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 commuted_ = new bool [nVars ()];
00227 CoinFillN (commuted_, nVars (), false);
00228
00229 std::vector <std::vector <CouenneConstraint *>::iterator> iters2erase;
00230
00231 for (std::vector <CouenneConstraint *>::iterator i = constraints_.begin ();
00232 i != constraints_.end (); ++i) {
00233
00234 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00235 printf ("\nReformulating constraint: ");
00236 (*i) -> print ();
00237 }
00238
00239 CouNumber
00240 conLb = (*((*i) -> Lb ())) (),
00241 conUb = (*((*i) -> Ub ())) ();
00242
00243
00244
00245
00246
00247 expression *eBody = (*i) -> Body ();
00248
00249 if (eBody -> Linearity () <= CONSTANT) {
00250
00251 CouNumber bodyVal = (*eBody)();
00252
00253 if ((bodyVal < conLb - COUENNE_BOUND_PREC) ||
00254 (bodyVal > conUb + COUENNE_BOUND_PREC)) {
00255
00256 jnlst_ -> Printf (J_SUMMARY, J_PROBLEM,
00257 "Constraint: all variables eliminated, but value %g out of bounds [%g,%g]: ",
00258 bodyVal, conLb, conUb);
00259
00260 if (jnlst_ -> ProduceOutput (J_SUMMARY, J_PROBLEM))
00261 (*i) -> print ();
00262
00263 retval = false;
00264 break;
00265
00266 } else {
00267
00268 iters2erase.push_back (i);
00269 continue;
00270 }
00271 }
00272
00273 exprAux *aux = (*i) -> standardize (this);
00274
00275 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00276 printf (" reformulated: aux w[%d] ", aux ? (aux -> Index ()) : -2);
00277 (*i) -> print ();
00278 }
00279
00280 if (aux) {
00281
00282
00283
00284
00285
00286 aux -> top_level () = true;
00287
00288
00289
00290
00291
00292
00293
00294
00295 (*i) -> Body (new exprClone (aux));
00296
00297
00298 }
00299 else {
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 iters2erase.push_back (i);
00331 }
00332
00333
00334
00335 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {printf (" --> "); (*i) -> print (); printf ("\n\n");}
00336
00337
00338
00339
00340 }
00341
00342 for (unsigned int i = iters2erase.size (); i--;)
00343 constraints_. erase (iters2erase [i]);
00344
00345 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00346
00347 printf ("Done with standardization (careful, bounds below can be nonsense):\n");
00348 print ();
00349 }
00350
00351
00352
00353 if (bonBase_) {
00354
00355 int freq;
00356
00357 if ((bonBase_ -> options () -> GetIntegerValue ("sdp_cuts", freq, "couenne.")) &&
00358 (freq != 0))
00359
00360 sdpCutGen_ = new CouenneSdpCuts (this, jnlst_, bonBase_ -> options ());
00361 }
00362
00363
00364
00365 #define ANTICIPATE_DELETE_REDUND
00366 #ifdef ANTICIPATE_DELETE_REDUND
00367
00368 bool has_changed;
00369
00370 do {
00371
00372 has_changed = false;
00373
00374
00375
00376
00377
00378 std::string delete_redund;
00379
00380 if (bonBase_) bonBase_ -> options () -> GetStringValue ("delete_redundant", delete_redund, "couenne.");
00381 else delete_redund = "yes";
00382
00383 if (delete_redund == "yes")
00384
00385
00386 for (std::vector <exprVar *>::iterator i = variables_.begin ();
00387 i != variables_.end (); ++i)
00388
00389 if (((*i) -> Multiplicity () > 0) && ((*i) -> Type () == AUX) && ((*i) -> sign () == expression::AUX_EQ)) {
00390
00391 int type = (*i) -> Image () -> Type ();
00392
00393 if ((type == VAR) || (type == AUX)) {
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 int
00408 indStays = (*i) -> Image () -> Index (),
00409 indLeaves = (*i) -> Index ();
00410
00411 if (indStays == indLeaves)
00412 continue;
00413
00414
00415
00416
00417
00418
00419 exprVar
00420 *varStays = variables_ [indStays],
00421 *varLeaves = variables_ [indLeaves];
00422
00423
00424
00425 varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
00426 varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
00427
00428 if (varStays -> isInteger () ||
00429 varLeaves -> isInteger ()) {
00430
00431 varStays -> lb () = ceil (varStays -> lb ());
00432 varStays -> ub () = floor (varStays -> ub ());
00433
00434 if (varStays -> Type () == AUX)
00435 varStays -> setInteger (true);
00436 else {
00437
00438 variables_ [indStays] = varStays = new exprIVar (indStays, &domain_);
00439 auxiliarize (varStays);
00440
00441 }
00442 }
00443
00444 auxiliarize (varLeaves, varStays);
00445
00446
00447 varLeaves -> zeroMult ();
00448 }
00449 }
00450
00451
00452
00453
00454
00455 for (std::vector <exprVar *>::iterator i = variables_. begin ();
00456 i != variables_. end (); ++i)
00457
00458 if (((*i) -> Multiplicity () > 0) &&
00459 ((*i) -> Type () == AUX)) {
00460
00461 expression
00462 *image = (*i) -> Image (),
00463 *simpl = image -> simplify ();
00464
00465 exprVar *subst = NULL;
00466
00467 if (simpl &&
00468 (subst = simpl -> standardize (this))) {
00469 if ((subst -> Type () == VAR) ||
00470 (subst -> Type () == AUX))
00471 simpl = new exprClone (subst);
00472 else simpl = subst;
00473 }
00474
00475 if (simpl && simpl != subst) {
00476
00477 has_changed = true;
00478
00479 delete (*i) -> Image ();
00480 (*i) -> Image (simpl);
00481 }
00482 }
00483
00484 } while (has_changed);
00485
00486
00487 #endif
00488
00489
00490
00491
00492
00493
00494 domain_.current () -> resize (nVars ());
00495
00496
00497 graph_ -> createOrder ();
00498
00499
00500 assert (graph_ -> checkCycles () == false);
00501
00502
00503
00504 int n = nVars ();
00505 numbering_ = new int [n];
00506 std::set <DepNode *, compNode> vertices = graph_ -> Vertices ();
00507
00508 for (std::set <DepNode *, compNode>::iterator i = vertices.begin ();
00509 i != vertices.end (); ++i)
00510
00511 numbering_ [(*i) -> Order ()] = (*i) -> Index ();
00512
00514
00515
00516
00517 for (int i = 0; i < nVars (); i++) {
00518
00519 int ord = numbering_ [i];
00520
00521 if (variables_ [ord] -> Multiplicity () <= 0)
00522 continue;
00523
00524 if (variables_ [ord] -> Type () == AUX) {
00525
00526
00527
00528
00529 if (variables_ [ord] -> Index () >= nOrigVars_) {
00530
00531 domain_.lb (ord) = -COIN_DBL_MAX;
00532 domain_.ub (ord) = COIN_DBL_MAX;
00533 }
00534
00535
00536
00537
00538 variables_ [ord] -> crossBounds ();
00539
00540
00541
00542 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00543 printf (":::: %3d %10g [%10g, %10g]",
00544 ord, domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
00545 }
00546
00547
00548 domain_.x (ord) = (*(variables_ [ord] -> Image ())) ();
00549 domain_.lb (ord) = (*(variables_ [ord] -> Lb ())) ();
00550 domain_.ub (ord) = (*(variables_ [ord] -> Ub ())) ();
00551
00552
00553
00554
00555
00556
00557
00558 if (jnlst_ -> ProduceOutput (J_ALL, J_REFORMULATE)) {
00559 printf (" --> %10g [%10g, %10g] [",
00560 domain_.x (ord), domain_.lb (ord), domain_.ub (ord));
00561 variables_ [ord] -> Lb () -> print (); printf (",");
00562 variables_ [ord] -> Ub () -> print (); printf ("]\n");
00563 }
00564
00565 bool integer = variables_ [ord] -> isInteger ();
00566
00567 if (integer) {
00568 domain_.lb (ord) = ceil (domain_.lb (ord) - COUENNE_EPS);
00569 domain_.ub (ord) = floor (domain_.ub (ord) + COUENNE_EPS);
00570 }
00571 }
00572 }
00573
00574 #ifndef ANTICIPATE_DELETE_REDUND
00575
00576
00577
00578
00579
00580 std::string delete_redund;
00581
00582 if (bonBase_) bonBase_ -> options () -> GetStringValue ("delete_redundant", delete_redund, "couenne.");
00583 else delete_redund = "yes";
00584
00585 if (delete_redund == "yes")
00586
00587
00588 for (std::vector <exprVar *>::iterator i = variables_.begin ();
00589 i != variables_.end (); ++i)
00590
00591 if (((*i) -> Type () == AUX) && ((*i) -> sign () == expression::AUX_EQ)) {
00592
00593 int type = (*i) -> Image () -> Type ();
00594
00595 if ((type == VAR) || (type == AUX)) {
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 int
00610 indStays = (*i) -> Image () -> Index (),
00611 indLeaves = (*i) -> Index ();
00612
00613 if (indStays == indLeaves)
00614 continue;
00615
00616
00617
00618
00619
00620
00621 exprVar
00622 *varStays = variables_ [indStays],
00623 *varLeaves = variables_ [indLeaves];
00624
00625
00626
00627 varStays -> lb () = varLeaves -> lb () = CoinMax (varStays -> lb (), varLeaves -> lb ());
00628 varStays -> ub () = varLeaves -> ub () = CoinMin (varStays -> ub (), varLeaves -> ub ());
00629
00630 if (varStays -> isInteger () ||
00631 varLeaves -> isInteger ()) {
00632
00633 varStays -> lb () = ceil (varStays -> lb ());
00634 varStays -> ub () = floor (varStays -> ub ());
00635
00636 if (varStays -> Type () == AUX)
00637 varStays -> setInteger (true);
00638 else {
00639
00640 variables_ [indStays] = varStays = new exprIVar (indStays, &domain_);
00641 auxiliarize (varStays);
00642
00643 }
00644 }
00645
00646 auxiliarize (varLeaves, varStays);
00647
00648
00649 varLeaves -> zeroMult ();
00650 }
00651 }
00652
00653 #endif
00654
00660 for (int ii=0; ii < nVars (); ii++) {
00661
00662 int i = numbering_ [ii];
00663
00664 if ((Var (i) -> Multiplicity () > 0) &&
00665 (Var (i) -> Type () == AUX) &&
00666 (Var (i) -> Image () -> isInteger ()) &&
00667 (Var (i) -> sign () == expression::AUX_EQ))
00668 Var (i) -> setInteger (true);
00669
00670
00671
00672 }
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 delete [] commuted_; commuted_ = NULL;
00706 delete graph_; graph_ = NULL;
00707
00708 return retval;
00709 }