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