00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00028 #ifndef _MODEL_HPP_
00029 #define _MODEL_HPP_
00030
00031 #include <api_exception.h>
00032
00033 namespace coco {
00034
00035 #define delnodes_insert(N) do {\
00036 std::vector<unsigned int>::iterator __x = \
00037 lower_bound((*delnodes).begin(), (*delnodes).end(), (unsigned int)(N)); \
00038 if(__x == (*delnodes).end() || *__x != (unsigned int)(N)) \
00039 (*delnodes).insert(__x, (unsigned int)(N)); \
00040 } while(0)
00041
00042 inline bool model_iddata::delete_ref(model_gid& __m)
00043 {
00044 for(std::list<model_gid*>::iterator __w = backref.begin(); __w != backref.end();
00045 ++__w)
00046 {
00047 if(*__w == &__m)
00048 {
00049 backref.erase(__w);
00050 break;
00051 }
00052 }
00053 return backref.empty();
00054 }
00055
00056 inline unsigned int model_iddata::get_node_id()
00057 {
00058 if(!node_free.empty())
00059 {
00060 std::pop_heap(node_free.begin(), node_free.end());
00061 unsigned int ___a = node_free.back();
00062 node_free.pop_back();
00063 return ___a;
00064 }
00065 else
00066 return node_num_max++;
00067 }
00068
00069 inline void model_iddata::remove_node_id(unsigned int _n)
00070 {
00071 if(_n == node_num_max-1)
00072 --node_num_max;
00073 else
00074 {
00075 node_free.push_back(_n);
00076 std::push_heap(node_free.begin(), node_free.end());
00077 }
00078 while(!node_free.empty() && node_free[0] == node_num_max-1)
00079 {
00080 --node_num_max;
00081 std::pop_heap(node_free.begin(), node_free.end());
00082 node_free.pop_back();
00083 }
00084 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00085 ++__b)
00086 (*__b)->remove_node_ref(_n);
00087 }
00088
00089 inline unsigned int model_iddata::get_var_id()
00090 {
00091 if(!var_free.empty())
00092 {
00093 std::pop_heap(var_free.begin(), var_free.end());
00094 unsigned int ___a = var_free.back();
00095 var_free.pop_back();
00096 return ___a;
00097 }
00098 else
00099 return var_num_max++;
00100 }
00101
00102 inline void model_iddata::remove_var_id(unsigned int _n)
00103 {
00104 if(_n == var_num_max-1)
00105 --var_num_max;
00106 else
00107 {
00108 var_free.push_back(_n);
00109 std::push_heap(var_free.begin(), var_free.end());
00110 }
00111 while(!var_free.empty() && var_free[0] == var_num_max-1)
00112 {
00113 --var_num_max;
00114 std::pop_heap(var_free.begin(), var_free.end());
00115 var_free.pop_back();
00116 }
00117 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00118 ++__b)
00119 (*__b)->remove_var_ref(_n);
00120 if(var_names.size() > _n)
00121 var_names[_n] = std::string();
00122 }
00123
00124 inline unsigned int model_iddata::get_const_id()
00125 {
00126 if(!const_free.empty())
00127 {
00128 std::pop_heap(const_free.begin(), const_free.end());
00129 unsigned int ___a = const_free.back();
00130 const_free.pop_back();
00131 return ___a;
00132 }
00133 else
00134 return const_num_max++;
00135 }
00136
00137 inline void model_iddata::remove_const_id(unsigned int _n)
00138 {
00139 if(_n == const_num_max-1)
00140 --const_num_max;
00141 else
00142 {
00143 const_free.push_back(_n);
00144 std::push_heap(const_free.begin(), const_free.end());
00145 }
00146 while(!const_free.empty() &&
00147 const_free[0] == const_num_max-1)
00148 {
00149 --const_num_max;
00150 std::pop_heap(const_free.begin(), const_free.end());
00151 const_free.pop_back();
00152 }
00153 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00154 ++__b)
00155 (*__b)->remove_const_ref(_n);
00156 if(const_names.size() > _n)
00157 const_names[_n] = std::string();
00158 }
00159
00160 inline void model_iddata::number_of_nodes(unsigned int _n)
00161 {
00162 node_num_max = _n;
00163 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00164 ++__b)
00165 (*__b)->upd_number_of_nodes(_n);
00166 }
00167
00168 inline void model_iddata::number_of_variables(unsigned int _n)
00169 {
00170 var_num_max = _n;
00171 var_names.insert(var_names.end(), _n - var_names.size(), std::string());
00172 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00173 ++__b)
00174 (*__b)->upd_number_of_variables(_n);
00175 }
00176
00177 inline void model_iddata::number_of_constraints(unsigned int _n)
00178 {
00179 const_num_max = _n;
00180 const_names.insert(const_names.end(), _n - const_names.size(), std::string());
00181 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00182 ++__b)
00183 (*__b)->upd_number_of_constraints(_n);
00184 }
00185
00186 inline const std::string model_iddata::model_name() const
00187 {
00188 if(mod_name.empty())
00189 return std::string("%%model");
00190 else
00191 return mod_name;
00192 }
00193
00194 inline void model_iddata::model_name(const std::string& vn)
00195 {
00196 mod_name = vn;
00197 }
00198
00199 inline const std::string model_iddata::var_name(unsigned int n) const
00200 {
00201 if(n >= var_names.size() || var_names[n].empty())
00202 {
00203 char __s[32];
00204 sprintf(__s, "%%x%d", n);
00205 return std::string(__s);
00206 }
00207 else
00208 return var_names[n];
00209 }
00210
00211 inline void model_iddata::var_name(unsigned int n, const std::string& vn)
00212 {
00213 if(n >= var_names.size())
00214 {
00215 if(n > var_names.size())
00216 var_names.insert(var_names.end(), n-var_names.size(), std::string());
00217 var_names.push_back(vn);
00218 }
00219 else
00220 var_names[n] = vn;
00221 }
00222
00223 inline const std::string model_iddata::const_name(unsigned int n) const
00224 {
00225 if(n >= const_names.size() || const_names[n].empty())
00226 {
00227 char __s[32];
00228 sprintf(__s, "%%c%d", n);
00229 return std::string(__s);
00230 }
00231 else
00232 return const_names[n];
00233 }
00234
00235 inline void model_iddata::const_name(unsigned int n, const std::string& vn)
00236 {
00237 if(n >= const_names.size())
00238 {
00239 if(n > const_names.size())
00240 const_names.insert(const_names.end(), n-const_names.size(), std::string());
00241 const_names.push_back(vn);
00242 }
00243 else
00244 const_names[n] = vn;
00245 }
00246
00247 inline const std::string model_iddata::obj_name() const
00248 {
00249 if(obj_names.empty())
00250 return std::string("%o");
00251 else
00252 return obj_names;
00253 }
00254
00255 inline void model_iddata::obj_name(const std::string& vn) { obj_names = vn; }
00256 inline double model_iddata::obj_adj() const { return obj_adjs; }
00257 inline void model_iddata::obj_adj(double adj) { obj_adjs = adj; }
00258 inline double model_iddata::obj_mult() const { return obj_mults; }
00259 inline void model_iddata::obj_mult(double mult) { obj_mults = mult; }
00260
00261 inline std::pair<const std::string, double> model_iddata::fixed_var( unsigned int n)
00262 const
00263 {
00264 if(n >= fixed_vars.size())
00265 {
00266 throw api_exception(apiee_internal, "index error in fixed_var!");
00267 }
00268 return fixed_vars[n];
00269 }
00270
00271 inline void model_iddata::fixed_var(const std::string& vn, double val)
00272 {
00273 fixed_vars.push_back(std::make_pair(vn, val));
00274 }
00275
00276 inline const std::string& model_iddata::unused_var(unsigned int n) const
00277 {
00278 if(n >= unused_vars.size())
00279 {
00280 throw api_exception(apiee_internal, "index error in unused_var!");
00281 }
00282 return unused_vars[n];
00283 }
00284
00285 inline void model_iddata::unused_var(const std::string& vn)
00286 {
00287 unused_vars.push_back(vn);
00288 }
00289
00290 inline const std::string& model_iddata::unused_constr(unsigned int n) const
00291 {
00292 if(n >= unused_constrs.size())
00293 {
00294 throw api_exception(apiee_internal, "index error in unused_constr!");
00295 }
00296 return unused_constrs[n];
00297 }
00298
00299 inline void model_iddata::unused_constr(const std::string& vn)
00300 {
00301 unused_constrs.push_back(vn);
00302 }
00303
00304 inline model_gid::model_gid(model& __m, model_iddata* __i)
00305 : model_ref(__m), glob_ref(), gvar_ref(), gconst_ref(), const_back_ref()
00306 {
00307 if(__i == NULL)
00308 _id = new model_iddata;
00309 else
00310 _id = __i;
00311 _id->new_ref(*this);
00312 }
00313
00314 inline model_gid::model_gid(model& __m, unsigned int n, model_iddata* __i)
00315 : model_ref(__m), glob_ref(), gvar_ref(), gconst_ref(), const_back_ref()
00316 {
00317 if(__i == NULL)
00318 _id = new model_iddata(n);
00319 else
00320 _id = __i;
00321 _id->new_ref(*this);
00322 }
00323
00324 inline model_gid::model_gid(model& __mr, const model_gid& __m)
00325 : _id(__m._id), model_ref(__mr), glob_ref(__m.glob_ref),
00326 gvar_ref(__m.gvar_ref), gconst_ref(__m.gconst_ref),
00327 const_back_ref(__m.const_back_ref)
00328 {
00329 _id->new_ref(*this);
00330 std::vector<model::walker>::iterator __x, __e;
00331 model::walker mgr(__m.model_ref.ground()), gr(__mr.ground());
00332 __e = glob_ref.end();
00333 for(__x = glob_ref.begin(); __x != __e; ++__x)
00334 if(*__x == mgr)
00335 *__x = gr;
00336 __e = gvar_ref.end();
00337 for(__x = gvar_ref.begin(); __x != __e; ++__x)
00338 if(*__x == mgr)
00339 *__x = gr;
00340 __e = gconst_ref.end();
00341 for(__x = gconst_ref.begin(); __x != __e; ++__x)
00342 if(*__x == mgr)
00343 *__x = gr;
00344 }
00345
00346 inline void model_gid::upd_number_of_nodes(unsigned int _n)
00347 {
00348 int __x;
00349 if((__x = _n - glob_ref.size()) > 0)
00350 glob_ref.insert(glob_ref.end(), __x, model_ref.ground());
00351 }
00352
00353 inline void model_gid::upd_number_of_variables(unsigned int _n)
00354 {
00355 int __x;
00356 unsigned int _n_old = (unsigned int)gvar_ref.size();
00357
00358 if((__x = _n - gvar_ref.size()) > 0)
00359 {
00360 model::walker _gr = model_ref.ground();
00361
00362 gvar_ref.insert(gvar_ref.end(), __x, _gr);
00363 for(model::ref_iterator __b = glob_ref.begin(); __b != glob_ref.end();
00364 ++__b)
00365 {
00366 if((*__b) != _gr)
00367 {
00368 (*__b)->v_i.reserve(_n);
00369 (*__b)->v_i.unset(_n_old, _n-1);
00370 }
00371 }
00372 }
00373 }
00374
00375 inline void model_gid::upd_number_of_constraints(unsigned int _n)
00376 {
00377 int __x;
00378 if((__x = _n - gconst_ref.size()) > 0)
00379 gconst_ref.insert(gconst_ref.end(), __x, model_ref.ground());
00380 }
00381
00382 inline void model_gid::renumber_variables(
00383 std::vector<std::pair<unsigned int,unsigned int> >& __v)
00384 {
00385 unsigned int i;
00386 for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00387 __i != __v.end(); ++__i)
00388 {
00389 i = (*__i).second;
00390 gvar_ref[i] = gvar_ref[(*__i).first];
00391 gvar_ref[i]->params = i;
00392 }
00393 }
00394
00395 inline void model_gid::renumber_constraints(
00396 std::vector<std::pair<unsigned int,unsigned int> >& __v)
00397 {
00398 unsigned int i;
00399 std::map<unsigned int, unsigned int>::iterator __mf;
00400 for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i =
00401 __v.begin(); __i != __v.end(); ++__i)
00402 {
00403 i = (*__i).second;
00404 gconst_ref[i] = gconst_ref[(*__i).first];
00405 unsigned int n = gconst_ref[i]->node_num;
00406 __mf = const_back_ref.find(n);
00407 if(__mf == const_back_ref.end())
00408 throw api_exception(apiee_internal,
00409 "This can't happen in renumber_constraints!");
00410 const_back_ref.erase(__mf);
00411 const_back_ref.insert(std::make_pair(n, i));
00412 }
00413 }
00414
00415 inline void model_gid::mk_globref(unsigned int n, const model::walker& __w)
00416 {
00417 if(glob_ref.size() > n)
00418 glob_ref[n] = __w;
00419 else if(n == glob_ref.size())
00420 glob_ref.push_back(__w);
00421 else
00422 {
00423 glob_ref.insert(glob_ref.end(), n-glob_ref.size()+1, model_ref.ground());
00424 glob_ref[n] = __w;
00425 }
00426 }
00427
00428 inline void model_gid::mk_gvarref(unsigned int n, const model::walker& __w)
00429 {
00430 if(gvar_ref.size() > n)
00431 gvar_ref[n] = __w;
00432 else if(n == gvar_ref.size())
00433 gvar_ref.push_back(__w);
00434 else
00435 {
00436 gvar_ref.insert(gvar_ref.end(), n-gvar_ref.size()+1, model_ref.ground());
00437 gvar_ref[n] = __w;
00438 }
00439 }
00440
00441 inline void model_gid::mk_gconstref(unsigned int n, const model::walker& __w)
00442 {
00443 if(n == gconst_ref.size())
00444 gconst_ref.push_back(__w);
00445 else
00446 {
00447 if(gconst_ref.size() <= n)
00448 gconst_ref.insert(gconst_ref.end(), n-gconst_ref.size()+1,
00449 model_ref.ground());
00450 gconst_ref[n] = __w;
00451 std::map<unsigned int, unsigned int>::iterator __mf =
00452 const_back_ref.find(__w->node_num);
00453 if(__mf != const_back_ref.end())
00454 const_back_ref.erase(__mf);
00455 }
00456 const_back_ref.insert(std::make_pair(__w->node_num, n));
00457 }
00458
00459 inline void model_gid::remove_const_ref(unsigned int _n)
00460 {
00461 std::map<unsigned int, unsigned int>::iterator __mf;
00462 if(gconst_ref.size() > _n && gconst_ref[_n] != model_ref.ground())
00463 {
00464 __mf = const_back_ref.find(gconst_ref[_n]->node_num);
00465 if(__mf != const_back_ref.end())
00466 const_back_ref.erase(__mf);
00467 if(gconst_ref.size() == _n) gconst_ref.pop_back();
00468 else gconst_ref[_n] = model_ref.ground();
00469 }
00470 else
00471 {
00472 for(__mf = const_back_ref.begin(); __mf != const_back_ref.end(); ++__mf)
00473 if((*__mf).second == _n)
00474 {
00475 const_back_ref.erase(__mf);
00476 break;
00477 }
00478 }
00479 }
00480
00481 inline bool model_gid::get_const_num(unsigned int node_num,
00482 unsigned int& const_num)
00483 {
00484 std::map<unsigned int, unsigned int>::iterator __mf =
00485 const_back_ref.find(node_num);
00486 if(__mf == const_back_ref.end())
00487 return false;
00488 const_num = (*__mf).second;
00489 return true;
00490 }
00491
00492 inline void model_gid::make_const_back_ref(unsigned int node, unsigned int cnum)
00493 {
00494 std::map<unsigned int, unsigned int>::iterator __mf =
00495 const_back_ref.find(node);
00496 if(__mf != const_back_ref.end())
00497 const_back_ref.erase(__mf);
00498 const_back_ref.insert(std::make_pair(node, cnum));
00499 }
00500
00501 inline const std::map<int, std::vector<double > >& model_gid::trace_points()
00502 const { return _id->trace_points; }
00503
00504 inline const std::map<int, std::vector<double > >& model_gid::optima()
00505 const { return _id->optima; }
00506
00507 inline bool model::is_empty(const walker& __w) const { return gid->empty(__w); }
00508 inline model::walker model::empty_reference() const
00509 { return gid->empty_reference(); }
00510
00511 inline void model::detach_gid() { gid = new model_gid(*this, *gid); }
00512
00513 inline model::model(int __num_of_vars) : _Base(), node_ref(), var_ref(),
00514 ghost_ref(), keep_gid(true),
00515 destroy_node_ref(false), lin(), matd(),
00516 mati(), ocoeff(0), objective(ground()),
00517 constraints(), has_read_errors(false)
00518 { gid = new model_gid(*this, __num_of_vars); }
00519
00520 inline model::model(model_gid* __id, bool clone) :
00521 _Base(), node_ref(), var_ref(),
00522 ghost_ref(), destroy_node_ref(false),
00523 lin(), matd(), mati(),
00524 ocoeff(0), objective(ground()),
00525 constraints(), has_read_errors(false)
00526 {
00527 keep_gid = true;
00528 if(__id)
00529 {
00530 if(clone)
00531 {
00532 gid = __id;
00533 keep_gid = false;
00534 }
00535 else
00536 gid = new model_gid(*this, *__id);
00537 }
00538 else
00539 gid = new model_gid(*this);
00540 }
00541
00542 inline model::model(const model& __m) : _Base(__m), node_ref(),
00543 var_ref(), ghost_ref(), gid(), keep_gid(true),
00544 destroy_node_ref(false),
00545 lin(__m.lin), matd(__m.matd),
00546 mati(__m.mati), ocoeff(__m.ocoeff),
00547 constraints(),
00548 has_read_errors(__m.has_read_errors)
00549 {
00550 #if MODEL_INLINE_DEBUG
00551 std::cerr << "Copy constructor of model called " << std::endl;
00552 #endif
00553 gid = new model_gid(*this, *__m.gid_data());
00554
00555 copy_contents(gid, __m);
00556 }
00557
00558 inline model::model(model_gid* __id, const model& __m) : _Base(__m),
00559 node_ref(), var_ref(), ghost_ref(), gid(__id),
00560 keep_gid(false), destroy_node_ref(false),
00561 lin(__m.lin), matd(__m.matd),
00562 mati(__m.mati), ocoeff(__m.ocoeff),
00563 constraints(),
00564 has_read_errors(__m.has_read_errors)
00565 {
00566 if(!__id)
00567 {
00568 throw api_exception(apiee_internal,
00569 "NULL gid is forbidden in model constructor!");
00570 }
00571 copy_contents(gid, __m);
00572 }
00573
00574 inline model::~model()
00575 {
00576 #if MODEL_INLINE_DEBUG
00577
00578 std::cerr << "Destructor of model called" << std::endl;
00579 #endif
00580 if(destroy_node_ref)
00581 {
00582 #if MODEL_INLINE_DEBUG
00583 std::cerr << "\tremoving node references" << std::endl;
00584 #endif
00585 free_all();
00586 }
00587 if(keep_gid)
00588 {
00589 #if MODEL_INLINE_DEBUG
00590 std::cerr << "\tremoving gid" << std::endl;
00591 #endif
00592 delete gid;
00593 }
00594 }
00595
00596 inline bool model::get_const_num(unsigned int node_num,
00597 unsigned int& const_num) const
00598 { return gid->get_const_num(node_num, const_num); }
00599
00600 inline void model::free_nodes_on_destroy()
00601 {
00602 #if MODEL_INLINE_DEBUG
00603 std::cerr << "\t(before) destroy_node_ref = " << destroy_node_ref << std::endl;
00604 #endif
00605 destroy_node_ref = true;
00606 #if MODEL_INLINE_DEBUG
00607 std::cerr << "\t(after) destroy_node_ref = " << destroy_node_ref << std::endl;
00608 #endif
00609 }
00610
00611 inline void model::keep_nodes_on_destroy()
00612 {
00613 #if MODEL_INLINE_DEBUG
00614 std::cerr << "\t(before) destroy_node_ref = " << destroy_node_ref << std::endl;
00615 #endif
00616 destroy_node_ref = false;
00617 #if MODEL_INLINE_DEBUG
00618 std::cerr << "\t(after) destroy_node_ref = " << destroy_node_ref << std::endl;
00619 #endif
00620 }
00621
00622 inline const std::string model::model_name() const { return gid->model_name(); }
00623 inline const std::string model::var_name(unsigned int n) const
00624 { return gid->var_name(n); }
00625 inline const std::string model::const_name(unsigned int n) const
00626 { return gid->const_name(n); }
00627 inline const std::string model::obj_name() const { return gid->obj_name(); }
00628 inline double model::obj_adj() const { return gid->obj_adj(); }
00629 inline double model::obj_mult() const { return gid->obj_mult(); }
00630 inline size_t model::n_fixed_vars() const { return gid->n_fixed_vars(); }
00631 inline std::pair<const std::string, double> model::fixed_var(unsigned int n) const
00632 { return gid->fixed_var(n); }
00633 inline size_t model::n_unused_vars() const { return gid->n_unused_vars(); }
00634 inline const std::string& model::unused_var(unsigned int n) const
00635 { return gid->unused_var(n); }
00636 inline size_t model::n_unused_constrs() const
00637 { return gid->n_unused_constrs(); }
00638 inline const std::string& model::unused_constr(unsigned int n) const
00639 { return gid->unused_constr(n); }
00640 inline const std::map<int, std::vector<double > >& model::trace_points() const
00641 { return gid->trace_points(); }
00642 inline const std::map<int, std::vector<double > >& model::optima() const
00643 { return gid->optima(); }
00644
00645 inline unsigned int model::number_of_variables() const
00646 { return gid->number_of_variables(); }
00647
00648 inline unsigned int model::number_of_constraints() const
00649 { return gid->number_of_constraints(); }
00650
00651 inline unsigned int model::number_of_nodes() const
00652 { return gid->number_of_nodes(); }
00653
00654 inline const model::walker& model::node(unsigned int i) const
00655 { return gid->node(i); }
00656
00657 inline const model::walker& model::var(unsigned int i) const
00658 { return gid->variable(i); }
00659
00660 inline const model::walker& model::constraint(unsigned int i) const
00661 { return gid->constraint(i); }
00662
00665 class model::sort_constraints :
00666 public std::binary_function<walker, walker, bool>
00667 {
00668 public:
00669 bool operator()(const walker& _c1, const walker& _c2) const
00670 {
00671 if(_c1.is_leaf() != _c2.is_leaf())
00672 {
00673 if(_c1.is_leaf()) return true;
00674 else if(_c2.is_leaf()) return false;
00675 }
00676 if(_c1->sem.degree != _c2->sem.degree)
00677 {
00678 if(_c1->sem.degree == 1) return true;
00679 else if(_c2->sem.degree == 1) return false;
00680 }
00681 if(_c1->f_bounds.is_thin() != _c2->f_bounds.is_thin())
00682 return _c1->f_bounds.is_thin() ? true : false;
00683 else if(_c1->f_bounds.is_bounded() == _c2->f_bounds.is_bounded() ||
00684 _c1->f_bounds.is_unbounded_below() == _c2->f_bounds.is_unbounded_below()||
00685 _c1->f_bounds.is_unbounded_above() == _c2->f_bounds.is_unbounded_above())
00686 return _c1->node_num < _c2->node_num;
00687 else if(_c1->f_bounds.is_unbounded_below())
00688 return true;
00689 else if(_c2->f_bounds.is_unbounded_below())
00690 return false;
00691 else
00692 return _c1->f_bounds.is_bounded() ? false : true;
00693 }
00694 };
00695
00696 #define SIMPLIFY_0_IS_CONST 1
00697 #define SIMPLIFY_0_CONST_IS_INTEGER (1<<24)
00698 #define SIMPLIFY_0_CONST_IS_EQUATION (1<<25)
00699
00700 #define SIMPLIFY_0_IS_VAR (1<<1)
00701
00702 #define SIMPLIFY_0_IS_SUM (1<<2)
00703 #define SIMPLIFY_0_SUM_IS_SIMPLE (1<<24)
00704
00705 #define SIMPLIFY_0_IS_PROD (1<<3)
00706 #define SIMPLIFY_0_PROD_IS_SIMPLE (1<<24)
00707
00708 #define SIMPLIFY_0_IS_MULTIPLICATIVE (1<<4)
00709 #define SIMPLIFY_0_IS_CORRECTEDMULT (1<<5)
00710
00711 #define SIMPLIFY_0_IS_GHOST (1<<31)
00712
00713 #define SIMPLIFY_0_SKIP_THIS_NODE (1<<30)
00714
00716 class model::simplify_visitor_0 : public postorder_visitor<expression_node,
00717 simplify_visitor_0,
00718 const simplify_visitor_0&>
00719 {
00720 int num_of_vars;
00721 semantics s;
00722 int n, ndel, ncorr;
00723 variable_indicator v_i;
00724 std::vector<unsigned int>* delnodes;
00725 std::vector<unsigned int>* delghosts;
00726 std::vector<std::pair<unsigned int,unsigned int> >* deledges;
00727 std::vector<std::pair<unsigned int,unsigned int> > trans_ghosts;
00728 std::vector<std::triple<unsigned int,unsigned int,unsigned int> >
00729 trans_edges;
00730 std::vector<bool>* visited;
00731 unsigned int flags;
00732 basic_alltype m;
00733 int nnum;
00734 int l_nnum;
00735 unsigned int l_flags;
00736 semantics l_s;
00737 const std::vector<double> *transfer;
00738 model* __mod;
00739 int r_idx;
00740
00741 public:
00742 simplify_visitor_0() : num_of_vars(0), s(), n(0), ndel(0), ncorr(0), v_i(0),
00743 delnodes(NULL), delghosts(NULL), deledges(NULL),
00744 trans_ghosts(), trans_edges(), visited(NULL),
00745 flags(0), m(0), nnum(-1), l_nnum(-1),
00746 l_flags(0), l_s(), transfer(NULL), __mod(NULL),
00747 r_idx(-1) {}
00748
00749 public:
00750 simplify_visitor_0(int __nv, std::vector<unsigned int>* __dn,
00751 std::vector<unsigned int>* __dg,
00752 std::vector<std::pair<unsigned int,unsigned int> >* __de,
00753 std::vector<bool>* __vt, model* __m) :
00754 num_of_vars(__nv), s(), n(0), ndel(0), ncorr(0),
00755 v_i(__nv), delnodes(__dn), delghosts(__dg),
00756 deledges(__de), trans_ghosts(), trans_edges(),
00757 visited(__vt), flags(0), m(0), nnum(-1), l_nnum(-1),
00758 l_flags(0), l_s(), transfer(NULL), __mod(__m),
00759 r_idx(-1)
00760 { v_i.clear(); }
00761
00762 simplify_visitor_0(const simplify_visitor_0& __x) :
00763 num_of_vars(__x.num_of_vars), s(__x.s),
00764 n(__x.n), ndel(__x.ndel), ncorr(__x.ncorr), v_i(__x.v_i),
00765 delnodes(__x.delnodes), delghosts(__x.delghosts),
00766 deledges(__x.deledges), trans_ghosts(),
00767 trans_edges(),
00768 visited(__x.visited), flags(__x.flags), m(__x.m),
00769 nnum(__x.nnum), l_nnum(__x.l_nnum), l_flags(__x.l_flags),
00770 l_s(__x.l_s), transfer(__x.transfer), __mod(__x.__mod),
00771 r_idx(__x.r_idx)
00772 { }
00773
00774 void vinit()
00775 { n = 0; s = semantics(); v_i.clear(); flags = 0; ncorr = 0;
00776 m = 0; nnum = -1; l_nnum = -1; l_flags = 0; ndel = 0; r_idx = -1;}
00777 void init() { vinit(); }
00778
00779 void postorder_help(const expression_node &r, unsigned int n_chld);
00780 bool postorder(expression_node &r);
00781
00782 bool preorder(expression_node &r)
00783 {
00784
00785 std::vector<unsigned int>::iterator __x;
00786 if(r.operator_type == EXPRINFO_GHOST)
00787 {
00788 __x = lower_bound((*delghosts).begin(), (*delghosts).end(),
00789 r.node_num);
00790 if(__x != (*delghosts).end() && *__x == r.node_num)
00791 {
00792 flags |= SIMPLIFY_0_SKIP_THIS_NODE;
00793 return false;
00794 }
00795 }
00796 else
00797 {
00798 __x = lower_bound((*delnodes).begin(), (*delnodes).end(),
00799 r.node_num);
00800 if(__x != (*delnodes).end() && *__x == r.node_num)
00801 {
00802 flags |= SIMPLIFY_0_SKIP_THIS_NODE;
00803 return false;
00804 }
00805 }
00806
00807 init();
00808 if((*visited)[r.node_num])
00809 {
00810 n = r.n_children;
00811 ndel = n-r.coeffs.size();
00812 v_i.set_all(r.v_i);
00813 s = r.sem;
00814 return false;
00815 }
00816 else
00817 return true;
00818 }
00819
00820 simplify_visitor_0 value() { return *this; }
00821 simplify_visitor_0 vvalue() { s.degree = -2; return *this; }
00822
00823 void simple_sum_prod_update(expression_node& r,
00824 const simplify_visitor_0& __s)
00825 {
00826 std::vector<unsigned int>::iterator __x;
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() + r.params.nd();
00831 r.coeffs[0] *= (*__s.transfer)[0];
00832 if(__s.flags & SIMPLIFY_0_IS_GHOST)
00833 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
00834 else
00835 {
00836 model::walker _node = __mod->node(__s.nnum);
00837 if(_node->n_parents == 1)
00838 delnodes_insert(__s.nnum);
00839 else
00840 {
00841 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
00842 _node->n_parents--;
00843 }
00844 }
00845 }
00846 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
00847 {
00848 r.coeffs[n] *= __s.m.nd();
00849 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
00850 __mod->node(__s.nnum)->params = 1.;
00851 }
00852 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
00853 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
00854 {
00855 r.coeffs[0] *= __s.m.nd();
00856 if(__s.flags & SIMPLIFY_0_IS_GHOST)
00857 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
00858 else
00859 {
00860 model::walker _node = __mod->node(__s.nnum);
00861 if(_node->n_parents == 1)
00862 delnodes_insert(__s.nnum);
00863 else
00864 {
00865 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
00866 _node->n_parents--;
00867 }
00868 }
00869 }
00870 }
00871
00872 void transfer_ghost_down(unsigned int nnum, unsigned int pnum)
00873 {
00874
00875 model::walker _w = __mod->node(nnum), _wc;
00876 children_iterator _c;
00877 std::vector<unsigned int> unum;
00878 std::vector<unsigned int>::iterator __x;
00879
00880 for(_c = _w.child_begin(); _c != _w.child_end(); ++_c)
00881 {
00882 _wc = _w >> _c;
00883 unum.push_back(_wc->node_num);
00884 }
00885
00886 model::walker _go = __mod->ghost(nnum);
00887 model::walker _pr = __mod->node(pnum);
00888 if(_go.n_parents() == 1)
00889 {
00890
00891 __x = lower_bound((*delghosts).begin(), (*delghosts).end(), nnum);
00892 if(__x == (*delghosts).end() || *__x != nnum)
00893 (*delghosts).insert(__x, nnum);
00894 }
00895 for(unsigned int i=0; i<unum.size(); ++i)
00896 {
00897 if(i == 0)
00898 {
00899 if(__mod->exchange_ghost(_pr, _go, unum[i]))
00900 __mod->remove_edge_and_deattach(_pr, _go);
00901 }
00902 else
00903 __mod->safe_ghost(_pr, unum[i]);
00904 __x = lower_bound((*delghosts).begin(), (*delghosts).end(), unum[i]);
00905
00906
00907 if(__x != (*delghosts).end() && *__x == nnum)
00908 (*delghosts).erase(__x);
00909 }
00910 }
00911
00912 void vcollect(const simplify_visitor_0& __s);
00913
00914 void collect(expression_node &r, const simplify_visitor_0& __s);
00915 };
00916
00919 class model::simplify_visitor_m : public postorder_visitor<expression_node,
00920 const simplify_visitor_m&,
00921 const simplify_visitor_m&>
00922 {
00923 int num_of_vars;
00924 semantics s;
00925 int n, ndel;
00926 variable_indicator v_i;
00927 std::vector<unsigned int>* delnodes;
00928 std::vector<std::pair<unsigned int,unsigned int> >* deledges;
00929 std::vector<bool>* visited;
00930 unsigned int flags;
00931 basic_alltype m;
00932 int nnum;
00933 int l_nnum;
00934 unsigned int l_flags;
00935 semantics l_s;
00936 const std::vector<double> *transfer;
00937 model* __mod;
00938 int r_idx;
00939
00940 public:
00941 simplify_visitor_m() : num_of_vars(0), s(), n(0), ndel(0), v_i(0),
00942 delnodes(NULL), deledges(NULL), visited(NULL),
00943 flags(0), m(0), nnum(-1), l_nnum(-1), l_flags(0),
00944 l_s(), transfer(NULL), __mod(NULL), r_idx(-1) {}
00945
00946 public:
00947 simplify_visitor_m(int __nv, std::vector<unsigned int>* __dn,
00948 std::vector<std::pair<unsigned int,unsigned int> >* __de,
00949 std::vector<bool>* __vt, model* __m) :
00950 num_of_vars(__nv), s(), n(0), ndel(0), v_i(__nv),
00951 delnodes(__dn), deledges(__de), visited(__vt),
00952 flags(0), m(0), nnum(-1), l_nnum(-1), l_flags(0),
00953 l_s(), transfer(NULL), __mod(__m), r_idx(-1)
00954 { v_i.clear(); }
00955
00956 simplify_visitor_m(const simplify_visitor_m& __x) :
00957 num_of_vars(__x.num_of_vars), s(__x.s),
00958 n(__x.n), ndel(__x.ndel), v_i(__x.v_i),
00959 delnodes(__x.delnodes), deledges(__x.deledges),
00960 visited(__x.visited), flags(__x.flags), m(__x.m),
00961 nnum(__x.nnum), l_nnum(__x.l_nnum), l_flags(__x.l_flags),
00962 l_s(__x.l_s), transfer(__x.transfer), __mod(__x.__mod),
00963 r_idx(__x.r_idx)
00964 { }
00965
00966 void vinit()
00967 { n = 0; s = semantics(); v_i.clear(); flags = 0;
00968 m = 0; nnum = -1; l_nnum = -1; l_flags = 0; ndel = 0; r_idx = -1;}
00969 void init() { vinit(); }
00970
00971 void postorder_help(const expression_node &r, unsigned int n_chld);
00972 bool postorder(expression_node &r);
00973
00974 bool preorder(expression_node &r)
00975 { init();
00976 if((*visited)[r.node_num])
00977 {
00978 n = r.n_children;
00979 v_i = r.v_i;
00980 s = r.sem;
00981 return false;
00982 }
00983 else
00984 return true;
00985 }
00986
00987 const simplify_visitor_m& value() { return *this; }
00988 const simplify_visitor_m& vvalue() { s.degree = -2; return *this; }
00989
00990 void vcollect(const simplify_visitor_m& __s) {}
00991
00992 void collect(expression_node &r, const simplify_visitor_m& __s);
00993 };
00994
00995
00996 inline bool model::children_eq(walker __n1, walker __n2)
00997 {
00998 children_iterator _c1, _c2;
00999 walker _e1, _e2;
01000
01001 for(_c1 = __n1.child_begin(), _c2 = __n2.child_begin();
01002 _c1 != __n1.child_end(); ++_c1, ++_c2)
01003 {
01004 _e1 = __n1 >> _c1;
01005 _e2 = __n2 >> _c2;
01006 if(_e1.is_sky() != _e2.is_sky())
01007 return false;
01008 if(_e1->node_num != _e2->node_num)
01009 return false;
01010 }
01011 return true;
01012 }
01013
01014 inline void model::basic_simplify_1_flood(walker __s,
01015 std::vector<int>& _combined)
01016 {
01017 parents_iterator __p;
01018 walker __ew;
01019
01020 for(__p = __s.parent_begin(); __p != __s.parent_end(); ++__p)
01021 {
01022 __ew = __s << __p;
01023 if(!__ew.is_ground())
01024 ++_combined[__ew->node_num];
01025 }
01026 }
01027
01028 inline bool model::basic_simplify_1_is_ready(walker __s,
01029 const std::vector<int>& _combined, bool all_finished)
01030 {
01031 parents_iterator _p;
01032 walker _w;
01033
01034 for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
01035 {
01036 _w = __s << _p;
01037 if(_combined[_w->node_num] == (int)_w->n_children)
01038 {
01039 if(!all_finished)
01040 return true;
01041 }
01042 else if(all_finished)
01043 return false;
01044 }
01045 return all_finished;
01046 }
01047
01048 #if 0
01049 class model::simplify_visitor_thin : public postorder_visitor<expression_node,
01050 double>
01051 {
01052 private:
01053 double r;
01054 int last_nn;
01055
01056 public:
01057 simplify_visitor_thin() { }
01058
01059 void vinit() { r = COCO_INF; }
01060
01061 void init() { vinit(); }
01062
01063 bool postorder(expression_node &r)
01064 {
01065 if(r.operator_type < 0)
01066 {
01067 switch(r.operator_type)
01068 {
01069 case EXPRINFO_CONSTANT:
01070 r = r.params.nd();
01071 break;
01072 case EXPRINFO_VARIABLE:
01073 if(r.f_bounds.is_thin())
01074 r = r.f_bounds.inf();
01075 else
01076 r = COCO_INF;
01077 break;
01078 case EXPRINFO_SUM:
01079 flags |= SIMPLIFY_0_IS_SUM;
01080 break;
01081 case EXPRINFO_PROD:
01082 flags |= SIMPLIFY_0_IS_PROD;
01083 m = r.params.nd();
01084 transfer = &r.coeffs;
01085 if(n - ndel == 1)
01086 flags |= SIMPLIFY_0_PROD_IS_SIMPLE;
01087 break;
01088 case EXPRINFO_SQUARE:
01089 case EXPRINFO_INTPOWER:
01090 break;
01091 case EXPRINFO_MAX:
01092 case EXPRINFO_MIN:
01093 case EXPRINFO_INVERT:
01094 case EXPRINFO_DIV:
01095 case EXPRINFO_SQROOT:
01096 case EXPRINFO_POW:
01097 case EXPRINFO_ABS:
01098 case EXPRINFO_EXP:
01099 case EXPRINFO_LOG:
01100 case EXPRINFO_SIN:
01101 case EXPRINFO_COS:
01102 case EXPRINFO_ATAN2:
01103 case EXPRINFO_GAUSS:
01104 s.degree = -1;
01105 break;
01106 case EXPRINFO_LIN:
01107 break;
01108 case EXPRINFO_QUAD:
01109 break;
01110 default:
01111
01112 break;
01113 }
01114 }
01115 else if(r.operator_type > 0)
01116 {
01117 s.degree = -1;
01118 s.property_flags.convex = t_maybe;
01119 s.property_flags.concave = t_maybe;
01120 s.property_flags.separable = t_maybe;
01121 }
01122 s.dim = v_i.sum(0, num_of_vars);
01123 r.sem = s;
01124 r.v_i = v_i;
01125 if(r.operator_type == EXPRINFO_CONSTANT ||
01126 r.operator_type == EXPRINFO_VARIABLE)
01127 r.n_children = 0;
01128 else
01129 r.n_children = n - ndel;
01130 nnum = r.node_num;
01131 if(s.degree < 0) s.degree = -1;
01132 return false;
01133 }
01134
01135 const simplify_visitor_thin& value() { return *this; }
01136 const simplify_visitor_thin& vvalue() { s.degree = -2; return *this; }
01137
01138 void simple_sum_prod_update(expression_node& r, const simplify_visitor_thin& __s)
01139 {
01140 if(__s.flags & SIMPLIFY_0_IS_SUM &&
01141 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
01142 {
01143 r.params = r.coeffs[0] * __s.m.nd();
01144 r.coeffs[0] *= (*__s.transfer)[0];
01145 (*delnodes).push_back(__s.nnum);
01146 }
01147 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01148 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01149 {
01150 r.coeffs[0] *= __s.m.nd();
01151 (*delnodes).push_back(__s.nnum);
01152 }
01153 }
01154
01155 void vcollect(const simplify_visitor_thin& __s)
01156 {
01157 if((__s.flags & SIMPLIFY_0_IS_SUM &&
01158 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE && __s.m.nd() == 0) ||
01159 (__s.flags & SIMPLIFY_0_IS_PROD &&
01160 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE && __s.m.nd() == 1))
01161 {
01162 (*delnodes).push_back(__s.nnum);
01163 }
01164 }
01165
01166 void collect(expression_node &r, const simplify_visitor_thin& __s)
01167 {
01168 if(r.operator_type < 0)
01169 {
01170 switch(r.operator_type)
01171 {
01172 case EXPRINFO_CONSTANT:
01173 case EXPRINFO_VARIABLE:
01174 break;
01175 case EXPRINFO_SUM:
01176 if(n == 0)
01177 {
01178 s.degree = __s.s.degree;
01179 s.property_flags = __s.s.property_flags;
01180 }
01181 else
01182 {
01183 if(__s.s.degree == -1 || __s.s.degree > s.degree)
01184 s.degree = __s.s.degree;
01185 }
01186 if(__s.flags & SIMPLIFY_0_IS_CONST)
01187 {
01188 double help =
01189 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01190 __s.m.nd();
01191 r.params = r.params.nd() + r.coeffs[n-ndel] * help;
01192 r.coeffs.erase(r.coeffs.begin() + n);
01193 (*delnodes).push_back(__s.nnum);
01194 ndel++;
01195 }
01196 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01197 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01198 {
01199 r.coeffs[n-ndel] *= __s.m.nd();
01200 (*delnodes).push_back(__s.nnum);
01201 }
01202 else if(__s.flags & SIMPLIFY_0_IS_SUM)
01203 {
01204 double help = r.coeffs[n-ndel];
01205
01206 r.params = r.params.nd() + __s.m.nd();
01207 r.coeffs.erase(r.coeffs.begin()+(n-ndel));
01208 ndel++;
01209 for(std::vector<double>::iterator b = __s.transfer->begin();
01210 b != __s.transfer->end(); ++b)
01211 r.coeffs.push_back(*b * help);
01212 n += __s.transfer->size();
01213 (*delnodes).push_back(__s.nnum);
01214 }
01215 break;
01216 case EXPRINFO_PROD:
01217 if(n == 0)
01218 {
01219 s.degree = __s.s.degree;
01220 s.property_flags = __s.s.property_flags;
01221 }
01222 else
01223 {
01224 if(__s.s.degree == -1 || s.degree == -1)
01225 s.degree = -1;
01226 else
01227 s.degree += __s.s.degree;
01228 }
01229 if(r.coeffs[n] != 1)
01230 {
01231 r.params = r.params.nd() * r.coeffs[n];
01232 r.coeffs[n] = 1;
01233 }
01234 if(__s.flags & SIMPLIFY_0_IS_CONST)
01235 {
01236 double help =
01237 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01238 __s.m.nd();
01239 r.params = r.params.nd() * help;
01240 r.coeffs.pop_back();
01241 (*delnodes).push_back(__s.nnum);
01242 ndel++;
01243 }
01244 else if(__s.flags & SIMPLIFY_0_IS_PROD)
01245 {
01246 r.params = r.params.nd() * __s.m.nd();
01247 r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
01248 n += __s.transfer->size()-1;
01249 (*delnodes).push_back(__s.nnum);
01250 }
01251 break;
01252 case EXPRINFO_MAX:
01253 case EXPRINFO_MIN:
01254 break;
01255 case EXPRINFO_POW:
01256 if(n == 0)
01257 {
01258 if(__s.flags & SIMPLIFY_0_IS_CONST)
01259 {
01260 double help =
01261 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01262 __s.m.nd();
01263 r.operator_type = EXPRINFO_EXP;
01264 r.coeffs[0] = std::log(r.coeffs[0] * help) * r.coeffs[1];
01265 r.coeffs.pop_back();
01266 (*delnodes).push_back(__s.nnum);
01267 s.degree = -1;
01268 ndel++;
01269 }
01270 else
01271 s.degree = __s.s.degree;
01272 simple_sum_prod_update(r, __s);
01273 }
01274 if(n != 0 && r.params.nd() == 0 &&
01275 __s.flags & SIMPLIFY_0_IS_CONST &&
01276 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER)
01277 {
01278 r.params = __s.m.nn();
01279 r.operator_type = EXPRINFO_INTPOWER;
01280 (*delnodes).push_back(__s.nnum);
01281 s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
01282 ndel++;
01283 }
01284 break;
01285 case EXPRINFO_SQUARE:
01286 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*2;
01287 if(__s.flags & SIMPLIFY_0_IS_CONST)
01288 {
01289 double help =
01290 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01291 __s.m.nd();
01292 r.operator_type = EXPRINFO_CONSTANT;
01293 help *= r.coeffs[0];
01294 help += r.params.nd();
01295 r.params = help*help;
01296 (*delnodes).push_back(__s.nnum);
01297 }
01298 else
01299 simple_sum_prod_update(r, __s);
01300 break;
01301 case EXPRINFO_SQROOT:
01302 if(__s.flags & SIMPLIFY_0_IS_CONST)
01303 {
01304 double help =
01305 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01306 __s.m.nd();
01307 r.operator_type = EXPRINFO_CONSTANT;
01308 help *= r.coeffs[0];
01309 help += r.params.nd();
01310 r.params = std::sqrt(help);
01311 (*delnodes).push_back(__s.nnum);
01312 }
01313 else
01314 simple_sum_prod_update(r, __s);
01315 break;
01316 case EXPRINFO_ABS:
01317 if(__s.flags & SIMPLIFY_0_IS_CONST)
01318 {
01319 double help =
01320 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01321 __s.m.nd();
01322 r.operator_type = EXPRINFO_CONSTANT;
01323 help *= r.coeffs[0];
01324 help += r.params.nd();
01325 r.params = std::fabs(help);
01326 (*delnodes).push_back(__s.nnum);
01327 }
01328 else
01329 simple_sum_prod_update(r, __s);
01330 break;
01331 case EXPRINFO_EXP:
01332 if(__s.flags & SIMPLIFY_0_IS_CONST)
01333 {
01334 double help =
01335 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01336 __s.m.nd();
01337 r.operator_type = EXPRINFO_CONSTANT;
01338 help *= r.coeffs[0];
01339 help += r.params.nd();
01340 r.params = std::exp(help);
01341 (*delnodes).push_back(__s.nnum);
01342 }
01343 else
01344 simple_sum_prod_update(r, __s);
01345 break;
01346 case EXPRINFO_LOG:
01347 if(__s.flags & SIMPLIFY_0_IS_CONST)
01348 {
01349 double help =
01350 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01351 __s.m.nd();
01352 r.operator_type = EXPRINFO_CONSTANT;
01353 help *= r.coeffs[0];
01354 help += r.params.nd();
01355 r.params = std::log(help);
01356 (*delnodes).push_back(__s.nnum);
01357 }
01358 else
01359 simple_sum_prod_update(r, __s);
01360 break;
01361 case EXPRINFO_SIN:
01362 if(__s.flags & SIMPLIFY_0_IS_CONST)
01363 {
01364 double help =
01365 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01366 __s.m.nd();
01367 r.operator_type = EXPRINFO_CONSTANT;
01368 help *= r.coeffs[0];
01369 help += r.params.nd();
01370 r.params = std::sin(help);
01371 (*delnodes).push_back(__s.nnum);
01372 }
01373 else
01374 simple_sum_prod_update(r, __s);
01375 break;
01376 case EXPRINFO_COS:
01377 if(__s.flags & SIMPLIFY_0_IS_CONST)
01378 {
01379 double help =
01380 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01381 __s.m.nd();
01382 r.operator_type = EXPRINFO_CONSTANT;
01383 help *= r.coeffs[0];
01384 help += r.params.nd();
01385 r.params = std::cos(help);
01386 (*delnodes).push_back(__s.nnum);
01387 }
01388 else
01389 simple_sum_prod_update(r, __s);
01390 break;
01391 case EXPRINFO_ATAN2:
01392
01393 break;
01394 case EXPRINFO_GAUSS:
01395 if(__s.flags & SIMPLIFY_0_IS_CONST)
01396 {
01397 double help =
01398 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01399 __s.m.nd();
01400 r.operator_type = EXPRINFO_CONSTANT;
01401 help *= r.coeffs[0];
01402 help -= r.params.d()[0];
01403 help /= r.params.d()[1];
01404 r.params = std::exp(-help*help);
01405 (*delnodes).push_back(__s.nnum);
01406 }
01407 else if(__s.flags & SIMPLIFY_0_IS_SUM &&
01408 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
01409 {
01410 std::vector<double> m = r.params.d();
01411
01412 m[0] -= r.coeffs[0]*__s.m.nd();
01413 r.params = m;
01414 r.coeffs[0] *= (*__s.transfer)[0];
01415 (*delnodes).push_back(__s.nnum);
01416 }
01417 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01418 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01419 {
01420 r.coeffs[0] *= __s.m.nd();
01421 (*delnodes).push_back(__s.nnum);
01422 }
01423 break;
01424 case EXPRINFO_INVERT:
01425 if(r.coeffs[0] != 1)
01426 {
01427 r.params = r.params.nd() / r.coeffs[0];
01428 r.coeffs[0] = 1.;
01429 }
01430 if(__s.flags & SIMPLIFY_0_IS_CONST)
01431 {
01432 double help =
01433 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01434 __s.m.nd();
01435 r.operator_type = EXPRINFO_CONSTANT;
01436 r.params = r.params.nd() / help;
01437 (*delnodes).push_back(__s.nnum);
01438 }
01439 break;
01440 case EXPRINFO_DIV:
01441 if(n == 0 && __s.flags & SIMPLIFY_0_IS_CONST)
01442 {
01443 double help =
01444 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01445 __s.m.nd();
01446 r.operator_type = EXPRINFO_INVERT;
01447 r.params = help*r.coeffs[0];
01448 r.coeffs.erase(r.coeffs.begin());
01449 (*delnodes).push_back(__s.nnum);
01450 s.degree = __s.s.degree;
01451 ndel++;
01452 }
01453 else if(n == 0)
01454 {
01455 r.params = r.coeffs[0];
01456 r.coeffs[0] = 1;
01457 }
01458 if(n != 0)
01459 {
01460 if(__s.flags & SIMPLIFY_0_IS_CONST)
01461 {
01462 double help =
01463 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01464 __s.m.nd();
01465 r.operator_type = EXPRINFO_PROD;
01466 r.params = 1./help;
01467 r.coeffs.pop_back();
01468 (*delnodes).push_back(__s.nnum);
01469 ndel++;
01470 }
01471 else
01472 {
01473 r.params = r.params.nd() / r.coeffs[1];
01474 r.coeffs[1] = 1;
01475 s.degree = -1;
01476 }
01477 }
01478 break;
01479 case EXPRINFO_INTPOWER:
01480 if(r.params.nn() > 0)
01481 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.nn();
01482 else
01483 s.degree = -1;
01484 if(__s.flags & SIMPLIFY_0_IS_CONST)
01485 {
01486 double help =
01487 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01488 __s.m.nd();
01489 r.operator_type = EXPRINFO_CONSTANT;
01490 r.params = std::pow(help, r.params.nn());
01491 (*delnodes).push_back(__s.nnum);
01492 }
01493 break;
01494 case EXPRINFO_LIN:
01495 break;
01496 case EXPRINFO_QUAD:
01497 break;
01498 default:
01499
01500 break;
01501 }
01502 }
01503 else if(r.operator_type > 0)
01504 {
01505 ;
01506 }
01507 n++;
01508 v_i.set_all(__s.v_i);
01509 }
01510 };
01511 #endif
01512
01513 inline bool model::simplify_thin()
01514 {
01515 return false;
01516 }
01517
01518 inline void model::arrange_constraints()
01519 {
01520 sort(constraints.begin(), constraints.end(), sort_constraints());
01521 }
01522
01523 inline int model::next_num() { return gid->get_node_id(); }
01524 inline int model::next_variable_num() { return gid->get_var_id(); }
01525 inline int model::next_constraint_num() { return gid->get_const_id(); }
01526
01527 inline void model::renumber_variables()
01528 {
01529 gid->compress_numbers(true);
01530 detect_0chain();
01531 }
01532
01533 inline void model::compress_numbers()
01534 {
01535 gid->compress_numbers();
01536 detect_0chain();
01537 }
01538
01541 struct model::__docompare_nodes
01542 {
01543 bool operator() (const model::walker& _a, unsigned int _b) const
01544 {return _a->node_num < _b;}
01545 bool operator() (unsigned int _a, const model::walker& _b) const
01546 {return _a < _b->node_num;}
01547 bool operator() (const model::walker& _a, const model::walker& _b) const
01548 {return _a->node_num < _b->node_num;}
01549 };
01550
01553 struct model::__docompare_variables
01554 {
01555 bool operator() (const model::walker& _a, unsigned int _b) const
01556 {return _a->params.nn() < (int)_b;}
01557 bool operator() (unsigned int _a, const model::walker& _b) const
01558 {return (int)_a < _b->params.nn();}
01559 bool operator() (const model::walker& _a, const model::walker& _b) const
01560 {return _a->params.nn() < _b->params.nn();}
01561 };
01562
01563 inline model::walker model::store_node(const walker& _w)
01564 {
01565 if(!gid->have_glob_ref(_w->node_num))
01566 gid->number_of_nodes(_w->node_num+1);
01567
01568 ref_iterator __x(lower_bound(node_ref.begin(),
01569 node_ref.end(), _w->node_num, __docompare_nodes()));
01570
01571 if(__x != node_ref.end() && (*__x)->node_num == _w->node_num)
01572 *__x = _w;
01573 else
01574 node_ref.insert(__x, _w);
01575 gid->mk_globref(_w->node_num, _w);
01576 return _w;
01577 }
01578
01579 inline model::walker model::store_variable(const walker& _w)
01580 {
01581 if(_w->node_num >= number_of_nodes())
01582 gid->number_of_nodes(_w->node_num+1);
01583
01584 ref_iterator __x(lower_bound(var_ref.begin(),
01585 var_ref.end(), _w->params.nn(), __docompare_variables()));
01586
01587 if(__x != var_ref.end() && (*__x)->params.nn() == _w->params.nn())
01588 *__x = _w;
01589 else
01590 var_ref.insert(__x, _w);
01591 gid->mk_gvarref(_w->params.nn(), _w);
01592 return _w;
01593 }
01594
01595 inline model::walker model::store_constraint(const walker& _w)
01596 {
01597 unsigned int dummy;
01598 if(!gid->get_const_num(_w->node_num, dummy))
01599 {
01600
01601 constraints.push_back(_w);
01602 gid->mk_gconstref(next_constraint_num(), _w);
01603 }
01604 return _w;
01605 }
01606
01607 inline model::walker model::store_ghost(const walker& _w)
01608 {
01609 if(!gid->have_glob_ref(_w->node_num))
01610 gid->number_of_nodes(_w->node_num+1);
01611
01612 ref_iterator __x(lower_bound(ghost_ref.begin(),
01613 ghost_ref.end(), _w->node_num, __docompare_nodes()));
01614
01615 if(__x != ghost_ref.end() && (*__x)->node_num == _w->node_num)
01616 *__x = _w;
01617 else
01618 ghost_ref.insert(__x, _w);
01619 return _w;
01620 }
01621
01622 inline void model::free_all()
01623 {
01624 #if MODEL_INLINE_DEBUG
01625 std::cerr << "Removing all var refs" << std::endl;
01626 #endif
01627 std::vector<int> _all_vars;
01628 _all_vars.reserve(var_ref.size());
01629
01630 for(std::vector<walker>::iterator __i = var_ref.begin();
01631 __i != var_ref.end(); ++__i)
01632 _all_vars.push_back((*__i)->params.nn());
01633 for(std::vector<int>::iterator __i = _all_vars.begin();
01634 __i != _all_vars.end(); ++__i)
01635 free_var_num(*__i);
01636
01637 #if MODEL_INLINE_DEBUG
01638 std::cerr << "Removing all const refs" << std::endl;
01639 #endif
01640 std::vector<std::pair<walker, unsigned int> > _all_consts;
01641 _all_consts.reserve(constraints.size());
01642
01643 for(std::vector<walker>::iterator __j = constraints.begin();
01644 __j != constraints.end(); ++__j)
01645 {
01646 unsigned int cnum;
01647 if(gid->get_const_num((*__j)->node_num, cnum))
01648 _all_consts.push_back(std::make_pair(*__j, cnum));
01649 }
01650 for(std::vector<std::pair<walker, unsigned int> >::iterator
01651 __k = _all_consts.begin();
01652 __k != _all_consts.end(); ++__k)
01653 free_const_num((*__k).first, (*__k).second);
01654
01655 #if MODEL_INLINE_DEBUG
01656 std::cerr << "Removing all node refs" << std::endl;
01657 #endif
01658 std::vector<unsigned int> _all_nodes;
01659 _all_nodes.reserve(node_ref.size());
01660
01661 for(std::vector<walker>::iterator __i = node_ref.begin();
01662 __i != node_ref.end(); ++__i)
01663 _all_nodes.push_back((*__i)->node_num);
01664 for(std::vector<unsigned int>::iterator __i = _all_nodes.begin();
01665 __i != _all_nodes.end(); ++__i)
01666 free_node_num(*__i);
01667
01668 }
01669
01670 inline void model::free_node_num(unsigned int _nnum)
01671 {
01672 #if MODEL_INLINE_DEBUG
01673 std::cerr << "Removing node " << _nnum << std::endl;
01674 #endif
01675 ref_iterator __x(lower_bound(node_ref.begin(),
01676 node_ref.end(), _nnum, __docompare_nodes()));
01677 if(__x != node_ref.end() && (*__x)->node_num == _nnum)
01678 node_ref.erase(__x);
01679 gid->remove_node_id(_nnum);
01680 }
01681
01682 inline void model::free_var_num(int _vnum)
01683 {
01684 #if MODEL_INLINE_DEBUG
01685 std::cerr << "Removing var " << _vnum << std::endl;
01686 #endif
01687 ref_iterator __x(lower_bound(var_ref.begin(),
01688 var_ref.end(), _vnum, __docompare_variables()));
01689 if(__x != var_ref.end() && (*__x)->params.nn() == _vnum)
01690 var_ref.erase(__x);
01691 gid->remove_var_id(_vnum);
01692 }
01693
01694 inline void model::free_const_num(const walker& _w, unsigned int _cnum)
01695 {
01696 #if MODEL_INLINE_DEBUG
01697 std::cerr << "Removing constraint " << _cnum << std::endl;
01698 #endif
01699 ref_iterator __x;
01700 for(__x = constraints.begin(); __x != constraints.end(); ++__x)
01701 if((*__x) == _w) break;
01702 if(__x != constraints.end())
01703 constraints.erase(__x);
01704 gid->remove_const_id(_cnum);
01705 }
01706
01707 inline void model::remove_node(const walker& _w)
01708 {
01709 remove_node(_w, _w->node_num);
01710 }
01711
01712 inline void model::remove_node(unsigned int __node_num)
01713 {
01714 remove_node(gid->node(__node_num), __node_num);
01715 }
01716
01717 inline void model::new_variables(int _new_num_of_vars)
01718 {
01719 gid->number_of_variables(_new_num_of_vars);
01720 }
01721
01722 inline model::walker model::constant(double _constant)
01723 {
01724 expression_node _en(EXPRINFO_CONSTANT, next_num());
01725
01726 _en.v_i.reserve(gid->number_of_variables());
01727 _en.v_i.clear();
01728 _en.params = _constant;
01729
01730 return store_node(between_back(ground(), sky(), _en));
01731 }
01732
01733 inline model::walker model::constant(const std::vector<double>& _constant)
01734 {
01735 expression_node _en(EXPRINFO_CONSTANT, next_num());
01736
01737 _en.v_i.reserve(gid->number_of_variables());
01738 _en.v_i.clear();
01739 _en.params = _constant;
01740
01741 return store_node(between_back(ground(), sky(), _en));
01742 }
01743
01744 inline model::walker model::ghost(unsigned int _nnum)
01745 {
01746 ref_iterator __x;
01747
01748 __x = lower_bound(ghost_ref.begin(), ghost_ref.end(), _nnum,
01749 __docompare_nodes());
01750 if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
01751 return *__x;
01752 else
01753 {
01754 walker __r;
01755 expression_node _en(EXPRINFO_GHOST, _nnum);
01756 _en.params = false;
01757 _en.f_bounds = interval(-COCO_INF,COCO_INF);
01758 __r = between_back(ground(), sky(), _en);
01759 ghost_ref.insert(__x, __r);
01760 return __r;
01761 }
01762 }
01763
01764 inline bool model::exchange_ghost(walker prnt, walker gh_old,
01765 unsigned int _nnum)
01766 {
01767 ref_iterator __x;
01768 bool ret(false);
01769
01770 __x = lower_bound(ghost_ref.begin(), ghost_ref.end(), _nnum,
01771 __docompare_nodes());
01772 if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
01773 replace_edge_to_child(prnt, gh_old, *__x);
01774 else
01775 {
01776 walker __r;
01777 expression_node _en(EXPRINFO_GHOST, _nnum);
01778 _en.params = false;
01779 _en.f_bounds = interval(-COCO_INF,COCO_INF);
01780
01781 children_iterator _cit;
01782 _cit = prnt._C_w_cur->get_childentry_iterator((void*)gh_old.node());
01783 __r = between(prnt, _cit, sky(), sky().parent_end(), _en);
01784 if(gh_old.n_parents() > 1)
01785 remove_edge(prnt, gh_old);
01786 else
01787 ret = true;
01788 ghost_ref.insert(__x, __r);
01789 }
01790 return ret;
01791 }
01792
01793 inline void model::safe_ghost(walker prnt, unsigned int _nnum)
01794 {
01795 ref_iterator __x;
01796
01797 __x = lower_bound(ghost_ref.begin(), ghost_ref.end(), _nnum,
01798 __docompare_nodes());
01799 if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
01800 {
01801 add_edge_back(prnt, *__x);
01802 }
01803 else
01804 {
01805 walker __r;
01806 expression_node _en(EXPRINFO_GHOST, _nnum);
01807 _en.params = false;
01808 _en.f_bounds = interval(-COCO_INF,COCO_INF);
01809 __r = between_back(prnt, sky(), _en);
01810 ghost_ref.insert(__x, __r);
01811 }
01812 }
01813
01814 inline model::walker model::binary(const walker& _op1, const walker& _op2,
01815 int expr_type, double _coeff1, double _coeff2)
01816 {
01817 expression_node _en(expr_type, next_num());
01818 std::vector<walker> _w(2);
01819
01820 _en.v_i = (*_op1).v_i;
01821 _en.v_i.set_all((*_op2).v_i);
01822 _w[0] = _op1;
01823 _w[1] = _op2;
01824 _en.coeffs.push_back(_coeff1);
01825 _en.coeffs.push_back(_coeff2);
01826 if(expr_type == EXPRINFO_PROD || expr_type == EXPRINFO_DIV||
01827 expr_type == EXPRINFO_INVERT)
01828 _en.params = 1.;
01829 else
01830 _en.params = 0.;
01831 return store_node(split_back(ground(), _w, _en));
01832 }
01833
01834 inline model::walker model::binary(const walker& _op1, const walker& _op2,
01835 int expr_type, const basic_alltype& _params,
01836 double _coeff1, double _coeff2)
01837 {
01838 expression_node _en(expr_type, next_num());
01839 std::vector<walker> _w(2);
01840
01841 _en.v_i = (*_op1).v_i;
01842 _en.v_i.set_all((*_op2).v_i);
01843 _en.params = _params;
01844 _w[0] = _op1;
01845 _w[1] = _op2;
01846 _en.coeffs.push_back(_coeff1);
01847 _en.coeffs.push_back(_coeff2);
01848 return store_node(split_back(ground(), _w, _en));
01849 }
01850
01851 inline model::walker model::unary(const walker& _op1, int expr_type,
01852 double _coeff)
01853 {
01854 expression_node _en(expr_type, next_num());
01855
01856 _en.v_i = (*_op1).v_i;
01857 _en.coeffs.push_back(_coeff);
01858 if(expr_type == EXPRINFO_INVERT)
01859 _en.params = 1.;
01860 else
01861 _en.params = 0.;
01862 return store_node(split_back(ground(), _op1, _en));
01863 }
01864
01865 inline model::walker model::unary(const walker& _op1, int expr_type,
01866 const basic_alltype& _params, double _coeff)
01867 {
01868 expression_node _en(expr_type, next_num());
01869
01870 _en.v_i = (*_op1).v_i;
01871 _en.params = _params;
01872 _en.coeffs.push_back(_coeff);
01873 return store_node(split_back(ground(), _op1, _en));
01874 }
01875
01876 inline model::walker model::nary(const std::vector<walker>& _op, int expr_type,
01877 const std::vector<double>& _coeffs)
01878 {
01879 expression_node _en(expr_type, next_num());
01880
01881 _en.v_i = (*_op[0]).v_i;
01882 for(const_ref_iterator b = _op.begin(); b != _op.end(); ++b)
01883 _en.v_i.set_all((**b).v_i);
01884 if(_coeffs.size() == 0)
01885 _en.coeffs.insert(_en.coeffs.end(),_op.size(),1.0);
01886 else
01887 _en.coeffs = _coeffs;
01888 if(expr_type == EXPRINFO_PROD)
01889 _en.params = 1.;
01890 else
01891 _en.params = 0.;
01892 return store_node(split_back(ground(), _op, _en));
01893 }
01894
01895 inline model::walker model::nary(const std::vector<walker>& _op, int expr_type,
01896 const basic_alltype& _params,
01897 const std::vector<double>& _coeffs)
01898 {
01899 expression_node _en(expr_type, next_num());
01900
01901 _en.v_i = (*_op[0]).v_i;
01902 for(const_ref_iterator b = _op.begin(); b != _op.end(); ++b)
01903 _en.v_i.set_all((**b).v_i);
01904 _en.params = _params;
01905 if(_coeffs.size() == 0)
01906 _en.coeffs.insert(_en.coeffs.end(),_op.size(),1.0);
01907 else
01908 _en.coeffs = _coeffs;
01909 return store_node(split_back(ground(), _op, _en));
01910 }
01911
01912 template <typename _TT>
01913 inline void model::read_vector(std::vector<_TT>& hd, char *& cq,
01914 const char *format, const char *message,
01915 int ln)
01916 {
01917 _TT help;
01918
01919 cq += strspn(cq+1, " \t")+1;
01920 for(; cq; )
01921 {
01922 char *ct;
01923
01924 ct = strsep(&cq, ",");
01925 ct += strspn(ct, " \t");
01926 if(sscanf(ct, format, &help) != 1)
01927 {
01928 throw api_exception(apiee_io, std::string("Malformed Input: Line ")+
01929 convert_to_str(ln)+": "+message);
01930 }
01931 hd.push_back(help);
01932 }
01933 }
01934
01935 inline void model::clr_sky_ground_link()
01936 {
01937 if(ground().n_children() != 1 || !empty())
01938 remove_edge(ground(), sky());
01939 }
01940
01941 inline void model::set_counters()
01942 {
01943 ref_iterator __e = node_ref.end();
01944 walker _x;
01945 for(ref_iterator __x = node_ref.begin(); __x != __e; ++__x)
01946 {
01947 _x = *__x;
01948 if(_x.n_children() == 1)
01949 {
01950 walker _c = _x >> _x.child_begin();
01951 if(_c == sky())
01952 _x->n_children = 0;
01953 else
01954 _x->n_children = 1;
01955 }
01956 else
01957 _x->n_children = (unsigned int)_x.n_children();
01958 if(_x.n_parents() == 1)
01959 {
01960 walker _c = _x >> _x.parent_begin();
01961 if(_c == ground())
01962 _x->n_parents = 0;
01963 else
01964 _x->n_parents = 1;
01965 }
01966 else
01967 _x->n_parents = (unsigned int)_x.n_parents();
01968 }
01969 }
01970
01972 struct model::detect_0chain_visitor_st
01973 {
01974 std::pair<unsigned int,unsigned int> r;
01975 unsigned int *f;
01976 std::vector<unsigned int>* t;
01977 std::vector<unsigned int>* d;
01978 std::vector<unsigned int>* nn;
01979 bool new_number;
01980 };
01981
01984 class model::detect_0chain_visitor : public
01985 cached_forward_evaluator_base<model::detect_0chain_visitor_st,
01986 expression_node, std::pair<unsigned int,unsigned int>,
01987 model::const_walker>
01988 {
01989 private:
01991 typedef cached_forward_evaluator_base<model::detect_0chain_visitor_st,
01992 expression_node, std::pair<unsigned int,unsigned int>,
01993 model::const_walker> _Base;
01994 public:
01998 detect_0chain_visitor(std::vector<unsigned int>& __t,
01999 std::vector<unsigned int>& __d,
02000 std::vector<unsigned int>& __nn, unsigned int &d)
02001 {
02002 eval_data.r = std::make_pair(0,0);
02003 eval_data.t = &__t;
02004 eval_data.d = &__d;
02005 eval_data.f = &d;
02006 eval_data.nn = &__nn;
02007 eval_data.new_number = false;
02008 }
02009
02011 detect_0chain_visitor(const detect_0chain_visitor& __x) : _Base(__x)
02012 {}
02013
02015 ~detect_0chain_visitor() {}
02016
02018
02020 void initialize() { return; }
02021
02022 bool is_cached(const expression_node& __data)
02023 { return (*eval_data.t)[__data.node_num] != 0; }
02024
02025 void retrieve_from_cache(const expression_node& __data)
02026 { eval_data.r = std::make_pair((*eval_data.t)[__data.node_num],
02027 (*eval_data.d)[__data.node_num]); }
02028
02029 int initialize(const expression_node& __data)
02030 {
02031 if(__data.operator_type == EXPRINFO_VARIABLE)
02032 {
02033 unsigned int __h;
02034 eval_data.new_number = true;
02035 __h = (*eval_data.f)++;
02036 eval_data.r = std::make_pair(__h,0);
02037 (*eval_data.nn).push_back(__data.node_num);
02038 }
02039 else
02040 {
02041 eval_data.new_number = false;
02042 eval_data.r = std::make_pair(0,0);
02043 }
02044 return 1;
02045 }
02046
02047 void calculate(const expression_node& __data)
02048 {
02049 (*eval_data.t)[__data.node_num] = eval_data.r.first;
02050 (*eval_data.d)[__data.node_num] = eval_data.r.second;
02051 }
02052
02053 int update(const std::pair<unsigned int,unsigned int>& __rval) { return 0; }
02054
02055 int update(const expression_node& __data,
02056 const std::pair<unsigned int,unsigned int>& __rval)
02057 {
02058 if(__data.operator_type == EXPRINFO_CONSTANT ||
02059 __data.operator_type == EXPRINFO_VARIABLE || __rval.first == 0)
02060 return 0;
02061 if(eval_data.r.first == 0)
02062 eval_data.r = std::make_pair(__rval.first,__rval.second+1);
02063 else if(eval_data.r.first == __rval.first)
02064 eval_data.r.second++;
02065 else if(!eval_data.new_number)
02066 {
02067 int __h;
02068 eval_data.new_number = true;
02069 __h = (*eval_data.f)++;
02070 eval_data.r = std::make_pair(__h,0);
02071 (*eval_data.nn).push_back(__data.node_num);
02072 }
02073 return 0;
02074 }
02075
02076 std::pair<unsigned int,unsigned int> calculate_value(bool eval_all)
02077 { return eval_data.r; }
02079 };
02080
02082 struct model::lincoeff_visitor_ret
02083 {
02084 bool was_lin;
02085 bool was_const;
02086 int node_num;
02087 double const_trans;
02088 };
02089
02091 struct model::lincoeff_visitor_st
02092 {
02093 const model* mod;
02094 const std::vector<interval>* ranges;
02095 linalg::sparse_vector<double>* coeffs;
02096
02097 double* constant;
02098 double old_trans;
02099 double trans;
02100 double mm_help;
02101 lincoeff_visitor_ret r;
02102 int old_nlin;
02103 int in_nlin;
02104 unsigned int n;
02105 };
02106
02109 class model::lincoeff_visitor : public
02110 cached_backward_evaluator_base<lincoeff_visitor_st, expression_node,
02111 lincoeff_visitor_ret, model::const_walker>
02112 {
02113 private:
02115 typedef cached_backward_evaluator_base<lincoeff_visitor_st,
02116 expression_node, lincoeff_visitor_ret, model::const_walker> _Base;
02117
02118 public:
02122 lincoeff_visitor(const std::vector<interval>* _rg,
02123 linalg::sparse_vector<double>* _cf, double* _cs,
02124 const model* _m)
02125 {
02126 eval_data.trans = 1;
02127 eval_data.old_trans = 1;
02128 eval_data.n = 0;
02129 eval_data.r.was_lin = true;
02130 eval_data.r.was_const = false;
02131 eval_data.r.const_trans = 0;
02132 eval_data.r.node_num = -1;
02133 eval_data.old_nlin = -1;
02134 eval_data.in_nlin = -1;
02135 eval_data.ranges = _rg;
02136 eval_data.coeffs = _cf;
02137 eval_data.constant = _cs;
02138 eval_data.mod = _m;
02139 }
02140
02142 lincoeff_visitor(const lincoeff_visitor& __x) : _Base(__x) {}
02143
02145 ~lincoeff_visitor() {}
02146
02148
02150 bool is_cached(const expression_node& __data)
02151 {
02152 return (__data.operator_type == EXPRINFO_LIN ||
02153 __data.operator_type == EXPRINFO_QUAD);
02154 }
02155
02156 virtual const_walker short_cut_to(const expression_node& __data)
02157 {
02158 return eval_data.mod->sky();
02159 }
02160
02161 void initialize()
02162 {
02163 eval_data.n = 0;
02164 eval_data.r.was_lin = false;
02165 eval_data.r.was_const = false;
02166 eval_data.r.node_num = -1;
02167 eval_data.r.const_trans = 0;
02168 eval_data.old_nlin = eval_data.in_nlin;
02169 eval_data.old_trans = eval_data.trans;
02170 }
02171
02172 void initialize(const expression_node& __data)
02173 {
02174 eval_data.n = 0;
02175 eval_data.r.was_lin = false;
02176 eval_data.r.was_const = false;
02177 eval_data.r.node_num = __data.node_num;
02178 eval_data.r.const_trans = 0;
02179 eval_data.old_nlin = eval_data.in_nlin;
02180 eval_data.old_trans = eval_data.trans;
02181 }
02182
02183 void retrieve_from_cache(const expression_node& __data)
02184 {
02185 if(__data.operator_type == EXPRINFO_LIN)
02186 {
02187 eval_data.r.was_lin = true;
02188 if(eval_data.trans == 1)
02189 {
02190 linalg_add(*eval_data.coeffs, eval_data.mod->lin[__data.params.nn()],
02191 *eval_data.coeffs);
02192 }
02193 else
02194 {
02195 linalg_add(*eval_data.coeffs,
02196 linalg_scale(eval_data.mod->lin[__data.params.nn()],
02197 eval_data.trans),
02198 *eval_data.coeffs);
02199 }
02200 }
02201 else if(__data.operator_type == EXPRINFO_QUAD)
02202 eval_data.r.was_lin = eval_data.r.was_const = false;
02203 }
02204
02205 int calculate(const expression_node& __data)
02206 {
02207 if(__data.operator_type < 0)
02208 {
02209 switch(__data.operator_type)
02210 {
02211 case EXPRINFO_CONSTANT:
02212 eval_data.r.was_lin = true;
02213 eval_data.r.was_const = true;
02214 eval_data.r.const_trans = __data.params.nd();
02215 break;
02216 case EXPRINFO_VARIABLE:
02217 if(eval_data.ranges &&
02218 (*eval_data.ranges)[__data.node_num].is_thin())
02219 {
02220 eval_data.r.was_const = true;
02221 eval_data.r.const_trans =
02222 (*eval_data.ranges)[__data.node_num].sup();
02223 }
02224 else if(__data.f_bounds.is_thin())
02225 {
02226 eval_data.r.was_const = true;
02227 eval_data.r.const_trans = __data.f_bounds.sup();
02228 }
02229 else if(eval_data.old_nlin == -1)
02230 (*eval_data.coeffs)[__data.params.nn()] += eval_data.old_trans;
02231 eval_data.r.was_lin = true;
02232 break;
02233 case EXPRINFO_SUM:
02234 if(eval_data.old_nlin == -1)
02235 *eval_data.constant += eval_data.old_trans * __data.params.nd();
02236 break;
02237 case EXPRINFO_PROD:
02238 case EXPRINFO_DIV:
02239 eval_data.old_trans *= __data.params.nd();
02240 eval_data.in_nlin = 1;
02241 break;
02242 case EXPRINFO_INVERT:
02243 eval_data.old_trans *= __data.params.nd();
02244 eval_data.in_nlin = 2;
02245 break;
02246 case EXPRINFO_MAX:
02247 case EXPRINFO_MIN:
02248 eval_data.in_nlin = -2;
02249 eval_data.r.was_lin = eval_data.r.was_const = true;
02250 eval_data.r.const_trans = __data.params.nd();
02251 break;
02252 case EXPRINFO_ABS:
02253 if(eval_data.ranges)
02254 {
02255 if((*eval_data.ranges)[__data.node_num].sup() <= 0)
02256 eval_data.old_trans *= -1;
02257 else if((*eval_data.ranges)[__data.node_num].inf() < 0)
02258 eval_data.in_nlin = 1;
02259 }
02260 else
02261 {
02262 if(__data.f_bounds.sup() <= 0)
02263 {
02264 eval_data.old_trans *= -1;
02265 }
02266 else if(__data.f_bounds.inf() < 0)
02267 eval_data.in_nlin = 1;
02268 }
02269 break;
02270 case EXPRINFO_ATAN2:
02271 eval_data.in_nlin = 2;
02272 break;
02273 case EXPRINFO_POW:
02274 eval_data.in_nlin = 2;
02275 break;
02276 case EXPRINFO_INTPOWER:
02277 if(__data.params.nn() != 1)
02278 eval_data.in_nlin = 2;
02279 break;
02280 case EXPRINFO_SQUARE:
02281 case EXPRINFO_SQROOT:
02282 case EXPRINFO_EXP:
02283 case EXPRINFO_LOG:
02284 case EXPRINFO_SIN:
02285 case EXPRINFO_COS:
02286 case EXPRINFO_GAUSS:
02287 eval_data.in_nlin = 2;
02288 break;
02289 case EXPRINFO_LIN:
02290 case EXPRINFO_QUAD:
02291 throw api_exception(apiee_internal, "Must not be here in lincoeff_visitor::calculate");
02292 break;
02293 default:
02294 throw api_exception(apiee_internal,
02295 std::string("Unknown expression type in lincoeff_visitor::calculate: ")+
02296 convert_to_str(__data.operator_type));
02297 break;
02298 }
02299 }
02300 else if(__data.operator_type > 0)
02301 {
02302 eval_data.r.was_lin = false;
02303 eval_data.r.was_const = false;
02304 eval_data.in_nlin = 3;
02305 }
02306 if(!__data.coeffs.empty())
02307 eval_data.trans = eval_data.old_trans * __data.coeffs[0];
02308 return 1;
02309 }
02310
02311 int update(const expression_node& __data, const lincoeff_visitor_ret& __rval)
02312 {
02313 if(__data.operator_type < 0)
02314 {
02315 switch(__data.operator_type)
02316 {
02317 case EXPRINFO_CONSTANT:
02318 case EXPRINFO_VARIABLE:
02319 break;
02320 case EXPRINFO_SUM:
02321 if(eval_data.n == 0)
02322 {
02323 eval_data.r.was_lin = __rval.was_lin;
02324 eval_data.r.was_const = __rval.was_const;
02325 }
02326 else if(__rval.was_const && eval_data.r.was_const)
02327 {
02328 eval_data.r.was_lin = true;
02329 eval_data.r.const_trans =
02330 (eval_data.n == 0 ? __rval.const_trans
02331 : __rval.const_trans + eval_data.r.const_trans);
02332 }
02333 else if(__rval.was_const && eval_data.r.was_lin)
02334 eval_data.r.const_trans += __rval.const_trans;
02335 else if(eval_data.r.was_const && __rval.was_lin)
02336 {
02337 eval_data.r.was_const = false;
02338 eval_data.r.was_lin = true;
02339 }
02340 else if(!__rval.was_lin)
02341 eval_data.r.was_lin = false;
02342 if(eval_data.n == __data.n_children - 1)
02343 {
02344 if(eval_data.r.was_const)
02345 eval_data.r.const_trans += __data.params.nd();
02346 else if(eval_data.r.was_lin && eval_data.old_nlin == -1)
02347 *eval_data.constant += eval_data.old_trans*
02348 (eval_data.r.const_trans + __data.params.nd());
02349 }
02350 break;
02351 case EXPRINFO_PROD:
02352 if(eval_data.n == 0)
02353 eval_data.r = __rval;
02354 else if(__rval.was_const && eval_data.r.was_const)
02355 {
02356 eval_data.r.was_lin = true;
02357 eval_data.r.const_trans =
02358 (eval_data.n == 0 ? __rval.const_trans
02359 : __rval.const_trans * eval_data.r.const_trans);
02360 }
02361 else if(__rval.was_const && eval_data.r.was_lin)
02362 eval_data.r.const_trans *= __rval.const_trans;
02363 else if(eval_data.r.was_const && __rval.was_lin)
02364 {
02365 eval_data.r.was_const = false;
02366 eval_data.r.was_lin = true;
02367 eval_data.r.node_num = __rval.node_num;
02368 }
02369 else
02370 eval_data.r.was_const = eval_data.r.was_lin = false;
02371 if(eval_data.n == __data.n_children - 1)
02372 {
02373 if(eval_data.r.was_lin && !eval_data.r.was_const)
02374 {
02375 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02376 eval_data.constant, eval_data.mod);
02377 lv.eval_data.trans =
02378 eval_data.old_trans * eval_data.r.const_trans;
02379 eval_data.r = evaluate(lv,
02380 (const_walker) eval_data.mod->node(eval_data.r.node_num));
02381 }
02382 else if(eval_data.r.was_const)
02383 eval_data.r.const_trans *= __data.params.nd();
02384 eval_data.r.node_num = __data.node_num;
02385 }
02386 break;
02387 case EXPRINFO_INVERT:
02388 if(__rval.was_const)
02389 {
02390 eval_data.r.was_const = true;
02391 eval_data.r.was_lin = true;
02392 eval_data.r.const_trans =
02393 __data.params.nd()/__rval.const_trans;
02394 }
02395 else
02396 eval_data.r.was_lin = false;
02397 break;
02398 case EXPRINFO_DIV:
02399 if(__rval.was_const)
02400 {
02401 if(eval_data.n == 0)
02402 {
02403 eval_data.r.const_trans = __rval.const_trans;
02404 eval_data.r.was_const = true;
02405 }
02406 else if(eval_data.n == 1)
02407 {
02408 if(eval_data.r.was_const && __rval.const_trans != 0)
02409 {
02410 eval_data.r.const_trans =
02411 eval_data.r.const_trans/__rval.const_trans;
02412 eval_data.r.was_lin = true;
02413 }
02414 else
02415 eval_data.r.was_lin = eval_data.r.was_const = false;
02416 }
02417 }
02418 else
02419 eval_data.r.was_const = eval_data.r.was_lin = false;
02420 break;
02421 case EXPRINFO_MAX:
02422 if(__rval.was_const && eval_data.r.was_const)
02423 {
02424 if(__rval.const_trans > eval_data.r.const_trans)
02425 eval_data.r.const_trans = __rval.const_trans;
02426 }
02427 else if(__rval.was_const && !eval_data.r.was_const)
02428 {
02429 if(__rval.const_trans > eval_data.mm_help)
02430 {
02431 eval_data.r.was_const = true;
02432 eval_data.r.was_lin = true;
02433 eval_data.r.const_trans = __rval.const_trans;
02434 }
02435 }
02436 else if(eval_data.r.was_const && !__rval.was_const)
02437 {
02438 interval _rg =
02439 (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02440 if(eval_data.r.const_trans <= _rg.sup())
02441 {
02442 eval_data.r.was_const = false;
02443 eval_data.r.was_lin = __rval.was_lin;
02444 eval_data.r.node_num = __rval.node_num;
02445 eval_data.r.const_trans = _rg.inf();
02446 eval_data.mm_help = _rg.sup();
02447 eval_data.in_nlin = eval_data.n;
02448 }
02449 }
02450 else
02451 {
02452 interval _rg =
02453 (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02454 if(eval_data.r.const_trans <= _rg.sup())
02455 {
02456 if(eval_data.mm_help < _rg.inf())
02457 {
02458 eval_data.r.was_lin = __rval.was_lin;
02459 eval_data.r.node_num = __rval.node_num;
02460 eval_data.r.const_trans = _rg.inf();
02461 eval_data.mm_help = _rg.sup();
02462 eval_data.in_nlin = eval_data.n;
02463 }
02464 else
02465 {
02466 eval_data.r.was_lin = false;
02467 if(_rg.inf() < eval_data.r.const_trans)
02468 eval_data.r.const_trans = _rg.inf();
02469 if(_rg.sup() > eval_data.mm_help)
02470 eval_data.mm_help = _rg.sup();
02471 }
02472 }
02473 }
02474 if(eval_data.n == __data.n_children - 1)
02475 {
02476 if(eval_data.r.was_lin && !eval_data.r.was_const &&
02477 eval_data.old_nlin == -1)
02478 {
02479 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02480 eval_data.constant, eval_data.mod);
02481 lv.eval_data.trans =
02482 eval_data.old_trans * __data.coeffs[eval_data.in_nlin];
02483 eval_data.r = evaluate(lv,
02484 (const_walker) eval_data.mod->node(eval_data.r.node_num));
02485 }
02486 eval_data.r.node_num = __data.node_num;
02487 }
02488 break;
02489 case EXPRINFO_MIN:
02490 if(__rval.was_const && eval_data.r.was_const)
02491 {
02492 if(__rval.const_trans < eval_data.r.const_trans)
02493 eval_data.r.const_trans = __rval.const_trans;
02494 }
02495 else if(__rval.was_const && !eval_data.r.was_const)
02496 {
02497 if(__rval.const_trans < eval_data.mm_help)
02498 {
02499 eval_data.r.was_const = true;
02500 eval_data.r.was_lin = true;
02501 eval_data.r.const_trans = __rval.const_trans;
02502 }
02503 }
02504 else if(eval_data.r.was_const && !__rval.was_const)
02505 {
02506 interval _rg =
02507 (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02508 if(eval_data.r.const_trans >= _rg.inf())
02509 {
02510 eval_data.r.was_const = false;
02511 eval_data.r.was_lin = __rval.was_lin;
02512 eval_data.r.node_num = __rval.node_num;
02513 eval_data.r.const_trans = _rg.sup();
02514 eval_data.mm_help = _rg.inf();
02515 eval_data.in_nlin = eval_data.n;
02516 }
02517 }
02518 else
02519 {
02520 interval _rg =
02521 (*eval_data.ranges)[__rval.node_num]*__data.coeffs[eval_data.n];
02522 if(eval_data.r.const_trans >= _rg.inf())
02523 {
02524 if(eval_data.mm_help > _rg.sup())
02525 {
02526 eval_data.r.was_lin = __rval.was_lin;
02527 eval_data.r.node_num = __rval.node_num;
02528 eval_data.r.const_trans = _rg.sup();
02529 eval_data.mm_help = _rg.inf();
02530 eval_data.in_nlin = eval_data.n;
02531 }
02532 else
02533 {
02534 eval_data.r.was_lin = false;
02535 if(_rg.sup() > eval_data.r.const_trans)
02536 eval_data.r.const_trans = _rg.sup();
02537 if(_rg.inf() < eval_data.mm_help)
02538 eval_data.mm_help = _rg.inf();
02539 }
02540 }
02541 }
02542 if(eval_data.n == __data.n_children - 1)
02543 {
02544 if(eval_data.r.was_lin && !eval_data.r.was_const &&
02545 eval_data.old_nlin == -1)
02546 {
02547 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02548 eval_data.constant, eval_data.mod);
02549 lv.eval_data.trans =
02550 eval_data.old_trans * __data.coeffs[eval_data.in_nlin];
02551 eval_data.r = evaluate(lv,
02552 (const_walker) eval_data.mod->node(eval_data.r.node_num));
02553 }
02554 eval_data.r.node_num = __data.node_num;
02555 }
02556 break;
02557 case EXPRINFO_ABS:
02558 if(__rval.was_const)
02559 {
02560 eval_data.r.was_const = eval_data.r.was_lin = true;
02561 eval_data.r.const_trans = std::fabs(__data.coeffs[0]*__rval.const_trans+
02562 __data.params.nd());
02563 }
02564 else if(eval_data.ranges && eval_data.old_nlin == -1)
02565 {
02566 if((*eval_data.ranges)[__data.node_num].sup() <= 0)
02567 *eval_data.constant -= eval_data.old_trans*__data.params.nd();
02568 else if((*eval_data.ranges)[__data.node_num].inf() >= 0)
02569 *eval_data.constant += eval_data.old_trans*__data.params.nd();
02570 }
02571 else if(eval_data.old_nlin == -1)
02572 {
02573 if(__data.f_bounds.sup() <= 0)
02574 *eval_data.constant -= eval_data.old_trans*__data.params.nd();
02575 else if(__data.f_bounds.inf() >= 0)
02576 *eval_data.constant += eval_data.old_trans*__data.params.nd();
02577 }
02578 break;
02579 case EXPRINFO_SQUARE:
02580 if(__rval.was_const)
02581 {
02582 eval_data.r.was_const = eval_data.r.was_lin = true;
02583 eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans+
02584 __data.params.nd();
02585 eval_data.r.const_trans *= eval_data.r.const_trans;
02586 }
02587 else
02588 eval_data.r.was_lin = false;
02589 break;
02590 case EXPRINFO_SQROOT:
02591 if(__rval.was_const)
02592 {
02593 eval_data.r.was_const = eval_data.r.was_lin = true;
02594 eval_data.r.const_trans = std::sqrt(__data.coeffs[0]*__rval.const_trans+
02595 __data.params.nd());
02596 }
02597 else
02598 eval_data.r.was_lin = false;
02599 break;
02600 case EXPRINFO_INTPOWER:
02601 if(__rval.was_const)
02602 {
02603 eval_data.r.was_const = eval_data.r.was_lin = true;
02604 switch(__data.params.nn())
02605 {
02606 case 0:
02607 eval_data.r.const_trans = 1;
02608 break;
02609 case 1:
02610 eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02611 break;
02612 case 2:
02613 eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02614 eval_data.r.const_trans *= eval_data.r.const_trans;
02615 break;
02616 case -1:
02617 eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02618 eval_data.r.const_trans = 1./eval_data.r.const_trans;
02619 break;
02620 case -2:
02621 eval_data.r.const_trans = __data.coeffs[0]*__rval.const_trans;
02622 eval_data.r.const_trans =
02623 1./(eval_data.r.const_trans*eval_data.r.const_trans);
02624 break;
02625 default:
02626 eval_data.r.const_trans =
02627 std::pow(__data.coeffs[0]*__rval.const_trans,
02628 __data.params.nn());
02629 break;
02630 }
02631 }
02632 else if(__data.params.nn() == 0)
02633 {
02634 eval_data.r.was_const = eval_data.r.was_lin = true;
02635 eval_data.r.const_trans = 1;
02636 }
02637 else if(__data.params.nn() != 1)
02638 eval_data.r.was_lin = false;
02639 break;
02640 case EXPRINFO_POW:
02641 if(eval_data.n == 0)
02642 {
02643 eval_data.r.was_lin = __rval.was_lin;
02644 eval_data.r.node_num = __rval.node_num;
02645 }
02646 if(__rval.was_const)
02647 {
02648 if(eval_data.n == 0)
02649 {
02650 eval_data.r.const_trans = __rval.const_trans;
02651 eval_data.r.was_const = true;
02652 }
02653 else if(eval_data.n == 1)
02654 {
02655 if(eval_data.r.was_const)
02656 {
02657 eval_data.r.const_trans = std::pow(__data.coeffs[0]*
02658 eval_data.r.const_trans+__data.params.nd(),
02659 __data.coeffs[1]*__rval.const_trans);
02660 eval_data.r.was_lin = true;
02661 }
02662 else if(__rval.const_trans == 0)
02663 {
02664 eval_data.r.const_trans = 1;
02665 eval_data.r.was_lin = eval_data.r.was_const = true;
02666 }
02667 else if(__rval.const_trans == 1 && eval_data.r.was_lin
02668 && eval_data.old_nlin == -1)
02669 {
02670
02671 lincoeff_visitor lv(eval_data.ranges, eval_data.coeffs,
02672 eval_data.constant, eval_data.mod);
02673 lv.eval_data.trans = eval_data.old_trans;
02674 eval_data.r = evaluate(lv,
02675 (const_walker) eval_data.mod->node(eval_data.r.node_num));
02676 }
02677 else
02678 eval_data.r.was_lin = eval_data.r.was_const = false;
02679 }
02680 }
02681 else
02682 eval_data.r.was_const = eval_data.r.was_lin = false;
02683 if(eval_data.n == 1)
02684 eval_data.r.node_num = __data.node_num;
02685 break;
02686 case EXPRINFO_EXP:
02687 if(__rval.was_const)
02688 {
02689 eval_data.r.was_const = eval_data.r.was_lin = true;
02690 eval_data.r.const_trans = std::exp(__data.coeffs[0]*__rval.const_trans+
02691 __data.params.nd());
02692 }
02693 else
02694 eval_data.r.was_lin = false;
02695 break;
02696 case EXPRINFO_LOG:
02697 if(__rval.was_const)
02698 {
02699 eval_data.r.was_const = eval_data.r.was_lin = true;
02700 eval_data.r.const_trans = std::log(__data.coeffs[0]*__rval.const_trans+
02701 __data.params.nd());
02702 }
02703 else
02704 eval_data.r.was_lin = false;
02705 break;
02706 case EXPRINFO_SIN:
02707 if(__rval.was_const)
02708 {
02709 eval_data.r.was_const = eval_data.r.was_lin = true;
02710 eval_data.r.const_trans = std::sin(__data.coeffs[0]*__rval.const_trans+
02711 __data.params.nd());
02712 }
02713 else
02714 eval_data.r.was_lin = false;
02715 break;
02716 case EXPRINFO_COS:
02717 if(__rval.was_const)
02718 {
02719 eval_data.r.was_const = eval_data.r.was_lin = true;
02720 eval_data.r.const_trans = std::cos(__data.coeffs[0]*__rval.const_trans+
02721 __data.params.nd());
02722 }
02723 else
02724 eval_data.r.was_lin = false;
02725 break;
02726 case EXPRINFO_ATAN2:
02727 if(__rval.was_const)
02728 {
02729 if(eval_data.n == 0)
02730 {
02731 eval_data.r.const_trans = __rval.const_trans;
02732 eval_data.r.was_const = true;
02733 }
02734 else if(eval_data.n == 1)
02735 {
02736 if(eval_data.r.was_const)
02737 {
02738 eval_data.r.const_trans =
02739 std::atan2(eval_data.r.const_trans, __rval.const_trans);
02740 eval_data.r.was_lin = true;
02741 }
02742 else
02743 eval_data.r.was_lin = eval_data.r.was_const = false;
02744 }
02745 }
02746 else
02747 eval_data.r.was_const = eval_data.r.was_lin = false;
02748 break;
02749 case EXPRINFO_GAUSS:
02750 if(__rval.was_const)
02751 {
02752 eval_data.r.was_const = eval_data.r.was_lin = true;
02753 eval_data.r.const_trans =
02754 (__data.coeffs[0]*__rval.const_trans-__data.params.d()[0])/
02755 __data.params.d()[1];
02756 eval_data.r.const_trans = std::exp(eval_data.r.const_trans*
02757 eval_data.r.const_trans);
02758 }
02759 else
02760 eval_data.r.was_lin = false;
02761 break;
02762 case EXPRINFO_LIN:
02763 case EXPRINFO_QUAD:
02764 throw api_exception(apiee_internal, "Must not be here in lincoeff_visitor::update");
02765 break;
02766 default:
02767 throw api_exception(apiee_internal,
02768 std::string("Unknown expression type in lincoeff_visitor::update: ")+
02769 convert_to_str(__data.operator_type));
02770 break;
02771 }
02772 }
02773 else if(__data.operator_type > 0)
02774 {
02775 eval_data.r.was_lin = false;
02776 }
02777 eval_data.r.was_lin = eval_data.r.was_lin || __rval.was_lin;
02778 if(++eval_data.n < __data.n_children)
02779 eval_data.trans = eval_data.old_trans * __data.coeffs[eval_data.n];
02780 return 0;
02781 }
02782
02783 int update(const lincoeff_visitor_ret& __rval)
02784 {
02785 if(__rval.was_const)
02786 *eval_data.constant += __rval.const_trans;
02787 eval_data.r.was_lin = eval_data.r.was_lin || __rval.was_lin;
02788 return 0;
02789 }
02790
02791 lincoeff_visitor_ret calculate_value(bool eval_all)
02792 { return eval_data.r; }
02794 };
02795
02796 inline bool model::get_linear_coeffs(const const_walker& expr,
02797 linalg::sparse_vector<double>& coeffs,
02798 double& constant, const std::vector<interval>& _ranges)
02799 {
02800 lincoeff_visitor lv(&_ranges, &coeffs, &constant, this);
02801 lincoeff_visitor_ret r = evaluate(lv, expr);
02802 if(r.was_const)
02803 constant += r.const_trans;
02804 return r.was_lin;
02805 }
02806
02807 inline bool model::get_linear_coeffs(const const_walker& expr,
02808 linalg::sparse_vector<double>& coeffs,
02809 double& constant)
02810 {
02811 lincoeff_visitor lv(NULL, &coeffs, &constant, this);
02812 lincoeff_visitor_ret r = evaluate(lv, expr);
02813 if(r.was_const)
02814 constant += r.const_trans;
02815 return r.was_lin;
02816 }
02817
02818 inline void model::simplify_visitor_0::postorder_help(const expression_node &r,
02819 unsigned int n_chld)
02820 {
02821 if(r.operator_type <= 0)
02822 {
02823 switch(r.operator_type)
02824 {
02825 case EXPRINFO_GHOST:
02826 { model::walker _w = __mod->node(r.node_num);
02827 if(_w->operator_type != EXPRINFO_GHOST)
02828 postorder_help(*_w, _w.n_children());
02829 v_i = _w->var_indicator();
02830 s = _w->sem;
02831 }
02832 flags |= SIMPLIFY_0_IS_GHOST;
02833 break;
02834 case EXPRINFO_CONSTANT:
02835 s.degree = 0;
02836 s.dim = 0;
02837 s.property_flags.c_info = c_linear;
02838 s.property_flags.separable = t_true;
02839 flags |= SIMPLIFY_0_IS_CONST;
02840 if(is_integer(r.params.nd()))
02841 {
02842 int i = get_integer(r.params.nd());
02843 flags |= SIMPLIFY_0_CONST_IS_INTEGER;
02844 m = i;
02845 }
02846 else
02847 m = r.params.nd();
02848 break;
02849 case EXPRINFO_VARIABLE:
02850 s.degree = 1;
02851 s.dim = 1;
02852 s.property_flags.c_info = c_linear;
02853 s.property_flags.separable = t_true;
02854 flags |= SIMPLIFY_0_IS_VAR;
02855 v_i.set(r.params.nn());
02856 break;
02857 case EXPRINFO_SUM:
02858 case EXPRINFO_MEAN:
02859 flags |= SIMPLIFY_0_IS_SUM;
02860 m = r.params.nd();
02861 transfer = &r.coeffs;
02862 if(n_chld == 1)
02863 flags |= SIMPLIFY_0_SUM_IS_SIMPLE;
02864 break;
02865 case EXPRINFO_PROD:
02866 flags |= SIMPLIFY_0_IS_PROD;
02867 m = r.params.nd();
02868 transfer = &r.coeffs;
02869 if(n_chld == 1)
02870 flags |= SIMPLIFY_0_PROD_IS_SIMPLE;
02871 break;
02872 case EXPRINFO_SQUARE:
02873 case EXPRINFO_INTPOWER:
02874 break;
02875 case EXPRINFO_INVERT:
02876 case EXPRINFO_DIV:
02877 flags |= SIMPLIFY_0_IS_MULTIPLICATIVE;
02878 m = r.params.nd();
02879 s.degree = -1;
02880 break;
02881 case EXPRINFO_IN:
02882 case EXPRINFO_IF:
02883 case EXPRINFO_AND:
02884 case EXPRINFO_OR:
02885 case EXPRINFO_NOT:
02886 case EXPRINFO_IMPLIES:
02887 case EXPRINFO_COUNT:
02888 case EXPRINFO_ALLDIFF:
02889 case EXPRINFO_LEVEL:
02890 case EXPRINFO_NEIGHBOR:
02891 case EXPRINFO_NOGOOD:
02892 s.annotation_flags.integer = true;
02893
02894 case EXPRINFO_MAX:
02895 case EXPRINFO_MIN:
02896 case EXPRINFO_SQROOT:
02897 case EXPRINFO_ABS:
02898 case EXPRINFO_POW:
02899 case EXPRINFO_EXP:
02900 case EXPRINFO_LOG:
02901 case EXPRINFO_SIN:
02902 case EXPRINFO_COS:
02903 case EXPRINFO_ATAN2:
02904 case EXPRINFO_GAUSS:
02905 s.degree = -1;
02906 break;
02907 case EXPRINFO_LIN:
02908 break;
02909 case EXPRINFO_QUAD:
02910 break;
02911 default:
02912
02913 break;
02914 }
02915 }
02916 else if(r.operator_type > 0)
02917 {
02918 s.degree = -1;
02919 s.property_flags.c_info = c_maybe;
02920 s.property_flags.separable = t_maybe;
02921 }
02922 s.dim = v_i.sum(0, num_of_vars);
02923
02924 nnum = r.node_num;
02925 if(s.degree < 0) s.degree = -1;
02926 }
02927
02928 inline void model::simplify_visitor_m::postorder_help(const expression_node &r,
02929 unsigned int n_chld)
02930 {
02931 if(r.operator_type <= 0)
02932 {
02933 switch(r.operator_type)
02934 {
02935 case EXPRINFO_GHOST:
02936 { model::walker _w = __mod->node(r.node_num);
02937 if(_w->operator_type != EXPRINFO_GHOST)
02938 postorder_help(*_w, (unsigned int)_w.n_children());
02939 v_i = _w->var_indicator();
02940 s = _w->sem;
02941 }
02942 flags |= SIMPLIFY_0_IS_GHOST;
02943 break;
02944 case EXPRINFO_CONSTANT:
02945 s.degree = 0;
02946 s.dim = 0;
02947 s.property_flags.c_info = c_linear;
02948 s.property_flags.separable = t_true;
02949 flags |= SIMPLIFY_0_IS_CONST;
02950 if(is_integer(r.params.nd()))
02951 {
02952 int i = get_integer(r.params.nd());
02953 flags |= SIMPLIFY_0_CONST_IS_INTEGER;
02954 m = i;
02955 }
02956 else
02957 m = r.params.nd();
02958 break;
02959 case EXPRINFO_VARIABLE:
02960 s.degree = 1;
02961 s.dim = 1;
02962 s.property_flags.c_info = c_linear;
02963 s.property_flags.separable = t_true;
02964 flags |= SIMPLIFY_0_IS_VAR;
02965 v_i.set(r.params.nn());
02966 break;
02967 case EXPRINFO_SUM:
02968 case EXPRINFO_PROD:
02969 case EXPRINFO_SQUARE:
02970 case EXPRINFO_INTPOWER:
02971 case EXPRINFO_INVERT:
02972 case EXPRINFO_DIV:
02973 break;
02974 case EXPRINFO_IN:
02975 case EXPRINFO_IF:
02976 case EXPRINFO_AND:
02977 case EXPRINFO_OR:
02978 case EXPRINFO_NOT:
02979 case EXPRINFO_IMPLIES:
02980 case EXPRINFO_COUNT:
02981 case EXPRINFO_ALLDIFF:
02982 case EXPRINFO_LEVEL:
02983 case EXPRINFO_NEIGHBOR:
02984 case EXPRINFO_NOGOOD:
02985 s.annotation_flags.integer = true;
02986
02987 case EXPRINFO_MAX:
02988 case EXPRINFO_MIN:
02989 case EXPRINFO_SQROOT:
02990 case EXPRINFO_ABS:
02991 case EXPRINFO_POW:
02992 case EXPRINFO_EXP:
02993 case EXPRINFO_LOG:
02994 case EXPRINFO_SIN:
02995 case EXPRINFO_COS:
02996 case EXPRINFO_ATAN2:
02997 case EXPRINFO_GAUSS:
02998 s.degree = -1;
02999 break;
03000 case EXPRINFO_LIN:
03001 break;
03002 case EXPRINFO_QUAD:
03003 break;
03004 default:
03005
03006 break;
03007 }
03008 }
03009 else if(r.operator_type > 0)
03010 {
03011 s.degree = -1;
03012 s.property_flags.c_info = c_maybe;
03013 s.property_flags.separable = t_maybe;
03014 }
03015 s.dim = v_i.sum(0, num_of_vars);
03016
03017 nnum = r.node_num;
03018 if(s.degree < 0) s.degree = -1;
03019 }
03020
03021 #if DEBUG_EXPRESSIONS
03022 }
03023 #include <g_algotest.h>
03024 namespace coco {
03025 class __test_expr_help
03026 {
03027 public:
03028 unsigned int operator()(const expression_node& __n) const
03029 {
03030 return __n.test();
03031 }
03032 };
03033
03034 inline void consistency_test(const model& __m)
03035 {
03036 recursive_consistency_test(__m.ground(), __test_expr_help());
03037 }
03038 #endif
03039
03040 }
03041
03042 #endif