Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

model.cc

Go to the documentation of this file.
00001 // Model implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2001-2003 Hermann Schichl
00004 //
00005 // This file is part of the COCONUT API.  This library
00006 // is free software; you can redistribute it and/or modify it under the
00007 // terms of the Library GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // Library GNU General Public License for more details.
00015 
00016 // As a special exception, you may use this file as part of a free software
00017 // library without restriction.  Specifically, if other files instantiate
00018 // templates or use macros or inline functions from this file, or you compile
00019 // this file and link it with other files to produce an executable, this
00020 // file does not by itself cause the resulting executable to be covered by
00021 // the Library GNU General Public License.  This exception does not however
00022 // invalidate any other reasons why the executable file might be covered by
00023 // the Library GNU General Public License.
00024 
00027 #include <model.h>
00028 
00029 extern const char *expr_names[];
00030 
00031 void model_iddata::compress_numbers(bool renum_vars,
00032                                                bool renum_consts)
00033 {
00034   unsigned int il, iu, jl, ju, idx = node_num_max-1;
00035   std::vector<std::pair<unsigned int,unsigned int> > __v;
00036   
00037   if(node_free.size() != 0)
00038   {
00039     sort(node_free.begin(), node_free.end());
00040     __v.reserve(node_free.size());
00041     for(il = 0, iu = node_free.size()-1, jl = node_free[il], ju = node_free[iu];
00042         il <= iu;)
00043     {
00044       if(idx <= ju)
00045       {
00046         if(idx == ju)
00047           --idx;
00048         else
00049           node_num_max++; /* this is a correction for the subtraction later */
00050         if(iu == 0)
00051           break;
00052         --iu;
00053         ju = node_free[iu];
00054       }
00055       else
00056       {
00057         __v.push_back(std::make_pair(idx,jl));
00058         --idx;
00059         ++il;
00060         jl = node_free[il];
00061       }
00062     }
00063     node_num_max -= node_free.size();
00064     node_free.erase(node_free.begin(), node_free.end());
00065   }
00066   if(__v.size() != 0)
00067   {
00068     for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00069         ++__b)
00070       (*__b)->renumber_nodes(__v);
00071   }
00072   __v.erase(__v.begin(), __v.end());
00073 
00074   if(renum_vars && var_free.size() != 0)
00075   {
00076     sort(var_free.begin(), var_free.end());
00077     __v.reserve(var_free.size());
00078     for(il = 0, iu = var_free.size()-1, jl = var_free[il], ju = var_free[iu];
00079         il <= iu;)
00080     {
00081       if(idx <= ju)
00082       {
00083         if(idx == ju)
00084           --idx;
00085         else
00086           var_num_max++; /* this is a correction for the subtraction later */
00087         if(iu == 0)
00088           break;
00089         --iu;
00090         ju = var_free[iu];
00091       }
00092       else
00093       {
00094         __v.push_back(std::make_pair(idx,jl));
00095         --idx;
00096         ++il;
00097         jl = var_free[il];
00098       }
00099     }
00100     var_num_max -= var_free.size();
00101     var_free.erase(var_free.begin(), var_free.end());
00102   }
00103   if(__v.size() != 0)
00104   {
00105     for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00106         __i != __v.end(); ++__i)
00107       var_names[(*__i).second] = var_names[(*__i).first];
00108     var_names.erase(var_names.begin(), var_names.begin()+number_of_variables());
00109     for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00110         ++__b)
00111       (*__b)->renumber_variables(__v);
00112   }
00113   __v.erase(__v.begin(), __v.end());
00114 
00115   if(renum_consts && const_free.size() != 0)
00116   {
00117     sort(const_free.begin(), const_free.end());
00118     __v.reserve(const_free.size());
00119     for(il = 0, iu = const_free.size()-1, jl = const_free[il],
00120         ju = const_free[iu]; il <= iu;)
00121     {
00122       if(idx <= ju)
00123       {
00124         if(idx == ju)
00125           --idx;
00126         else
00127           const_num_max++; /* this is a correction for the subtraction later */
00128         if(iu == 0)
00129           break;
00130         --iu;
00131         ju = const_free[iu];
00132       }
00133       else
00134       {
00135         __v.push_back(std::make_pair(idx,jl));
00136         --idx;
00137         ++il;
00138         jl = const_free[il];
00139       }
00140     }
00141     const_num_max -= const_free.size();
00142     const_free.erase(const_free.begin(), const_free.end());
00143   }
00144   if(__v.size() != 0)
00145   {
00146     for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00147         __i != __v.end(); ++__i)
00148       const_names[(*__i).second] = const_names[(*__i).first];
00149     const_names.erase(const_names.begin(), const_names.begin()+number_of_constraints());
00150     for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00151         ++__b)
00152       (*__b)->renumber_constraints(__v);
00153   }
00154 }
00155 
00156 void model_gid::renumber_nodes(
00157         std::vector<std::pair<unsigned int,unsigned int> >& __v)
00158 {
00159   int i;
00160   std::map<unsigned int, unsigned int>::iterator __mf;
00161   for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00162       __i != __v.end(); ++__i)
00163   {
00164     i = (*__i).second;
00165     glob_ref[i] = glob_ref[(*__i).first];
00166     glob_ref[i]->node_num = i;
00167     __mf = const_back_ref.find((*__i).first);
00168     if(__mf != const_back_ref.end())
00169     {
00170       const_back_ref.insert(std::make_pair(i,(*__mf).second));
00171       const_back_ref.erase(__mf);
00172     }
00173   }
00174 }
00175 
00176 model::model(model_gid* __id, const erased_part& _ep, bool clone) :
00177                                        _Base(_ep), node_ref(), var_ref(),
00178                                        ghost_ref(), lin(), matd(), mati(),
00179                                        ocoeff(0), objective(ground()),
00180                                        constraints()
00181 {
00182   if(__id)
00183   {
00184     if(clone)
00185     {
00186       gid = new model_gid(*this, *__id);
00187       keep_gid = true;
00188     }
00189     else
00190     {
00191       gid = __id;
00192       keep_gid = false;
00193     }
00194   }
00195   else
00196   {
00197     std::cerr << "Erased parts with NULL gid are forbidden in model constructor!" <<  std::endl;
00198     throw "Programming error";
00199   } 
00200 
00201   std::vector<walker> __n(number_of_nodes(), ground());
00202   std::vector<walker> __v(number_of_variables(), ground());
00203   std::vector<unsigned int> __c(number_of_constraints(), 0);
00204   ref_iterator __x;
00205 
00206   fill_arrays(ground(), __n, __v, ghost_ref);
00207   for(__x = __n.begin(); __x != __n.end(); ++__x)
00208     if(*__x != ground())
00209     {
00210       node_ref.push_back(*__x);
00211       gid->mk_globref((*__x)->node_num, *__x);
00212     }
00213   for(__x = __v.begin(); __x != __v.end(); ++__x)
00214     if(*__x != ground())
00215     {
00216       var_ref.push_back(*__x);
00217       gid->mk_gvarref((*__x)->params.nn(), *__x);
00218     }
00219 
00220   objective = gid->empty_reference();
00221   ocoeff = 0;
00222 }
00223 
00224 void model::fill_arrays(walker __w, std::vector<walker>& __n,
00225                         std::vector<walker>& __v, std::vector<walker>& __g)
00226 {
00227   children_iterator __it, __e;
00228  
00229   if(__w.is_ground())
00230   {
00231     __e = __w.child_end();
00232     for(__it = __w.child_begin(); __it != __e; ++__it)
00233       fill_arrays(__w>>__it, __n, __v, __g);
00234   }
00235   else if(__w.is_sky())
00236     return;
00237   else
00238   {
00239     if(__n[__w->node_num] == ground())
00240     {
00241       if(__w->operator_type != EXPRINFO_GHOST)
00242         __n[__w->node_num] = __w;
00243       if(__w->operator_type == EXPRINFO_VARIABLE)
00244         __v[__w->params.nn()] = __w;
00245       else if(__w->operator_type == EXPRINFO_GHOST)
00246       {
00247         ref_iterator __x(lower_bound(__g.begin(), __g.end(), __w->node_num,
00248                          __docompare_nodes()));
00249         if(__x == __g.end() || *__x != __w)
00250           __g.insert(__x, __w);
00251       }
00252       __e = __w.child_end();
00253       for(__it = __w.child_begin(); __it != __e; ++__it)
00254         fill_arrays(__w>>__it, __n, __v, __g);
00255     }
00256   }
00257 }
00258 
00259 void model::copy_contents(model_gid* gid, const model& __m)
00260 {
00261   std::vector<walker> __n(__m.number_of_nodes(), ground());
00262   std::vector<walker> __v(__m.number_of_variables(), ground());
00263   std::vector<int> __c(__m.number_of_constraints(), -1);
00264   ref_iterator __x;
00265   unsigned int i;
00266 
00267   for(unsigned int i = 0; i < __m.number_of_constraints(); ++i)
00268   {
00269     walker gc(__m.constraint(i));
00270     if(!__m.gid->empty(gc))
00271       __c[i] = (int) gc->node_num;
00272   }
00273   ghost_ref.reserve(__m.ghost_ref.size());
00274   fill_arrays(ground(), __n, __v, ghost_ref);
00275   node_ref.reserve(__m.number_of_managed_nodes());
00276   var_ref.reserve(__m.number_of_managed_variables());
00277   for(__x = __n.begin(); __x != __n.end(); ++__x)
00278     if(*__x != ground())
00279     {
00280       node_ref.push_back(*__x);
00281       gid->mk_globref((*__x)->node_num, *__x);
00282     }
00283   for(__x = __v.begin(); __x != __v.end(); ++__x)
00284     if(*__x != ground())
00285     {
00286       var_ref.push_back(*__x);
00287       gid->mk_gvarref((*__x)->params.nn(), *__x);
00288     }
00289 
00290   constraints.reserve(__m.constraints.size());
00291   for(const_ref_iterator __b = __m.constraints.begin();
00292       __b != __m.constraints.end(); ++__b)
00293     constraints.push_back(gid->node((*__b)->node_num));
00294   for(i = 0; i < __c.size(); ++i)
00295     if(__c[i] != -1)
00296       gid->mk_gconstref(i, gid->node((unsigned int)__c[i]));
00297 
00298   if(__m.is_empty(__m.objective))
00299     objective = gid->empty_reference();
00300   else
00301     objective = gid->node(__m.objective->node_num);
00302 }
00303 
00304 model::model(const char* name, bool do_simplify) : _Base(), node_ref(),
00305                                 var_ref(), ghost_ref(), lin(), matd(), mati(),
00306                                 ocoeff(0), objective(ground()), constraints()
00307 {
00308 #if MODEL_INLINE_DEBUG
00309   std::cout << "model_constructor: 1" << std::endl;
00310 #endif
00311   std::ifstream inp(name);
00312 #if MODEL_INLINE_DEBUG
00313   std::cout << "model_constructor: 2" << std::endl;
00314 #endif
00315            
00316   if(!inp.is_open())
00317   {
00318     std::string str("Could not open file `");
00319     str += name;
00320     str += "': ";
00321     str += strerror(errno);
00322     throw (const char *)str.c_str();
00323   }
00324 #if MODEL_INLINE_DEBUG
00325   std::cout << "model_constructor: 6" << std::endl;
00326 #endif
00327   gid = new model_gid(*this);
00328   keep_gid = true;
00329 #if MODEL_INLINE_DEBUG
00330   std::cout << "model_constructor: 7" << std::endl;
00331 #endif
00332   read(inp);
00333 #if MODEL_INLINE_DEBUG
00334   std::cout << "model_constructor: 8" << std::endl;
00335 #endif
00336   if(do_simplify)
00337     basic_simplify();
00338   else
00339     set_counters();
00340 #if MODEL_INLINE_DEBUG
00341   std::cout << "model_constructor: 9" << std::endl;
00342 #endif
00343   prepare_after_read();
00344 #if MODEL_INLINE_DEBUG
00345   std::cout << "model_constructor: 10" << std::endl;
00346 #endif
00347 }
00348 
00349 #define throw_read(MSG) do { std::cerr << "Line " << ln << ": " << MSG;\
00350                              throw "Malformed Input!"; } while(0)
00351 #define MT_DBL    1
00352 #define MT_INTV   2
00353 #define MT_INT    3
00354 #define MT_STORED 8
00355 
00356 interval model::read_interval(char *& cq, int ln)
00357 {
00358   double lo, up;
00359 
00360   if(cq[0] != '[')
00361     throw_read("Interval specifier: no `['");
00362   else
00363   {
00364     char *cr;
00365     
00366     cq++;
00367     cr = strsep(&cq, ",");
00368     if(cq == NULL)
00369       throw_read("Interval specifier: no `,' inside interval");
00370     if(!strcmp(cr, "-I"))
00371       lo = -INFINITY;
00372     else if(!strcmp(cr, "I"))
00373       lo = INFINITY;
00374     else if(sscanf(cr, "%lf", &lo) != 1)
00375       throw_read("Interval specifier: not a wellformed interval lower bound");
00376     cr = strsep(&cq, "]");
00377     if(cq == NULL)
00378       throw_read("Interval specifier: missing closing `]'");
00379     if(!strcmp(cr, "-I"))
00380       up = -INFINITY;
00381     else if(!strcmp(cr, "I"))
00382       up = INFINITY;
00383     else if(sscanf(cr, "%lf", &up) != 1)
00384       throw_read("Interval specifier: not a wellformed interval upper bound");
00385     cr = strsep(&cq, ",");
00386   }
00387   return interval(lo,up);
00388 }
00389 
00390 void model::read(std::istream &i)
00391 {
00392   char buf[1000], *cp, *cq;
00393   double coef;
00394   int ln = 0, do_mng, found_mng, found_varidx, found_sem, _hlp;
00395   unsigned int nnum1, nnum2;
00396   std::vector<walker> nodes;
00397   std::vector<unsigned int> v_var_idx;
00398   std::map<unsigned int, std::pair<int,void *> > matrix_def;
00399   interval hi;
00400 
00401   objective = ground();
00402   ocoeff = 0;
00403   try
00404   {
00405     do
00406     {
00407       do_mng = 1;
00408       found_mng = 0;
00409       found_sem = 0;
00410       found_varidx = 0;
00411       hi.set(-INFINITY, INFINITY);
00412 
00413       i.getline(buf, 999);
00414       ln++;
00415       cp = buf;
00416 
00417       if(!strncmp(cp, "<N>", 3)) // read the global information
00418       { 
00419         char c[3] = "xx";
00420 
00421         cp += 3;
00422         cp += strspn(cp, " \t");
00423         switch(cp[0])
00424         {
00425           case 'c':
00426             {
00427               cp += strspn(cp+1, " \t")+1;
00428 
00429               if(sscanf(cp, "%u %u", &nnum1, &nnum2) != 2)
00430                 throw_read("Malformed Global Info: Constraint Number");
00431               if(nnum1 >= number_of_constraints())
00432                 gid->number_of_constraints(nnum1+1);
00433               gid->make_const_back_ref(nnum2, nnum1);
00434             }
00435             break;
00436           case 'C':
00437             {
00438               int stl;
00439               cp += strspn(cp+1, " \t")+1;
00440 
00441               char *__hlp = new char[strlen(cp)+1];
00442               if(sscanf(cp, "%u '%s", &nnum1, __hlp) != 2 ||
00443                  __hlp[stl = strlen(__hlp)-1] != '\'')
00444                 throw_read("Malformed Global Info: Constraint Name");
00445               __hlp[stl] = '\0';
00446               if(nnum1 >= number_of_constraints())
00447                 gid->number_of_constraints(nnum1+1);
00448               gid->const_name(nnum1, __hlp);
00449               delete [] __hlp;
00450             }
00451             break;
00452           case 'F':
00453             {
00454               int stl;
00455               cp += strspn(cp+1, " \t")+1;
00456 
00457               char *__hlp = new char[strlen(cp)+1];
00458               if(sscanf(cp, "'%s %lf", __hlp, &coef) != 2 ||
00459                  __hlp[stl = strlen(__hlp)-1] != '\'')
00460                 throw_read("Malformed Global Info: Variable Name");
00461               __hlp[stl] = '\0';
00462               gid->fixed_var(__hlp, coef);
00463               delete [] __hlp;
00464             }
00465             break;
00466           case 'M':
00467             cp += strspn(cp+1, " \t")+1;
00468             if(sscanf(cp, "%u m%c%c", &nnum1, c, c+1) != 3)
00469               throw_read("Malformed Global Info: Objective function");
00470             if(!strcmp("in", c))
00471               ocoeff = 1;
00472             else if(!strcmp("ax", c))
00473               ocoeff = -1;
00474             else if(!strcmp("00", c))
00475               ocoeff = 0;
00476             else
00477               throw_read("Malformed Global Info: Objective function is neither max nor min");
00478             if(ocoeff != 0)
00479               objective = nodes[nnum1];
00480             else
00481               objective = ground();
00482             break;
00483           case 'N':
00484             {
00485               int stl;
00486               cp += strspn(cp+1, " \t")+1;
00487 
00488               char *__hlp = new char[strlen(cp)+1];
00489               if(sscanf(cp, "%u '%s", &nnum1, __hlp) != 2 ||
00490                  __hlp[stl = strlen(__hlp)-1] != '\'')
00491                 throw_read("Malformed Global Info: Variable Name");
00492               __hlp[stl] = '\0';
00493               gid->var_name(nnum1, __hlp);
00494               delete [] __hlp;
00495             }
00496             break;
00497           case 'O':
00498             {
00499               int stl;
00500 
00501               cp += strspn(cp+1, " \t")+1;
00502               cq = strsep(&cp, ":");
00503               char *__hlp = new char[strlen(cq)+1];
00504 
00505               if(sscanf(cq, "'%s", __hlp) != 1 ||
00506                  __hlp[stl = strlen(__hlp)-1] != '\'')
00507                 throw_read("Malformed Global Info: Objective Info");
00508               else
00509               {
00510                 __hlp[stl] = '\0';
00511                 gid->obj_name(__hlp);
00512               }
00513               if(cp && *cp != '\0')
00514               {
00515                 cp += strspn(cp, " \t");
00516                 cq = strsep(&cp, ",");
00517 
00518                 if(sscanf(cq, "d %lf", &coef) != 1)
00519                   throw_read("Malformed Global Info: Objective Info");
00520                 else
00521                   gid->obj_adj(coef);
00522                 if(cp && *cp != '\0')
00523                 {
00524                   cp += strspn(cp, " \t");
00525                   if(sscanf(cp, "%lf", &coef) != 1)
00526                     throw_read("Malformed Global Info: Objective Info");
00527                   else
00528                     gid->obj_mult(coef);
00529                 }
00530               }
00531               delete [] __hlp;
00532             }
00533             break;
00534           case 'V':
00535             cp += strspn(cp+1, " \t")+1;
00536             if(sscanf(cp, "%u", &nnum1) != 1)
00537               throw_read("Malformed Global Info: Num of Vars");
00538             gid->number_of_variables(nnum1);
00539 #if MODEL_INLINE_DEBUG
00540             std::cout << "gid : number of variables = " <<
00541                          gid->number_of_variables() << std::endl;
00542 #endif
00543             break;
00544           case 'S':
00545             {
00546               int stl;
00547               cp += strspn(cp+1, " \t")+1;
00548               char *__hlp = new char[strlen(cp)+1];
00549               if(sscanf(cp, "'%s", __hlp) != 1 ||
00550                  __hlp[stl = strlen(__hlp)-1] != '\'')
00551                 throw_read("Malformed Global Info: Automatic Constraint");
00552               else
00553               {
00554                 __hlp[stl] = '\0';
00555                 gid->unused_constr(__hlp);
00556               }
00557               delete [] __hlp;
00558             }
00559             break;
00560           case 'U':
00561             {
00562               int stl;
00563               cp += strspn(cp+1, " \t")+1;
00564               char *__hlp = new char[strlen(cp)+1];
00565               if(sscanf(cp, "'%s", __hlp) != 1 ||
00566                  __hlp[stl = strlen(__hlp)-1] != '\'')
00567                 throw_read("Malformed Global Info: Unused Variable");
00568               else
00569               {
00570                 __hlp[stl] = '\0';
00571                 gid->unused_var(__hlp);
00572               }
00573               delete [] __hlp;
00574             }
00575             break;
00576           default: 
00577             throw_read("Malformed Global Info: Wrong type");
00578             break;
00579         }
00580       }
00581       else if(!strncmp(cp, "<M>", 3)) // read a matrix definition
00582       {
00583         bool is_for_lin = false;
00584         unsigned int mat_num = 0;
00585         char dens, shape;
00586         
00587         cp+=3;
00588         cp+=strspn(cp, " \t");
00589         if(sscanf(cp, "L %u %u", &nnum1, &nnum2) == 2)
00590         {
00591           is_for_lin = true;
00592           dens = 'D';
00593           shape = 'R';
00594         }
00595         else if(sscanf(cp, "%u %c %c %u %u", &mat_num, &dens, &shape, &nnum1,
00596                                         &nnum2) != 5)
00597           throw_read("Malformed Matrix Definition");
00598         if(dens != 'D' && dens != 'I' && dens != 'N')
00599           throw_read("Malformed Matrix Definition: must be double, interval, or integer");
00600         if(shape != 'R' && shape != 'S' && shape != 'T')
00601           throw_read("Malformed Matrix Definition: must be rectangular, symmetric, or triangular");
00602         if(shape == 'S' || shape == 'T')
00603           throw_read("Matrix shapes not yet implemented!");
00604         if(is_for_lin)
00605           lin = matrix<double>(nnum1,nnum2);
00606         else
00607         {
00608           void *matrix_storage;
00609           int matrix_type;
00610 
00611           matrix_type = (dens == 'D' ? MT_DBL :
00612                                         (dens == 'I' ? MT_INTV : MT_INT));
00613           switch(dens)
00614           {
00615             case 'D':
00616               matrix_storage = (void *) new matrix<double>(nnum1,nnum2);
00617               break;
00618             case 'I':
00619               matrix_storage = (void *) new matrix<interval>(nnum1,nnum2);
00620               break;
00621             case 'N':
00622               matrix_storage = (void *) new matrix<int>(nnum1,nnum2);
00623               break;
00624           }
00625           matrix_def.insert(std::make_pair(mat_num, 
00626                                 std::make_pair(matrix_type, matrix_storage)));
00627         }
00628       }
00629       else if(!strncasecmp(cp, "<R>", 3)) // read a matrix row
00630       {
00631         unsigned int mat_num = 0;
00632         bool dense = (cp[1] == 'R');
00633         std::vector<unsigned int> s_idx;
00634         unsigned int dim_r, dim_c;
00635         unsigned int idx, ridx;
00636         int matrix_type;
00637         void *matrix_storage;
00638 
00639         cp+=3+strspn(cp+3, " \t");
00640         cq = strchr(cp, ':');
00641         if(!cq)
00642           throw_read("Malformed Matrix Row Definition");
00643         *cq++ = '\0';
00644         if(cp[0] == 'L' && isspace(cp[1]))
00645         {
00646           cp += 1+strspn(cp+1, " \t");
00647           if(sscanf(cp, "%u", &nnum1) != 1)
00648             throw_read("Malformed Matrix Row Definition: row number?");
00649           dim_r = lin.nrows();
00650           dim_c = lin.ncols();
00651           matrix_storage = (void *)(&lin);
00652           matrix_type = MT_DBL;
00653         }
00654         else if(sscanf(cp, "%u %u", &mat_num, &nnum1) == 2)
00655         {
00656           std::pair<int,void*> x;
00657           std::map<unsigned int,std::pair<int,void*> >::iterator _x;
00658 
00659           _x = matrix_def.find(mat_num);
00660           if(_x == matrix_def.end())
00661             throw_read("Malformed Matrix Row Definition: matrix not yet defined!");
00662           x = (*_x).second;
00663           matrix_type = x.first;
00664           matrix_storage = x.second;
00665           if(matrix_type & MT_STORED)
00666             throw_read("Malplaced Matrix Row Definition: matrix has been used!");
00667           switch(matrix_type)
00668           {
00669             case MT_DBL:
00670               dim_r = ((matrix<double>*)matrix_storage)->nrows();
00671               dim_c = ((matrix<double>*)matrix_storage)->ncols();
00672               break;
00673             case MT_INTV:
00674               dim_r = ((matrix<interval>*)matrix_storage)->nrows();
00675               dim_c = ((matrix<interval>*)matrix_storage)->ncols();
00676               break;
00677             case MT_INT:
00678               dim_r = ((matrix<int>*)matrix_storage)->nrows();
00679               dim_c = ((matrix<int>*)matrix_storage)->ncols();
00680               break;
00681           }
00682         }
00683         else
00684           throw_read("Malformed Matrix Row Definition: matrix & row number?");
00685         if(nnum1 >= dim_r)
00686           throw_read("Malformed Matrix Row Definition: row number out of range!");
00687         cp = cq;
00688         if(!dense)
00689         {
00690           cp = strchr(cp, ':');
00691           if(!cp)
00692             throw_read("Malformed Matrix Row Definition: sparse needs two vectors");
00693           *cp++ = '\0';
00694           cq += strspn(cq, " \t");
00695           for(; cq; )
00696           {
00697             char *ct;
00698 
00699             ct = strsep(&cq, ",");
00700             ct += strspn(ct, " \t");
00701             if(sscanf(ct, "%u", &nnum2) != 1)
00702               throw_read("Malformed Matrix Row Definition: index vector definition");
00703             if(nnum2 >= dim_c)
00704               throw_read("Malformed Matrix Row Definition: column number out of range!");
00705             s_idx.push_back(nnum2);
00706           }
00707         }
00708         cp += strspn(cp, " \t");
00709         idx = 0;
00710         for(; cp; )
00711         {
00712           char *ct;
00713 
00714           if(dense)
00715           {
00716             if(idx >= dim_c)
00717               throw_read("Malformed Matrix Row Definition: value vector too long!");
00718             ridx = idx;
00719           }
00720           else
00721           {
00722             if(idx >= s_idx.size())
00723               throw_read("Malformed Matrix Row Definition: value vector longer than index vector!");
00724             ridx = s_idx[idx];
00725           }
00726           ct = strsep(&cp, ",");
00727           ct += strspn(ct, " \t");
00728           switch(matrix_type)
00729           {
00730             case MT_DBL:
00731               if(sscanf(ct, "%lf", &coef) != 1)
00732                 throw_read("Malformed Matrix Row Definition: value vector definition - no integer!");
00733               (*(matrix<double>*)matrix_storage)(nnum1,ridx) = coef;
00734               break;
00735             case MT_INTV:
00736               hi = read_interval(ct, ln);
00737               (*(matrix<interval>*)matrix_storage)(nnum1,ridx) = hi;
00738               break;
00739             case MT_INT:
00740               if(sscanf(ct, "%u", &nnum2) != 1)
00741                 throw_read("Malformed Matrix Row Definition: value vector definition - no integer!");
00742               (*(matrix<int>*)matrix_storage)(nnum1,ridx) = nnum2;
00743               break;
00744           }
00745           idx++;
00746         }
00747         if(dense && idx < dim_c)
00748           throw_read("Malformed Matrix Row Definition: value vector too short!");
00749         else if(!dense && idx < s_idx.size())
00750           throw_read("Malformed Matrix Row Definition: value vector shorter than index vector!");
00751       }
00752       else if(!strncmp(cp, "<H>", 3)) // read helper information
00753       {
00754         std::cerr << "Helper information is not yet implemented!" << std::endl;
00755         throw "NYI";
00756       }
00757       else if((_hlp = sscanf(cp, "<E> %u %u %lf", &nnum1, &nnum2, &coef)) == 3
00758               || _hlp == 2) // read an edge
00759       {
00760         add_edge_back(nodes[nnum1], nodes[nnum2]);
00761         remove_edge(nodes[nnum1], sky());
00762         remove_edge(ground(), nodes[nnum2]);
00763         nodes[nnum1]->coeffs.push_back(_hlp == 2 ? 1.0 : coef);
00764       }
00765       else if(sscanf(cp, "<%u>", &nnum1) == 1) // read a node definition
00766       {
00767 #if MODEL_INLINE_DEBUG
00768         std::cout << "Read a node : nnum = " << nnum1 << std::endl;
00769 #endif
00770         additional_info_u mng(0.0);
00771         semantics _sem;
00772         char _h;
00773 
00774         if(nnum1 >= nodes.size())
00775           nodes.insert(nodes.end(), nnum1-nodes.size()+1, ground());
00776         for(cp = strchr(cp, '>')+1; cp; )
00777         {
00778           cq = strsep(&cp, ":");
00779           cq += strspn(cq, " \t");
00780           if(cq[1] != ' ')
00781             _h = ' ';
00782           else
00783             _h = cq[0];
00784           switch(_h)
00785           {
00786             case 'V':
00787               if(sscanf(cq, "V %u", &nnum2) != 1)
00788                 throw_read("Variable definition");
00789               else
00790               {
00791                 if(nnum2 >= gid->number_of_variables())
00792                   new_variables(nnum2+1);
00793                 
00794                 expression_node _en(EXPRINFO_VARIABLE, nnum1);
00795 
00796                 _en.v_i.reserve(gid->number_of_variables());
00797                 _en.v_i.set(nnum2);
00798                 _en.params = (int)nnum2;
00799                 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
00800 
00801                 gid->mk_gvarref(nnum2, nodes[nnum1]);
00802                 do_mng = 0;
00803               }
00804               break;
00805             case 'C':
00806               if(sscanf(cq, "C %lf", &coef) != 1)
00807                 throw_read("Constant definition");
00808               else
00809               {
00810                 expression_node _en(EXPRINFO_CONSTANT, nnum1);
00811                 _en.v_i.reserve(gid->number_of_variables());
00812                 _en.v_i.clear();
00813                 _en.params = coef;
00814 
00815                 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
00816                 do_mng = 0;
00817               }
00818               break;
00819             case 'G':
00820               if(sscanf(cq, "G %c", &_h) != 1 || (_h != 'T' && _h != 'F'))
00821                 throw_read("Ghost definition");
00822               else
00823               {
00824                 expression_node _en(EXPRINFO_GHOST, nnum1);
00825                 _en.v_i.reserve(gid->number_of_variables());
00826                 _en.v_i.clear();
00827                 _en.params = (_h == 'T' ? true : false);
00828                 _en.f_bounds = interval(-INFINITY,INFINITY);
00829 
00830                 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
00831                 do_mng = 0;
00832               }
00833               break;
00834             case 'l':
00835               {
00836                 std::vector<bool> hd;
00837                 char _l;
00838 
00839                 cq += strspn(cq+1, " \t")+1;
00840                 for(; cq; )
00841                 {
00842                   char *ct;
00843 
00844                   ct = strsep(&cq, ",");
00845                   ct += strspn(ct, " \t");
00846                   if(sscanf(ct, "%c", &_l) != 1 || (_l != 'T' && _l != 'F'))
00847                     throw_read("Boolean additional definition");
00848                   hd.push_back(_l == 'T' ? true : false);
00849                 }
00850                 if(hd.size() == 1)
00851                   mng = hd[0];
00852                 else
00853                   mng = hd;
00854                 found_mng = 1;
00855               }
00856               break;
00857             case 'S':
00858               {
00859                 char *ct;
00860 
00861                 cq += strspn(cq+1, " \t")+1;
00862                 if(cq[0] != '\"')
00863                   throw_read("String additional definition");
00864                 ct = cq+1;
00865                 while(1)
00866                 {
00867                   ct = strchr(ct, '\"');
00868                   if(ct == NULL)
00869                     throw_read("String additional definition");
00870                   if(*(ct-1) != '\\')
00871                     break;
00872                   ct += 1;
00873                 }
00874                 
00875                 *ct = '\0';
00876                 mng = cq;
00877                 cq = ct+1;
00878                 found_mng = 1;
00879               }
00880               break;
00881             case 'd':
00882               {
00883                 std::vector<double> hd;
00884 
00885                 cq += strspn(cq+1, " \t")+1;
00886                 for(; cq; )
00887                 {
00888                   char *ct;
00889 
00890                   ct = strsep(&cq, ",");
00891                   ct += strspn(ct, " \t");
00892                   if(sscanf(ct, "%lf", &coef) != 1)
00893                     throw_read("Double additional definition");
00894                   hd.push_back(coef);
00895                 }
00896                 if(hd.size() == 1)
00897                   mng = hd[0];
00898                 else
00899                   mng = hd;
00900                 found_mng = 1;
00901               }
00902               break;
00903             case 'n':
00904               {
00905                 std::vector<int> hd;
00906                 int ihlp;
00907 
00908                 cq += strspn(cq+1, " \t")+1;
00909                 for(; cq; )
00910                 {
00911                   char *ct;
00912 
00913                   ct = strsep(&cq, ",");
00914                   ct += strspn(ct, " \t");
00915                   if(sscanf(ct, "%d", &ihlp) != 1)
00916                     throw_read("Integer additional definition");
00917                   hd.push_back(ihlp);
00918                 }
00919                 if(hd.size() == 1)
00920                   mng = hd[0];
00921                 else
00922                   mng = hd;
00923                 found_mng = 1;
00924               }
00925               break;
00926             case 'i':
00927               {
00928                 std::vector<interval> hd;
00929 
00930                 cq += strspn(cq+1, " \t")+1;
00931                 for(; cq; )
00932                 {
00933                   cq += strspn(cq, " \t");
00934                   hd.push_back(read_interval(cq, ln));
00935                 }
00936                 if(hd.size() == 1)
00937                   mng = hd[0];
00938                 else
00939                   mng = hd;
00940                 found_mng = 1;
00941               }
00942               break;
00943             case 'm':
00944               if(sscanf(cq, "m %u", &nnum2) != 1)
00945                 throw_read("Matrix reference");
00946               else
00947               {
00948                 do_mng = 2;
00949                 found_mng = nnum2+2;
00950               }
00951               break;
00952             case 'v':
00953               {
00954                 std::vector<unsigned int> hd;
00955                 int ihlp;
00956 
00957                 cq += strspn(cq+1, " \t")+1;
00958                 for(; cq; )
00959                 {
00960                   char *ct;
00961 
00962                   ct = strsep(&cq, ",");
00963                   ct += strspn(ct, " \t");
00964                   if(sscanf(ct, "%d", &ihlp) != 1)
00965                     throw_read("Var index additional definition");
00966                   hd.push_back(ihlp);
00967                 }
00968                 found_varidx = 1;
00969                 v_var_idx = hd;
00970               }
00971               break;
00972             case 'b':
00973               cq += strspn(cq+1, " \t")+1;
00974               hi = read_interval(cq, ln);
00975               break;
00976             case 's':
00977               cq += strspn(cq+1, " \t")+1;
00978               _sem.read(cq);
00979               found_sem = 1;
00980               break;
00981             default:
00982               for(nnum2 = 0; expr_names[nnum2]; nnum2++)
00983                 if(!strcmp(expr_names[nnum2], cq))
00984                   break;
00985               if(expr_names[nnum2] == NULL)
00986                  throw_read("Unknown operator");
00987               else
00988               {
00989                 expression_node _en(-nnum2, nnum1);
00990                 
00991                 _en.v_i.reserve(gid->number_of_variables());
00992                 _en.v_i.clear();
00993 #if MODEL_INLINE_DEBUG
00994                 std::cout << "Expression node number = " << _en.node_num <<
00995                              std::endl;
00996 #endif
00997                 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
00998 #if MODEL_INLINE_DEBUG
00999                 std::cout << "Sky node number = " << sky()->node_num <<
01000                              std::endl;
01001 #endif
01002               }
01003               break;
01004           }
01005         }
01006         if(!found_mng && (nodes[nnum1]->operator_type == EXPRINFO_PROD ||
01007            nodes[nnum1]->operator_type == EXPRINFO_INVERT))
01008         {
01009           mng = 1.;
01010           do_mng = 1;
01011         }
01012         if(do_mng == 2)
01013         {
01014           int matrix_type;
01015           void* matrix_storage;
01016           std::map<unsigned int,std::pair<int,void*> >::iterator __x;
01017           std::pair<int,void*> x;
01018 
01019           nnum2 = found_mng-2;
01020           __x = matrix_def.find(nnum2);
01021           if(__x == matrix_def.end())
01022             throw_read("Matrix reference is referencing undefined matrix");
01023           x = (*__x).second;
01024           matrix_type = x.first;
01025           matrix_storage = x.second;
01026           switch(matrix_type & ~MT_STORED)
01027           {
01028             case MT_DBL:
01029               if(matrix_type & MT_STORED)
01030                 nodes[nnum1]->params = *(matrix<double>*)matrix_storage;
01031               else
01032                 nodes[nnum1]->params.set_m((matrix<double>*)
01033                                                 matrix_storage);
01034               break;
01035             case MT_INTV:
01036               if(matrix_type & MT_STORED)
01037                 nodes[nnum1]->params = *(matrix<interval>*)matrix_storage;
01038               else
01039                 nodes[nnum1]->params.set_im((matrix<interval>*)
01040                                                 matrix_storage);
01041               break;
01042             case MT_INT:
01043               if(matrix_type & MT_STORED)
01044                 nodes[nnum1]->params = *(matrix<int>*)matrix_storage;
01045               else
01046                 nodes[nnum1]->params.set_nm((matrix<int>*)matrix_storage);
01047               break;
01048           }
01049           if(!(matrix_type & MT_STORED))
01050           {
01051             matrix_type |= MT_STORED;
01052             matrix_def.erase(__x);
01053             matrix_def.insert(std::make_pair(nnum2, std::make_pair(matrix_type,
01054                     matrix_storage)));
01055           }
01056         }
01057         else if(do_mng)
01058           nodes[nnum1]->params = mng;
01059         if(found_sem)
01060           nodes[nnum1]->sem = _sem;
01061         nodes[nnum1]->set_bounds(hi);
01062         nodes[nnum1]->n_parents = 1;
01063         if(found_varidx)
01064         {
01065           nodes[nnum1]->is_var = v_var_idx.size();
01066           nodes[nnum1]->var_idx = v_var_idx;
01067         }
01068       }
01069       else if(buf[0] != '\0')
01070         throw_read("Unknown input");
01071     } while(buf[0] != '\0');
01072   }
01073   catch(const char *str)
01074   {
01075     std::cerr << "Error: malformed input on line " << ln << ": " << str << "!" <<
01076          std::endl;
01077     std::terminate();
01078   }
01079   clr_sky_ground_link();
01080   for(std::map<unsigned int,std::pair<int,void*> >::iterator __x = matrix_def.begin();
01081       __x != matrix_def.end(); ++__x)
01082   {
01083     std::pair<int,void*> x;
01084     x = (*__x).second;
01085     if(!(x.first & MT_STORED))
01086     {
01087       switch(x.first)
01088       {
01089         case MT_DBL:
01090           delete (matrix<double>*) x.second;
01091           break;
01092         case MT_INTV:
01093           delete (matrix<interval>*) x.second;
01094           break;
01095         case MT_INT:
01096           delete (matrix<int>*) x.second;
01097           break;
01098       }
01099     }
01100   }
01101   for(int i = node_ref.size()-1; i >= 0; --i)
01102   {
01103     if(node_ref[i] == ground())
01104     {
01105       std::cerr << "Undefined node in node_ref!" << std::endl;
01106       throw "Programming error";
01107     }
01108     else
01109     {
01110       walker __w = node_ref[i] << node_ref[i].parent_begin();
01111       if(__w == ground())
01112         node_ref[i]->n_parents = 0;
01113     }
01114   }
01115 #if MODEL_INLINE_DEBUG
01116   std::cout << "BrYcE : " << sky()->node_num << std::endl;
01117 #endif
01118 }
01119 
01120 bool model::simplify_visitor_0::postorder(expression_node &r)
01121 {
01122   postorder_help(r, n-ndel);
01123   // now adapt semantics
01124   if(r.sem.convexity().t() == 0)
01125     r.sem.convexity(s.convexity());
01126   r.sem.separability(s.separability());
01127   r.sem.degree = s.degree;
01128   r.sem.dim = s.dim;
01129 
01130   r.v_i = v_i;
01131   if(r_idx != -1)
01132   {
01133     int ne_del = n-ndel-r_idx-1;
01134     r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01135                    r.coeffs.end());
01136     ndel += ne_del;
01137     r_idx = -1;
01138   }
01139   if(r.operator_type == EXPRINFO_CONSTANT ||
01140      r.operator_type == EXPRINFO_VARIABLE ||
01141      r.operator_type == EXPRINFO_GHOST)
01142     r.n_children = 0;
01143   else
01144     r.n_children = n - ndel;
01145   return false;
01146 }
01147   
01148 void model::simplify_visitor_0::vcollect(const simplify_visitor_0& __s)
01149 {
01150   if((__s.flags & SIMPLIFY_0_IS_CONST)) // this is not a real constraint
01151   {
01152     double help = __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01153                                                            __s.m.nd();
01154     walker _n = __mod->node(__s.nnum);
01155     if(!_n->f_bounds.is_entire()) // this is not a pure objective
01156     {
01157       if(_n->f_bounds.contains(help)) // this constraint is always fulfilled
01158         (*delnodes).push_back(__s.nnum);
01159     }
01160     if(_n == __mod->objective) // the objective is constant
01161     {
01162       __mod->ocoeff = 0;
01163       __mod->gid->obj_adj(__mod->gid->obj_adj()+help);
01164       if(_n->operator_type == EXPRINFO_CONSTANT) // objective is really a const.
01165         _n->params = 0.;
01166     }
01167   }
01168   if((__s.flags & SIMPLIFY_0_IS_SUM &&
01169       __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE) ||
01170      (__s.flags & SIMPLIFY_0_IS_PROD &&
01171       __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE))
01172   { // there is a l*<node>+m or l*<node> expression on top -> remove
01173     walker _n = __mod->node(__s.nnum);
01174     walker _c;
01175     std::vector<unsigned int>::const_iterator _b, _e((*delnodes).end());
01176 
01177     // find the only non-deleted child
01178     for(children_iterator _ci = _n.child_begin(); _ci != _n.child_end(); ++_ci)
01179     {
01180       _c = _n >> _ci;
01181       unsigned int _cnn = _c->node_num;
01182       for(_b = (*delnodes).begin(); _b != _e; ++_b)
01183         if((*_b) == _cnn)
01184           break;
01185       if(_b == _e) // this is it
01186         break;
01187     }
01188     
01189     if(!_n->f_bounds.is_entire())
01190     {
01191       if(__s.flags & SIMPLIFY_0_IS_SUM)
01192       {
01193         _n->f_bounds -= __s.m.nd();
01194         _n->f_bounds /= (*__s.transfer)[0];
01195       }
01196       else
01197         _n->f_bounds /= __s.m.nd();
01198       _c->f_bounds.intersect(_n->f_bounds);
01199     }
01200     if(_n == __mod->objective)
01201     {
01202       double a = __mod->gid->obj_adj(),
01203              m = __mod->gid->obj_mult();
01204       if(__s.flags & SIMPLIFY_0_IS_SUM)
01205       {
01206         a += m * __s.m.nd();
01207         m *= (*__s.transfer)[0];
01208       }
01209       else
01210         m *= __s.m.nd();
01211       __mod->gid->obj_adj(a);
01212       if(m < 0)
01213       {
01214         __mod->ocoeff = -__mod->ocoeff;
01215         __mod->gid->obj_adj(-__mod->obj_adj());
01216         m = -m;
01217       }
01218       __mod->gid->obj_mult(m);
01219     }
01220     (*delnodes).push_back(__s.nnum);
01221   }
01222   if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01223   // we can transfer a factor
01224   {
01225     walker _n = __mod->node(__s.nnum);
01226     double help = __s.m.nd();
01227     _n->f_bounds /= help;
01228     if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01229       _n->params = 1.;
01230     if(_n == __mod->objective)
01231     {
01232       if(help < 0)
01233       {
01234         __mod->ocoeff = -__mod->ocoeff;
01235         __mod->gid->obj_adj(-__mod->obj_adj());
01236         help = -help;
01237       }
01238       help *= __mod->gid->obj_mult();
01239       __mod->gid->obj_mult(help);
01240     }
01241   }
01242 }
01243 
01244 void model::simplify_visitor_0::collect(expression_node &r,
01245     const simplify_visitor_0& __s)
01246 {
01247   nnum = r.node_num;
01248   if(r.operator_type < 0)
01249   {
01250     switch(r.operator_type)
01251     {
01252       case EXPRINFO_CONSTANT:
01253       case EXPRINFO_VARIABLE:
01254       case EXPRINFO_GHOST:
01255         // constants, variables, and ghosts have no children
01256         break;
01257       case EXPRINFO_SUM:
01258         if(n == 0)
01259         {
01260           s.degree = __s.s.degree;
01261           s.property_flags = __s.s.property_flags;
01262           if(r.coeffs[0] < 0)
01263             s.property_flags.c_info == -s.property_flags.c_info;
01264           if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01265              is_integer(r.params.nd()))
01266             s.annotation_flags.integer = true;
01267           r_idx = -1;
01268         }
01269         else
01270         { 
01271           if(s.degree == -1 || __s.s.degree == -1)
01272             s.degree = -1;
01273           else if(__s.s.degree > s.degree)
01274             s.degree = __s.s.degree;
01275           s.property_flags.c_info = convex_e();
01276           if(s.property_flags.separable != t_true ||
01277              __s.s.property_flags.separable != t_true)
01278             s.property_flags.separable = t_maybe;
01279           if(s.annotation_flags.integer && 
01280              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01281             s.annotation_flags.integer = false;
01282           if(l_nnum == __s.nnum)
01283           {
01284             if(r_idx == -1)
01285               r_idx = n-ndel-1;
01286             r.coeffs[r_idx] += r.coeffs[n-ndel];
01287             (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01288           }
01289           else if(r_idx != -1)
01290           {
01291             int ne_del = n-ndel-r_idx-1;
01292             r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01293                            r.coeffs.begin()+n-ndel);
01294             ndel += ne_del;
01295             r_idx = -1;
01296           }
01297         }
01298         if(__s.flags & SIMPLIFY_0_IS_CONST)
01299         { 
01300           double help =
01301               __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01302                                                            __s.m.nd();
01303           r.params = r.params.nd() + r.coeffs[n-ndel] * help;
01304           r.coeffs.erase(r.coeffs.begin() + n);
01305           (*delnodes).push_back(__s.nnum);
01306           ndel++;
01307         }
01308         else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01309                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01310         {
01311           r.coeffs[n-ndel] *= __s.m.nd();
01312           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01313             transfer_ghost_down(__s.nnum, r.node_num);
01314           else
01315             (*delnodes).push_back(__s.nnum);
01316         }
01317         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01318         {
01319           r.coeffs[n-ndel] *= __s.m.nd();
01320           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01321             __mod->node(__s.nnum)->params = 1.;
01322         }
01323         else if(__s.flags & SIMPLIFY_0_IS_SUM) 
01324         {
01325           double help = r.coeffs[n-ndel];
01326 
01327           r.params = r.params.nd() + __s.m.nd();
01328           r.coeffs.erase(r.coeffs.begin()+(n-ndel));
01329           ndel++;
01330           for(std::vector<double>::const_iterator b = __s.transfer->begin();
01331               b != __s.transfer->end(); ++b)
01332             r.coeffs.push_back(*b * help);
01333           n += __s.transfer->size();
01334           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01335             transfer_ghost_down(__s.nnum, r.node_num);
01336           else
01337             (*delnodes).push_back(__s.nnum);
01338         }
01339         break;
01340       case EXPRINFO_MEAN:
01341         if(n == 0)
01342         {
01343           s.degree = __s.s.degree;
01344           s.property_flags = __s.s.property_flags;
01345           if(r.coeffs[0] < 0)
01346           {
01347             r.operator_type = EXPRINFO_SUM;
01348             s.property_flags.c_info == -s.property_flags.c_info;
01349           }
01350           r_idx = -1;
01351         }
01352         else
01353         { 
01354           if(s.degree == -1 || __s.s.degree == -1)
01355             s.degree = -1;
01356           else if(__s.s.degree > s.degree)
01357             s.degree = __s.s.degree;
01358           s.property_flags.c_info = convex_e();
01359           if(s.property_flags.separable != t_true ||
01360              __s.s.property_flags.separable != t_true)
01361             s.property_flags.separable = t_maybe;
01362           if(l_nnum == __s.nnum)
01363           {
01364             if(r_idx == -1)
01365               r_idx = n-ndel-1;
01366             r.coeffs[r_idx] += r.coeffs[n-ndel];
01367             (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01368           }
01369           else if(r_idx != -1)
01370           {
01371             int ne_del = n-ndel-r_idx-1;
01372             r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01373                            r.coeffs.begin()+n-ndel);
01374             ndel += ne_del;
01375             r_idx = -1;
01376           }
01377         }
01378         if(__s.flags & SIMPLIFY_0_IS_CONST)
01379         { 
01380           double help =
01381               __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01382                                                            __s.m.nd();
01383           r.operator_type = EXPRINFO_SUM;
01384           r.params = r.params.nd() + r.coeffs[n-ndel] * help;
01385           r.coeffs.erase(r.coeffs.begin() + n);
01386           (*delnodes).push_back(__s.nnum);
01387           ndel++;
01388         }
01389         else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01390                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01391         {
01392           r.operator_type = EXPRINFO_SUM;
01393           r.coeffs[n-ndel] *= __s.m.nd();
01394           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01395             transfer_ghost_down(__s.nnum, r.node_num);
01396           else
01397             (*delnodes).push_back(__s.nnum);
01398         }
01399         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01400         {
01401           r.operator_type = EXPRINFO_SUM;
01402           r.coeffs[n-ndel] *= __s.m.nd();
01403           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01404             __mod->node(__s.nnum)->params = 1.;
01405         }
01406         else if(__s.flags & SIMPLIFY_0_IS_SUM) 
01407         {
01408           double help = r.coeffs[n-ndel];
01409 
01410           r.operator_type = EXPRINFO_SUM;
01411           r.params = r.params.nd() + __s.m.nd();
01412           r.coeffs.erase(r.coeffs.begin()+(n-ndel));
01413           ndel++;
01414           for(std::vector<double>::const_iterator b = __s.transfer->begin();
01415               b != __s.transfer->end(); ++b)
01416             r.coeffs.push_back(*b * help);
01417           n += __s.transfer->size();
01418           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01419             transfer_ghost_down(__s.nnum, r.node_num);
01420           else
01421             (*delnodes).push_back(__s.nnum);
01422         }
01423         break;
01424       case EXPRINFO_PROD:
01425         if(n == 0)
01426         {
01427           s.degree = __s.s.degree;
01428           s.property_flags = __s.s.property_flags;
01429           m = 1.;
01430           if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01431              is_integer(r.params.nd()))
01432             s.annotation_flags.integer = true;
01433         }
01434         else
01435         { 
01436           if(__s.s.degree == -1 || s.degree == -1)
01437             s.degree = -1;
01438           else
01439             s.degree += __s.s.degree;
01440           s.property_flags.c_info = convex_e();
01441           s.property_flags.separable = t_maybe;
01442           if(s.annotation_flags.integer && 
01443              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01444             s.annotation_flags.integer = false;
01445         }
01446         if(r.coeffs[n] != 1)
01447         {
01448           r.params = r.params.nd() * r.coeffs[n];
01449           r.coeffs[n] = 1;
01450         }
01451         if(__s.flags & SIMPLIFY_0_IS_CONST)
01452         { 
01453           double help =
01454               __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01455                                                            __s.m.nd();
01456           r.params = r.params.nd() * help;
01457           r.coeffs.pop_back();
01458           (*delnodes).push_back(__s.nnum);
01459           ndel++;
01460         }
01461         else if(__s.flags & SIMPLIFY_0_IS_PROD)
01462         {
01463           r.params = r.params.nd() * __s.m.nd();
01464           r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
01465           n += __s.transfer->size()-1;
01466           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01467             transfer_ghost_down(__s.nnum, r.node_num);
01468           else
01469             (*delnodes).push_back(__s.nnum);
01470         }
01471         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01472         {
01473           r.params = r.params.nd() * __s.m.nd();
01474           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01475             __mod->node(__s.nnum)->params = 1.;
01476         }
01477         if(r.params.nd() != 1)
01478         {
01479           flags |= SIMPLIFY_0_IS_MULTIPLICATIVE;
01480         }
01481         break;
01482       case EXPRINFO_MONOME:
01483         if(n == 0)
01484         {
01485           s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.n()[0];
01486           s.property_flags = __s.s.property_flags;
01487           s.property_flags.c_info = convex_e();
01488           m = 1.;
01489           if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
01490             s.annotation_flags.integer = true;
01491         }
01492         else
01493         { 
01494           if(__s.s.degree == -1 || s.degree == -1)
01495             s.degree = -1;
01496           else
01497             s.degree += __s.s.degree*r.params.n()[n];
01498           s.property_flags.c_info = convex_e();
01499           s.property_flags.separable = t_maybe;
01500           if(s.annotation_flags.integer && 
01501              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01502             s.annotation_flags.integer = false;
01503         }
01504         if(__s.flags & SIMPLIFY_0_IS_CONST)
01505         { 
01506           double help =
01507               __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01508                                                            __s.m.nd();
01509           m = m.nd() * pow(help, r.params.n()[n]);
01510           r.coeffs.pop_back();
01511           (*delnodes).push_back(__s.nnum);
01512           ndel++;
01513         }
01514         else if(__s.flags & SIMPLIFY_0_IS_PROD)
01515         {
01516           m = m.nd()*pow(__s.m.nd(),r.params.n()[n]);
01517           r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
01518           r.params.n().insert(r.params.n().begin()+n, __s.transfer->size()-1,
01519               r.params.n()[n]);
01520           n += __s.transfer->size()-1;
01521           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01522             transfer_ghost_down(__s.nnum, r.node_num);
01523           else
01524             (*delnodes).push_back(__s.nnum);
01525         }
01526         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01527         {
01528           m = m.nd() * pow(__s.m.nd(),r.params.n()[n]);
01529           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01530             __mod->node(__s.nnum)->params = 1.;
01531         }
01532         if(m.nd() != 1)
01533         {
01534           flags |= (SIMPLIFY_0_IS_MULTIPLICATIVE | SIMPLIFY_0_IS_CORRECTEDMULT);
01535         }
01536         break;
01537       case EXPRINFO_MAX:
01538       case EXPRINFO_MIN:
01539         if(n == 0)
01540         {
01541           if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01542              is_integer(r.params.nd()))
01543             s.annotation_flags.integer = true;
01544         }
01545         else if(s.annotation_flags.integer && 
01546              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01547           s.annotation_flags.integer = false;
01548         if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01549         {
01550           r.coeffs[n] *= __s.m.nd();
01551           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01552             __mod->node(__s.nnum)->params = 1.;
01553         }
01554         break;
01555       case EXPRINFO_SCPROD:
01556         if(n == 0)
01557         {
01558           s.property_flags.c_info = convex_e();
01559           if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
01560             s.annotation_flags.integer = true;
01561         }
01562         else if(n & 1) // n odd
01563         { 
01564           r.coeffs[n-1] *= r.coeffs[n];
01565           r.coeffs[n] = 1.;
01566           if(s.degree == -1 || __s.s.degree == -1 || l_s.degree == -1)
01567             s.degree = -1;
01568           else if(__s.s.degree+l_s.degree > s.degree)
01569             s.degree = __s.s.degree+l_s.degree;
01570           s.property_flags.separable = t_maybe;
01571           if(s.annotation_flags.integer &&
01572              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n-1])))
01573             s.annotation_flags.integer = false;
01574         }
01575         else
01576         {
01577           if(s.annotation_flags.integer &&
01578              !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01579             s.annotation_flags.integer = false;
01580         }
01581         if(__s.flags & SIMPLIFY_0_IS_PROD &&
01582                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01583         {
01584           r.coeffs[n-ndel] *= __s.m.nd();
01585           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01586             transfer_ghost_down(__s.nnum, r.node_num);
01587           else
01588             (*delnodes).push_back(__s.nnum);
01589         }
01590         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01591         {
01592           r.coeffs[n-ndel] *= __s.m.nd();
01593           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01594             __mod->node(__s.nnum)->params = 1.;
01595         }
01596         break;
01597       case EXPRINFO_NORM:
01598         if(n == 0)
01599         {
01600           s.degree = -1;
01601           s.property_flags = __s.s.property_flags;
01602           s.property_flags.c_info = convex_e();
01603           s.annotation_flags.integer = false;
01604         }
01605         else
01606         { 
01607           if(s.property_flags.separable != t_true ||
01608              __s.s.property_flags.separable != t_true)
01609             s.property_flags.separable = t_maybe;
01610         }
01611         if(__s.flags & SIMPLIFY_0_IS_PROD &&
01612                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01613         {
01614           r.coeffs[n-ndel] *= pow(fabs(__s.m.nd()), r.params.nd());
01615           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01616             transfer_ghost_down(__s.nnum, r.node_num);
01617           else
01618             (*delnodes).push_back(__s.nnum);
01619         }
01620         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01621         {
01622           r.coeffs[n-ndel] *= pow(fabs(__s.m.nd()), r.params.nd());
01623           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01624             __mod->node(__s.nnum)->params = 1.;
01625         }
01626         break;
01627       case EXPRINFO_POW:
01628         {
01629           bool spupd = false;
01630           if(n == 0)
01631           {
01632             if(__s.flags & SIMPLIFY_0_IS_CONST)
01633             { // a^x = exp(x * ln a)
01634               double help =
01635                   __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01636                                                                __s.m.nd();
01637               r.operator_type = EXPRINFO_EXP;
01638               r.coeffs[0] = log(r.coeffs[0] * help) * r.coeffs[1];
01639               r.coeffs.pop_back();
01640               (*delnodes).push_back(__s.nnum);
01641               s.degree = -1;
01642               ndel++;
01643             }
01644             else
01645               s.degree = __s.s.degree;
01646             if((__s.flags & SIMPLIFY_0_IS_SUM &&
01647                  __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE) ||
01648                (__s.flags & SIMPLIFY_0_IS_PROD &&
01649                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE))
01650             {
01651               transfer = __s.transfer;
01652               m = __s.m;
01653               nnum = __s.nnum;
01654               flags = __s.flags;
01655               //simple_sum_prod_update(r, __s);
01656             }
01657             else
01658               transfer = NULL;
01659           }
01660           if(n != 0 && r.params.nd() == 0 &&
01661              __s.flags & SIMPLIFY_0_IS_CONST &&
01662              __s.flags & SIMPLIFY_0_CONST_IS_INTEGER)
01663           {
01664             double help = __s.m.nn()*r.coeffs[n];
01665             r.coeffs[n] = 1.;
01666             long int helpl = lrint(help);
01667             if(helpl - help == 0 && helpl < MAXINT && helpl > -MAXINT)
01668             {
01669               switch(helpl)
01670               {
01671 #if 0
01672                 // There is still a lurking bug
01673                 case 0:
01674                   r.operator_type = EXPRINFO_CONSTANT;
01675                   r.params = 1.;
01676                   r.coeffs.erase(r.coeffs.begin(),r.coeffs.end());
01677                   (*delnodes).push_back(__s.nnum);
01678                   s.degree = 0;
01679                   ndel++;
01680                   break;
01681                 case 1:
01682                   (*delnodes).push_back(__s.nnum);
01683                   (*delnodes).push_back(r.node_num);
01684                   break;
01685 #endif
01686                 case 2:
01687                   r.operator_type = EXPRINFO_SQUARE;
01688                   (*delnodes).push_back(__s.nnum);
01689                   s.degree = s.degree == -1 ? -1 : s.degree*2;
01690                   r.coeffs.pop_back();
01691                   ndel++;
01692                   spupd = true;
01693                   break;
01694                 case -1:
01695                   r.params = r.coeffs[0];
01696                   r.coeffs[0] = 1.;
01697                   r.operator_type = EXPRINFO_INVERT;
01698                   (*delnodes).push_back(__s.nnum);
01699                   s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
01700                   flags = SIMPLIFY_0_IS_MULTIPLICATIVE;
01701                   r.coeffs.pop_back();
01702                   ndel++;
01703                   break;
01704                 default:
01705                   r.params = (int) helpl;
01706                   r.operator_type = EXPRINFO_INTPOWER;
01707                   (*delnodes).push_back(__s.nnum);
01708                   s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
01709                   r.coeffs.pop_back();
01710                   ndel++;
01711                   break;
01712               }
01713             }
01714             //else
01715             //  spupd = true;
01716           }
01717           //else if(n != 0)
01718           //  spupd = true;
01719           if(spupd)
01720             simple_sum_prod_update(r, *this);
01721           if(n != 0)
01722           {
01723             if(flags != SIMPLIFY_0_IS_MULTIPLICATIVE)
01724               flags = 0;
01725             nnum = r.node_num;
01726           }
01727           if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01728           {
01729             r.coeffs[n] *= __s.m.nd();
01730             if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01731               __mod->node(__s.nnum)->params = 1.;
01732           }
01733           s.property_flags.c_info = convex_e();
01734           s.property_flags.separable = t_maybe;
01735         }
01736         break;
01737       case EXPRINFO_SQUARE:
01738         s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*2;
01739         if(__s.flags & SIMPLIFY_0_IS_CONST)
01740         { // compute constant expressions
01741           double help =
01742                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01743                                                           __s.m.nd();
01744           r.operator_type = EXPRINFO_CONSTANT;
01745           help *= r.coeffs[0];
01746           help += r.params.nd();
01747           r.params = help*help;
01748           (*delnodes).push_back(__s.nnum);
01749           s.degree = 0;
01750         }
01751         else
01752           simple_sum_prod_update(r, __s);
01753         if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01754            is_integer(r.params.nd()))
01755           s.annotation_flags.integer = true;
01756         break;
01757       case EXPRINFO_SQROOT:
01758         if(__s.flags & SIMPLIFY_0_IS_CONST)
01759         { // compute constant expressions
01760           double help =
01761                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01762                                                           __s.m.nd();
01763           r.operator_type = EXPRINFO_CONSTANT;
01764           help *= r.coeffs[0];
01765           help += r.params.nd();
01766           r.params = sqrt(help);
01767           (*delnodes).push_back(__s.nnum);
01768           s.degree = 0;
01769         }
01770         else
01771           simple_sum_prod_update(r, __s);
01772         break;
01773       case EXPRINFO_ABS:
01774         if(__s.flags & SIMPLIFY_0_IS_CONST)
01775         { // compute constant expressions
01776           double help =
01777                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01778                                                           __s.m.nd();
01779           r.operator_type = EXPRINFO_CONSTANT;
01780           help *= r.coeffs[0];
01781           help += r.params.nd();
01782           r.params = fabs(help);
01783           (*delnodes).push_back(__s.nnum);
01784           s.degree = 0;
01785         }
01786         else
01787           simple_sum_prod_update(r, __s);
01788         if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01789            is_integer(r.params.nd()))
01790           s.annotation_flags.integer = true;
01791         break;
01792       case EXPRINFO_EXP:
01793         if(__s.flags & SIMPLIFY_0_IS_CONST)
01794         { // compute constant expressions
01795           double help =
01796                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01797                                                           __s.m.nd();
01798           r.operator_type = EXPRINFO_CONSTANT;
01799           help *= r.coeffs[0];
01800           help += r.params.nd();
01801           r.params = exp(help);
01802           (*delnodes).push_back(__s.nnum);
01803           s.degree = 0;
01804         }
01805         else
01806           simple_sum_prod_update(r, __s);
01807         break;
01808       case EXPRINFO_LOG:
01809         if(__s.flags & SIMPLIFY_0_IS_CONST)
01810         { // compute constant expressions
01811           double help =
01812                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01813                                                           __s.m.nd();
01814           r.operator_type = EXPRINFO_CONSTANT;
01815           help *= r.coeffs[0];
01816           help += r.params.nd();
01817           r.params = log(help);
01818           (*delnodes).push_back(__s.nnum);
01819           s.degree = 0;
01820         }
01821         else
01822           simple_sum_prod_update(r, __s);
01823         break;
01824       case EXPRINFO_SIN:
01825         if(__s.flags & SIMPLIFY_0_IS_CONST)
01826         { // compute constant expressions
01827           double help =
01828                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01829                                                           __s.m.nd();
01830           r.operator_type = EXPRINFO_CONSTANT;
01831           help *= r.coeffs[0];
01832           help += r.params.nd();
01833           r.params = sin(help);
01834           (*delnodes).push_back(__s.nnum);
01835           s.degree = 0;
01836         }
01837         else
01838           simple_sum_prod_update(r, __s);
01839         break;
01840       case EXPRINFO_COS:
01841         if(__s.flags & SIMPLIFY_0_IS_CONST)
01842         { // compute constant expressions
01843           double help =
01844                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01845                                                           __s.m.nd();
01846           r.operator_type = EXPRINFO_CONSTANT;
01847           help *= r.coeffs[0];
01848           help += r.params.nd();
01849           r.params = cos(help);
01850           (*delnodes).push_back(__s.nnum);
01851           s.degree = 0;
01852         }
01853         else
01854           simple_sum_prod_update(r, __s);
01855         break;
01856       case EXPRINFO_ATAN2:
01857         if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01858         {
01859           r.coeffs[n] *= __s.m.nd();
01860           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01861             __mod->node(__s.nnum)->params = 1.;
01862         }
01863         // const should be computed here, too.
01864         break;
01865       case EXPRINFO_GAUSS:
01866         if(__s.flags & SIMPLIFY_0_IS_CONST)
01867         { // compute constant expressions
01868           double help =
01869                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01870                                                           __s.m.nd();
01871           r.operator_type = EXPRINFO_CONSTANT;
01872           help *= r.coeffs[0];
01873           help -= r.params.d()[0];
01874           help /= r.params.d()[1];
01875           r.params = exp(-help*help);
01876           (*delnodes).push_back(__s.nnum);
01877           s.degree = 0;
01878         }
01879         else if(__s.flags & SIMPLIFY_0_IS_SUM &&
01880            __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
01881         {
01882           std::vector<double> m = r.params.d();
01883 
01884           m[0] -= r.coeffs[0]*__s.m.nd();
01885           r.params = m;
01886           r.coeffs[0] *= (*__s.transfer)[0];
01887           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01888             transfer_ghost_down(__s.nnum, r.node_num);
01889           else
01890             (*delnodes).push_back(__s.nnum);
01891         }
01892         else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01893                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01894         {
01895           r.coeffs[0] *= __s.m.nd();
01896           if(__s.flags & SIMPLIFY_0_IS_GHOST)
01897             transfer_ghost_down(__s.nnum, r.node_num);
01898           else
01899             (*delnodes).push_back(__s.nnum);
01900         }
01901         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01902         {
01903           r.coeffs[0] *= __s.m.nd();
01904           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01905             __mod->node(__s.nnum)->params = 1.;
01906         }
01907         break;
01908       case EXPRINFO_INVERT:
01909         if(r.coeffs[0] != 1)
01910         {
01911           r.params = r.params.nd() / r.coeffs[0];
01912           r.coeffs[0] = 1.;
01913         }
01914         if(__s.flags & SIMPLIFY_0_IS_CONST)
01915         { // compute constant expressions
01916           double help =
01917                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01918                                                           __s.m.nd();
01919           r.operator_type = EXPRINFO_CONSTANT;
01920           r.params = r.params.nd() / help;
01921           (*delnodes).push_back(__s.nnum);
01922           s.degree = 0;
01923         }
01924         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01925         {
01926           r.params = r.params.nd() / __s.m.nd();
01927           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01928             __mod->node(__s.nnum)->params = 1.;
01929         }
01930         break;
01931       case EXPRINFO_DIV:
01932         if(n == 0 && __s.flags & SIMPLIFY_0_IS_CONST)
01933         {
01934           double help =
01935               __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01936                                                            __s.m.nd();
01937           r.operator_type = EXPRINFO_INVERT;
01938           r.params = help*r.coeffs[0];
01939           r.coeffs.erase(r.coeffs.begin());
01940           (*delnodes).push_back(__s.nnum);
01941           s.degree = __s.s.degree;
01942           ndel++;
01943         }
01944         else if(n == 0)
01945         {
01946           r.params = r.coeffs[0];
01947           r.coeffs[0] = 1;
01948         }
01949         if(n != 0)
01950         {
01951           if(__s.flags & SIMPLIFY_0_IS_CONST)
01952           {
01953             double help =
01954                  __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01955                                                            __s.m.nd();
01956             r.operator_type = EXPRINFO_PROD;
01957             r.params = 1./help;
01958             r.coeffs.pop_back();
01959             (*delnodes).push_back(__s.nnum);
01960             ndel++;
01961           }
01962           else
01963           {
01964             r.params = r.params.nd() / r.coeffs[1];
01965             r.coeffs[1] = 1;
01966             s.degree = -1;
01967           }
01968         }
01969         if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01970         {
01971           if(n == 0)
01972             r.params = r.params.nd() * __s.m.nd();
01973           else
01974             r.params = r.params.nd() / __s.m.nd();
01975           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01976             __mod->node(__s.nnum)->params = 1.;
01977         }
01978         break;
01979       case EXPRINFO_INTPOWER:
01980         if(r.params.nn() > 0)
01981           s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.nn();
01982         else
01983           s.degree = -1;
01984         if(__s.flags & SIMPLIFY_0_IS_CONST)
01985         { // compute constant expressions
01986           double help =
01987                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01988                                                           __s.m.nd();
01989           r.operator_type = EXPRINFO_CONSTANT;
01990           r.params = pow(help, r.params.nn());
01991           (*delnodes).push_back(__s.nnum);
01992           s.degree = 0;
01993         }
01994         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01995         {
01996           r.coeffs[0] *= __s.m.nd();
01997           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01998             __mod->node(__s.nnum)->params = 1.;
01999         }
02000         if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
02001           s.annotation_flags.integer = true;
02002         break;
02003       case EXPRINFO_IN:
02004         if(n == 0)
02005           r_idx = -1;
02006         else
02007         {
02008           if(l_nnum == __s.nnum)
02009           {
02010             if(r_idx == -1)
02011               r_idx = n-ndel-1;
02012             r.params.i()[n-ndel] /= r.coeffs[n-ndel];
02013             r.coeffs[n-ndel] = 1.;
02014             r.params.i()[r_idx].intersect(r.params.i()[n-ndel]);
02015             (*deledges).push_back(std::make_pair(nnum, __s.nnum));
02016           }
02017           else if(r_idx != -1)
02018           {
02019             int ne_del = n-ndel-r_idx-1;
02020             r.coeffs.erase(r.coeffs.begin()+r_idx+1,
02021                            r.coeffs.begin()+n-ndel);
02022             r.params.i().erase(r.params.i().begin()+r_idx+1,
02023                                r.params.i().begin()+n-ndel);
02024             ndel += ne_del;
02025             r_idx = -1;
02026           }
02027         }
02028         if(__s.flags & SIMPLIFY_0_IS_CONST)
02029         { // compute constant expressions
02030           double help =
02031                 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02032                                                           __s.m.nd();
02033           help *= r.coeffs[n-ndel];
02034           if(r.params.i()[n-ndel].contains(help))
02035           {
02036             r.params.i().erase(r.params.i().begin()+n-ndel);
02037             (*delnodes).push_back(__s.nnum);
02038             ndel++;
02039           }
02040         }
02041         else if(__s.flags & SIMPLIFY_0_IS_PROD &&
02042                 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
02043         {
02044           r.coeffs[n-ndel] *= __s.m.nd();
02045           if(__s.flags & SIMPLIFY_0_IS_GHOST)
02046             transfer_ghost_down(__s.nnum, r.node_num);
02047           else
02048             (*delnodes).push_back(__s.nnum);
02049         }
02050         else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02051         {
02052           r.coeffs[n-ndel] *= __s.m.nd();
02053           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02054             __mod->node(__s.nnum)->params = 1.;
02055         }
02056         else if(__s.flags & SIMPLIFY_0_IS_SUM &&
02057            __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
02058         {
02059           double help = r.coeffs[n-ndel]*__s.m.nd();
02060           r.params.i()[n-ndel] -= help;
02061           r.coeffs[n-ndel] *= (*__s.transfer)[0];
02062           if(__s.flags & SIMPLIFY_0_IS_GHOST)
02063             transfer_ghost_down(__s.nnum, r.node_num);
02064           else
02065             (*delnodes).push_back(__s.nnum);
02066         }
02067         if(r.coeffs[n-ndel] != 1)
02068         {
02069           r.params.i()[n-ndel] /= r.coeffs[n-ndel];
02070           r.coeffs[n-ndel] = 1.;
02071         }
02072         break;
02073       case EXPRINFO_POLY:
02074       case EXPRINFO_IF:
02075       case EXPRINFO_AND:
02076       case EXPRINFO_OR:
02077       case EXPRINFO_NOT:
02078       case EXPRINFO_IMPLIES:
02079       case EXPRINFO_COUNT:
02080       case EXPRINFO_ALLDIFF:
02081       case EXPRINFO_LEVEL:
02082       case EXPRINFO_NEIGHBOR:
02083       case EXPRINFO_NOGOOD:
02084         if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02085         {
02086           r.coeffs[n] *= __s.m.nd();
02087           if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02088             __mod->node(__s.nnum)->params = 1.;
02089         }
02090       case EXPRINFO_EXPECTATION:
02091       case EXPRINFO_INTEGRAL:
02092         std::cerr << "simplify_visitor_0: Integral Operations NYI" << std::endl;
02093         throw "NYI";
02094         break;
02095       case EXPRINFO_LOOKUP:
02096       case EXPRINFO_PWLIN:
02097       case EXPRINFO_SPLINE:
02098       case EXPRINFO_PWCONSTLC:
02099       case EXPRINFO_PWCONSTRC:
02100         std::cerr << "simplify_visitor_0: Table Operations NYI" << std::endl;
02101         throw "NYI";
02102         break;
02103       case EXPRINFO_DET:
02104       case EXPRINFO_COND:
02105       case EXPRINFO_PSD:
02106       case EXPRINFO_MPROD:
02107       case EXPRINFO_FEM:
02108         std::cerr << "simplify_visitor_0: Matrix Operations NYI" << std::endl;
02109         throw "NYI";
02110         break;
02111       case EXPRINFO_RE:
02112       case EXPRINFO_IM:
02113       case EXPRINFO_ARG:
02114       case EXPRINFO_CPLXCONJ:
02115         std::cerr << "simplify_visitor_0: Complex Numbers NYI" << std::endl;
02116         throw "NYI";
02117         break;
02118       case EXPRINFO_CMPROD:
02119       case EXPRINFO_CGFEM:
02120         std::cerr << "simplify_visitor_0: Constant Matrix Operations NYI" << std::endl;
02121         throw "NYI";
02122         break;
02123       case EXPRINFO_LIN:
02124         break;
02125       case EXPRINFO_QUAD:
02126         break;
02127       default:
02128         std::cerr << "Simplifier: Unknown Operator Type " << r.operator_type
02129           << std::endl;
02130         throw "NYI";
02131         break;
02132     }
02133   }
02134   else if(r.operator_type > 0)
02135   {
02136     ;
02137   }
02138   n++;
02139   v_i.set_all(__s.v_i);
02140   l_nnum = __s.nnum;
02141   l_flags = __s.flags;
02142   l_s = __s.s;
02143 }
02144 
02145 bool model::basic_simplify_0()
02146 {
02147   std::vector<unsigned int> delnodes;
02148   std::vector<std::pair<unsigned int,unsigned int> > deledges;
02149   simplify_visitor_0 w(gid->number_of_variables(), &delnodes, &deledges, this);
02150   bool result = false;
02151 
02152   recursive_postorder_walk(ground(), w);
02153   result = !delnodes.empty() || !deledges.empty();
02154   for(std::vector<std::pair<unsigned int,unsigned int> >::iterator b =
02155       deledges.begin(); b != deledges.end(); ++b)
02156     remove_edge(node((*b).first),node((*b).second));
02157   for(std::vector<unsigned int>::iterator b = delnodes.begin(); b != delnodes.end();
02158       ++b)
02159     remove_node(*b);
02160   return result;
02161 }
02162 
02163 bool model::basic_simplify_1_merge(walker __s, std::list<walker>& _todo,
02164                                    std::vector<int>& _combined, std::vector<bool>& _fld,
02165                                    std::vector<int>& _sorted)
02166 {
02167   std::list<walker> dew;
02168   walker _ew, _fw;
02169   parents_iterator _p, _q;
02170   bool result = false;
02171   unsigned int snn = __s == sky() ? number_of_nodes() : __s->node_num;
02172 
02173   if(_sorted[snn] <= 0)
02174   {
02175     _sorted[snn] += 2; // 0 -> 2, -1 -> 1
02176     sort_parent_edges(__s, expression_node::parents_compare());
02177   }
02178   for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
02179   {
02180     _ew = __s << _p;
02181     if(_combined[_ew->node_num] != (int)_ew->n_children)
02182       continue;
02183     if(abs(_sorted[_ew->node_num]) != 1)
02184     {
02185       _sorted[_ew->node_num]--; // 2 -> 1, 0 -> -1
02186       if(_ew->operator_type == EXPRINFO_SUM ||
02187          _ew->operator_type == EXPRINFO_PROD ||
02188          _ew->operator_type == EXPRINFO_MAX ||
02189          _ew->operator_type == EXPRINFO_MIN ||
02190          _ew->operator_type == EXPRINFO_MONOME ||
02191          _ew->operator_type == EXPRINFO_NORM ||
02192          _ew->operator_type == EXPRINFO_MEAN)
02193       {
02194         // this is an awful hack, but I have not found a better
02195         // one. The cleanest way would be to fully work out the
02196         // "real" dag class which depends on an edge class
02197         std::map<std::pair<unsigned int, unsigned int>,
02198                  std::pair<double, int> > __nr_c_ref;
02199         std::map<std::pair<unsigned int, unsigned int>,
02200                  std::pair<double, int> >::iterator __f;
02201         children_iterator _c;
02202         int n;
02203         
02204         for(_c = _ew.child_begin(), n=0; _c != _ew.child_end(); ++_c, ++n)
02205         {
02206           unsigned int cnn = (_ew >> _c)->node_num, _h;
02207           for(_h = 0; ; _h++)
02208           {
02209             __f = __nr_c_ref.find(std::make_pair(cnn, _h));
02210             if(__f == __nr_c_ref.end())
02211               break;
02212           }
02213           if(_ew->operator_type == EXPRINFO_MONOME)
02214             __nr_c_ref.insert(std::make_pair(std::make_pair(cnn, _h),
02215                            std::make_pair(_ew->coeffs[n],_ew->params.n()[n])));
02216           else
02217             __nr_c_ref.insert(std::make_pair(std::make_pair(cnn, _h),
02218                               std::make_pair(_ew->coeffs[n],0)));
02219         }
02220         sort_child_edges(_ew, expression_node::children_compare());
02221         for(_c = _ew.child_begin(), n=0; _c != _ew.child_end(); ++_c, ++n)
02222         {
02223           unsigned int cnn = (_ew >> _c)->node_num, _h;
02224 
02225           for(_h = 0; ; _h++)
02226           {
02227             __f = __nr_c_ref.find(std::make_pair(cnn, _h));
02228 #if 0
02229           if(__f == __nr_c_ref.end())
02230           {
02231             std::cerr << "FATAL Error: This can't happen ;) in basic_simplify_1_merge"
02232               << std::endl;
02233             exit(-42);    // guess why!
02234           }
02235 #endif
02236             if(__f != __nr_c_ref.end())
02237               break;
02238           }
02239           _ew->coeffs[n] = __f->second.first;
02240           if(_ew->operator_type == EXPRINFO_MONOME)
02241             _ew->params.n()[n] = __f->second.second;
02242           __nr_c_ref.erase(__f);
02243         }
02244       }
02245     }
02246   }
02247   for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
02248   {
02249     _ew = __s << _p;
02250     if(_combined[_ew->node_num] == (int)_ew->n_children)
02251       break;
02252   }
02253   while(_p != __s.parent_end())
02254   {
02255     for(_q = __s.parent_begin(); _q != __s.parent_end(); ++_q)
02256     {
02257       _ew = __s << _q;
02258       if(_combined[_ew->node_num] == (int)_ew->n_children)
02259         break;
02260     }
02261     for(++_p; _p != __s.parent_end(); ++_p)
02262     {
02263       _fw = __s << _p;
02264       if(_combined[_fw->node_num] != (int)_fw->n_children)
02265         continue;
02266       if(_ew.node() == _fw.node())
02267       {
02268         _q = _p;
02269         _ew = __s << _q;
02270         continue;
02271       }
02272       if(expression_node::parents_compare_eq()(*_ew, *_fw) &&
02273          children_eq(_ew, _fw))
02274         // up until now they are all equal
02275         dew.insert(dew.end(), _fw);
02276       else
02277       { // now they have changed
02278         if(dew.size() != 0)
02279           /* more than one have to be merged */
02280           break;
02281         else
02282         {
02283           /* no merging necessary, so flood it unless it's already flooded */
02284           if(!_fld[_ew->node_num])
02285           {
02286             _fld[_ew->node_num] = true;
02287             basic_simplify_1_flood(_ew, _combined);
02288             if(_ew->operator_type != EXPRINFO_CONSTANT)
02289               _todo.push_back(_ew);
02290           }
02291           _q = _p;
02292           _ew = __s << _q;
02293         }
02294       }
02295     }
02296     if(dew.size() == 0)
02297     { /* we are at the end of the parents list */
02298       if(!_fld[_ew->node_num])
02299       {
02300         _fld[_ew->node_num] = true;
02301         basic_simplify_1_flood(_ew, _combined);
02302         if(_ew->operator_type != EXPRINFO_CONSTANT)
02303           _todo.push_back(_ew);
02304       }
02305       break;
02306     }
02307 
02308     /* now merge */
02309     _ew->n_parents += dew.size();
02310     for(std::list<walker>::iterator _b = dew.begin(); _b != dew.end(); ++_b)
02311     {
02312       std::list<walker>::iterator _hlp;
02313       
02314       free_node_num((*_b)->node_num);
02315 
02316       for(_hlp = _todo.begin(); _hlp != _todo.end(); ++_hlp)
02317       {
02318         if(*_hlp == *_b)
02319         {
02320           _todo.erase(_hlp);
02321           break;
02322         }
02323       }
02324 
02325       if(objective == *_b)
02326         objective = _ew;
02327       
02328       // make sure that constraint numbering still works
02329       unsigned int cn;
02330       if(get_const_num((*_b)->node_num, cn))
02331       {
02332         unsigned int cc;
02333         if(get_const_num(_ew->node_num, cc))
02334         {
02335           gid->unused_constr(const_name(cn));
02336           gid->remove_const_id(cn);
02337         }
02338         else
02339           gid->make_const_back_ref(_ew->node_num, cn);
02340         // remove the constraint from the constraints array
02341         for(std::vector<walker>::iterator __x = constraints.begin();
02342             __x != constraints.end(); ++__x)
02343           if(*__x == *_b)
02344           {
02345             constraints.erase(__x);
02346             break;
02347           }
02348       }
02349       
02350 #if MODEL_INLINE_DEBUG_SIMPLIFY
02351       std::cout << "Merging " << _ew->node_num << " and " <<
02352         (*_b)->node_num << std::endl;
02353 #endif
02354       merge(_ew, *_b, false);
02355       result = true;
02356     }
02357     dew.erase(dew.begin(), dew.end());
02358     if(_ew->operator_type == EXPRINFO_VARIABLE)
02359       store_variable(_ew);
02360     else if(_ew->operator_type == EXPRINFO_GHOST)
02361       store_ghost(_ew);
02362 
02363     /* this one is finished, so flood it unless it's already flooded */
02364     if(!_fld[_ew->node_num])
02365     {
02366       _fld[_ew->node_num] = true;
02367       basic_simplify_1_flood(_ew, _combined);
02368       if(_ew->operator_type != EXPRINFO_CONSTANT)
02369         _todo.push_back(_ew);
02370     }
02371     for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
02372     {
02373       _fw = __s << _p;
02374       if(_combined[_fw->node_num] == (int)_fw->n_children)
02375         break;
02376     }
02377   }
02378   return result;
02379 }
02380 
02381 bool model::basic_simplify_1()
02382 {
02383   std::vector<int> _combined(number_of_nodes(), 0);
02384   std::vector<bool> _fld(number_of_nodes(), false);
02385   std::vector<int> _sorted(number_of_nodes()+1, 0);
02386   std::list<walker> _todo(1, sky());
02387   std::list<walker>::iterator __xxcl, __help;
02388   bool result = false;
02389 
02390   while(!_todo.empty())
02391   {
02392     for(__xxcl = _todo.begin(); __xxcl != _todo.end(); __xxcl = __help)
02393     {
02394 #if MODEL_INLINE_DEBUG_SIMPLIFY
02395       for(std::list<walker>::const_iterator __rr = _todo.begin();
02396           __rr != _todo.end(); ++__rr)
02397         std::cerr << (*__rr)->node_num << ", ";
02398       std::cerr << std::endl;
02399 #endif
02400       __help = __xxcl;
02401       ++__help;
02402       if((*__xxcl).is_ground()||(*__xxcl).is_root())
02403         // everything ends at root nodes or above
02404         _todo.erase(__xxcl);
02405       else if((*__xxcl).is_sky() ||
02406               basic_simplify_1_is_ready(*__xxcl, _combined, false))
02407       { /* some of the parents of this node are ready to be merged */
02408         result = basic_simplify_1_merge(*__xxcl, _todo, _combined, _fld,
02409                                         _sorted) || result;
02410         if(basic_simplify_1_is_ready(*__xxcl, _combined, true))
02411         /* all of the parents of this node are merged */
02412           _todo.erase(__xxcl);
02413       }
02414     }
02415   }
02416   return result;
02417 }
02418 
02419 bool model::basic_simplify_2()
02420 {
02421   //walker h;
02422 
02423   return false;
02424 }
02425 
02426 void model::prepare_after_read()
02427 {
02428   walker _w;
02429   unsigned int cnum;
02430 
02431   compress_numbers();
02432   for(ref_iterator _x = node_ref.begin(); _x != node_ref.end(); ++_x)
02433   {
02434     _w = *_x;
02435     if(_w->f_bounds.inf() != -INFINITY || _w->f_bounds.sup() != INFINITY)
02436     {
02437       constraints.insert(constraints.end(), _w);
02438       if(!gid->get_const_num(_w->node_num, cnum))
02439         cnum = next_constraint_num();
02440       gid->mk_gconstref(cnum, _w);
02441     }
02442   }
02443   
02444   arrange_constraints();
02445 }
02446 
02447 bool model::basic_simplify()
02448 {
02449   bool have_simplified = false, first = true;
02450   int have_simp;
02451 
02452   have_simp = 7;
02453   do
02454   {
02455     have_simp &= ~1;
02456     if((first || have_simp) && basic_simplify_0())
02457       have_simp |= 1;
02458 #if MODEL_INLINE_DEBUG_SIMPLIFY
02459     write();
02460 #endif
02461     have_simp &= ~2;
02462     if((first || have_simp) && basic_simplify_1())
02463       have_simp |= 2;
02464 #if MODEL_INLINE_DEBUG_SIMPLIFY
02465     write();
02466 #endif
02467     have_simp &= ~4;
02468     if((first || have_simp) && basic_simplify_2())
02469       have_simp |= 4;
02470 #if MODEL_INLINE_DEBUG_SIMPLIFY && 0
02471     write();
02472 #endif
02473     have_simplified = have_simplified || (have_simp != 0);
02474     first = false;
02475   } while(have_simp != 0);
02476 
02477   return have_simplified;
02478 }
02479 
02480 void model::write(std::ostream &o) const
02481 {
02482   std::vector<bool> _nprinted(number_of_nodes(), false);
02483   expression_print_visitor p(_nprinted, o);
02484   int precsave = o.precision(18);
02485   
02486   o << "<N> V " << gid->number_of_variables() << std::endl;
02487   for(children_iterator b = ground().child_begin(); b != ground().child_end();
02488       b++)
02489   {
02490     recursive_preorder_walk_if(ground() >> b, p);
02491   }
02492   o << "<N> M ";
02493   if((const_walker) objective != ground())
02494     o << objective->node_num;
02495   else
02496     o << '0';
02497   o << ' ';
02498   if(ocoeff == -1)
02499     o << "max";
02500   else if(ocoeff == 1)
02501     o << "min";
02502   else
02503     o << "m00";
02504   o << std::endl;
02505 
02506   for(unsigned int i=0; i < number_of_variables(); ++i)
02507     o << "<N> N " << i << " '" << gid->var_name(i) << "'" << std::endl;
02508   for(unsigned int i=0; i < gid->n_fixed_vars(); ++i)
02509     o << "<N> F '" << gid->fixed_var(i).first << "' "
02510       << gid->fixed_var(i).second << std::endl;
02511   for(unsigned int i=0; i < gid->n_unused_vars(); ++i)
02512     o << "<N> U '" << gid->unused_var(i) << "'" << std::endl;
02513   for(unsigned int i=0; i < gid->n_unused_constrs(); ++i)
02514     o << "<N> S '" << gid->unused_constr(i) << "'" << std::endl;
02515   for(std::vector<walker>::const_iterator __b = constraints.begin();
02516       __b != constraints.end(); ++__b)
02517   {
02518     unsigned int cn;
02519     if(!gid->get_const_num((*__b)->node_num, cn))
02520     {
02521       std::cerr << "FATAL in write: Could not get constraint number for node "
02522         << (*__b)->node_num << std::endl;
02523       throw "Programming error";
02524     }
02525     o << "<N> c " << cn << " " << (*__b)->node_num << std::endl;
02526     o << "<N> C " << cn << " '" << const_name(cn) << "'" << std::endl;
02527   }
02528 #if 0
02529   for(unsigned int i=0; i < gid->number_of_constraints(); ++i)
02530   {
02531     if(constraint(i) == (const walker&) ground()) continue;
02532     o << "<N> c " << i << " " << constraint(i)->node_num << std::endl;
02533     o << "<N> C " << i << " '" << const_name(i) << "'" << std::endl;
02534   }
02535 #endif
02536   if(ocoeff != 0 || gid->obj_adj() != 0)
02537   {
02538     if(ocoeff == 0) gid->obj_mult(1);
02539     o << "<N> O '" << gid->obj_name() << "'";
02540     if(gid->obj_adj() != 0 || gid->obj_mult() != 1)
02541       o << ": d " << gid->obj_adj();
02542     if(gid->obj_mult() != 1)
02543       o << ", " << gid->obj_mult();
02544     o << std::endl;
02545   }
02546   o.precision(precsave);
02547 }
02548 
02549 model::walker model::variable(unsigned int _vnum)
02550 {
02551   bool make_new(false);
02552   walker __r(ground());
02553   ref_iterator __x(var_ref.end());
02554 
02555   if(!gid->have_gvar_ref(_vnum))
02556   {
02557     new_variables(_vnum+1);
02558     make_new = true;
02559   }
02560   else
02561   {
02562     __x = lower_bound(var_ref.begin(), var_ref.end(), _vnum,
02563                       __docompare_variables());
02564     if(__x != var_ref.end() && (*__x)->params.nn() == (int)_vnum)
02565     {
02566       __r = *__x;
02567       make_new = false;
02568     }
02569     else if(gid->empty(var(_vnum)))
02570       make_new = true;
02571   }
02572   if(make_new)
02573   {
02574     expression_node _en(EXPRINFO_VARIABLE, next_num());
02575     _en.v_i.reserve(gid->number_of_variables());
02576     _en.v_i.set(_vnum);
02577     _en.params = (int)_vnum;
02578     __r = between_back(ground(), sky(), _en);
02579     var_ref.insert(__x, __r);
02580     return store_node(__r);
02581   }
02582   else if(__r == ground()) // we have to produce a ghost variable
02583   {
02584     __r = var(_vnum);
02585     __r = ghost(__r->node_num);
02586     // var_ref.insert(__x, __r); removed Oct. 20 (ghosts must not be in var_ref)
02587     return __r;
02588   }
02589   else
02590     return __r;
02591 }
02592 
02593 model::walker model::vnary(int expr_type, ...)
02594 {
02595   va_list _a_list;
02596   expression_node _en(expr_type, next_num());
02597   std::vector<walker> _args;
02598   const walker* _e;
02599   int __i;
02600 
02601   va_start(_a_list, expr_type);
02602   for(__i=0;;__i++)
02603   {
02604     _e = va_arg(_a_list, const walker*);
02605     if(_e == EXPR_LASTARG) break;
02606     _args.push_back(*_e);
02607     _en.v_i.set_all((*_e)->v_i);
02608   }
02609   va_end(_a_list);
02610   _en.coeffs.insert(_en.coeffs.end(),__i,1.0);
02611   if(expr_type == EXPRINFO_PROD)
02612     _en.params = 1.;
02613   else
02614     _en.params = 0.;
02615   return store_node(split_back(ground(), _args, _en));
02616 }
02617 
02618 void model::detect_0chain()
02619 {
02620   unsigned int f = 1;
02621   unsigned int n = number_of_nodes();
02622   std::vector<unsigned int> t(n,0);
02623   std::vector<unsigned int> depth(n,0);
02624   std::vector<unsigned int> base;
02625 
02626   detect_0chain_visitor d(t, depth, base, f);
02627 
02628   evaluate(d, ground());
02629   for(unsigned int i = 0; i < n; ++i)
02630   {
02631     if(gid->empty(gid->node(i)))
02632       continue;
02633     if(t[i] == 0)
02634     {
02635       gid->node(i)->sem.info_flags.has_0chnbase = t_false;
02636       gid->node(i)->sem._0chnbase = i;
02637       continue;
02638     }
02639     if(base[t[i]-1] == i)
02640       gid->node(i)->sem.info_flags.has_0chnbase = t_false;
02641     else
02642       gid->node(i)->sem.info_flags.has_0chnbase = 
02643                                         (depth[i] == 1 ? t_maybe : t_true);
02644     gid->node(i)->sem._0chnbase = base[t[i]-1];
02645   }
02646 }

Generated on Tue Nov 4 01:57:58 2003 for COCONUT API by doxygen1.2.18