/home/coin/SVN-release/OS-2.1.0/Couenne/src/readnl/readnl.cpp

Go to the documentation of this file.
00001 /* $Id: readnl.cpp 184 2009-07-01 16:09:17Z pbelotti $
00002  *
00003  * Name:    readnl.cpp
00004  * Author:  Pietro Belotti
00005  * Purpose: define a reader for .nl files. Adapted from ampl2ev3 by L. Liberti and S. Galli 
00006  *
00007  * (C) Carnegie-Mellon University, 2006. 
00008  * This file is licensed under the Common Public License (CPL)
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 //#define DEBUG
00037 
00038 // check if an expression is a null pointer or equals zero
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                           //  && (fabs (e -> dL) < COUENNE_EPS)
00043                           // *** CHECK THIS! dL is the derivative
00044                           )));} 
00045 
00046 // Reads a MINLP from an AMPL .nl file through the ASL methods
00047 int CouenneProblem::readnl (const ASL *asl) {
00048 
00049   problemName_ = filename;
00050 
00051   // number of defined variables (aka common expressions)
00052   ndefined_ = como + comc + comb + como1 + comc1; 
00053 
00054   // see "hooking your solver to AMPL", by David M. Gay, tables 3, 4, and 5
00055 
00056   // nonlinear in both objectives and constraints
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   // nonlinear in either objectives or constraints
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_);//arc
00076   for (int i = n_var - (CoinMax (nlvc,nlvo) +niv+nbv+nwv); i--;) addVariable(false, &domain_);//other
00077   for (int i = 0; i < nbv; i++)                                  addVariable(true,  &domain_);//binary
00078   for (int i = 0; i < niv; i++)                                  addVariable(true,  &domain_);//int.
00079 
00080   // add space for common expressions
00081   for (int i = ndefined_; i--;)                                  addVariable(false, &domain_);
00082 
00083   // common expressions (or defined variables) ///////////////////////////////////////
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   // Each has a linear and a nonlinear part (thanks to Dominique
00097   // Orban: http://www.gerad.ca/~orban/drampl/def-vars.html)
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;  // Number of linear terms
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         //vp = (expr_v *)((char *)L->v.rp - ((char *)&ev.v - (char *)&ev));
00119         //Printf( " %-g x[%-d]", L->fac, (int)(vp - VAR_E) );   
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 //((const ASL_fg *) asl) -> I.cexps_
00125                 //L [j]. v.i
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;  // Number of linear terms
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         //vp = (expr_v *)((char *)L->v.rp - ((char *)&ev.v - (char *)&ev));
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 //((const ASL_fg *) asl) -> I.cexps_
00172                 //L [j]. v.i
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     //    addAuxiliary (nl2e (((const ASL_fg *) asl) -> I.cexps1_ [i] . e, asl));
00193   }
00194 
00195   // objective functions /////////////////////////////////////////////////////////////
00196 
00197   for (int i = 0; i < n_obj; i++) {
00198 
00200     int nterms = 0;
00201 
00202     // count nonzero terms in linear part
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) { // have linear terms
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         // delete node without deleting children (they are now in body)
00237         nl -> ArgList (NULL);
00238         delete nl;
00239       }
00240       else {
00241 
00242         expression **nll = new expression * [1];
00243 
00244         *nll = nl;
00245 
00246         // apparently, objconst (i) is included in the obj expression
00247         body = exprGroup::genExprGroup (0., lcoeff, nll, 1);
00248         //body = new exprGroup (objconst (i), indexL, coeff, nll, 1);
00249       }
00250 
00251       delete [] indexL;
00252       delete [] coeff;
00253 
00254     } else
00255       // apparently, objconst (i) is included in the obj expression
00256       body = nl;
00257       //if (fabs (objconst (i) > COUENNE_EPS))
00258       //body = new exprSum (nl, new exprConst (objconst (i)));
00259       //else 
00260 
00262 
00263     expression *subst = body -> simplify ();
00264 
00265     if (subst) {
00266       delete body; // VALGRIND
00267       body = subst;
00268     }
00269 
00270     // ThirdParty/ASL/solvers/asl.h, line 336: 0 is minimization, 1 is maximization
00271     addObjective (body, (OBJ_sense [i] == 0) ? "min" : "max");
00272   }
00273 
00274   // constraints ///////////////////////////////////////////////////////////////////
00275 
00276   int *nterms = new int [n_con];
00277 
00278   // allocate space for argument list of all constraints' summations
00279   // of linear and nonlinear terms
00280 
00281   // init array with # terms of each constraint
00282   for (int i = n_con; i--;) 
00283     *nterms++ = 0;
00284   nterms -= n_con;
00285 
00286   cgrad *congrad;
00287 
00288   // count all linear terms
00289   if (A_colstarts && A_vals)         // Constraints' linear info is stored in 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 {                             // Constraints' linear info is stored in Cgrad
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   // vectors of the linear part
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   // set linear terms
00318 
00319   if (A_colstarts && A_vals)         // Constraints' linear info is stored in 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 {                             // Constraints' linear info is stored in Cgrad
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   // set constraints' bound and sign and store nonlinear part ///////////////////////////////
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     // set constraint sign
00376     if (lb > negInfinity)
00377       if (ub < Infinity) sign = COUENNE_RNG;
00378       else               sign = COUENNE_GE;
00379     else                 sign = COUENNE_LE;
00380 
00381     // this is an equality constraint  
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       /*std::vector <std::pair <exprVar *, CouNumber> > lcoeff;
00398       for (int i=0, *ind = indexL; *ind >= 0; *ind++, i++)
00399       lcoeff.push_back (std::pair <exprVar *, CouNumber> (Var (*ind), coeff [i]));*/
00400 
00401       if ((code == COU_EXPRSUM) || 
00402           (code == COU_EXPRGROUP)) {
00403 
00404         body    = exprGroup::genExprGroup (0., lcoeff, (*nll) -> ArgList (), (*nll) -> nArgs ());
00405         // delete node without deleting children (they are now in body)
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; // VALGRIND
00420       body = subst;
00421     }
00422 
00423     // add them (and set lower-upper bound)
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   // create room for problem's variables and bounds
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   // lower and upper bounds ///////////////////////////////////////////////////////////////
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   // initial x ////////////////////////////////////////////////////////////////////
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 }

Generated on Tue Mar 30 03:04:38 2010 by  doxygen 1.4.7