00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "asl.h"
00012
00013 #include "nlp.h"
00014 #include "getstub.h"
00015 #include "opcode.hd"
00016
00017 #include "CoinHelperFunctions.hpp"
00018 #include "CoinTime.hpp"
00019
00020 #include "CouenneProblem.hpp"
00021
00022 #if defined HAVE_CSTDINT
00023 #include "cstdint"
00024 #elif defined HAVE_STDINT_H
00025 #include "stdint.h"
00026 #endif
00027
00028 #include "CouenneTypes.hpp"
00029 #include "CouenneExprSum.hpp"
00030 #include "CouenneExprOpp.hpp"
00031 #include "CouenneExprMul.hpp"
00032 #include "CouenneExprSub.hpp"
00033 #include "CouenneExprClone.hpp"
00034 #include "CouenneExprGroup.hpp"
00035
00036 #define OBJ_DE ((const ASL_fg *) asl) -> I.obj_de_
00037 #define VAR_E ((const ASL_fg *) asl) -> I.var_e_
00038 #define CON_DE ((const ASL_fg *) asl) -> I.con_de_
00039 #define OBJ_sense ((const ASL_fg *) asl) -> i.objtype_
00040
00041 #define THRESHOLD_OUTPUT_READNL 10000
00042
00043
00044
00045 using namespace Couenne;
00046
00047
00048 inline bool is_expr_zero (expr* e)
00049 {return ((e==NULL) || ((((Intcast (e->op)) == OPNUM) &&
00050 (fabs (((expr_n *)e) -> v) < COUENNE_EPS)
00051
00052
00053 )));}
00054
00055 void createCommonExpr (CouenneProblem *p, const ASL *asl, int i, int which);
00056
00057
00058 int CouenneProblem::readnl (const ASL *asl) {
00059
00060 problemName_ = filename;
00061
00062
00063 ndefined_ = como + comc + comb + como1 + comc1;
00064
00065
00066
00067
00068 if (nlvb >= 0) {
00069 for (int i = 0; i < nlvb - nlvbi; i++) addVariable (false, &domain_);
00070 for (int i = 0; i < nlvbi; i++) addVariable (true, &domain_);
00071 }
00072
00073
00074 if (nlvo > nlvc) {
00075 for (int i = 0; i < nlvc - (nlvb + nlvci); i++) addVariable (false, &domain_);
00076 for (int i = 0; i < nlvci; i++) addVariable (true, &domain_);
00077 for (int i = 0; i < nlvo - (nlvc + nlvoi); i++) addVariable (false, &domain_);
00078 for (int i = 0; i < nlvoi; i++) addVariable (true, &domain_);
00079 } else {
00080 for (int i = 0; i < nlvo - (nlvb + nlvoi); i++) addVariable (false, &domain_);
00081 for (int i = 0; i < nlvoi; i++) addVariable (true, &domain_);
00082 for (int i = 0; i < nlvc - (nlvo + nlvci); i++) addVariable (false, &domain_);
00083 for (int i = 0; i < nlvci; i++) addVariable (true, &domain_);
00084 }
00085
00086 for (int i = 0; i < nwv; i++) addVariable(false, &domain_);
00087 for (int i = n_var - (CoinMax (nlvc,nlvo) +niv+nbv+nwv); i--;) addVariable(false, &domain_);
00088 for (int i = 0; i < nbv; i++) addVariable(true, &domain_);
00089 for (int i = 0; i < niv; i++) addVariable(true, &domain_);
00090
00091
00092 for (int i = ndefined_; i--;) addVariable(false, &domain_);
00093
00094 double now = CoinCpuTime ();
00095
00096 if (nVars () > THRESHOLD_OUTPUT_READNL) {
00097 jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "Reading problem: ");
00098 fflush(stdout);
00099 }
00100
00101
00102
00103 #ifdef DEBUG
00104 printf ("ndefd_ = %d\n", ndefined_);
00105 printf ("tot var = %d\n", variables_ . size ());
00106 printf ("c_vars_ = %d\n", ((const ASL_fg *) asl) -> i.c_vars_ );
00107 printf ("comb_ = %d\n", ((const ASL_fg *) asl) -> i.comb_ );
00108 printf ("combc_ = %d\n", ((const ASL_fg *) asl) -> i.combc_ );
00109 printf ("comc1_ = %d\n", ((const ASL_fg *) asl) -> i.comc1_ );
00110 printf ("comc_ = %d\n", ((const ASL_fg *) asl) -> i.comc_ );
00111 printf ("como1_ = %d\n", ((const ASL_fg *) asl) -> i.como1_ );
00112 printf ("como_ = %d\n", ((const ASL_fg *) asl) -> i.como_ );
00113 #endif
00114
00115
00116
00117
00118 for (int i = 0; i < como + comc + comb; i++)
00119 createCommonExpr (this, asl, i, 0);
00120
00121 for (int i = 0; i < como1 + comc1; i++)
00122 createCommonExpr (this, asl, i, 1);
00123
00124
00125
00126
00127
00128 if (n_obj == 0) {
00129
00130
00131
00132 jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "Couenne: warning, no objective function found\nAdded fictitious function f(x)=0\n");
00133 addObjective (new exprConst (0.), "min");
00134 }
00135
00136 for (int i = 0; i < n_obj; i++) {
00137
00139 int nterms = 0;
00140
00141
00142
00143 for (ograd *objgrad = Ograd [i];
00144 objgrad;
00145 objgrad = objgrad -> next)
00146 if (fabs (objgrad -> coef) > COUENNE_EPS)
00147 nterms++;
00148
00149 expression
00150 *body,
00151 *nl = nl2e (OBJ_DE [i] . e, asl);
00152
00153 if (nterms) {
00154
00155 int *indexL = new int [nterms+1];
00156 CouNumber *coeff = new CouNumber [nterms];
00157
00158 for (ograd *objgrad = Ograd [i]; objgrad; objgrad = objgrad -> next)
00159 if (fabs (objgrad -> coef) > COUENNE_EPS) {
00160
00161 *indexL++ = objgrad -> varno;
00162 *coeff++ = objgrad -> coef;
00163 }
00164
00165 *indexL = -1;
00166
00167 indexL -= nterms;
00168 coeff -= nterms;
00169
00170 std::vector <std::pair <exprVar *, CouNumber> > lcoeff;
00171 indcoe2vector (indexL, coeff, lcoeff);
00172
00173 if (nl -> code () == COU_EXPRSUM) {
00174 body = exprGroup::genExprGroup (0., lcoeff, nl -> ArgList (), nl -> nArgs ());
00175
00176 nl -> ArgList (NULL);
00177 delete nl;
00178 }
00179 else {
00180
00181 expression **nll = new expression * [1];
00182
00183 *nll = nl;
00184
00185
00186 body = exprGroup::genExprGroup (0., lcoeff, nll, 1);
00187
00188 }
00189
00190 delete [] indexL;
00191 delete [] coeff;
00192
00193 } else
00194
00195 body = nl;
00196
00197
00198
00199
00201
00202 expression *subst = body -> simplify ();
00203
00204 if (subst) {
00205 delete body;
00206 body = subst;
00207 }
00208
00209
00210 addObjective (body, (OBJ_sense [i] == 0) ? "min" : "max");
00211 }
00212
00213
00214
00215 int *nterms = new int [n_con];
00216
00217
00218
00219
00220
00221 for (int i = n_con; i--;)
00222 *nterms++ = 0;
00223 nterms -= n_con;
00224
00225 cgrad *congrad;
00226
00227
00228 if (A_colstarts && A_vals)
00229 for (register int j = A_colstarts [n_var]; j--;) {
00230
00231 real coeff = A_vals [j];
00232
00233 if (fabs (coeff) > COUENNE_EPS)
00234 nterms [A_rownos [j]] ++;
00235 }
00236 else {
00237 for (register int i = 0; i < n_con; i++)
00238 for (congrad = Cgrad [i];
00239 congrad;
00240 congrad = congrad -> next)
00241 if (fabs (congrad -> coef) > COUENNE_EPS)
00242 nterms [i] ++;
00243 }
00244
00245
00246
00247 CouNumber **coeff = new CouNumber * [n_con];
00248 int **indexL = new int * [n_con];
00249
00250 for (register int i = n_con; i--;)
00251 *indexL++ = NULL;
00252
00253 indexL -= n_con;
00254
00255
00256
00257
00258 if (A_colstarts && A_vals)
00259 for (int j = 0; j < n_var; j++)
00260 for (register int i = A_colstarts [j], k = A_colstarts [j+1] - i; k--; i++) {
00261
00262 int rowno = A_rownos [i],
00263 nt = nterms [rowno] --;
00264
00265 CouNumber **cline = coeff + rowno;
00266 int **iline = indexL + rowno;
00267
00268 if (*iline==NULL) {
00269 *cline = new CouNumber [nt];
00270 *iline = new int [nt+1];
00271 (*iline) [nt] = -1;
00272 }
00273
00274 (*cline) [--nt] = A_vals [i];
00275 (*iline) [nt] = j;
00276
00277 }
00278 else {
00279 for (int i=0; i < n_con; i++) {
00280
00281 int nt = nterms [i];
00282
00283 CouNumber **cline = coeff + i;
00284 int **iline = indexL + i;
00285
00286 *cline = new CouNumber [nt];
00287 *iline = new int [nt+1];
00288 (*iline) [nt] = -1;
00289
00290 for (congrad = Cgrad [i]; congrad; congrad = congrad -> next)
00291 if (fabs (congrad -> coef) > COUENNE_EPS) {
00292 (*cline) [--nt] = congrad -> coef;
00293 (*iline) [nt] = congrad -> varno;
00294 }
00295 }
00296 }
00297
00298
00299
00300 for (int i = 0; i < n_con; i++) {
00301
00302 enum con_sign sign;
00303 double lb, ub;
00304
00305 if (Urhsx) {
00306 lb = LUrhs [i];
00307 ub = Urhsx [i];
00308 } else {
00309 int j = 2*i;
00310 lb = LUrhs [j];
00311 ub = LUrhs [j+1];
00312 }
00313
00314
00315 if (lb > negInfinity)
00316 if (ub < Infinity) sign = COUENNE_RNG;
00317 else sign = COUENNE_GE;
00318 else sign = COUENNE_LE;
00319
00320
00321 if (fabs (lb - ub) < COUENNE_EPS)
00322 sign = COUENNE_EQ;
00323
00324 expression *body;
00325
00326 expression **nll = new expression * [1];
00327 *nll = nl2e (CON_DE [i] . e, asl);
00328
00329 if (indexL [i] && (*(indexL [i]) >= 0)) {
00330
00331 int code = (*nll) -> code ();
00332
00333 std::vector <std::pair <exprVar *, CouNumber> > lcoeff;
00334 indcoe2vector (indexL [i], coeff [i], lcoeff);
00335
00336
00337
00338
00339
00340 if ((code == COU_EXPRSUM) ||
00341 (code == COU_EXPRGROUP)) {
00342
00343 body = exprGroup::genExprGroup (0., lcoeff, (*nll) -> ArgList (), (*nll) -> nArgs ());
00344
00345 (*nll) -> ArgList (NULL);
00346 delete *nll;
00347 delete [] nll;
00348 }
00349 else body = exprGroup::genExprGroup (0., lcoeff, nll, 1);
00350 }
00351 else {
00352 body = *nll;
00353 delete [] nll;
00354 }
00355
00356 expression *subst = body -> simplify ();
00357 if (subst) {
00358 delete body;
00359 body = subst;
00360 }
00361
00362
00363 switch (sign) {
00364
00365 case COUENNE_EQ: addEQConstraint (body, new exprConst (ub)); break;
00366 case COUENNE_LE: addLEConstraint (body, new exprConst (ub)); break;
00367 case COUENNE_GE: addGEConstraint (body, new exprConst (lb)); break;
00368 case COUENNE_RNG: addRNGConstraint (body, new exprConst (lb),
00369 new exprConst (ub)); break;
00370 default: printf ("Could not recognize constraint\n"); return -1;
00371 }
00372
00373 delete [] indexL [i];
00374 delete [] coeff [i];
00375 }
00376
00377 delete [] indexL;
00378 delete [] coeff;
00379
00380
00381 CouNumber
00382 *x = (CouNumber *) malloc ((n_var + ndefined_) * sizeof (CouNumber)),
00383 *lb = (CouNumber *) malloc ((n_var + ndefined_) * sizeof (CouNumber)),
00384 *ub = (CouNumber *) malloc ((n_var + ndefined_) * sizeof (CouNumber));
00385
00386 for (int i = n_var + ndefined_; i--;) {
00387 x [i] = 0.;
00388 lb [i] = -COUENNE_INFINITY;
00389 ub [i] = COUENNE_INFINITY;
00390 }
00391
00392 domain_.push (n_var + ndefined_, x, lb, ub);
00393
00394 free (x); free (lb); free (ub);
00395
00396
00397
00398 if (LUv) {
00399
00400 real *Uvx_copy = Uvx;
00401
00402 if (!Uvx_copy)
00403 for (register int i=0; i<n_var; i++) {
00404
00405 register int j = 2*i;
00406
00407 Lb (i) = LUv [j];
00408 Ub (i) = LUv [j+1];
00409 }
00410 else
00411 for (register int i=n_var; i--;) {
00412 Lb (i) = LUv [i];
00413 Ub (i) = Uvx_copy [i];
00414 }
00415
00416 } else
00417 for (register int i=n_var; i--;) {
00418 Lb (i) = - COUENNE_INFINITY;
00419 Ub (i) = COUENNE_INFINITY;
00420 }
00421
00422
00423
00424 for (register int i=n_var; i--;)
00425
00426 if (X0 && havex0 [i]) X (i) = X0 [i];
00427
00428 else {
00429
00430 CouNumber x, l = Lb (i), u = Ub (i);
00431
00432 if (l < - COUENNE_INFINITY)
00433 if (u > COUENNE_INFINITY) x = 0.;
00434 else x = u;
00435 else if (u > COUENNE_INFINITY) x = l;
00436 else x = 0.5 * (l+u);
00437
00438 X (i) = x;
00439 }
00440
00441 for (register int i=n_var; i<ndefined_; i++) {
00442
00443 X (i) = 0.;
00444 Lb (i) = -COUENNE_INFINITY;
00445 Ub (i) = COUENNE_INFINITY;
00446 }
00447
00448 delete [] nterms;
00449
00450 if (nVars () > THRESHOLD_OUTPUT_READNL) {
00451 jnlst_ -> Printf (Ipopt::J_ERROR, J_COUENNE, "%.1f seconds\n", CoinCpuTime () - now);
00452 fflush(stdout);
00453 }
00454
00455 return 0;
00456 }
00457
00458
00459
00460
00461
00462
00463 void createCommonExpr (CouenneProblem *p, const ASL *asl, int i, int which) {
00464
00465 struct cexp *common = ((const ASL_fg *) asl) -> I.cexps_ + i;
00466 struct cexp1 *common1 = ((const ASL_fg *) asl) -> I.cexps1_ + i;
00467
00468 expression *nle = p -> nl2e (which ? common1 -> e : common -> e, asl);
00469
00470 #ifdef DEBUG
00471 printf ("cexp1 %d [%d]: ", i, p -> Variables () . size ()); nle -> print (); printf (" ||| ");
00472 #endif
00473
00474 int nlin = which ? common1 -> nlin : common -> nlin;
00475
00476 if (nlin > 0) {
00477
00478 linpart *L = which ? common1 -> L : common -> L;
00479
00480 std::vector <std::pair <exprVar *, CouNumber> > lcoeff;
00481
00482 for (int j = 0; j < nlin; j++) {
00483
00484
00485 int indVar = ((uintptr_t) (L [j].v.rp) - (uintptr_t) VAR_E) / sizeof (expr_v);
00486 CouNumber coeff = L [j]. fac;
00487
00488 lcoeff.push_back (std::pair <exprVar *, CouNumber> (p -> Var (indVar), coeff));
00489
00490 #ifdef DEBUG
00491 Printf( " %+g x_%d (%-3d)", L [j]. fac, indVar,
00492 (expr_v *) (L [j].v.rp) - VAR_E
00493
00494 );
00495 #endif
00496 }
00497
00498 expression **al = new expression * [1];
00499 *al = nle;
00500
00501 expression *eg;
00502
00503 if (lcoeff.size () == 1 &&
00504 nle -> Type () == CONST &&
00505 nle -> Value () == 0.) {
00506
00507 CouNumber coeff = lcoeff [0].second;
00508
00509 if (coeff == 1.) eg = new exprClone (lcoeff [0].first);
00510 else if (coeff == -1.) eg = new exprOpp (new exprClone (lcoeff [0].first));
00511 else eg = new exprMul (new exprConst (coeff), new exprClone (lcoeff [0].first));
00512 } else eg = exprGroup::genExprGroup (0, lcoeff, al, 1);
00513
00514 int indVar = p -> nVars () - p -> nDefVars () + p -> commonExprs () . size ();
00515
00516 if (eg -> Index () != indVar) {
00517
00518 expression *body = new exprSub (eg, new exprClone (p -> Var (indVar)));
00519 p -> addEQConstraint (body, new exprConst (0.));
00520 }
00521
00522 p -> commonExprs () . push_back (new exprClone (eg));
00523 }
00524 else {
00525
00526 int indVar = p -> nVars () - p -> nDefVars () + p -> commonExprs () . size ();
00527
00528 if (nle -> Index () != indVar) {
00529
00530 expression *body = new exprSub (nle, new exprClone (p -> Var (indVar)));
00531 p -> addEQConstraint (body, new exprConst (0.));
00532 }
00533
00534 p -> commonExprs () . push_back (new exprClone (nle));
00535 }
00536
00537 #ifdef DEBUG
00538 printf ("\n");
00539 #endif
00540
00541 }