00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
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
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)
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
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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
01080 break;
01081 case EXPRINFO_GAUSS:
01082 if(__s.flags & SIMPLIFY_0_IS_CONST)
01083 {
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 {
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 {
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
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
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 {
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
01341
01342
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))
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
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
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;
01578 unsigned int *f;
01579 std::vector<unsigned int>* t;
01580 std::vector<unsigned int>* d;
01581 std::vector<unsigned int>* nn;
01582 bool new_number;
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 {}
01608
01609 ~detect_0chain_visitor() {}
01610
01611 void initialize() { return; }
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++;
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
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
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())
02025 {
02026 if(eval_data.mm_help < _rg.inf())
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
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
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())
02093 {
02094 if(eval_data.mm_help > _rg.sup())
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
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 {
02240
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());
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)
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)
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
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
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
02490 nnum = r.node_num;
02491 if(s.degree < 0) s.degree = -1;
02492 }
02493
02494
02495
02496 #endif