00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <fstream>
00011 #include <iomanip>
00012
00013 #include "CouenneProblem.hpp"
00014 #include "CouenneProblemElem.hpp"
00015 #include "CouenneExprVar.hpp"
00016
00017 #include "CouenneExprGroup.hpp"
00018 #include "CouenneExprQuad.hpp"
00019
00020 using namespace Couenne;
00021
00022
00023
00024
00025 double printLPquad (std::ofstream &f, const expression *ex, double mult) {
00026
00027 expression *mutex = const_cast <expression *> (ex);
00028
00029 exprGroup *e = dynamic_cast <exprGroup *> (mutex);
00030
00031 double sign = 1., retval = 0;
00032
00033 if (!e) {
00034 if (mutex -> code () == COU_EXPROPP) {
00035 ex = ex -> Argument () -> Original ();
00036 mutex = const_cast <expression *> (ex);
00037 sign = -1.;
00038 e = dynamic_cast <exprGroup *> (mutex);
00039 }
00040 }
00041
00042 int wrapCount = 0;
00043
00044 if (e) {
00045
00046
00047
00048 if (e -> getc0 () != 0)
00049 retval -= sign * e -> getc0 ();
00050
00051 for (std::vector <std::pair <exprVar *, CouNumber> >::iterator i = e -> lcoeff () . begin ();
00052 i != e -> lcoeff (). end (); ++i) {
00053
00054 CouNumber c = sign * i -> second;
00055
00056 if ((c > 0) &&
00057 ((i != e -> lcoeff (). begin ()) || (e -> getc0 () != 0)))
00058 f << '+';
00059
00060 f << c << ' ';
00061
00062 i -> first -> print (f);
00063
00064 if (!(++wrapCount % 10))
00065 f << std::endl;
00066 else f << ' ';
00067 }
00068 } else {
00069
00070
00071
00072
00073 retval -= ex -> Value ();
00074 }
00075
00076
00077 exprQuad *q = dynamic_cast <exprQuad *> (mutex);
00078
00079
00080
00081 if (q) {
00082
00083 std::vector <std::pair <exprVar *, exprQuad::sparseQcol> > &Q = q -> getQ ();
00084
00085 f << " + [ ";
00086
00087 for (std::vector <std::pair <exprVar *, exprQuad::sparseQcol> >::iterator i = Q. begin ();
00088 i != Q . end (); ++i) {
00089
00090 for (std::vector <std::pair <exprVar *, CouNumber> >::iterator j = i -> second. begin ();
00091 j != i -> second . end (); ++j) {
00092
00093 CouNumber c = mult * sign * j -> second;
00094
00095 if (c > 0)
00096 f << " +";
00097
00098 f << c << " ";
00099
00100 if (i -> first -> Index () ==
00101 j -> first -> Index ()) {
00102 i -> first -> print (f);
00103 f << "^2";
00104 } else {
00105 i -> first -> print (f); f << " * ";
00106 j -> first -> print (f);
00107 }
00108
00109 if (!(++wrapCount % 10))
00110 f << std::endl;
00111 else f << ' ';
00112 }
00113 }
00114
00115 f << " ] ";
00116 if (mult != 1)
00117 f << "/ " << mult;
00118 }
00119
00120 if ((mutex -> nArgs () == 1) &&
00121 (mutex -> ArgList () [0] -> Type () == CONST)) {
00122
00123 retval -= sign * mutex -> ArgList () [0] -> Value ();
00124
00125 } else {
00126
00127 f << " + [ ";
00128
00129 expression *arg = NULL, *arg2 = NULL;
00130 double signI;
00131
00132 for (int i=0; i<mutex -> nArgs ();) {
00133
00134 if (arg2) {
00135
00136 arg = arg2;
00137 arg2 = NULL;
00138 signI = -signI;
00139
00140 } else {
00141
00142 signI = sign;
00143
00144 arg = mutex -> ArgList () [i];
00145
00146 if (arg -> code () == COU_EXPROPP) {
00147
00148 arg = arg -> Argument ();
00149 signI = - sign;
00150 }
00151
00152 if (arg -> code () == COU_EXPRSUB) {
00153
00154 arg2 = arg -> ArgList () [1];
00155 arg = arg -> ArgList () [0];
00156 }
00157 }
00158
00159 if (arg -> code () == COU_EXPROPP) {
00160
00161 arg = arg -> Argument ();
00162 signI = - signI;
00163 }
00164
00165 if (arg -> Type () == CONST) retval -= signI * arg -> Value ();
00166
00167 else if ((arg -> code () == COU_EXPRPOW) &&
00168 (arg -> ArgList () [0] -> Type () == VAR) &&
00169 (arg -> ArgList () [1] -> Type () == CONST)) {
00170
00171 f << ((signI > 0) ? " + " : " - ");
00172 if (mult != 1) f << mult << " ";
00173 arg -> ArgList () [0] -> print (f);
00174 f << "^2";
00175 }
00176
00177 else if ((arg -> code () == COU_EXPRMUL) &&
00178 (arg -> ArgList () [0] -> Type () == CONST) &&
00179 (arg -> ArgList () [1] -> code () == COU_EXPRPOW) &&
00180 (arg -> ArgList () [1] -> ArgList () [0] -> Type () == VAR) &&
00181 (arg -> ArgList () [1] -> ArgList () [1] -> Type () == CONST)) {
00182
00183 double c = mult * signI * arg -> ArgList () [0] -> Value ();
00184 f << ((c > 0) ? '+' : ' ') << c << " ";
00185 arg -> ArgList () [1] -> ArgList () [0] -> print (f);
00186 f << "^2";
00187 }
00188
00189 else if ((arg -> code () == COU_EXPRMUL) &&
00190 (arg -> ArgList () [0] -> Type () == VAR) &&
00191 (arg -> ArgList () [1] -> Type () == VAR) &&
00192 (arg -> ArgList () [0] -> Index () !=
00193 arg -> ArgList () [1] -> Index ())) {
00194
00195 f << ((signI > 0) ? " + " : " - ");
00196 if (mult != 1) f << mult << " ";
00197 arg -> ArgList () [0] -> print (f); f << " * ";
00198 arg -> ArgList () [1] -> print (f);
00199 }
00200
00201 else if ((arg -> code () == COU_EXPRMUL) &&
00202 (arg -> ArgList () [0] -> Type () == VAR) &&
00203 (arg -> ArgList () [1] -> Type () == VAR) &&
00204 (arg -> ArgList () [0] -> Index () ==
00205 arg -> ArgList () [1] -> Index ())) {
00206
00207 f << ((signI > 0) ? " + " : " - ");
00208 if (mult != 1) f << mult << " ";
00209 arg -> ArgList () [1] -> print (f);
00210 f << "^2 ";
00211 }
00212
00213 else if ((arg -> code () == COU_EXPRMUL) &&
00214 (arg -> ArgList () [0] -> Type () == CONST) &&
00215 (arg -> ArgList () [1] -> code () == COU_EXPRMUL) &&
00216 (arg -> ArgList () [1] -> ArgList () [0] -> Type () == VAR) &&
00217 (arg -> ArgList () [1] -> ArgList () [1] -> Type () == VAR) &&
00218 (arg -> ArgList () [1] -> ArgList () [0] -> Index () !=
00219 arg -> ArgList () [1] -> ArgList () [1] -> Index ())) {
00220
00221 double c = mult * signI * arg -> ArgList () [0] -> Value ();
00222 f << ((c > 0) ? '+' : ' ') << c << " ";
00223 arg -> ArgList () [1] -> ArgList () [0] -> print (f); f << " * ";
00224 arg -> ArgList () [1] -> ArgList () [1] -> print (f);
00225 }
00226
00227 else if ((arg -> code () == COU_EXPRMUL) &&
00228 (arg -> ArgList () [0] -> Type () == CONST) &&
00229 (arg -> ArgList () [1] -> code () == COU_EXPRMUL) &&
00230 (arg -> ArgList () [1] -> ArgList () [0] -> Type () == VAR) &&
00231 (arg -> ArgList () [1] -> ArgList () [1] -> Type () == VAR) &&
00232 (arg -> ArgList () [1] -> ArgList () [0] -> Index () !=
00233 arg -> ArgList () [1] -> ArgList () [1] -> Index ())) {
00234
00235 double c = mult * signI * arg -> ArgList () [0] -> Value ();
00236 f << ((c > 0) ? '+' : ' ') << c << " ";
00237 arg -> ArgList () [1] -> ArgList () [0] -> print (f);
00238 f << "^2 ";
00239
00240 } else {
00241
00242 printf ("Can't recognize expression (code: %d), exiting: ", arg -> code ());
00243 arg -> print ();
00244 printf ("\nExpression: ");
00245 ex -> print ();
00246 printf ("\n");
00247 exit (-1);
00248 }
00249
00250 if (!(++wrapCount % 10))
00251 f << std::endl;
00252 else f << ' ';
00253
00254 if (!arg2) ++i;
00255 else if (arg -> code () == COU_EXPROPP)
00256 signI = - signI;
00257 }
00258
00259 f << " ] ";
00260 if (mult != 1)
00261 f << "/ " << mult;
00262 }
00263
00264 return retval;
00265 }
00266
00267
00268
00269
00270 void CouenneProblem::writeLP (const std::string &fname) {
00271
00272
00273
00274 for (int i=0; i < nVars (); i++)
00275 if (variables_ [i] -> Type () == AUX) {
00276 printf ("Auxiliary variables not supported in writeLP yet, bailing out\n");
00277 return;
00278 }
00279
00280 if (objectives_ [0] -> Body () -> Linearity () > QUADRATIC) {
00281 printf ("Objective is nonlinear and not quadratic, bailing out\n");
00282 return;
00283 }
00284
00285 for (int i=0; i < nCons (); i++) {
00286 if (constraints_ [i] -> Body () -> Linearity () > QUADRATIC) {
00287 printf ("Constraint %d is nonlinear and not quadratic, bailing out\n", i);
00288 return;
00289 }
00290 }
00291
00292 std::ofstream f (fname.c_str ());
00293
00294 f << std::setprecision (15);
00295
00296
00297
00298 f << "\\ Problem name (saved using Couenne): " << problemName_ << std::endl << std::endl;
00299
00300
00301
00302
00303 f << "minimize obj: ";
00304
00305 double objConst = printLPquad (f, objectives_ [0] -> Body (), 2);
00306 if (objConst != 0.) f << ((objConst > 0) ? " + " : " ") << objConst;
00307 f << std::endl << std::endl << "Subject To" << std::endl << std::endl;
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 for (int i=0; i < nCons (); i++) {
00356
00357
00358 CouNumber lb = (constraints_ [i] -> Lb () -> Value ()),
00359 ub = (constraints_ [i] -> Ub () -> Value ());
00360
00361 f << "con_" << i << ": ";
00362 double extraTerm = printLPquad (f, constraints_ [i] -> Body (), 1);
00363
00364 lb += extraTerm;
00365 ub += extraTerm;
00366
00367 if (lb > - COUENNE_INFINITY) {
00368 f << ' ';
00369 if (fabs (ub-lb) > COUENNE_EPS)
00370 f << '>';
00371 f << "= " << lb << std::endl;
00372 }
00373 else f << " <= " << ub << std::endl;
00374
00375 // if range constraint, print it once again
00376
00377 if (( lb > - COUENNE_INFINITY + 1)
00378 && (ub < COUENNE_INFINITY - 1)
00379 && (fabs (ub-lb) > COUENNE_EPS)) {
00380
00381 f << "con_" << i << "_rng: ";
00382 printLPquad (f, constraints_ [i] -> Body (), 1);
00383 f << " <= " << ub << std::endl;
00384 }
00385 }
00386
00387 f << "Bounds" << std::endl << std::endl;
00388
00389 for (int i=0; i < nVars (); i++) {
00390
00391 if ((Lb (i) == 0) && (Ub (i) >= COUENNE_INFINITY/2))
00392 continue;
00393
00394 if (Lb (i) != 0) f << Lb (i) << " <= ";
00395 variables_ [i] -> print (f);
00396 if (Ub (i) < + COUENNE_INFINITY/2) f << " <= " << Ub (i);
00397 f << std::endl;
00398 }
00399
00400 f << "Generals" << std::endl << std::endl;
00401
00402 int wrapcount = 0;
00403
00404 for (int i=0; i < nVars (); i++)
00405
00406 if (variables_ [i] -> isInteger ()) {
00407 variables_ [i] -> print (f);
00408 if (!(++wrapcount % 10))
00409 f << std::endl;
00410 else
00411 f << " ";
00412 }
00413
00414 f << std::endl << std::endl << "End" << std::endl;
00415
00416 f.close ();
00417 }