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

model-inline.h

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 #ifndef _MODEL_INLINE_H_
00028 #define _MODEL_INLINE_H_
00029 
00030 #define MODEL_INLINE_DEBUG 0
00031 #define MODEL_INLINE_DEBUG_SIMPLIFY 0
00032 
00033 inline bool model_iddata::delete_ref(model_gid& __m)
00034 {
00035   for(std::list<model_gid*>::iterator __w = backref.begin(); __w != backref.end();
00036       ++__w)
00037   {
00038     if(*__w == &__m)
00039     {
00040       backref.erase(__w);
00041       break;
00042     }
00043   }
00044   return backref.empty();
00045 }
00046 
00047 inline unsigned int model_iddata::get_node_id()
00048 {
00049   if(node_free.size() > 0)
00050   {
00051     unsigned int ___a = node_free.back();
00052     node_free.pop_back();
00053     return ___a;
00054   }
00055   else
00056     return node_num_max++;
00057 }
00058 
00059 inline void model_iddata::remove_node_id(unsigned int _n)
00060 {
00061   if(_n == node_num_max-1)
00062     --node_num_max;
00063   else
00064     node_free.push_back(_n);
00065   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00066       ++__b)
00067     (*__b)->remove_node_ref(_n);
00068 }
00069 
00070 inline unsigned int model_iddata::get_var_id()
00071 {
00072   if(var_free.size() > 0)
00073   {
00074     unsigned int ___a = var_free.back();
00075     var_free.pop_back();
00076     return ___a;
00077   }
00078   else
00079     return var_num_max++;
00080 }
00081 
00082 inline void model_iddata::remove_var_id(unsigned int _n)
00083 {
00084   if(_n == var_num_max-1)
00085     --var_num_max;
00086   else
00087     var_free.push_back(_n);
00088   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00089       ++__b)
00090     (*__b)->remove_var_ref(_n);
00091   if(var_names.size() > _n)
00092     var_names[_n] = std::string();
00093 }
00094 
00095 inline unsigned int model_iddata::get_const_id()
00096 {
00097   if(const_free.size() > 0)
00098   {
00099     unsigned int ___a = const_free.back();
00100     const_free.pop_back();
00101     return ___a;
00102   }
00103   else
00104     return const_num_max++;
00105 }
00106 
00107 inline void model_iddata::remove_const_id(unsigned int _n)
00108 {
00109   if(_n == const_num_max-1)
00110     --const_num_max;
00111   else
00112     const_free.push_back(_n);
00113   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00114       ++__b)
00115     (*__b)->remove_const_ref(_n);
00116   if(const_names.size() > _n)
00117     const_names[_n] = std::string();
00118 }
00119 
00120 inline void model_iddata::number_of_nodes(unsigned int _n)
00121 {
00122   node_num_max = _n;
00123   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00124       ++__b)
00125     (*__b)->upd_number_of_nodes(_n);
00126 }
00127 
00128 inline void model_iddata::number_of_variables(unsigned int _n)
00129 {
00130   var_num_max = _n;
00131   var_names.insert(var_names.end(), _n - var_names.size(), std::string());
00132   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00133       ++__b)
00134     (*__b)->upd_number_of_variables(_n);
00135 }
00136 
00137 inline void model_iddata::number_of_constraints(unsigned int _n)
00138 {
00139   const_num_max = _n;
00140   const_names.insert(const_names.end(), _n - const_names.size(), std::string());
00141   for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00142       ++__b)
00143     (*__b)->upd_number_of_constraints(_n);
00144 }
00145 
00146 inline const std::string model_iddata::var_name(unsigned int n) const
00147 {
00148   if(n >= var_names.size() || var_names[n] == std::string())
00149   {
00150     char __s[32];
00151     sprintf(__s, "%%x%d", n);
00152     return std::string(__s);
00153   }
00154   else
00155    return var_names[n];
00156 }
00157 
00158 inline void model_iddata::var_name(unsigned int n, const std::string& vn)
00159 {
00160   if(n >= var_names.size())
00161   {
00162     if(n > var_names.size())
00163       var_names.insert(var_names.end(), n-var_names.size(), std::string());
00164     var_names.push_back(vn);
00165   }
00166   else
00167     var_names[n] = vn;
00168 }
00169 
00170 inline const std::string model_iddata::const_name(unsigned int n) const
00171 {
00172   if(n >= const_names.size() || const_names[n] == std::string())
00173   {
00174     char __s[32];
00175     sprintf(__s, "%%c%d", n);
00176     return std::string(__s);
00177   }
00178   else
00179    return const_names[n];
00180 }
00181 
00182 inline void model_iddata::const_name(unsigned int n, const std::string& vn)
00183 {
00184   if(n >= const_names.size())
00185   {
00186     if(n > const_names.size())
00187       const_names.insert(const_names.end(), n-const_names.size(), std::string());
00188     const_names.push_back(vn);
00189   }
00190   else
00191     const_names[n] = vn;
00192 }
00193 
00194 inline const std::string model_iddata::obj_name() const
00195 {
00196   if(obj_names == std::string())
00197     return std::string("%o");
00198   else
00199     return obj_names;
00200 }
00201 
00202 inline void model_iddata::obj_name(const std::string& vn) { obj_names = vn; }
00203 inline double model_iddata::obj_adj() const { return obj_adjs; }
00204 inline void model_iddata::obj_adj(double adj) { obj_adjs = adj; }
00205 inline double model_iddata::obj_mult() const { return obj_mults; }
00206 inline void model_iddata::obj_mult(double mult) { obj_mults = mult; }
00207 
00208 inline std::pair<const std::string, double> model_iddata::fixed_var( unsigned int n)
00209   const
00210 {
00211   if(n >= fixed_vars.size())
00212   {
00213     std::cerr << "index error in fixed_var!" << std::endl;
00214     throw "Programming error";
00215   }
00216   return fixed_vars[n];
00217 }
00218 
00219 inline void model_iddata::fixed_var(const std::string& vn, double val)
00220 {
00221   fixed_vars.push_back(std::make_pair(vn, val));
00222 }
00223 
00224 inline const std::string& model_iddata::unused_var(unsigned int n) const
00225 {
00226   if(n >= unused_vars.size())
00227   {
00228     std::cerr << "index error in unused_var!" << std::endl;
00229     throw "Programming error";
00230   }
00231   return unused_vars[n];
00232 }
00233 
00234 inline void model_iddata::unused_var(const std::string& vn)
00235 {
00236   unused_vars.push_back(vn);
00237 }
00238 
00239 inline const std::string& model_iddata::unused_constr(unsigned int n) const
00240 {
00241   if(n >= unused_constrs.size())
00242   {
00243     std::cerr << "index error in unused_constr!" << std::endl;
00244     throw "Programming error";
00245   }
00246   return unused_constrs[n];
00247 }
00248 
00249 inline void model_iddata::unused_constr(const std::string& vn)
00250 {
00251   unused_constrs.push_back(vn);
00252 }
00253 
00254 inline void model_gid::upd_number_of_nodes(unsigned int _n)
00255 {
00256   int __x;
00257   if((__x = _n - glob_ref.size()) > 0)
00258     glob_ref.insert(glob_ref.end(), __x, model_ref.ground());
00259 }
00260 
00261 inline void model_gid::upd_number_of_variables(unsigned int _n)
00262 {
00263   int __x;
00264   unsigned int _n_old = gvar_ref.size();
00265 
00266   if((__x = _n - gvar_ref.size()) > 0)
00267   {
00268     model::walker _gr = model_ref.ground();
00269 
00270     gvar_ref.insert(gvar_ref.end(), __x, _gr);
00271     for(model::ref_iterator __b = glob_ref.begin(); __b != glob_ref.end();
00272         ++__b)
00273     {
00274       if((*__b) != _gr)
00275       {
00276         (*__b)->v_i.reserve(_n);
00277         (*__b)->v_i.unset(_n_old, _n-1);
00278       }
00279     }
00280   }
00281 }
00282 
00283 inline void model_gid::upd_number_of_constraints(unsigned int _n)
00284 {
00285   int __x;
00286   if((__x = _n - gconst_ref.size()) > 0)
00287     gconst_ref.insert(gconst_ref.end(), __x, model_ref.ground());
00288 }
00289 
00290 inline void model_gid::renumber_variables(
00291     std::vector<std::pair<unsigned int,unsigned int> >& __v)
00292 {
00293   int i;
00294   for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00295       __i != __v.end(); ++__i)
00296   {
00297     i = (*__i).second;
00298     gvar_ref[i] = gvar_ref[(*__i).first];
00299     gvar_ref[i]->params = i;
00300   }
00301 }
00302 
00303 inline void model_gid::renumber_constraints(
00304     std::vector<std::pair<unsigned int,unsigned int> >& __v)
00305 {
00306   unsigned int i;
00307   std::map<unsigned int, unsigned int>::iterator __mf;
00308   for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i =
00309       __v.begin(); __i != __v.end(); ++__i)
00310   {
00311     i = (*__i).second;
00312     gconst_ref[i] = gconst_ref[(*__i).first];
00313     unsigned int n = gconst_ref[i]->node_num;
00314     __mf = const_back_ref.find(n);
00315     if(__mf == const_back_ref.end())
00316       throw "This can't happen in renumber_constraints!";
00317     const_back_ref.erase(__mf);
00318     const_back_ref.insert(std::make_pair(n, i));
00319   }
00320 }
00321 
00322 inline void model_gid::mk_globref(unsigned int n, const model::walker& __w)
00323 {
00324   if(glob_ref.size() > n)
00325     glob_ref[n] = __w;
00326   else if(n == glob_ref.size())
00327     glob_ref.push_back(__w);
00328   else
00329   {
00330     glob_ref.insert(glob_ref.end(), n-glob_ref.size()+1, model_ref.ground());
00331     glob_ref[n] = __w;
00332   }
00333 }
00334 
00335 inline void model_gid::mk_gvarref(unsigned int n, const model::walker& __w)
00336 {
00337   if(gvar_ref.size() > n)
00338     gvar_ref[n] = __w;
00339   else if(n == gvar_ref.size())
00340     gvar_ref.push_back(__w);
00341   else
00342   {
00343     gvar_ref.insert(gvar_ref.end(), n-gvar_ref.size()+1, model_ref.ground());
00344     gvar_ref[n] = __w;
00345   }
00346 }
00347 
00348 inline void model_gid::mk_gconstref(unsigned int n, const model::walker& __w)
00349 {
00350   if(n == gconst_ref.size())
00351     gconst_ref.push_back(__w);
00352   else
00353   {
00354     if(gconst_ref.size() <= n)
00355       gconst_ref.insert(gconst_ref.end(), n-gconst_ref.size()+1,
00356                       model_ref.ground());
00357     gconst_ref[n] = __w;
00358     std::map<unsigned int, unsigned int>::iterator __mf =
00359       const_back_ref.find(__w->node_num);
00360     if(__mf != const_back_ref.end())
00361       const_back_ref.erase(__mf);
00362   }
00363   const_back_ref.insert(std::make_pair(__w->node_num, n));
00364 }
00365 
00366 inline void model_gid::remove_const_ref(unsigned int _n)
00367 {
00368   std::map<unsigned int, unsigned int>::iterator __mf;
00369   if(gconst_ref.size() > _n)
00370   {
00371     __mf = const_back_ref.find(gconst_ref[_n]->node_num);
00372     if(__mf != const_back_ref.end())
00373       const_back_ref.erase(__mf);
00374     if(gconst_ref.size() == _n) gconst_ref.pop_back();
00375     else gconst_ref[_n] = model_ref.ground();
00376   }
00377   else
00378   {
00379     for(__mf = const_back_ref.begin(); __mf != const_back_ref.end(); ++__mf)
00380       if((*__mf).second == _n)
00381       {
00382         const_back_ref.erase(__mf);
00383         break;
00384       }
00385   }
00386 }
00387 
00388 inline bool model_gid::get_const_num(unsigned int node_num,
00389                                      unsigned int& const_num)
00390 {
00391   std::map<unsigned int, unsigned int>::iterator __mf =
00392                                         const_back_ref.find(node_num);
00393   if(__mf == const_back_ref.end())
00394     return false;
00395   const_num = (*__mf).second;
00396   return true;
00397 }
00398 
00399 inline void model_gid::make_const_back_ref(unsigned int node, unsigned int cnum)
00400 {
00401   std::map<unsigned int, unsigned int>::iterator __mf =
00402                                         const_back_ref.find(node);
00403   if(__mf != const_back_ref.end())
00404     const_back_ref.erase(__mf);
00405   const_back_ref.insert(std::make_pair(node, cnum));
00406 }
00407 
00408 inline bool model::is_empty(const walker& __w) const { return gid->empty(__w); }
00409 inline model::walker model::empty_reference() const
00410         { return gid->empty_reference(); }
00411 
00412 inline void model::detach_gid() { gid = new model_gid(*this, *gid); }
00413 
00414 inline model::model(int __num_of_vars) : _Base(), node_ref(), var_ref(),
00415                                 ghost_ref(), keep_gid(true), lin(), matd(),
00416                                 mati(), ocoeff(0), objective(ground()),
00417                                 constraints()
00418 { gid = new model_gid(*this, __num_of_vars); }
00419 
00420 inline model::model(model_gid* __id, bool clone) :
00421                                        _Base(), node_ref(), var_ref(),
00422                                        ghost_ref(), lin(), matd(), mati(),
00423                                        ocoeff(0), objective(ground()),
00424                                        constraints()
00425 {
00426   keep_gid = true;
00427   if(__id) 
00428   {
00429     if(clone)
00430     {
00431       gid = __id;
00432       keep_gid = false;
00433     }
00434     else
00435       gid = new model_gid(*this, *__id);
00436   }
00437   else
00438     gid = new model_gid(*this);
00439 }
00440 
00441 inline model::model(const model& __m) : _Base(__m), node_ref(),
00442                                  var_ref(), ghost_ref(), gid(), keep_gid(true),
00443                                  lin(__m.lin), matd(__m.matd),
00444                                  mati(__m.mati), ocoeff(__m.ocoeff),
00445                                  constraints()
00446 {
00447 #if MODEL_INLINE_DEBUG
00448   std::cout << "Copy constructor of model called " << std::endl;
00449 #endif
00450   gid = new model_gid(*this, *__m.gid_data());
00451 
00452   copy_contents(gid, __m);
00453 }
00454 
00455 inline model::model(model_gid* __id, const model& __m) : _Base(__m),
00456                                  node_ref(), var_ref(), ghost_ref(), gid(__id),
00457                                  keep_gid(false),
00458                                  lin(__m.lin), matd(__m.matd),
00459                                  mati(__m.mati), ocoeff(__m.ocoeff),
00460                                  constraints()
00461 {
00462   if(!__id)
00463   {
00464     std::cerr << "NULL gid is forbidden in model constructor!" <<  std::endl;
00465     throw "Programming error";
00466   } 
00467   copy_contents(gid, __m);
00468 }
00469 
00470 inline model::~model()
00471 {
00472 #if MODEL_INLINE_DEBUG
00473   // brice 10/10/2002 : added a warning
00474   std::cerr << "Destructor of model called" << std::endl;
00475   if(keep_gid)
00476     delete gid;
00477 #endif
00478 }
00479 
00480 inline bool model::get_const_num(unsigned int node_num,
00481                                  unsigned int& const_num) const
00482         { return gid->get_const_num(node_num, const_num); }
00483  
00484 
00485 inline const std::string model::var_name(unsigned int n) const
00486         { return gid->var_name(n); }
00487 inline const std::string model::const_name(unsigned int n) const
00488         { return gid->const_name(n); }
00489 inline const std::string model::obj_name() const { return gid->obj_name(); }
00490 inline double model::obj_adj() const { return gid->obj_adj(); }
00491 inline double model::obj_mult() const { return gid->obj_mult(); }
00492 inline size_t model::n_fixed_vars() const { return gid->n_fixed_vars(); }
00493 inline std::pair<const std::string, double> model::fixed_var(unsigned int n) const
00494         { return gid->fixed_var(n); }
00495 inline size_t model::n_unused_vars() const { return gid->n_unused_vars(); }
00496 inline const std::string& model::unused_var(unsigned int n) const
00497         { return gid->unused_var(n); }
00498 inline size_t model::n_unused_constrs() const
00499         { return gid->n_unused_constrs(); }
00500 inline const std::string& model::unused_constr(unsigned int n) const
00501         { return gid->unused_constr(n); }
00502                                             
00503 inline unsigned int model::number_of_variables() const
00504 { return gid->number_of_variables(); }
00505 
00506 inline unsigned int model::number_of_constraints() const
00507 { return gid->number_of_constraints(); }
00508 
00509 inline unsigned int model::number_of_nodes() const
00510 { return gid->number_of_nodes(); }
00511 
00512 inline const model::walker& model::node(unsigned int i) const
00513 { return gid->node(i); }
00514 
00515 inline const model::walker& model::var(unsigned int i) const
00516 { return gid->variable(i); }
00517 
00518 inline const model::walker& model::constraint(unsigned int i) const
00519 { return gid->constraint(i); }
00520 
00521 class model::sort_constraints :
00522         public std::binary_function<walker, walker, bool>
00523 {
00524 public:
00525   bool operator()(const walker& _c1, const walker& _c2) const
00526   {
00527     if(_c1.is_leaf() != _c2.is_leaf())
00528       if(_c1.is_leaf()) return true;
00529       else if(_c2.is_leaf()) return false;
00530     if(_c1->sem.degree != _c2->sem.degree)
00531       if(_c1->sem.degree == 1) return true;
00532       else if(_c2->sem.degree == 1) return false;
00533     if(_c1->f_bounds.is_thin() != _c2->f_bounds.is_thin())
00534       return _c1->f_bounds.is_thin() ? true : false;
00535     else if(_c1->f_bounds.is_bounded() == _c2->f_bounds.is_bounded() ||
00536       _c1->f_bounds.is_unbounded_below() == _c2->f_bounds.is_unbounded_below()||
00537       _c1->f_bounds.is_unbounded_above() == _c2->f_bounds.is_unbounded_above())
00538       return _c1->node_num < _c2->node_num;
00539     else if(_c1->f_bounds.is_unbounded_below())
00540       return true;
00541     else if(_c2->f_bounds.is_unbounded_below())
00542       return false;
00543     else 
00544       return _c1->f_bounds.is_bounded() ? false : true;
00545   }
00546 };
00547 
00548 #define SIMPLIFY_0_IS_CONST             1
00549 #define SIMPLIFY_0_CONST_IS_INTEGER     (1<<24)
00550 
00551 #define SIMPLIFY_0_IS_VAR               (1<<1)
00552 
00553 #define SIMPLIFY_0_IS_SUM               (1<<2)
00554 #define SIMPLIFY_0_SUM_IS_SIMPLE        (1<<24)
00555 
00556 #define SIMPLIFY_0_IS_PROD              (1<<3)
00557 #define SIMPLIFY_0_PROD_IS_SIMPLE       (1<<24)
00558 
00559 #define SIMPLIFY_0_IS_MULTIPLICATIVE    (1<<4)
00560 #define SIMPLIFY_0_IS_CORRECTEDMULT     (1<<5)
00561 
00562 #define SIMPLIFY_0_IS_GHOST             (1<<31)
00563 
00564 class model::simplify_visitor_0 : public postorder_visitor<expression_node,
00565                                                 const simplify_visitor_0&,
00566                                                 const simplify_visitor_0&>
00567 {
00568   int num_of_vars;
00569   semantics s;
00570   int n, ndel;
00571   variable_indicator v_i;
00572   std::vector<unsigned int>* delnodes;
00573   std::vector<std::pair<unsigned int,unsigned int> >* deledges;
00574   unsigned int flags;
00575   additional_info_u m;
00576   int nnum;
00577   int l_nnum;
00578   unsigned int l_flags;
00579   semantics l_s;
00580   const std::vector<double> *transfer;
00581   model* __mod;
00582   int r_idx;
00583 
00584 public:
00585   simplify_visitor_0() : num_of_vars(0), s(), n(0), ndel(0), v_i(0),
00586                         delnodes(NULL), deledges(NULL), flags(0), m(0),
00587                         nnum(-1), l_nnum(-1), l_flags(0), l_s(),
00588                         transfer(NULL), __mod(NULL), r_idx(-1) {}
00589 
00590 public:
00591   simplify_visitor_0(int __nv, std::vector<unsigned int>* __dn,
00592                      std::vector<std::pair<unsigned int,unsigned int> >* __de,
00593                      model* __m) :
00594                         num_of_vars(__nv), s(), n(0), ndel(0), v_i(__nv),
00595                         delnodes(__dn), deledges(__de), flags(0), m(0),
00596                         nnum(-1), l_nnum(-1), l_flags(0), l_s(),
00597                         transfer(NULL), __mod(__m), r_idx(-1)
00598         { v_i.clear(); }
00599   // for postorder walking, the copy constructor resets the vsitor
00600   simplify_visitor_0(const simplify_visitor_0& __x) :
00601                       num_of_vars(__x.num_of_vars), s(__x.s),
00602                       n(__x.n), ndel(__x.ndel), v_i(__x.v_i),
00603                       delnodes(__x.delnodes), deledges(__x.deledges),
00604                       flags(__x.flags), m(__x.m), nnum(__x.nnum),
00605                       l_nnum(__x.l_nnum), l_flags(__x.l_flags),
00606                       l_s(__x.l_s), transfer(__x.transfer), __mod(__x.__mod),
00607                       r_idx(__x.r_idx)
00608         { }
00609 
00610   void vinit()
00611      { n = 0; s = semantics(); v_i.clear(); flags = 0;
00612        m = 0; nnum = -1; l_nnum = -1; l_flags = 0; ndel = 0; r_idx = -1;} 
00613   void init() { vinit(); }
00614 
00615     void postorder_help(const expression_node &r, unsigned int n_chld);
00616     bool postorder(expression_node &r);
00617     
00618     const simplify_visitor_0& value() { return *this; }
00619     const simplify_visitor_0& vvalue() { s.degree = -2; return *this; }
00620 
00621     void simple_sum_prod_update(expression_node& r, const simplify_visitor_0& __s)
00622     {
00623       if(__s.flags & SIMPLIFY_0_IS_SUM &&
00624          __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
00625       {
00626         r.params = r.coeffs[0] * __s.m.nd() + r.params.nd();
00627         r.coeffs[0] *= (*__s.transfer)[0];
00628         if(__s.flags & SIMPLIFY_0_IS_GHOST)
00629           transfer_ghost_down(__s.nnum, r.node_num);
00630         else
00631           (*delnodes).push_back(__s.nnum);
00632       }
00633       else if(__s.flags & SIMPLIFY_0_IS_PROD &&
00634               __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
00635       {
00636         r.coeffs[0] *= __s.m.nd();
00637         if(__s.flags & SIMPLIFY_0_IS_GHOST)
00638           transfer_ghost_down(__s.nnum, r.node_num);
00639         else
00640           (*delnodes).push_back(__s.nnum);
00641       }
00642       if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
00643       {
00644         r.coeffs[n] *= __s.m.nd();
00645         if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
00646           __mod->node(__s.nnum)->params = 1.;
00647       }
00648     }
00649 
00650     void transfer_ghost_down(unsigned int nnum, unsigned int pnum)
00651     {
00652       // this is only called for simple sums (n+c) and simple prods (n*c)
00653       model::walker _w = __mod->node(nnum), _wc;
00654       children_iterator _c;
00655       std::vector<unsigned int> unum;
00656       for(_c = _w.child_begin(); _c != _w.child_end(); ++_c)
00657       {
00658         _wc = _w >> _c;
00659         unum.push_back(_wc->node_num);
00660       }
00661       // find the appropriate ghost
00662       model::walker _go = __mod->ghost(nnum);
00663       model::walker _pr = __mod->node(pnum);
00664       bool do_remove = _go.n_parents() == 1;
00665       for(unsigned int i=0; i<unum.size(); ++i)
00666       {
00667         model::walker _gn = __mod->ghost(unum[i]);
00668         if(i == 0)
00669           __mod->replace_edge_to_child(_pr, _go, _gn);
00670         else
00671           __mod->add_edge_back(_pr, _gn);
00672       }
00673       if(do_remove)
00674         __mod->remove_node(_go, nnum);
00675     }
00676 
00677     void vcollect(const simplify_visitor_0& __s);
00678 
00679     void collect(expression_node &r, const simplify_visitor_0& __s);
00680   };
00681 
00682 
00683   inline bool model::children_eq(walker __n1, walker __n2)
00684   {
00685     children_iterator _c1, _c2;
00686     walker _e1, _e2;
00687 
00688     for(_c1 = __n1.child_begin(), _c2 = __n2.child_begin();
00689         _c1 != __n1.child_end(); ++_c1, ++_c2)
00690     {
00691       _e1 = __n1 >> _c1;
00692       _e2 = __n2 >> _c2;
00693       if(_e1.is_sky() != _e2.is_sky())
00694         return false;
00695       if(_e1->node_num != _e2->node_num)
00696         return false;
00697     }
00698     return true;
00699   }
00700 
00701   inline void model::basic_simplify_1_flood(walker __s,
00702       std::vector<int>& _combined)
00703   {
00704     parents_iterator __p;
00705     walker __ew;
00706 
00707     for(__p = __s.parent_begin(); __p != __s.parent_end(); ++__p)
00708     {
00709       __ew = __s << __p;
00710       if(!__ew.is_ground())
00711         ++_combined[__ew->node_num];
00712     }
00713   }
00714 
00715   inline bool model::basic_simplify_1_is_ready(walker __s,
00716       const std::vector<int>& _combined, bool all_finished)
00717   {
00718     parents_iterator _p;
00719     walker _w;
00720 
00721     for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
00722     {
00723       _w = __s << _p;
00724       if(_combined[_w->node_num] == (int)_w->n_children)
00725       {
00726         if(!all_finished)
00727           return true;
00728       }
00729       else if(all_finished)
00730         return false;
00731     }
00732     return all_finished;
00733   }
00734 
00735 #if 0
00736   class model::simplify_visitor_thin : public postorder_visitor<expression_node,
00737                                                                 double>
00738   {
00739   private:
00740     double r;
00741     int last_nn;
00742     
00743   public:
00744     simplify_visitor_thin() { }
00745     
00746     void vinit() { r = INFINITY; } 
00747 
00748     void init() { vinit(); }
00749 
00750     bool postorder(expression_node &r)
00751     {
00752       if(r.operator_type < 0)
00753       {
00754         switch(r.operator_type)
00755         {
00756           case EXPRINFO_CONSTANT:
00757             r = r.params.nd();
00758             break;
00759           case EXPRINFO_VARIABLE:
00760             if(r.f_bounds.is_thin())
00761               r = r.f_bounds.inf();
00762             else
00763               r = INFINITY;
00764             break;
00765           case EXPRINFO_SUM:
00766             flags |= SIMPLIFY_0_IS_SUM;
00767             break;
00768           case EXPRINFO_PROD:
00769             flags |= SIMPLIFY_0_IS_PROD;
00770             m = r.params.nd();
00771             transfer = &r.coeffs;
00772             if(n - ndel == 1) // this is \la*<node>
00773               flags |= SIMPLIFY_0_PROD_IS_SIMPLE;
00774             break;
00775           case EXPRINFO_SQUARE:
00776           case EXPRINFO_INTPOWER:
00777             break;
00778           case EXPRINFO_MAX:
00779           case EXPRINFO_MIN:
00780           case EXPRINFO_INVERT:
00781           case EXPRINFO_DIV:
00782           case EXPRINFO_SQROOT:
00783           case EXPRINFO_POW:
00784           case EXPRINFO_ABS:
00785           case EXPRINFO_EXP:
00786           case EXPRINFO_LOG:
00787           case EXPRINFO_SIN:
00788           case EXPRINFO_COS:
00789           case EXPRINFO_ATAN2:
00790           case EXPRINFO_GAUSS:
00791             s.degree = -1;
00792             break;
00793           case EXPRINFO_LIN:
00794             break;
00795           case EXPRINFO_QUAD:
00796             break;
00797           default:
00798             // give bad messages
00799             break;
00800         }
00801       }
00802       else if(r.operator_type > 0)
00803       {
00804         s.degree = -1;
00805         s.property_flags.convex = t_maybe;
00806         s.property_flags.concave = t_maybe;
00807         s.property_flags.separable = t_maybe;
00808       }
00809       s.dim = v_i.sum(0, num_of_vars);
00810       r.sem = s;
00811       r.v_i = v_i;
00812       if(r.operator_type == EXPRINFO_CONSTANT ||
00813          r.operator_type == EXPRINFO_VARIABLE)
00814         r.n_children = 0;
00815       else
00816         r.n_children = n - ndel;
00817       nnum = r.node_num;
00818       if(s.degree < 0) s.degree = -1;
00819       return false;
00820     }
00821     
00822     const simplify_visitor_thin& value() { return *this; }
00823     const simplify_visitor_thin& vvalue() { s.degree = -2; return *this; }
00824 
00825     void simple_sum_prod_update(expression_node& r, const simplify_visitor_thin& __s)
00826     {
00827       if(__s.flags & SIMPLIFY_0_IS_SUM &&
00828          __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
00829       {
00830         r.params = r.coeffs[0] * __s.m.nd();
00831         r.coeffs[0] *= (*__s.transfer)[0];
00832         (*delnodes).push_back(__s.nnum);
00833       }
00834       else if(__s.flags & SIMPLIFY_0_IS_PROD &&
00835               __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
00836       {
00837         r.coeffs[0] *= __s.m.nd();
00838         (*delnodes).push_back(__s.nnum);
00839       }
00840     }
00841 
00842     void vcollect(const simplify_visitor_thin& __s)
00843     {
00844       if((__s.flags & SIMPLIFY_0_IS_SUM &&
00845           __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE && __s.m.nd() == 0) ||
00846          (__s.flags & SIMPLIFY_0_IS_PROD &&
00847           __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE && __s.m.nd() == 1))
00848       { // there is a <node>+0 or <node>*1 expression on top -> remove
00849         (*delnodes).push_back(__s.nnum);
00850       }
00851     }
00852 
00853     void collect(expression_node &r, const simplify_visitor_thin& __s)
00854     {
00855       if(r.operator_type < 0)
00856       {
00857         switch(r.operator_type)
00858         {
00859           case EXPRINFO_CONSTANT:
00860           case EXPRINFO_VARIABLE:
00861             break;
00862           case EXPRINFO_SUM:
00863             if(n == 0)
00864             {
00865               s.degree = __s.s.degree;
00866               s.property_flags = __s.s.property_flags;
00867             }
00868             else
00869             { 
00870               if(__s.s.degree == -1 || __s.s.degree > s.degree)
00871                 s.degree = __s.s.degree;
00872             }
00873             if(__s.flags & SIMPLIFY_0_IS_CONST)
00874             { 
00875               double help =
00876                   __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
00877                                                                __s.m.nd();
00878               r.params = r.params.nd() + r.coeffs[n-ndel] * help;
00879               r.coeffs.erase(r.coeffs.begin() + n);
00880               (*delnodes).push_back(__s.nnum);
00881               ndel++;
00882             }
00883             else if(__s.flags & SIMPLIFY_0_IS_PROD &&
00884                     __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
00885             {
00886               r.coeffs[n-ndel] *= __s.m.nd();
00887               (*delnodes).push_back(__s.nnum);
00888             }
00889             else if(__s.flags & SIMPLIFY_0_IS_SUM)
00890             {
00891               double help = r.coeffs[n-ndel];
00892 
00893               r.params = r.params.nd() + __s.m.nd();
00894               r.coeffs.erase(r.coeffs.begin()+(n-ndel));
00895               ndel++;
00896               for(std::vector<double>::iterator b = __s.transfer->begin();
00897                   b != __s.transfer->end(); ++b)
00898                 r.coeffs.push_back(*b * help);
00899               n += __s.transfer->size();
00900               (*delnodes).push_back(__s.nnum);
00901             }
00902             break;
00903           case EXPRINFO_PROD:
00904             if(n == 0)
00905             {
00906               s.degree = __s.s.degree;
00907               s.property_flags = __s.s.property_flags;
00908             }
00909             else
00910             { 
00911               if(__s.s.degree == -1 || s.degree == -1)
00912                 s.degree = -1;
00913               else
00914                 s.degree += __s.s.degree;
00915             }
00916             if(r.coeffs[n] != 1)
00917             {
00918               r.params = r.params.nd() * r.coeffs[n];
00919               r.coeffs[n] = 1;
00920             }
00921             if(__s.flags & SIMPLIFY_0_IS_CONST)
00922             { 
00923               double help =
00924                   __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
00925                                                                __s.m.nd();
00926               r.params = r.params.nd() * help;
00927               r.coeffs.pop_back();
00928               (*delnodes).push_back(__s.nnum);
00929               ndel++;
00930             }
00931             else if(__s.flags & SIMPLIFY_0_IS_PROD)
00932             {
00933               r.params = r.params.nd() * __s.m.nd();
00934               r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
00935               n += __s.transfer->size()-1;
00936               (*delnodes).push_back(__s.nnum);
00937             }
00938             break;
00939           case EXPRINFO_MAX:
00940           case EXPRINFO_MIN:
00941             break;
00942           case EXPRINFO_POW:
00943             if(n == 0)
00944             {
00945               if(__s.flags & SIMPLIFY_0_IS_CONST)
00946               { // a^x = exp(x * ln a)
00947                 double help =
00948                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
00949                                                                  __s.m.nd();
00950                 r.operator_type = EXPRINFO_EXP;
00951                 r.coeffs[0] = log(r.coeffs[0] * help) * r.coeffs[1];
00952                 r.coeffs.pop_back();
00953                 (*delnodes).push_back(__s.nnum);
00954                 s.degree = -1;
00955                 ndel++;
00956               }
00957               else
00958                 s.degree = __s.s.degree;
00959               simple_sum_prod_update(r, __s);
00960             }
00961             if(n != 0 && r.params.nd() == 0 &&
00962                __s.flags & SIMPLIFY_0_IS_CONST &&
00963                __s.flags & SIMPLIFY_0_CONST_IS_INTEGER)
00964             {
00965               r.params = __s.m.nn();
00966               r.operator_type = EXPRINFO_INTPOWER;
00967               (*delnodes).push_back(__s.nnum);
00968               s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
00969               ndel++;
00970             }
00971             break;
00972           case EXPRINFO_SQUARE:
00973             s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*2;
00974             if(__s.flags & SIMPLIFY_0_IS_CONST)
00975             { // compute constant expressions
00976               double help =
00977                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
00978                                                               __s.m.nd();
00979               r.operator_type = EXPRINFO_CONSTANT;
00980               help *= r.coeffs[0];
00981               help += r.params.nd();
00982               r.params = help*help;
00983               (*delnodes).push_back(__s.nnum);
00984             }
00985             else
00986               simple_sum_prod_update(r, __s);
00987             break;
00988           case EXPRINFO_SQROOT:
00989             if(__s.flags & SIMPLIFY_0_IS_CONST)
00990             { // compute constant expressions
00991               double help =
00992                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
00993                                                               __s.m.nd();
00994               r.operator_type = EXPRINFO_CONSTANT;
00995               help *= r.coeffs[0];
00996               help += r.params.nd();
00997               r.params = sqrt(help);
00998               (*delnodes).push_back(__s.nnum);
00999             }
01000             else
01001               simple_sum_prod_update(r, __s);
01002             break;
01003           case EXPRINFO_ABS:
01004             if(__s.flags & SIMPLIFY_0_IS_CONST)
01005             { // compute constant expressions
01006               double help =
01007                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01008                                                               __s.m.nd();
01009               r.operator_type = EXPRINFO_CONSTANT;
01010               help *= r.coeffs[0];
01011               help += r.params.nd();
01012               r.params = fabs(help);
01013               (*delnodes).push_back(__s.nnum);
01014             }
01015             else
01016               simple_sum_prod_update(r, __s);
01017             break;
01018           case EXPRINFO_EXP:
01019             if(__s.flags & SIMPLIFY_0_IS_CONST)
01020             { // compute constant expressions
01021               double help =
01022                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01023                                                               __s.m.nd();
01024               r.operator_type = EXPRINFO_CONSTANT;
01025               help *= r.coeffs[0];
01026               help += r.params.nd();
01027               r.params = exp(help);
01028               (*delnodes).push_back(__s.nnum);
01029             }
01030             else
01031               simple_sum_prod_update(r, __s);
01032             break;
01033           case EXPRINFO_LOG:
01034             if(__s.flags & SIMPLIFY_0_IS_CONST)
01035             { // compute constant expressions
01036               double help =
01037                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01038                                                               __s.m.nd();
01039               r.operator_type = EXPRINFO_CONSTANT;
01040               help *= r.coeffs[0];
01041               help += r.params.nd();
01042               r.params = log(help);
01043               (*delnodes).push_back(__s.nnum);
01044             }
01045             else
01046               simple_sum_prod_update(r, __s);
01047             break;
01048           case EXPRINFO_SIN:
01049             if(__s.flags & SIMPLIFY_0_IS_CONST)
01050             { // compute constant expressions
01051               double help =
01052                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01053                                                               __s.m.nd();
01054               r.operator_type = EXPRINFO_CONSTANT;
01055               help *= r.coeffs[0];
01056               help += r.params.nd();
01057               r.params = sin(help);
01058               (*delnodes).push_back(__s.nnum);
01059             }
01060             else
01061               simple_sum_prod_update(r, __s);
01062             break;
01063           case EXPRINFO_COS:
01064             if(__s.flags & SIMPLIFY_0_IS_CONST)
01065             { // compute constant expressions
01066               double help =
01067                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01068                                                               __s.m.nd();
01069               r.operator_type = EXPRINFO_CONSTANT;
01070               help *= r.coeffs[0];
01071               help += r.params.nd();
01072               r.params = cos(help);
01073               (*delnodes).push_back(__s.nnum);
01074             }
01075             else
01076               simple_sum_prod_update(r, __s);
01077             break;
01078           case EXPRINFO_ATAN2:
01079             // const should be computed here, too.
01080             break;
01081           case EXPRINFO_GAUSS:
01082             if(__s.flags & SIMPLIFY_0_IS_CONST)
01083             { // compute constant expressions
01084               double help =
01085                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01086                                                               __s.m.nd();
01087               r.operator_type = EXPRINFO_CONSTANT;
01088               help *= r.coeffs[0];
01089               help -= r.params.d()[0];
01090               help /= r.params.d()[1];
01091               r.params = exp(-help*help);
01092               (*delnodes).push_back(__s.nnum);
01093             }
01094             else if(__s.flags & SIMPLIFY_0_IS_SUM &&
01095                __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
01096             {
01097               std::vector<double> m = r.params.d();
01098 
01099               m[0] -= r.coeffs[0]*__s.m.nd();
01100               r.params = m;
01101               r.coeffs[0] *= (*__s.transfer)[0];
01102               (*delnodes).push_back(__s.nnum);
01103             }
01104             else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01105                     __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01106             {
01107               r.coeffs[0] *= __s.m.nd();
01108               (*delnodes).push_back(__s.nnum);
01109             }
01110             break;
01111           case EXPRINFO_INVERT:
01112             if(r.coeffs[0] != 1)
01113             {
01114               r.params = r.params.nd() / r.coeffs[0];
01115               r.coeffs[0] = 1.;
01116             }
01117             if(__s.flags & SIMPLIFY_0_IS_CONST)
01118             { // compute constant expressions
01119               double help =
01120                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01121                                                               __s.m.nd();
01122               r.operator_type = EXPRINFO_CONSTANT;
01123               r.params = r.params.nd() / help;
01124               (*delnodes).push_back(__s.nnum);
01125             }
01126             break;
01127           case EXPRINFO_DIV:
01128             if(n == 0 && __s.flags & SIMPLIFY_0_IS_CONST)
01129             {
01130               double help =
01131                   __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01132                                                                __s.m.nd();
01133               r.operator_type = EXPRINFO_INVERT;
01134               r.params = help*r.coeffs[0];
01135               r.coeffs.erase(r.coeffs.begin());
01136               (*delnodes).push_back(__s.nnum);
01137               s.degree = __s.s.degree;
01138               ndel++;
01139             }
01140             else if(n == 0)
01141             {
01142               r.params = r.coeffs[0];
01143               r.coeffs[0] = 1;
01144             }
01145             if(n != 0)
01146             {
01147               if(__s.flags & SIMPLIFY_0_IS_CONST)
01148               {
01149                 double help =
01150                      __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01151                                                                __s.m.nd();
01152                 r.operator_type = EXPRINFO_PROD;
01153                 r.params = 1./help;
01154                 r.coeffs.pop_back();
01155                 (*delnodes).push_back(__s.nnum);
01156                 ndel++;
01157               }
01158               else
01159               {
01160                 r.params = r.params.nd() / r.coeffs[1];
01161                 r.coeffs[1] = 1;
01162                 s.degree = -1;
01163               }
01164             }
01165             break;
01166           case EXPRINFO_INTPOWER:
01167             if(r.params.nn() > 0)
01168               s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.nn();
01169             else
01170               s.degree = -1;
01171             if(__s.flags & SIMPLIFY_0_IS_CONST)
01172             { // compute constant expressions
01173               double help =
01174                     __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01175                                                               __s.m.nd();
01176               r.operator_type = EXPRINFO_CONSTANT;
01177               r.params = pow(help, r.params.nn());
01178               (*delnodes).push_back(__s.nnum);
01179             }
01180             break;
01181           case EXPRINFO_LIN:
01182             break;
01183           case EXPRINFO_QUAD:
01184             break;
01185           default:
01186             // give bad messages
01187             break;
01188         }
01189       }
01190       else if(r.operator_type > 0)
01191       {
01192         ;
01193       }
01194       n++;
01195       v_i.set_all(__s.v_i);
01196     }
01197   };
01198 #endif
01199 
01200   inline bool model::simplify_thin()
01201   {
01202     return false;
01203   }
01204 
01205   inline void model::arrange_constraints()
01206   {
01207     sort(constraints.begin(), constraints.end(), sort_constraints());
01208   }
01209 
01210   inline int model::next_num() { return gid->get_node_id(); }
01211   inline int model::next_variable_num() { return gid->get_var_id(); }
01212   inline int model::next_constraint_num() { return gid->get_const_id(); }
01213 
01214   inline void model::renumber_variables()
01215   {
01216     gid->compress_numbers(true);
01217     detect_0chain();
01218   }
01219 
01220   inline void model::compress_numbers()
01221   {
01222     gid->compress_numbers();
01223     detect_0chain();
01224   }
01225 
01226   struct model::__docompare_nodes
01227   {
01228     bool operator() (const model::walker& _a, unsigned int _b) const
01229       {return _a->node_num < _b;}
01230     bool operator() (unsigned int _a, const model::walker& _b) const
01231       {return _a < _b->node_num;}
01232     bool operator() (const model::walker& _a, const model::walker& _b) const
01233       {return _a->node_num < _b->node_num;}
01234   };
01235 
01236   struct model::__docompare_variables
01237   {
01238     bool operator() (const model::walker& _a, unsigned int _b) const
01239       {return _a->params.nn() < (int)_b;}
01240     bool operator() (unsigned int _a, const model::walker& _b) const
01241       {return (int)_a < _b->params.nn();}
01242     bool operator() (const model::walker& _a, const model::walker& _b) const
01243       {return _a->params.nn() < _b->params.nn();}
01244   };
01245 
01246   inline model::walker model::store_node(const walker& _w)
01247   {
01248     if(!gid->have_glob_ref(_w->node_num))
01249       gid->number_of_nodes(_w->node_num+1);
01250 
01251     ref_iterator __x(lower_bound(node_ref.begin(),
01252                   node_ref.end(), _w->node_num, __docompare_nodes()));
01253 
01254     if(__x != node_ref.end() && (*__x)->node_num == _w->node_num)
01255       *__x = _w;
01256     else
01257       node_ref.insert(__x, _w);
01258     gid->mk_globref(_w->node_num, _w);
01259     return _w;
01260   }
01261 
01262   inline model::walker model::store_variable(const walker& _w)
01263   {
01264     if(_w->node_num >= number_of_nodes())
01265       gid->number_of_nodes(_w->node_num+1);
01266 
01267     ref_iterator __x(lower_bound(var_ref.begin(),
01268                   var_ref.end(), _w->params.nn(), __docompare_variables()));
01269 
01270     if(__x != var_ref.end() && (*__x)->params.nn() == _w->params.nn())
01271       *__x = _w;
01272     else
01273       var_ref.insert(__x, _w);
01274     gid->mk_gvarref(_w->params.nn(), _w);
01275     return _w;
01276   }
01277 
01278   inline model::walker model::store_constraint(const walker& _w)
01279   {
01280     unsigned int dummy;
01281     if(!gid->get_const_num(_w->node_num, dummy))
01282     {
01283       // it is not already stored
01284       constraints.push_back(_w);
01285       gid->mk_gconstref(next_constraint_num(), _w);
01286     }
01287     return _w;
01288   }
01289 
01290   inline model::walker model::store_ghost(const walker& _w)
01291   {
01292     if(!gid->have_glob_ref(_w->node_num))
01293       gid->number_of_nodes(_w->node_num+1);
01294 
01295     ref_iterator __x(lower_bound(ghost_ref.begin(),
01296                   ghost_ref.end(), _w->node_num, __docompare_nodes()));
01297 
01298     if(__x != ghost_ref.end() && (*__x)->node_num == _w->node_num)
01299       *__x = _w;
01300     else
01301       ghost_ref.insert(__x, _w);
01302     return _w;
01303   }
01304 
01305   inline void model::free_node_num(unsigned int _nnum)
01306   {
01307 #if MODEL_INLINE_DEBUG
01308     std::cout << "Removing node " << _nnum << std::endl;
01309 #endif
01310     ref_iterator __x(lower_bound(node_ref.begin(),
01311                   node_ref.end(), _nnum, __docompare_nodes()));
01312     if(__x != node_ref.end() && (*__x)->node_num == _nnum)
01313       node_ref.erase(__x);
01314     gid->remove_node_id(_nnum);
01315   }
01316 
01317   inline void model::remove_node(const walker& _w, unsigned int _nnum)
01318   {
01319     walker __h = _w;
01320     unsigned int cn;
01321 
01322     if(_w->operator_type == EXPRINFO_GHOST)
01323     { // only remove ghosts from the reference
01324       ref_iterator __x(lower_bound(ghost_ref.begin(),
01325                     ghost_ref.end(), _nnum, __docompare_nodes()));
01326       if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
01327         ghost_ref.erase(__x);
01328       erase(__h);
01329       return;
01330     }
01331     if(is_empty(_w))
01332     {
01333       std::cerr << "Error: Trying to remove node, which is already removed.";
01334       std::terminate();
01335       return;
01336     }
01337     if(_w == objective)
01338     {
01339       if(_w->n_children != 1)
01340       // cannot erase the objective node unless it has only one child
01341       // never mind about not removing it, it has to be a root node
01342       // anyway.
01343         return;
01344       walker _ew = _w;
01345       objective = _ew >> _ew.child_begin();
01346     }
01347     if(get_const_num(_nnum, cn))
01348     {
01349       unsigned int ccn;
01350       if(_w->n_children != 0)
01351       {
01352         walker _ew = _w;
01353         _ew >>= _ew.child_begin();
01354         if(get_const_num(_ew->node_num, ccn)) // the child is a constraint as well
01355         {
01356           gid->unused_constr(const_name(cn));
01357           gid->remove_const_id(cn);
01358         }
01359         else
01360           gid->make_const_back_ref(_ew->node_num, cn);
01361       }
01362       else
01363       {
01364         gid->unused_constr(const_name(cn));
01365         gid->remove_const_id(cn);
01366       }
01367       // remove the constraint from the constraints array
01368       for(std::vector<walker>::iterator __x = constraints.begin();
01369           __x != constraints.end(); ++__x)
01370         if(*__x == _w)
01371         {
01372           constraints.erase(__x);
01373           break;
01374         }
01375     }
01376     ref_iterator __x(lower_bound(node_ref.begin(),
01377                   node_ref.end(), _nnum, __docompare_nodes()));
01378     if(__x != node_ref.end() && (*__x)->node_num == _nnum)
01379       node_ref.erase(__x);
01380     free_node_num(_nnum);
01381     erase(__h);
01382   }
01383 
01384   inline void model::remove_node(const walker& _w)
01385   {
01386     remove_node(_w, _w->node_num);
01387   }
01388 
01389   inline void model::remove_node(unsigned int __node_num)
01390   {
01391     remove_node(gid->node(__node_num), __node_num);
01392   }
01393 
01394   inline void model::new_variables(int _new_num_of_vars)
01395   {
01396     gid->number_of_variables(_new_num_of_vars);
01397   }
01398 
01399   inline model::walker model::constant(double _constant)
01400   {
01401     expression_node _en(EXPRINFO_CONSTANT, next_num());
01402 
01403     _en.v_i.reserve(gid->number_of_variables());
01404     _en.v_i.clear();
01405     _en.params = _constant;
01406 
01407     return store_node(between_back(ground(), sky(), _en));
01408   }
01409 
01410   inline model::walker model::constant(const std::vector<double>& _constant)
01411   {
01412     expression_node _en(EXPRINFO_CONSTANT, next_num());
01413 
01414     _en.v_i.reserve(gid->number_of_variables());
01415     _en.v_i.clear();
01416     _en.params = _constant;
01417 
01418     return store_node(between_back(ground(), sky(), _en));
01419   }
01420 
01421   inline model::walker model::ghost(unsigned int _nnum)
01422   {
01423     ref_iterator __x;
01424 
01425     __x = lower_bound(ghost_ref.begin(), ghost_ref.end(), _nnum,
01426                         __docompare_nodes());
01427     if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
01428       return *__x;
01429     else // make a new one
01430     {
01431       walker __r;
01432       expression_node _en(EXPRINFO_GHOST, _nnum);
01433       _en.params = false;
01434       _en.f_bounds = interval(-INFINITY,INFINITY);
01435       __r = between_back(ground(), sky(), _en);
01436       ghost_ref.insert(__x, __r);
01437       return __r;
01438     }
01439   }
01440 
01441   inline model::walker model::binary(const walker& _op1, const walker& _op2,
01442                               int expr_type, double _coeff1, double _coeff2)
01443   {
01444     expression_node _en(expr_type, next_num());
01445     std::vector<walker> _w(2);
01446 
01447     _en.v_i = (*_op1).v_i;
01448     _en.v_i.set_all((*_op2).v_i);
01449     _w[0] = _op1;
01450     _w[1] = _op2;
01451     _en.coeffs.push_back(_coeff1);
01452     _en.coeffs.push_back(_coeff2);
01453     if(expr_type == EXPRINFO_PROD || expr_type == EXPRINFO_DIV||
01454        expr_type == EXPRINFO_INVERT)
01455       _en.params = 1.;
01456     else
01457       _en.params = 0.;
01458     return store_node(split_back(ground(), _w, _en));
01459   }
01460 
01461   inline model::walker model::binary(const walker& _op1, const walker& _op2,
01462                               int expr_type, additional_info_u _params,
01463                               double _coeff1, double _coeff2)
01464   {
01465     expression_node _en(expr_type, next_num());
01466     std::vector<walker> _w(2);
01467 
01468     _en.v_i = (*_op1).v_i;
01469     _en.v_i.set_all((*_op2).v_i);
01470     _en.params = _params;
01471     _w[0] = _op1;
01472     _w[1] = _op2;
01473     _en.coeffs.push_back(_coeff1);
01474     _en.coeffs.push_back(_coeff2);
01475     return store_node(split_back(ground(), _w, _en));
01476   }
01477 
01478   inline model::walker model::unary(const walker& _op1, int expr_type,
01479                              double _coeff)
01480   {
01481     expression_node _en(expr_type, next_num());
01482 
01483     _en.v_i = (*_op1).v_i;
01484     _en.coeffs.push_back(_coeff);
01485     if(expr_type == EXPRINFO_INVERT)
01486       _en.params = 1.;
01487     else
01488       _en.params = 0.;
01489     return store_node(split_back(ground(), _op1, _en));
01490   }
01491 
01492   inline model::walker model::unary(const walker& _op1, int expr_type,
01493                              additional_info_u _params, double _coeff)
01494   {
01495     expression_node _en(expr_type, next_num());
01496 
01497     _en.v_i = (*_op1).v_i;
01498     _en.params = _params;
01499     _en.coeffs.push_back(_coeff);
01500     return store_node(split_back(ground(), _op1, _en));
01501   }
01502 
01503   inline model::walker model::nary(const std::vector<walker>& _op, int expr_type,
01504                                    const std::vector<double>& _coeffs)
01505   {
01506     expression_node _en(expr_type, next_num());
01507 
01508     _en.v_i = (*_op[0]).v_i;
01509     for(const_ref_iterator b = _op.begin(); b != _op.end(); ++b)
01510       _en.v_i.set_all((**b).v_i);
01511     if(_coeffs.size() == 0)
01512       _en.coeffs.insert(_en.coeffs.end(),_op.size(),1.0);
01513     else
01514       _en.coeffs = _coeffs;
01515     if(expr_type == EXPRINFO_PROD)
01516       _en.params = 1.;
01517     else
01518       _en.params = 0.;
01519     return store_node(split_back(ground(), _op, _en));
01520   }
01521 
01522   inline model::walker model::nary(const std::vector<walker>& _op, int expr_type,
01523                             additional_info_u _params,
01524                             const std::vector<double>& _coeffs)
01525   {
01526     expression_node _en(expr_type, next_num());
01527 
01528     _en.v_i = (*_op[0]).v_i;
01529     for(const_ref_iterator b = _op.begin(); b != _op.end(); ++b)
01530       _en.v_i.set_all((**b).v_i);
01531     _en.params = _params;
01532     if(_coeffs.size() == 0)
01533       _en.coeffs.insert(_en.coeffs.end(),_op.size(),1.0);
01534     else
01535       _en.coeffs = _coeffs;
01536     return store_node(split_back(ground(), _op, _en));
01537   }
01538 
01539   inline void model::clr_sky_ground_link()
01540   {
01541     if(ground().n_children() != 1 || !empty())
01542       remove_edge(ground(), sky());
01543   }
01544 
01545   inline void model::set_counters()
01546   {
01547     ref_iterator __e = node_ref.end();
01548     walker _x;
01549     for(ref_iterator __x = node_ref.begin(); __x != __e; ++__x)
01550     {
01551       _x = *__x;
01552       if(_x.n_children() == 1)
01553       {
01554         walker _c = _x >> _x.child_begin();
01555         if(_c == sky())
01556           _x->n_children = 0;
01557         else
01558           _x->n_children = 1;
01559       }
01560       else
01561         _x->n_children = _x.n_children();
01562       if(_x.n_parents() == 1)
01563       {
01564         walker _c = _x >> _x.parent_begin();
01565         if(_c == ground())
01566           _x->n_parents = 0;
01567         else
01568           _x->n_parents = 1;
01569       }
01570       else
01571         _x->n_parents = _x.n_parents();
01572     }
01573   }
01574 
01575   struct model::detect_0chain_visitor_st
01576   {
01577     std::pair<unsigned int,unsigned int> r;    // return value (node num, depth)
01578     unsigned int *f;                      // counter
01579     std::vector<unsigned int>* t;              // type
01580     std::vector<unsigned int>* d;              // depth
01581     std::vector<unsigned int>* nn;             // base
01582     bool new_number;                      // a new chain??
01583   };
01584 
01585   class model::detect_0chain_visitor : public
01586     cached_forward_evaluator_base<model::detect_0chain_visitor_st,
01587                           expression_node, std::pair<unsigned int,unsigned int>,
01588                           model::walker>
01589   {
01590   private:
01591     typedef cached_forward_evaluator_base<model::detect_0chain_visitor_st,
01592                   expression_node, std::pair<unsigned int,unsigned int>,
01593                   model::walker> _Base;
01594   public:
01595     detect_0chain_visitor(std::vector<unsigned int>& __t, std::vector<unsigned int>& __d,
01596                              std::vector<unsigned int>& __nn, unsigned int &d)
01597           {
01598             eval_data.r = std::make_pair(0,0);
01599             eval_data.t = &__t;
01600             eval_data.d = &__d;
01601             eval_data.f = &d;
01602             eval_data.nn = &__nn;
01603             eval_data.new_number = false;
01604           }
01605 
01606     detect_0chain_visitor(const detect_0chain_visitor& __x) : _Base(__x)
01607           {} // constructor os assign the value
01608 
01609     ~detect_0chain_visitor() {} // destructor
01610 
01611     void initialize() { return; } // does nothing
01612 
01613     bool is_cached(const expression_node& __data)
01614       { return (*eval_data.t)[__data.node_num] != 0; }
01615 
01616     void retrieve_from_cache(const expression_node& __data)
01617       { eval_data.r = std::make_pair((*eval_data.t)[__data.node_num],
01618                                 (*eval_data.d)[__data.node_num]); }
01619 
01620     int initialize(const expression_node& __data)
01621       { 
01622         if(__data.operator_type == EXPRINFO_VARIABLE)
01623         {
01624           unsigned int __h;
01625           eval_data.new_number = true;
01626           __h = (*eval_data.f)++;
01627           eval_data.r = std::make_pair(__h,0);
01628           (*eval_data.nn).push_back(__data.node_num);
01629         }
01630         else
01631         {
01632           eval_data.new_number = false;
01633           eval_data.r = std::make_pair(0,0);
01634         }
01635         return 1;
01636       }
01637 
01638     void calculate(const expression_node& __data)
01639       {
01640         (*eval_data.t)[__data.node_num] = eval_data.r.first;
01641         (*eval_data.d)[__data.node_num] = eval_data.r.second;
01642       }
01643 
01644     int update(const std::pair<unsigned int,unsigned int>& __rval) { return 0; }
01645 
01646     int update(const expression_node& __data,
01647                 const std::pair<unsigned int,unsigned int>& __rval)
01648       {
01649         if(__data.operator_type == EXPRINFO_CONSTANT ||
01650            __data.operator_type == EXPRINFO_VARIABLE || __rval.first == 0)
01651           return 0;
01652         if(eval_data.r.first == 0)
01653           eval_data.r = std::make_pair(__rval.first,__rval.second+1);
01654         else if(eval_data.r.first == __rval.first)
01655           eval_data.r.second++;  // so it definitely is >1 later.
01656         else if(!eval_data.new_number)
01657         {
01658           int __h;
01659           eval_data.new_number = true;
01660           __h = (*eval_data.f)++;
01661           eval_data.r = std::make_pair(__h,0);
01662           (*eval_data.nn).push_back(__data.node_num);
01663         }
01664         return 0;
01665       }
01666 
01667     std::pair<unsigned int,unsigned int> calculate_value(bool eval_all)
01668       { return eval_data.r; }
01669   };
01670 
01671   struct model::lincoeff_visitor_ret
01672   {
01673     bool was_lin;
01674     bool was_const;
01675     int node_num;
01676     double const_trans;
01677   };
01678 
01679   struct model::lincoeff_visitor_st
01680   {
01681     const model* mod;
01682     const std::vector<interval>* ranges;
01683     sparse_vector<double>* coeffs;
01684     //mtl::compressed1D<double>* coeffs;
01685     double* constant;
01686     double old_trans, trans, mm_help;
01687     lincoeff_visitor_ret r;
01688     int old_nlin, in_nlin;
01689     unsigned int n;
01690   };
01691 
01692   class model::lincoeff_visitor : public
01693     cached_backward_evaluator_base<lincoeff_visitor_st, expression_node,
01694                             lincoeff_visitor_ret, model::walker>
01695   {
01696   private:
01697     typedef cached_backward_evaluator_base<lincoeff_visitor_st, expression_node,
01698                               lincoeff_visitor_ret, model::walker> _Base;
01699 
01700   public:
01701     lincoeff_visitor(const std::vector<interval>* _rg,
01702                      sparse_vector<double>* _cf, double* _cs,
01703                      const model* _m)
01704     {
01705       eval_data.trans = 1;
01706       eval_data.old_trans = 1;
01707       eval_data.n = 0;
01708       eval_data.r.was_lin = true;
01709       eval_data.r.was_const = false;
01710       eval_data.r.const_trans = 0;
01711       eval_data.r.node_num = -1;
01712       eval_data.old_nlin = -1;
01713       eval_data.in_nlin = -1;
01714       eval_data.ranges = _rg;
01715       eval_data.coeffs = _cf;
01716       eval_data.constant = _cs;
01717       eval_data.mod = _m;
01718     }
01719 
01720     lincoeff_visitor(const lincoeff_visitor& __x) : _Base(__x) {}
01721 
01722     ~lincoeff_visitor() {}
01723 
01724     bool is_cached(const expression_node& __data)
01725     {
01726       return (__data.operator_type == EXPRINFO_LIN ||
01727           __data.operator_type == EXPRINFO_QUAD);
01728     }
01729 
01730     void initialize()
01731     {
01732       eval_data.n = 0;
01733       eval_data.r.was_lin = false;
01734       eval_data.r.was_const = false;
01735       eval_data.r.node_num = -1;
01736       eval_data.r.const_trans = 0;
01737       eval_data.old_nlin = eval_data.in_nlin;
01738       eval_data.old_trans = eval_data.trans;
01739     }
01740 
01741     void initialize(const expression_node& __data)
01742     {
01743       eval_data.n = 0;
01744       eval_data.r.was_lin = false;
01745       eval_data.r.was_const = false;
01746       eval_data.r.node_num = __data.node_num;
01747       eval_data.r.const_trans = 0;
01748       eval_data.old_nlin = eval_data.in_nlin;
01749       eval_data.old_trans = eval_data.trans;
01750     }
01751 
01752     void retrieve_from_cache(const expression_node& __data)
01753     {
01754       if(__data.operator_type == EXPRINFO_LIN)
01755       {
01756         eval_data.r.was_lin = true;
01757         if(eval_data.trans == 1)
01758         {
01759           linalg_add(*eval_data.coeffs, eval_data.mod->lin[__data.params.nn()],
01760               *eval_data.coeffs);
01761         }
01762         else
01763         {
01764           linalg_add(*eval_data.coeffs,
01765               linalg_scale(eval_data.mod->lin[__data.params.nn()],
01766                            eval_data.trans),
01767               *eval_data.coeffs);
01768         }
01769       }
01770       else if(__data.operator_type == EXPRINFO_QUAD)
01771         eval_data.r.was_lin = eval_data.r.was_const = false;
01772     }
01773 
01774     int calculate(const expression_node& __data)
01775     {
01776       if(__data.operator_type < 0)
01777       {
01778         switch(__data.operator_type)
01779         {
01780           case EXPRINFO_CONSTANT:
01781             eval_data.r.was_lin = true;
01782             eval_data.r.was_const = true;
01783             eval_data.r.const_trans = __data.params.nd();
01784             break;
01785           case EXPRINFO_VARIABLE:
01786             if(eval_data.ranges &&
01787                (*eval_data.ranges)[__data.node_num].is_thin())
01788             {
01789               eval_data.r.was_const = true;
01790               eval_data.r.const_trans =
01791                                   (*eval_data.ranges)[__data.node_num].sup();
01792             }
01793             else if(__data.f_bounds.is_thin())
01794             {
01795               eval_data.r.was_const = true;
01796               eval_data.r.const_trans = __data.f_bounds.sup();
01797             }
01798             else if(eval_data.old_nlin == -1)
01799               (*eval_data.coeffs)[__data.params.nn()] += eval_data.old_trans;
01800             eval_data.r.was_lin = true;
01801             break;
01802           case EXPRINFO_SUM:
01803             if(eval_data.old_nlin == -1)
01804               *eval_data.constant += eval_data.old_trans * __data.params.nd();
01805             break;
01806           case EXPRINFO_PROD:
01807           case EXPRINFO_DIV:
01808             eval_data.old_trans *= __data.params.nd();
01809             eval_data.in_nlin = 1;
01810             break;
01811           case EXPRINFO_INVERT:
01812             eval_data.old_trans *= __data.params.nd();
01813             eval_data.in_nlin = 2;
01814             break;
01815           case EXPRINFO_MAX:
01816           case EXPRINFO_MIN:
01817             eval_data.in_nlin = -2;
01818             eval_data.r.was_lin = eval_data.r.was_const = true;
01819             eval_data.r.const_trans = __data.params.nd();
01820             break;
01821           case EXPRINFO_ABS:
01822             if(eval_data.ranges)
01823             {
01824               if((*eval_data.ranges)[__data.node_num].sup() <= 0)
01825                 eval_data.old_trans *= -1;
01826               else if((*eval_data.ranges)[__data.node_num].inf() < 0)
01827                 eval_data.in_nlin = 1;
01828             }
01829             else
01830             {
01831               if(__data.f_bounds.sup() <= 0)
01832               {
01833                 eval_data.old_trans *= -1;
01834               }
01835               else if(__data.f_bounds.inf() < 0)
01836                 eval_data.in_nlin = 1;
01837             }
01838             break;
01839           case EXPRINFO_ATAN2:
01840             eval_data.in_nlin = 2;
01841             break;
01842           case EXPRINFO_POW:
01843             eval_data.in_nlin = 2;
01844             break;
01845           case EXPRINFO_INTPOWER:
01846             if(__data.params.nn() != 1)
01847               eval_data.in_nlin = 2;
01848             break;
01849           case EXPRINFO_SQUARE:
01850           case EXPRINFO_SQROOT:
01851           case EXPRINFO_EXP:
01852           case EXPRINFO_LOG:
01853           case EXPRINFO_SIN:
01854           case EXPRINFO_COS:
01855           case EXPRINFO_GAUSS:
01856             eval_data.in_nlin = 2;
01857             break;
01858           case EXPRINFO_LIN:
01859           case EXPRINFO_QUAD:
01860             std::cerr << "Must not be here in lincoeff_visitor" << std::endl;
01861             throw "Strange error";
01862             break;
01863           default:
01864             std::cerr << "Unknown expression type in get_linear_coeffs" <<
01865               std::endl;
01866             throw "Programming error";
01867             break;
01868         }
01869       }
01870       else if(__data.operator_type > 0)
01871       {
01872         eval_data.r.was_lin = false;
01873         eval_data.r.was_const = false;
01874         eval_data.in_nlin = 3;
01875       }
01876       if(!__data.coeffs.empty())
01877         eval_data.trans = eval_data.old_trans * __data.coeffs[0];
01878       return 1;
01879     }
01880 
01881     int update(const expression_node& __data, const lincoeff_visitor_ret& __rval)
01882     {
01883       if(__data.operator_type < 0)
01884       {
01885         switch(__data.operator_type)
01886         {
01887           case EXPRINFO_CONSTANT:
01888           case EXPRINFO_VARIABLE:
01889             break;
01890           case EXPRINFO_SUM:
01891             if(eval_data.n == 0)
01892             {
01893               eval_data.r.was_lin = __rval.was_lin;
01894               eval_data.r.was_const = __rval.was_const;
01895             }
01896             else if(__rval.was_const && eval_data.r.was_const)
01897             {
01898               eval_data.r.was_lin = true;
01899               eval_data.r.const_trans = 
01900                 (eval_data.n == 0 ? __rval.const_trans
01901                            : __rval.const_trans + eval_data.r.const_trans);
01902             }
01903             else if(__rval.was_const && eval_data.r.was_lin)
01904               eval_data.r.const_trans += __rval.const_trans;
01905             else if(eval_data.r.was_const && __rval.was_lin)
01906             {
01907               eval_data.r.was_const = false;
01908               eval_data.r.was_lin = true;
01909             }
01910             else if(!__rval.was_lin)
01911               eval_data.r.was_lin = false;
01912             if(eval_data.n == __data.n_children - 1)
01913             {
01914               if(eval_data.r.was_const)
01915                 eval_data.r.const_trans += __data.params.nd();
01916               else if(eval_data.r.was_lin && eval_data.old_nlin == -1)
01917                 *eval_data.constant += eval_data.old_trans*
01918                   (eval_data.r.const_trans + __data.params.nd());
01919             }
01920             break;
01921           case EXPRINFO_PROD:
01922             if(eval_data.n == 0)
01923               eval_data.r = __rval;
01924             else if(__rval.was_const && eval_data.r.was_const)
01925             {
01926               eval_data.r.was_lin = true;
01927               eval_data.r.const_trans = 
01928                 (eval_data.n == 0 ? __rval.const_trans
01929                            : __rval.const_trans * eval_data.r.const_trans);
01930             }
01931             else if(__rval.was_const && eval_data.r.was_lin)
01932               eval_data.r.const_trans *= __rval.const_trans;
01933             else if(eval_data.r.was_const && __rval.was_lin)
01934             {
01935               eval_data.r.was_const = false;
01936               eval_data.r.was_lin = true;
01937               eval_data.r.node_num = __rval.node_num;
01938             }
01939             else
01940               eval_data.r.was_const = eval_data.r.was_lin = false;
01941             if(eval_data.n == __data.n_children - 1)
01942             {
01943               if(eval_data.r.was_lin && !eval_data.r.was_const)
01944               {
01945                 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
01946                                     eval_data.constant, eval_data.mod);
01947                 lv.eval_data.trans =
01948                                   eval_data.old_trans * eval_data.r.const_trans;
01949                 eval_data.r = evaluate(lv,
01950                                   eval_data.mod->node(eval_data.r.node_num));
01951               }
01952               else if(eval_data.r.was_const)
01953                 eval_data.r.const_trans *= __data.params.nd();
01954               eval_data.r.node_num = __data.node_num;
01955             }
01956             break;
01957           case EXPRINFO_INVERT:
01958             if(__rval.was_const)
01959             {
01960               eval_data.r.was_const = true;
01961               eval_data.r.was_lin = true;
01962               eval_data.r.const_trans =
01963                           __data.params.nd()/__rval.const_trans;
01964             }
01965             else
01966               eval_data.r.was_lin = false;
01967             break;
01968           case EXPRINFO_DIV:
01969             if(__rval.was_const)
01970             {
01971               if(eval_data.n == 0)
01972               {
01973                 eval_data.r.const_trans = __rval.const_trans;
01974                 eval_data.r.was_const = true;
01975               }
01976               else if(eval_data.n == 1)
01977               {
01978                 if(eval_data.r.was_const && __rval.const_trans != 0)
01979                 {
01980                   eval_data.r.const_trans =
01981                           eval_data.r.const_trans/__rval.const_trans;
01982                   eval_data.r.was_lin = true;
01983                 }
01984                 else
01985                   eval_data.r.was_lin = eval_data.r.was_const = false;
01986               }
01987             }
01988             else
01989               eval_data.r.was_const = eval_data.r.was_lin = false;
01990             break;
01991           case EXPRINFO_MAX:
01992             if(__rval.was_const && eval_data.r.was_const)
01993             {
01994               if(__rval.const_trans > eval_data.r.const_trans)
01995                 eval_data.r.const_trans = __rval.const_trans;
01996             }
01997             else if(__rval.was_const && !eval_data.r.was_const)
01998             {
01999               if(__rval.const_trans > eval_data.mm_help)
02000               {
02001                 eval_data.r.was_const = true;
02002                 eval_data.r.was_lin = true;
02003                 eval_data.r.const_trans = __rval.const_trans;
02004               }
02005             }
02006             else if(eval_data.r.was_const && !__rval.was_const)
02007             {
02008               interval _rg =
02009                  (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02010               if(eval_data.r.const_trans <= _rg.sup())
02011               {
02012                 eval_data.r.was_const = false;
02013                 eval_data.r.was_lin = __rval.was_lin;
02014                 eval_data.r.node_num = __rval.node_num;
02015                 eval_data.r.const_trans = _rg.inf();
02016                 eval_data.mm_help = _rg.sup();
02017                 eval_data.in_nlin = eval_data.n;
02018               }
02019             }
02020             else // both were not const
02021             {
02022               interval _rg =
02023                  (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02024               if(eval_data.r.const_trans <= _rg.sup()) // otherwise no change
02025               {
02026                 if(eval_data.mm_help < _rg.inf()) // the new one rules
02027                 {
02028                   eval_data.r.was_lin = __rval.was_lin;
02029                   eval_data.r.node_num = __rval.node_num;
02030                   eval_data.r.const_trans = _rg.inf();
02031                   eval_data.mm_help = _rg.sup();
02032                   eval_data.in_nlin = eval_data.n;
02033                 }
02034                 else // they mix
02035                 {
02036                   eval_data.r.was_lin = false;
02037                   if(_rg.inf() < eval_data.r.const_trans)
02038                     eval_data.r.const_trans = _rg.inf();
02039                   if(_rg.sup() > eval_data.mm_help)
02040                     eval_data.mm_help = _rg.sup();
02041                 }
02042               }
02043             }
02044             if(eval_data.n == __data.n_children - 1)
02045             {
02046               if(eval_data.r.was_lin && !eval_data.r.was_const &&
02047                  eval_data.old_nlin == -1)
02048               {
02049                 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02050                                     eval_data.constant, eval_data.mod);
02051                 lv.eval_data.trans =
02052                           eval_data.old_trans * __data.coeffs[eval_data.in_nlin];
02053                 eval_data.r = evaluate(lv,
02054                                   eval_data.mod->node(eval_data.r.node_num));
02055               }
02056               eval_data.r.node_num = __data.node_num;
02057             }
02058             break;
02059           case EXPRINFO_MIN:
02060             if(__rval.was_const && eval_data.r.was_const)
02061             {
02062               if(__rval.const_trans < eval_data.r.const_trans)
02063                 eval_data.r.const_trans = __rval.const_trans;
02064             }
02065             else if(__rval.was_const && !eval_data.r.was_const)
02066             {
02067               if(__rval.const_trans < eval_data.mm_help)
02068               {
02069                 eval_data.r.was_const = true;
02070                 eval_data.r.was_lin = true;
02071                 eval_data.r.const_trans = __rval.const_trans;
02072               }
02073             }
02074             else if(eval_data.r.was_const && !__rval.was_const)
02075             {
02076               interval _rg =
02077                  (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02078               if(eval_data.r.const_trans >= _rg.inf())
02079               {
02080                 eval_data.r.was_const = false;
02081                 eval_data.r.was_lin = __rval.was_lin;
02082                 eval_data.r.node_num = __rval.node_num;
02083                 eval_data.r.const_trans = _rg.sup();
02084                 eval_data.mm_help = _rg.inf();
02085                 eval_data.in_nlin = eval_data.n;
02086               }
02087             }
02088             else // both were not const
02089             {
02090               interval _rg =
02091                  (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02092               if(eval_data.r.const_trans >= _rg.inf()) // otherwise no change
02093               {
02094                 if(eval_data.mm_help > _rg.sup()) // the new one rules
02095                 {
02096                   eval_data.r.was_lin = __rval.was_lin;
02097                   eval_data.r.node_num = __rval.node_num;
02098                   eval_data.r.const_trans = _rg.sup();
02099                   eval_data.mm_help = _rg.inf();
02100                   eval_data.in_nlin = eval_data.n;
02101                 }
02102                 else // they mix
02103                 {
02104                   eval_data.r.was_lin = false;
02105                   if(_rg.sup() > eval_data.r.const_trans)
02106                     eval_data.r.const_trans = _rg.sup();
02107                   if(_rg.inf() < eval_data.mm_help)
02108                     eval_data.mm_help = _rg.inf();
02109                 }
02110               }
02111             }
02112             if(eval_data.n == __data.n_children - 1)
02113             {
02114               if(eval_data.r.was_lin && !eval_data.r.was_const &&
02115                  eval_data.old_nlin == -1)
02116               {
02117                 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02118                                     eval_data.constant, eval_data.mod);
02119                 lv.eval_data.trans =
02120                           eval_data.old_trans * __data.coeffs[eval_data.in_nlin];
02121                 eval_data.r = evaluate(lv,
02122                           eval_data.mod->node(eval_data.r.node_num));
02123               }
02124               eval_data.r.node_num = __data.node_num;
02125             }
02126             break;
02127           case EXPRINFO_ABS:
02128             if(__rval.was_const)
02129             {
02130               eval_data.r.was_const = eval_data.r.was_lin = true;
02131               eval_data.r.const_trans = fabs(__data.coeffs[0]*__rval.const_trans+
02132                   __data.params.nd());
02133             }
02134             else if(eval_data.ranges && eval_data.old_nlin == -1)
02135             {
02136               if((*eval_data.ranges)[__data.node_num].sup() <= 0)
02137                 *eval_data.constant -= eval_data.old_trans*__data.params.nd();
02138               else if((*eval_data.ranges)[__data.node_num].inf() >= 0)
02139                 *eval_data.constant += eval_data.old_trans*__data.params.nd();
02140             }
02141             else if(eval_data.old_nlin == -1)
02142             {
02143               if(__data.f_bounds.sup() <= 0)
02144                 *eval_data.constant -= eval_data.old_trans*__data.params.nd();
02145               else if(__data.f_bounds.inf() >= 0)
02146                 *eval_data.constant += eval_data.old_trans*__data.params.nd();
02147             }
02148             break;
02149           case EXPRINFO_SQUARE:
02150             if(__rval.was_const)
02151             {
02152               eval_data.r.was_const = eval_data.r.was_lin = true;
02153               eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans+
02154                   __data.params.nd();
02155               eval_data.r.const_trans *= eval_data.r.const_trans;
02156             }
02157             else
02158               eval_data.r.was_lin = false;
02159             break;
02160           case EXPRINFO_SQROOT:
02161             if(__rval.was_const)
02162             {
02163               eval_data.r.was_const = eval_data.r.was_lin = true;
02164               eval_data.r.const_trans = sqrt(__data.coeffs[0]*__rval.const_trans+
02165                   __data.params.nd());
02166             }
02167             else
02168               eval_data.r.was_lin = false;
02169             break;
02170           case EXPRINFO_INTPOWER:
02171             if(__rval.was_const)
02172             {
02173               eval_data.r.was_const = eval_data.r.was_lin = true;
02174               switch(__data.params.nn())
02175               {
02176                 case 0:
02177                   eval_data.r.const_trans = 1;
02178                   break;
02179                 case 1:
02180                   eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02181                   break;
02182                 case 2:
02183                   eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02184                   eval_data.r.const_trans *= eval_data.r.const_trans;
02185                   break;
02186                 case -1:
02187                   eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02188                   eval_data.r.const_trans = 1./eval_data.r.const_trans;
02189                   break;
02190                 case -2:
02191                   eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02192                   eval_data.r.const_trans =
02193                             1./(eval_data.r.const_trans*eval_data.r.const_trans);
02194                   break;
02195                 default:
02196                   eval_data.r.const_trans =
02197                                   pow(__data.coeffs[0]*__rval.const_trans,
02198                                       __data.params.nn());
02199                   break;
02200               }
02201             }
02202             else if(__data.params.nn() == 0)
02203             {
02204               eval_data.r.was_const = eval_data.r.was_lin = true;
02205               eval_data.r.const_trans = 1;
02206             }
02207             else if(__data.params.nn() != 1)
02208               eval_data.r.was_lin = false;
02209             break;
02210           case EXPRINFO_POW:
02211             if(eval_data.n == 0)
02212             {
02213               eval_data.r.was_lin = __rval.was_lin;
02214               eval_data.r.node_num = __rval.node_num;
02215             }
02216             if(__rval.was_const)
02217             {
02218               if(eval_data.n == 0)
02219               {
02220                 eval_data.r.const_trans = __rval.const_trans;
02221                 eval_data.r.was_const = true;
02222               }
02223               else if(eval_data.n == 1)
02224               {
02225                 if(eval_data.r.was_const)
02226                 {
02227                   eval_data.r.const_trans = pow(__data.coeffs[0]*
02228                       eval_data.r.const_trans+__data.params.nd(),
02229                       __data.coeffs[1]*__rval.const_trans);
02230                   eval_data.r.was_lin = true;
02231                 }
02232                 else if(__rval.const_trans == 0)
02233                 {
02234                   eval_data.r.const_trans = 1;
02235                   eval_data.r.was_lin = eval_data.r.was_const = true;
02236                 }
02237                 else if(__rval.const_trans == 1 && eval_data.r.was_lin
02238                         && eval_data.old_nlin == -1)
02239                 { // this is bad, since that means that we have to
02240                   // rewalk the left part of the graph
02241                   lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02242                                       eval_data.constant, eval_data.mod);
02243                   lv.eval_data.trans = eval_data.old_trans;
02244                   eval_data.r = evaluate(lv,
02245                                   eval_data.mod->node(eval_data.r.node_num));
02246                 }
02247                 else
02248                   eval_data.r.was_lin = eval_data.r.was_const = false;
02249               }
02250             }
02251             else
02252               eval_data.r.was_const = eval_data.r.was_lin = false;
02253             if(eval_data.n == 1)
02254               eval_data.r.node_num = __data.node_num;
02255             break;
02256           case EXPRINFO_EXP:
02257             if(__rval.was_const)
02258             {
02259               eval_data.r.was_const = eval_data.r.was_lin = true;
02260               eval_data.r.const_trans = exp(__data.coeffs[0]*__rval.const_trans+
02261                   __data.params.nd());
02262             }
02263             else
02264               eval_data.r.was_lin = false;
02265             break;
02266           case EXPRINFO_LOG:
02267             if(__rval.was_const)
02268             {
02269               eval_data.r.was_const = eval_data.r.was_lin = true;
02270               eval_data.r.const_trans = log(__data.coeffs[0]*__rval.const_trans+
02271                   __data.params.nd());
02272             }
02273             else
02274               eval_data.r.was_lin = false;
02275             break;
02276           case EXPRINFO_SIN:
02277             if(__rval.was_const)
02278             {
02279               eval_data.r.was_const = eval_data.r.was_lin = true;
02280               eval_data.r.const_trans = sin(__data.coeffs[0]*__rval.const_trans+
02281                   __data.params.nd());
02282             }
02283             else
02284               eval_data.r.was_lin = false;
02285             break;
02286           case EXPRINFO_COS:
02287             if(__rval.was_const)
02288             {
02289               eval_data.r.was_const = eval_data.r.was_lin = true;
02290               eval_data.r.const_trans = cos(__data.coeffs[0]*__rval.const_trans+
02291                   __data.params.nd());
02292             }
02293             else
02294               eval_data.r.was_lin = false;
02295             break;
02296           case EXPRINFO_ATAN2:
02297             if(__rval.was_const)
02298             {
02299               if(eval_data.n == 0)
02300               {
02301                 eval_data.r.const_trans = __rval.const_trans;
02302                 eval_data.r.was_const = true;
02303               }
02304               else if(eval_data.n == 1)
02305               {
02306                 if(eval_data.r.was_const)
02307                 {
02308                   eval_data.r.const_trans =
02309                           atan2(eval_data.r.const_trans, __rval.const_trans);
02310                   eval_data.r.was_lin = true;
02311                 }
02312                 else
02313                   eval_data.r.was_lin = eval_data.r.was_const = false;
02314               }
02315             }
02316             else
02317               eval_data.r.was_const = eval_data.r.was_lin = false;
02318             break;
02319         case EXPRINFO_GAUSS:
02320           if(__rval.was_const)
02321           {
02322             eval_data.r.was_const = eval_data.r.was_lin = true;
02323             eval_data.r.const_trans =
02324               (__data.coeffs[0]*__rval.const_trans-__data.params.d()[0])/
02325                                               __data.params.d()[1];
02326             eval_data.r.const_trans = exp(eval_data.r.const_trans*
02327                 eval_data.r.const_trans);
02328           }
02329           else
02330             eval_data.r.was_lin = false;
02331           break;
02332         case EXPRINFO_LIN:
02333         case EXPRINFO_QUAD:
02334           std::cerr << "Must not be here in lincoeff_visitor" << std::endl;
02335           throw "Strange error";
02336           break;
02337         default:
02338           std::cerr << "Unknown expression type in get_linear_coeffs" <<
02339             std::endl;
02340           throw "Programming error";
02341           break;
02342       }
02343     }
02344     else if(__data.operator_type > 0)
02345     {
02346       eval_data.r.was_lin = false;
02347     }
02348     eval_data.r.was_lin = eval_data.r.was_lin || __rval.was_lin;
02349     if(++eval_data.n < __data.n_children)
02350       eval_data.trans = eval_data.old_trans * __data.coeffs[eval_data.n];
02351     return 0;
02352   }
02353   
02354   int update(const lincoeff_visitor_ret& __rval)
02355         {
02356           if(__rval.was_const)
02357             *eval_data.constant += __rval.const_trans;
02358           eval_data.r.was_lin = eval_data.r.was_lin || __rval.was_lin;
02359           return 0;
02360         }
02361 
02362   lincoeff_visitor_ret calculate_value(bool eval_all)
02363         { return eval_data.r; }
02364 };
02365 
02366 inline bool model::get_linear_coeffs(const walker& expr, sparse_vector<double>& coeffs,
02367                         double& constant, const std::vector<interval>& _ranges)
02368 {
02369   lincoeff_visitor lv(&_ranges, &coeffs, &constant, this);
02370   lincoeff_visitor_ret r = evaluate(lv, expr);
02371   if(r.was_const)
02372     constant += r.const_trans;
02373   return r.was_lin;
02374 }
02375 
02376 inline bool model::get_linear_coeffs(const walker& expr, sparse_vector<double>& coeffs,
02377                               double& constant)
02378 {
02379   lincoeff_visitor lv(NULL, &coeffs, &constant, this);
02380   lincoeff_visitor_ret r = evaluate(lv, expr);
02381   if(r.was_const)
02382     constant += r.const_trans;
02383   return r.was_lin;
02384 }
02385 
02386 inline void model::simplify_visitor_0::postorder_help(const expression_node &r,
02387     unsigned int n_chld)
02388 {
02389   if(r.operator_type <= 0)
02390   {
02391     switch(r.operator_type)
02392     {
02393       case EXPRINFO_GHOST:
02394         { model::walker _w = __mod->node(r.node_num);
02395           postorder_help(*_w, _w.n_children());     // this sets flags, m,...
02396           v_i = _w->var_indicator();
02397           s = _w->sem;
02398         }
02399         flags |= SIMPLIFY_0_IS_GHOST;
02400         break;
02401       case EXPRINFO_CONSTANT:
02402         s.degree = 0;
02403         s.dim = 0;
02404         s.property_flags.c_info = c_linear;
02405         s.property_flags.separable = t_true;
02406         flags |= SIMPLIFY_0_IS_CONST;
02407         if(is_integer(r.params.nd()))
02408         {
02409           int i = get_integer(r.params.nd());
02410           flags |= SIMPLIFY_0_CONST_IS_INTEGER;
02411           m = i;
02412         }
02413         else
02414           m = r.params.nd();
02415         break;
02416       case EXPRINFO_VARIABLE:
02417         s.degree = 1;
02418         s.dim = 1;
02419         s.property_flags.c_info = c_linear;
02420         s.property_flags.separable = t_true;
02421         flags |= SIMPLIFY_0_IS_VAR;
02422         v_i.set(r.params.nn());
02423         break;
02424       case EXPRINFO_SUM:
02425         flags |= SIMPLIFY_0_IS_SUM;
02426         m = r.params.nd();
02427         transfer = &r.coeffs;
02428         if(n_chld == 1) // this is \la+<node>
02429           flags |= SIMPLIFY_0_SUM_IS_SIMPLE;
02430         break;
02431       case EXPRINFO_PROD:
02432         flags |= SIMPLIFY_0_IS_PROD;
02433         m = r.params.nd();
02434         transfer = &r.coeffs;
02435         if(n_chld == 1) // this is \la*<node>
02436           flags |= SIMPLIFY_0_PROD_IS_SIMPLE;
02437         break;
02438       case EXPRINFO_SQUARE:
02439       case EXPRINFO_INTPOWER:
02440         break;
02441       case EXPRINFO_INVERT:
02442       case EXPRINFO_DIV:
02443         flags |= SIMPLIFY_0_IS_MULTIPLICATIVE;
02444         m = r.params.nd();
02445         s.degree = -1;
02446         break;
02447       case EXPRINFO_IN:
02448       case EXPRINFO_IF:
02449       case EXPRINFO_AND:
02450       case EXPRINFO_OR:
02451       case EXPRINFO_NOT:
02452       case EXPRINFO_IMPLIES:
02453       case EXPRINFO_COUNT:
02454       case EXPRINFO_ALLDIFF:
02455       case EXPRINFO_LEVEL:
02456       case EXPRINFO_NEIGHBOR:
02457       case EXPRINFO_NOGOOD:
02458         s.annotation_flags.integer = true;
02459         // no break!
02460       case EXPRINFO_MAX:
02461       case EXPRINFO_MIN:
02462       case EXPRINFO_SQROOT:
02463       case EXPRINFO_ABS:
02464       case EXPRINFO_POW:
02465       case EXPRINFO_EXP:
02466       case EXPRINFO_LOG:
02467       case EXPRINFO_SIN:
02468       case EXPRINFO_COS:
02469       case EXPRINFO_ATAN2:
02470       case EXPRINFO_GAUSS:
02471         s.degree = -1;
02472         break;
02473       case EXPRINFO_LIN:
02474         break;
02475       case EXPRINFO_QUAD:
02476         break;
02477       default:
02478         // give bad messages
02479         break;
02480     }
02481   }
02482   else if(r.operator_type > 0)
02483   {
02484     s.degree = -1;
02485     s.property_flags.c_info = c_maybe;
02486     s.property_flags.separable = t_maybe;
02487   }
02488   s.dim = v_i.sum(0, num_of_vars);
02489   // now adapt semantics
02490   nnum = r.node_num;
02491   if(s.degree < 0) s.degree = -1;
02492 }
02493 
02494 //#include <model.cc>
02495 
02496 #endif /* _MODEL_INLINE_H_ */

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