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

Go to the documentation of this file.
00001 /* $Id: readnl.cpp 752 2011-08-08 03:45:07Z 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-10. 
00008  * This file is licensed under the Eclipse Public License (EPL)
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 //#define DEBUG
00044 
00045 using namespace Couenne;
00046 
00047 // check if an expression is a null pointer or equals zero
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                           //  && (fabs (e -> dL) < COUENNE_EPS)
00052                           // *** CHECK THIS! dL is the derivative
00053                           )));} 
00054 
00055 void createCommonExpr (CouenneProblem *p, const ASL *asl, int i, int which);
00056 
00057 // Reads a MINLP from an AMPL .nl file through the ASL methods
00058 int CouenneProblem::readnl (const ASL *asl) {
00059 
00060   problemName_ = filename;
00061 
00062   // number of defined variables (aka common expressions)
00063   ndefined_ = como + comc + comb + como1 + comc1; 
00064 
00065   // see "hooking your solver to AMPL", by David M. Gay, tables 3, 4, and 5
00066 
00067   // nonlinear in both objectives and constraints
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   // nonlinear in either objectives or constraints
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_);//arc
00087   for (int i = n_var - (CoinMax (nlvc,nlvo) +niv+nbv+nwv); i--;) addVariable(false, &domain_);//other
00088   for (int i = 0; i < nbv; i++)                                  addVariable(true,  &domain_);//binary
00089   for (int i = 0; i < niv; i++)                                  addVariable(true,  &domain_);//int.
00090 
00091   // add space for common expressions
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   // common expressions (or defined variables) ///////////////////////////////////////
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   // Each has a linear and a nonlinear part (thanks to Dominique
00116   // Orban: http://www.gerad.ca/~orban/drampl/def-vars.html)
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   //commonexprs_ . erase (commonexprs_ . begin (), commonexprs_ . end ());
00125 
00126   // objective functions /////////////////////////////////////////////////////////////
00127 
00128   if (n_obj == 0) {
00129 
00130     // strange, no objective function. Add one equal to zero
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     // count nonzero terms in linear part
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) { // have linear terms
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         // delete node without deleting children (they are now in body)
00176         nl -> ArgList (NULL);
00177         delete nl;
00178       }
00179       else {
00180 
00181         expression **nll = new expression * [1];
00182 
00183         *nll = nl;
00184 
00185         // apparently, objconst (i) is included in the obj expression
00186         body = exprGroup::genExprGroup (0., lcoeff, nll, 1);
00187         //body = new exprGroup (objconst (i), indexL, coeff, nll, 1);
00188       }
00189 
00190       delete [] indexL;
00191       delete [] coeff;
00192 
00193     } else
00194       // apparently, objconst (i) is included in the obj expression
00195       body = nl;
00196       //if (fabs (objconst (i) > COUENNE_EPS))
00197       //body = new exprSum (nl, new exprConst (objconst (i)));
00198       //else 
00199 
00201 
00202     expression *subst = body -> simplify ();
00203 
00204     if (subst) {
00205       delete body; // VALGRIND
00206       body = subst;
00207     }
00208 
00209     // ThirdParty/ASL/solvers/asl.h, line 336: 0 is minimization, 1 is maximization
00210     addObjective (body, (OBJ_sense [i] == 0) ? "min" : "max");
00211   }
00212 
00213   // constraints ///////////////////////////////////////////////////////////////////
00214 
00215   int *nterms = new int [n_con];
00216 
00217   // allocate space for argument list of all constraints' summations
00218   // of linear and nonlinear terms
00219 
00220   // init array with # terms of each constraint
00221   for (int i = n_con; i--;) 
00222     *nterms++ = 0;
00223   nterms -= n_con;
00224 
00225   cgrad *congrad;
00226 
00227   // count all linear terms
00228   if (A_colstarts && A_vals)         // Constraints' linear info is stored in 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 {                             // Constraints' linear info is stored in Cgrad
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   // vectors of the linear part
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   // set linear terms
00257 
00258   if (A_colstarts && A_vals)         // Constraints' linear info is stored in 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 {                             // Constraints' linear info is stored in Cgrad
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   // set constraints' bound and sign and store nonlinear part ///////////////////////////////
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     // set constraint sign
00315     if (lb > negInfinity)
00316       if (ub < Infinity) sign = COUENNE_RNG;
00317       else               sign = COUENNE_GE;
00318     else                 sign = COUENNE_LE;
00319 
00320     // this is an equality constraint  
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       /*std::vector <std::pair <exprVar *, CouNumber> > lcoeff;
00337       for (int i=0, *ind = indexL; *ind >= 0; *ind++, i++)
00338       lcoeff.push_back (std::pair <exprVar *, CouNumber> (Var (*ind), coeff [i]));*/
00339 
00340       if ((code == COU_EXPRSUM) || 
00341           (code == COU_EXPRGROUP)) {
00342 
00343         body    = exprGroup::genExprGroup (0., lcoeff, (*nll) -> ArgList (), (*nll) -> nArgs ());
00344         // delete node without deleting children (they are now in body)
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; // VALGRIND
00359       body = subst;
00360     }
00361 
00362     // add them (and set lower-upper bound)
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   // create room for problem's variables and bounds
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   // lower and upper bounds ///////////////////////////////////////////////////////////////
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   // initial x ////////////////////////////////////////////////////////////////////
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 // Common code for common expressions (aka defined variables)
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;  // Number of linear terms
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       //vp = (expr_v *)((char *)L->v.rp - ((char *)&ev.v - (char *)&ev));
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 //((const ASL_fg *) asl) -> I.cexps_
00493               //L [j]. v.i
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   //    addAuxiliary (nl2e (((const ASL_fg *) asl) -> I.cexps1_ [i] . e, asl));
00541 }

Generated on Wed Nov 30 03:04:08 2011 by  doxygen 1.4.7