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 #include <coconut_config.h>
00029 #if defined(COCONUT_WINDOWS)
00030 #include <windows_utils.h>
00031 #else
00032 #include <libgen.h>
00033 #endif
00034 #include <model.h>
00035 #include <dbtables.h>
00036 #include <print_seq.h>
00037 #include <g_addalgo.h>
00038 #include <writer_utils.h>
00039
00040 namespace coco {
00041
00042 #ifdef COCONUT_WINDOWS
00043 template <>
00044 inline void model::read_vector(std::vector<double>& hd, char *& cq,
00045 const char *format, const char *message,
00046 int ln)
00047 {
00048 double help;
00049
00050 cq += strspn(cq+1, " \t")+1;
00051 for(; cq; )
00052 {
00053 char *ct;
00054
00055 ct = strsep(&cq, ",");
00056 ct += strspn(ct, " \t");
00057 if(!strncmp(ct, "inf", 3))
00058 {
00059 help = COCO_INF;
00060 }
00061 else if(!strncmp(ct, "-inf", 4))
00062 {
00063 help = -COCO_INF;
00064 }
00065 else if(sscanf(ct, format, &help) != 1)
00066 {
00067 throw api_exception(apiee_io, std::string("Malformed Input: Line ")+
00068 convert_to_str(ln)+": "+message);
00069 }
00070 hd.push_back(help);
00071 }
00072 }
00073 #endif
00074
00075 extern const char *expr_names[];
00076
00077 void model_iddata::compress_numbers(bool renum_vars,
00078 bool renum_consts)
00079 {
00080 unsigned int i_nodes, free_idx, next_gap;
00081 std::vector<std::pair<unsigned int,unsigned int> > __v;
00082
00083 if(node_free.size() != 0)
00084 {
00085 sort(node_free.begin(), node_free.end());
00086 __v.reserve(node_num_max-node_free[0]);
00087 i_nodes = node_free[0];
00088 free_idx = 1;
00089 next_gap = (free_idx == node_free.size() ? node_num_max : node_free[free_idx]-free_idx);
00090 node_num_max -= node_free.size();
00091 for(; i_nodes < node_num_max; ++i_nodes)
00092 {
00093 while(i_nodes == next_gap)
00094 {
00095 free_idx++;
00096 next_gap = (free_idx == node_free.size() ? node_num_max : node_free[free_idx]-free_idx);
00097 }
00098 __v.push_back(std::make_pair(i_nodes+free_idx, i_nodes));
00099 }
00100 node_free.erase(node_free.begin(), node_free.end());
00101 }
00102 if(__v.size() != 0)
00103 {
00104 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00105 ++__b)
00106 (*__b)->renumber_nodes(__v);
00107 __v.erase(__v.begin(), __v.end());
00108 }
00109
00110 if(renum_vars && var_free.size() != 0)
00111 {
00112 sort(var_free.begin(), var_free.end());
00113 __v.reserve(var_num_max-var_free[0]);
00114 i_nodes = var_free[0];
00115 free_idx = 1;
00116 next_gap = (free_idx == var_free.size() ? var_num_max : var_free[free_idx]-free_idx);
00117 var_num_max -= var_free.size();
00118 for(; i_nodes < var_num_max; ++i_nodes)
00119 {
00120 while(i_nodes == next_gap)
00121 {
00122 free_idx++;
00123 next_gap = (free_idx == var_free.size() ? var_num_max : var_free[free_idx]-free_idx);
00124 }
00125 __v.push_back(std::make_pair(i_nodes+free_idx, i_nodes));
00126 }
00127 var_free.erase(var_free.begin(), var_free.end());
00128 }
00129 if(!var_free.empty())
00130 std::make_heap(var_free.begin(), var_free.end());
00131 if(__v.size() != 0)
00132 {
00133 for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00134 __i != __v.end(); ++__i)
00135 var_names[(*__i).second] = var_names[(*__i).first];
00136 var_names.erase(var_names.begin(), var_names.begin()+number_of_variables());
00137 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00138 ++__b)
00139 (*__b)->renumber_variables(__v);
00140 }
00141 __v.erase(__v.begin(), __v.end());
00142
00143 if(renum_consts && const_free.size() != 0)
00144 {
00145 sort(const_free.begin(), const_free.end());
00146 __v.reserve(const_num_max-const_free[0]);
00147 i_nodes = const_free[0];
00148 free_idx = 1;
00149 next_gap = (free_idx == const_free.size() ? const_num_max : const_free[free_idx]-free_idx);
00150 const_num_max -= const_free.size();
00151 for(; i_nodes < const_num_max; ++i_nodes)
00152 {
00153 while(i_nodes == next_gap)
00154 {
00155 free_idx++;
00156 next_gap = (free_idx == const_free.size() ? const_num_max : const_free[free_idx]-free_idx);
00157 }
00158 __v.push_back(std::make_pair(i_nodes+free_idx, i_nodes));
00159 }
00160 const_free.erase(const_free.begin(), const_free.end());
00161 }
00162 if(__v.size() != 0)
00163 {
00164 for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00165 __i != __v.end(); ++__i)
00166 const_names[(*__i).second] = const_names[(*__i).first];
00167 const_names.erase(const_names.begin(), const_names.begin()+number_of_constraints());
00168 for(std::list<model_gid*>::iterator __b = backref.begin(); __b != backref.end();
00169 ++__b)
00170 (*__b)->renumber_constraints(__v);
00171 }
00172 if(!const_free.empty())
00173 std::make_heap(const_free.begin(), const_free.end());
00174 }
00175
00176 void model_gid::renumber_nodes(
00177 std::vector<std::pair<unsigned int,unsigned int> >& __v)
00178 {
00179 int i;
00180 std::map<unsigned int, unsigned int>::iterator __mf;
00181 for(std::vector<std::pair<unsigned int,unsigned int> >::iterator __i = __v.begin();
00182 __i != __v.end(); ++__i)
00183 {
00184 i = (*__i).second;
00185 glob_ref[i] = glob_ref[(*__i).first];
00186 glob_ref[i]->node_num = i;
00187 __mf = const_back_ref.find((*__i).first);
00188 if(__mf != const_back_ref.end())
00189 {
00190 const_back_ref.insert(std::make_pair(i,(*__mf).second));
00191 const_back_ref.erase(__mf);
00192 }
00193 }
00194 }
00195
00196 model::model(model_gid* __id, const erased_part& _ep, bool clone) :
00197 _Base(_ep), node_ref(), var_ref(),
00198 ghost_ref(), destroy_node_ref(false),
00199 lin(), matd(), mati(),
00200 ocoeff(0), objective(ground()),
00201 constraints(), has_read_errors(false)
00202 {
00203 keep_gid = true;
00204 if(__id)
00205 {
00206 if(clone)
00207 {
00208 gid = __id;
00209 keep_gid = false;
00210 }
00211 else
00212 gid = new model_gid(*this, *__id);
00213 }
00214 else
00215 {
00216 throw api_exception(apiee_internal,
00217 "Erased parts with NULL gid are forbidden in model constructor!");
00218 }
00219
00220 std::vector<walker> __n(number_of_nodes(), ground());
00221 std::vector<walker> __v(number_of_variables(), ground());
00222 std::vector<unsigned int> __c(number_of_constraints(), 0);
00223 ref_iterator __x;
00224
00225 fill_arrays(ground(), __n, __v, ghost_ref);
00226 for(__x = __n.begin(); __x != __n.end(); ++__x)
00227 if(*__x != ground())
00228 {
00229 node_ref.push_back(*__x);
00230 gid->mk_globref((*__x)->node_num, *__x);
00231 }
00232 for(__x = __v.begin(); __x != __v.end(); ++__x)
00233 if(*__x != ground())
00234 {
00235 var_ref.push_back(*__x);
00236 gid->mk_gvarref((*__x)->params.nn(), *__x);
00237 }
00238
00239 objective = gid->empty_reference();
00240 ocoeff = 0;
00241 }
00242
00243 void model::remove_node(const walker& _w, unsigned int _nnum)
00244 {
00245 walker __h = _w;
00246 unsigned int cn;
00247
00248 if(_w->operator_type == EXPRINFO_GHOST)
00249 {
00250 ref_iterator __x(lower_bound(ghost_ref.begin(),
00251 ghost_ref.end(), _nnum, __docompare_nodes()));
00252 if(__x != ghost_ref.end() && (*__x)->node_num == _nnum)
00253 ghost_ref.erase(__x);
00254 erase(__h);
00255 return;
00256 }
00257 if(_w->operator_type == EXPRINFO_VARIABLE)
00258 throw api_exception(apiee_internal,
00259 "in remove_node: Trying to remove a variable node!");
00260 if(is_empty(_w))
00261 throw api_exception(apiee_internal,
00262 "in remove_node: Trying to remove node, which is already removed.");
00263 if(_w == objective)
00264 {
00265 if(_w->n_children != 1)
00266
00267
00268
00269 return;
00270 walker _ew = _w;
00271 objective = _ew >> _ew.child_begin();
00272 }
00273 if(get_const_num(_nnum, cn))
00274 {
00275 unsigned int ccn;
00276 walker _ew;
00277 bool replace = false;
00278 if(_w->n_children != 0)
00279 {
00280 _ew = _w;
00281 _ew >>= _ew.child_begin();
00282 if(get_const_num(_ew->node_num, ccn))
00283 {
00284 gid->unused_constr(const_name(cn));
00285 gid->remove_const_id(cn);
00286 }
00287 else
00288 {
00289
00290 gid->remove_const_ref(cn);
00291
00292 gid->mk_gconstref(cn, _ew);
00293
00294 replace = true;
00295 }
00296 }
00297 else
00298 {
00299 gid->unused_constr(const_name(cn));
00300 gid->remove_const_id(cn);
00301 }
00302
00303 for(std::vector<walker>::iterator __x = constraints.begin();
00304 __x != constraints.end(); ++__x)
00305 if(*__x == _w)
00306 {
00307 if(replace)
00308 *__x = _ew;
00309 else
00310 constraints.erase(__x);
00311 break;
00312 }
00313 }
00314 ref_iterator __x(lower_bound(node_ref.begin(),
00315 node_ref.end(), _nnum, __docompare_nodes()));
00316 if(__x != node_ref.end() && (*__x)->node_num == _nnum)
00317 node_ref.erase(__x);
00318 free_node_num(_nnum);
00319 erase(__h);
00320 }
00321
00322 void model::fill_arrays(walker __w, std::vector<walker>& __n,
00323 std::vector<walker>& __v, std::vector<walker>& __g)
00324 {
00325 children_iterator __it, __e;
00326
00327 if(__w.is_ground())
00328 {
00329 __e = __w.child_end();
00330 for(__it = __w.child_begin(); __it != __e; ++__it)
00331 fill_arrays(__w>>__it, __n, __v, __g);
00332 }
00333 else if(__w.is_sky())
00334 return;
00335 else
00336 {
00337 if(__n[__w->node_num] == ground())
00338 {
00339 if(__w->operator_type != EXPRINFO_GHOST)
00340 __n[__w->node_num] = __w;
00341 if(__w->operator_type == EXPRINFO_VARIABLE)
00342 __v[__w->params.nn()] = __w;
00343 else if(__w->operator_type == EXPRINFO_GHOST)
00344 {
00345 ref_iterator __x(lower_bound(__g.begin(), __g.end(), __w->node_num,
00346 __docompare_nodes()));
00347 if(__x == __g.end() || *__x != __w)
00348 __g.insert(__x, __w);
00349 }
00350 __e = __w.child_end();
00351 for(__it = __w.child_begin(); __it != __e; ++__it)
00352 fill_arrays(__w>>__it, __n, __v, __g);
00353 }
00354 }
00355 }
00356
00357 void model::copy_contents(model_gid* gid, const model& __m)
00358 {
00359 std::vector<walker> __n(__m.number_of_nodes(), ground());
00360 std::vector<walker> __v(__m.number_of_variables(), ground());
00361 std::vector<int> __c(__m.number_of_constraints(), -1);
00362 ref_iterator __x;
00363 unsigned int i;
00364
00365 for(unsigned int i = 0; i < __m.number_of_constraints(); ++i)
00366 {
00367 walker gc(__m.constraint(i));
00368 if(!__m.gid->empty(gc))
00369 __c[i] = (int) gc->node_num;
00370 }
00371 ghost_ref.reserve(__m.ghost_ref.size());
00372 fill_arrays(ground(), __n, __v, ghost_ref);
00373 node_ref.reserve(__m.number_of_managed_nodes());
00374 var_ref.reserve(__m.number_of_managed_variables());
00375 for(__x = __n.begin(); __x != __n.end(); ++__x)
00376 if(*__x != ground())
00377 {
00378 node_ref.push_back(*__x);
00379 gid->mk_globref((*__x)->node_num, *__x);
00380 }
00381 for(__x = __v.begin(); __x != __v.end(); ++__x)
00382 if(*__x != ground())
00383 {
00384 var_ref.push_back(*__x);
00385 gid->mk_gvarref((*__x)->params.nn(), *__x);
00386 }
00387
00388 constraints.reserve(__m.constraints.size());
00389 for(const_ref_iterator __b = __m.constraints.begin();
00390 __b != __m.constraints.end(); ++__b)
00391 constraints.push_back(gid->node((*__b)->node_num));
00392 for(i = 0; i < __c.size(); ++i)
00393 if(__c[i] != -1)
00394 gid->mk_gconstref(i, gid->node((unsigned int)__c[i]));
00395
00396 if(__m.is_empty(__m.objective))
00397 objective = gid->empty_reference();
00398 else
00399 objective = gid->node(__m.objective->node_num);
00400 }
00401
00402 void model::model_read(std::istream& inp, bool do_simplify, vdbl::database* _db,
00403 vdbl::userid _uid, std::vector<annotation>* _la,
00404 std::string mname, bool continue_on_errors)
00405 {
00406 #if MODEL_INLINE_DEBUG
00407 std::cerr << "model_read: 1" << std::endl;
00408 #endif
00409 gid = new model_gid(*this);
00410 keep_gid = true;
00411 if(!mname.empty()) gid->model_name(mname);
00412 #if MODEL_INLINE_DEBUG
00413 std::cerr << "model_read: 2" << std::endl;
00414 #endif
00415 has_read_errors = !read(inp, _db, _uid, _la, continue_on_errors);
00416 #if MODEL_INLINE_DEBUG
00417 std::cerr << "model_read: 3" << std::endl;
00418 #endif
00419 if(do_simplify)
00420 basic_simplify();
00421 else
00422 micro_simplify();
00423 #if MODEL_INLINE_DEBUG
00424 std::cerr << "model_read: 4" << std::endl;
00425 #endif
00426 prepare_after_read();
00427 #if MODEL_INLINE_DEBUG
00428 std::cerr << "model_read: 5" << std::endl;
00429 #endif
00430 check_counters(true);
00431 }
00432
00433 model::model(std::istream& inp, bool do_simplify, vdbl::database* _db,
00434 vdbl::userid _uid, std::vector<annotation>* _la,
00435 std::string mname, bool continue_on_errors)
00436 : _Base(), node_ref(), var_ref(), ghost_ref(),
00437 destroy_node_ref(false), lin(), matd(), mati(),
00438 ocoeff(0), objective(ground()), constraints()
00439 {
00440 model_read(inp, do_simplify, _db, _uid, _la, mname, continue_on_errors);
00441 }
00442
00443 model::model(const char* name, bool do_simplify, vdbl::database* _db,
00444 vdbl::userid _uid, std::vector<annotation>* _la,
00445 bool continue_on_errors)
00446 : _Base(), node_ref(), var_ref(), ghost_ref(),
00447 destroy_node_ref(false), lin(), matd(), mati(),
00448 ocoeff(0), objective(ground()), constraints()
00449 {
00450 #if MODEL_INLINE_DEBUG
00451 std::cerr << "model_constructor: 1" << std::endl;
00452 #endif
00453 std::ifstream inp(name);
00454 #if MODEL_INLINE_DEBUG
00455 std::cerr << "model_constructor: 2" << std::endl;
00456 #endif
00457 char *nname = new char [strlen(name)+1];
00458 strcpy(nname, name);
00459
00460 std::string mname(basename(nname));
00461 size_t mnl(mname.length());
00462 if(mnl >= 4 && mname.substr(mnl-4,4) == ".dag")
00463 mname.erase(mnl-4,4);
00464
00465 if(!inp.is_open())
00466 {
00467 delete [] nname;
00468 throw api_exception(apiee_io, std::string("Could not open file `")+
00469 name+"': "+strerror(errno));
00470 }
00471 #if MODEL_INLINE_DEBUG
00472 std::cerr << "model_constructor: 3" << std::endl;
00473 #endif
00474 model_read(inp, do_simplify, _db, _uid, _la, mname, continue_on_errors);
00475 delete [] nname;
00476 }
00477
00478 #define throw_read(MSG) do { throw api_exception(apiee_io, \
00479 std::string("Malformed Input: Line ")+\
00480 convert_to_str(ln)+": "\
00481 +MSG); } while(0)
00482 #define MT_DBL 1
00483 #define MT_INTV 2
00484 #define MT_INT 3
00485 #define MT_STORED 8
00486
00487 interval model::read_interval(char *& cq, int ln)
00488 {
00489 double lo, up;
00490
00491 if(cq[0] != '[')
00492 throw_read("Interval specifier: no `['");
00493 else
00494 {
00495 char *cr;
00496
00497 cq++;
00498 cr = strsep(&cq, ",");
00499 if(cq == NULL)
00500 throw_read("Interval specifier: no `,' inside interval");
00501 if(!strcmp(cr, "-I"))
00502 lo = -COCO_INF;
00503 else if(!strcmp(cr, "I"))
00504 lo = COCO_INF;
00505 else if(coconut_sscanfdouble(&lo, cr, "") != 1)
00506 throw_read("Interval specifier: not a wellformed interval lower bound");
00507 cr = strsep(&cq, "]");
00508 if(cq == NULL)
00509 throw_read("Interval specifier: missing closing `]'");
00510 if(!strcmp(cr, "-I"))
00511 up = -COCO_INF;
00512 else if(!strcmp(cr, "I"))
00513 up = COCO_INF;
00514 else if(coconut_sscanfdouble(&up, cr, "") != 1)
00515 throw_read("Interval specifier: not a wellformed interval upper bound");
00516 cr = strsep(&cq, ",");
00517 }
00518 return interval(lo,up);
00519 }
00520
00521 void model::store_point_in_db(const std::vector<double>& pt,
00522 vdbl::database* _db, vdbl::userid _uid,
00523 unsigned int point_class, std::vector<annotation>* _la) const
00524 {
00525 vdbl::standard_table* ptb;
00526 vdbl::tableid _ti = get_point_table(_db, ptb, _uid);
00527
00528 dbt_row ptrow;
00529 ptrow.add("x", pt);
00530 ptrow.add("class", point_class);
00531
00532 vdbl::rowid _ri;
00533 ptb->insert_row(ptrow.row(), _ri);
00534
00535 if(_la)
00536 _la->push_back(annotation(_ti, _ri));
00537 }
00538
00539 #define MODEL_INITIAL_BUF_SIZE 1024
00540
00541 bool model::read(std::istream &i, vdbl::database *_db, vdbl::userid _uid,
00542 std::vector<annotation>* _la, bool continue_on_errors)
00543 {
00544 char *buf, *cp, *cq, nextbuf;
00545 size_t bufsize(MODEL_INITIAL_BUF_SIZE), bufread;
00546 double coef;
00547 int ln = 0, do_mng, found_mng, found_varidx, found_sem, _hlp;
00548 unsigned int nnum1, nnum2;
00549 std::vector<walker> nodes;
00550 std::vector<unsigned int> v_var_idx;
00551 std::map<unsigned int, std::pair<int,void *> > matrix_def;
00552 interval hi;
00553 std::string error_messages;
00554
00555 objective = ground();
00556 ocoeff = 0;
00557 buf = new char[bufsize];
00558 do
00559 {
00560 try
00561 {
00562 do_mng = 1;
00563 found_mng = 0;
00564 found_sem = 0;
00565 found_varidx = 0;
00566 hi.set(-COCO_INF, COCO_INF);
00567
00568 i.get(buf, bufsize, '\n');
00569 bufread = i.gcount();
00570 i.get(nextbuf);
00571 while(bufread == bufsize-1 && nextbuf != '\n')
00572 {
00573 buf[bufsize-1]=nextbuf;
00574 char *newbuf = new char [bufsize*2];
00575 memcpy(newbuf, buf, sizeof(char)*bufsize);
00576
00577 i.get(newbuf+bufsize, bufsize, '\n');
00578 bufread += 1+i.gcount();
00579 i.get(nextbuf);
00580
00581 delete [] buf;
00582 buf = newbuf;
00583 bufsize *= 2;
00584 }
00585 ln++;
00586 cp = buf;
00587
00588 if(!strncmp(cp, "<N>", 3))
00589 {
00590 char c[3] = "xx";
00591
00592 cp += 3;
00593 cp += strspn(cp, " \t");
00594 switch(cp[0])
00595 {
00596 case 'c':
00597 {
00598 cp += strspn(cp+1, " \t")+1;
00599
00600 if(sscanf(cp, "%u %u", &nnum1, &nnum2) != 2)
00601 throw_read("Malformed Global Info: Constraint Number");
00602 if(nnum1 >= number_of_constraints())
00603 gid->number_of_constraints(nnum1+1);
00604 gid->make_const_back_ref(nnum2, nnum1);
00605 }
00606 break;
00607 case 'C':
00608 {
00609 int stl;
00610 cp += strspn(cp+1, " \t")+1;
00611
00612 char *__hlp = new char[strlen(cp)+1];
00613 if(sscanf(cp, "%u '%s", &nnum1, __hlp) != 2 ||
00614 __hlp[stl = strlen(__hlp)-1] != '\'')
00615 throw_read("Malformed Global Info: Constraint Name");
00616 __hlp[stl] = '\0';
00617 if(nnum1 >= number_of_constraints())
00618 gid->number_of_constraints(nnum1+1);
00619 gid->const_name(nnum1, __hlp);
00620 delete [] __hlp;
00621 }
00622 break;
00623 case 'F':
00624 {
00625 int stl;
00626 cp += strspn(cp+1, " \t")+1;
00627
00628 char *__hlp = new char[strlen(cp)+1];
00629 if(coconut_sscanfdouble(&coef, cp, "'%s", __hlp) != 2 ||
00630 __hlp[stl = strlen(__hlp)-1] != '\'')
00631 throw_read("Malformed Global Info: Variable Name");
00632 __hlp[stl] = '\0';
00633 gid->fixed_var(__hlp, coef);
00634 delete [] __hlp;
00635 }
00636 break;
00637 case 'M':
00638 cp += strspn(cp+1, " \t")+1;
00639 if(sscanf(cp, "%u m%c%c", &nnum1, c, c+1) != 3)
00640 throw_read("Malformed Global Info: Objective function");
00641 if(!strcmp("in", c))
00642 ocoeff = 1;
00643 else if(!strcmp("ax", c))
00644 ocoeff = -1;
00645 else if(!strcmp("00", c))
00646 ocoeff = 0;
00647 else
00648 throw_read("Malformed Global Info: Objective function is neither max nor min");
00649 if(ocoeff != 0)
00650 objective = nodes[nnum1];
00651 else
00652 objective = ground();
00653 break;
00654 case 'N':
00655 {
00656 int stl;
00657 cp += strspn(cp+1, " \t")+1;
00658
00659 char *__hlp = new char[strlen(cp)+1];
00660 if(sscanf(cp, "%u '%s", &nnum1, __hlp) != 2 ||
00661 __hlp[stl = strlen(__hlp)-1] != '\'')
00662 throw_read("Malformed Global Info: Variable Name");
00663 __hlp[stl] = '\0';
00664 gid->var_name(nnum1, __hlp);
00665 delete [] __hlp;
00666 }
00667 break;
00668 case 'O':
00669 {
00670 int stl;
00671
00672 cp += strspn(cp+1, " \t")+1;
00673 cq = strsep(&cp, ":");
00674 char *__hlp = new char[strlen(cq)+1];
00675
00676 if(sscanf(cq, "'%s", __hlp) != 1 ||
00677 __hlp[stl = strlen(__hlp)-1] != '\'')
00678 throw_read("Malformed Global Info: Objective Info");
00679 else
00680 {
00681 __hlp[stl] = '\0';
00682 gid->obj_name(__hlp);
00683 }
00684 if(cp && *cp != '\0')
00685 {
00686 cp += strspn(cp, " \t");
00687 cq = strsep(&cp, ",");
00688
00689 if(coconut_sscanfdouble(&coef, cq, "d") != 1)
00690 throw_read("Malformed Global Info: Objective Info");
00691 else
00692 gid->obj_adj(coef);
00693 if(cp && *cp != '\0')
00694 {
00695 cp += strspn(cp, " \t");
00696 if(coconut_sscanfdouble(&coef, cp, "") != 1)
00697 throw_read("Malformed Global Info: Objective Info");
00698 else
00699 gid->obj_mult(coef);
00700 }
00701 }
00702 delete [] __hlp;
00703 }
00704 break;
00705 case 'V':
00706 cp += strspn(cp+1, " \t")+1;
00707 if(sscanf(cp, "%u", &nnum1) != 1)
00708 throw_read("Malformed Global Info: Num of Vars");
00709 gid->number_of_variables(nnum1);
00710 #if MODEL_INLINE_DEBUG
00711 std::cerr << "gid : number of variables = " <<
00712 gid->number_of_variables() << std::endl;
00713 #endif
00714 break;
00715 case 'S':
00716 {
00717 int stl;
00718 cp += strspn(cp+1, " \t")+1;
00719 char *__hlp = new char[strlen(cp)+1];
00720 if(sscanf(cp, "'%s", __hlp) != 1 ||
00721 __hlp[stl = strlen(__hlp)-1] != '\'')
00722 throw_read("Malformed Global Info: Automatic Constraint");
00723 else
00724 {
00725 __hlp[stl] = '\0';
00726 gid->unused_constr(__hlp);
00727 }
00728 delete [] __hlp;
00729 }
00730 break;
00731 case 'U':
00732 {
00733 int stl;
00734 cp += strspn(cp+1, " \t")+1;
00735 char *__hlp = new char[strlen(cp)+1];
00736 if(sscanf(cp, "'%s", __hlp) != 1 ||
00737 __hlp[stl = strlen(__hlp)-1] != '\'')
00738 throw_read("Malformed Global Info: Unused Variable");
00739 else
00740 {
00741 __hlp[stl] = '\0';
00742 gid->unused_var(__hlp);
00743 }
00744 delete [] __hlp;
00745 }
00746 break;
00747 case 'm':
00748 {
00749 int stl;
00750 cp += strspn(cp+1, " \t")+1;
00751
00752 char *__hlp = new char[strlen(cp)+1];
00753 if(sscanf(cp, "'%s", __hlp) != 1 ||
00754 __hlp[stl = strlen(__hlp)-1] != '\'')
00755 throw_read("Malformed Global Info: Model Name");
00756 __hlp[stl] = '\0';
00757 gid->model_name(__hlp);
00758 delete [] __hlp;
00759 }
00760 break;
00761 default:
00762 throw_read("Malformed Global Info: Wrong type");
00763 break;
00764 }
00765 }
00766 else if(!strncmp(cp, "<M>", 3))
00767 {
00768 bool is_for_lin = false;
00769 unsigned int mat_num = 0;
00770 char dens, shape;
00771
00772 cp+=3;
00773 cp+=strspn(cp, " \t");
00774 if(sscanf(cp, "L %u %u", &nnum1, &nnum2) == 2)
00775 {
00776 is_for_lin = true;
00777 dens = 'D';
00778 shape = 'R';
00779 }
00780 else if(sscanf(cp, "%u %c %c %u %u", &mat_num, &dens, &shape, &nnum1,
00781 &nnum2) != 5)
00782 throw_read("Malformed Matrix Definition");
00783 if(dens != 'D' && dens != 'I' && dens != 'N')
00784 throw_read("Malformed Matrix Definition: must be double, interval, or integer");
00785 if(shape != 'R' && shape != 'S' && shape != 'T')
00786 throw_read("Malformed Matrix Definition: must be rectangular, symmetric, or triangular");
00787 if(shape == 'S' || shape == 'T')
00788 throw_read("Matrix shapes not yet implemented!");
00789 if(is_for_lin)
00790 lin = linalg::matrix<double>(nnum1,nnum2);
00791 else
00792 {
00793 void *matrix_storage(NULL);
00794 int matrix_type;
00795
00796 matrix_type = (dens == 'D' ? MT_DBL :
00797 (dens == 'I' ? MT_INTV : MT_INT));
00798 switch(dens)
00799 {
00800 case 'D':
00801 matrix_storage = (void *) new linalg::matrix<double>(nnum1,nnum2);
00802 break;
00803 case 'I':
00804 matrix_storage = (void *) new linalg::matrix<interval>(nnum1,nnum2);
00805 break;
00806 case 'N':
00807 matrix_storage = (void *) new linalg::matrix<int>(nnum1,nnum2);
00808 break;
00809 }
00810 matrix_def.insert(std::make_pair(mat_num,
00811 std::make_pair(matrix_type, matrix_storage)));
00812 }
00813 }
00814 else if(!strncasecmp(cp, "<R>", 3))
00815 {
00816 unsigned int mat_num = 0;
00817 bool dense = (cp[1] == 'R');
00818 std::vector<unsigned int> s_idx;
00819 unsigned int dim_r(1), dim_c(1);
00820 unsigned int idx, ridx;
00821 int matrix_type;
00822 void *matrix_storage;
00823
00824 cp+=3+strspn(cp+3, " \t");
00825 cq = strchr(cp, ':');
00826 if(!cq)
00827 throw_read("Malformed Matrix Row Definition");
00828 *cq++ = '\0';
00829 if(cp[0] == 'L' && isspace(cp[1]))
00830 {
00831 cp += 1+strspn(cp+1, " \t");
00832 if(sscanf(cp, "%u", &nnum1) != 1)
00833 throw_read("Malformed Matrix Row Definition: row number?");
00834 dim_r = lin.nrows();
00835 dim_c = lin.ncols();
00836 matrix_storage = (void *)(&lin);
00837 matrix_type = MT_DBL;
00838 }
00839 else if(sscanf(cp, "%u %u", &mat_num, &nnum1) == 2)
00840 {
00841 std::pair<int,void*> x;
00842 std::map<unsigned int,std::pair<int,void*> >::iterator _x;
00843
00844 _x = matrix_def.find(mat_num);
00845 if(_x == matrix_def.end())
00846 throw_read("Malformed Matrix Row Definition: matrix not yet defined!");
00847 x = (*_x).second;
00848 matrix_type = x.first;
00849 matrix_storage = x.second;
00850 if(matrix_type & MT_STORED)
00851 throw_read("Malplaced Matrix Row Definition: matrix has been used!");
00852 switch(matrix_type)
00853 {
00854 case MT_DBL:
00855 dim_r = ((linalg::matrix<double>*)matrix_storage)->nrows();
00856 dim_c = ((linalg::matrix<double>*)matrix_storage)->ncols();
00857 break;
00858 case MT_INTV:
00859 dim_r = ((linalg::matrix<interval>*)matrix_storage)->nrows();
00860 dim_c = ((linalg::matrix<interval>*)matrix_storage)->ncols();
00861 break;
00862 case MT_INT:
00863 dim_r = ((linalg::matrix<int>*)matrix_storage)->nrows();
00864 dim_c = ((linalg::matrix<int>*)matrix_storage)->ncols();
00865 break;
00866 }
00867 }
00868 else
00869 throw_read("Malformed Matrix Row Definition: matrix & row number?");
00870 if(nnum1 >= dim_r)
00871 throw_read("Malformed Matrix Row Definition: row number out of range!");
00872 cp = cq;
00873 if(!dense)
00874 {
00875 cp = strchr(cp, ':');
00876 if(!cp)
00877 throw_read("Malformed Matrix Row Definition: sparse needs two vectors");
00878 *cp++ = '\0';
00879 cq += strspn(cq, " \t");
00880 for(; cq; )
00881 {
00882 char *ct;
00883
00884 ct = strsep(&cq, ",");
00885 ct += strspn(ct, " \t");
00886 if(sscanf(ct, "%u", &nnum2) != 1)
00887 throw_read("Malformed Matrix Row Definition: index vector definition");
00888 if(nnum2 >= dim_c)
00889 throw_read("Malformed Matrix Row Definition: column number out of range!");
00890 s_idx.push_back(nnum2);
00891 }
00892 }
00893 cp += strspn(cp, " \t");
00894 idx = 0;
00895 for(; cp; )
00896 {
00897 char *ct;
00898
00899 if(dense)
00900 {
00901 if(idx >= dim_c)
00902 throw_read("Malformed Matrix Row Definition: value vector too long!");
00903 ridx = idx;
00904 }
00905 else
00906 {
00907 if(idx >= s_idx.size())
00908 throw_read("Malformed Matrix Row Definition: value vector longer than index vector!");
00909 ridx = s_idx[idx];
00910 }
00911 ct = strsep(&cp, ",");
00912 ct += strspn(ct, " \t");
00913 switch(matrix_type)
00914 {
00915 case MT_DBL:
00916 if(coconut_sscanfdouble(&coef, ct, "") != 1)
00917 throw_read("Malformed Matrix Row Definition: value vector definition - no double!");
00918 else
00919 (*(linalg::matrix<double>*)matrix_storage)(nnum1,ridx) = coef;
00920 break;
00921 case MT_INTV:
00922 hi = read_interval(ct, ln);
00923 (*(linalg::matrix<interval>*)matrix_storage)(nnum1,ridx) = hi;
00924 break;
00925 case MT_INT:
00926 if(sscanf(ct, "%u", &nnum2) != 1)
00927 throw_read("Malformed Matrix Row Definition: value vector definition - no integer!");
00928 (*(linalg::matrix<int>*)matrix_storage)(nnum1,ridx) = nnum2;
00929 break;
00930 }
00931 idx++;
00932 }
00933 if(dense && idx < dim_c)
00934 throw_read("Malformed Matrix Row Definition: value vector too short!");
00935 else if(!dense && idx < s_idx.size())
00936 throw_read("Malformed Matrix Row Definition: value vector shorter than index vector!");
00937 }
00938 else if(!strncmp(cp, "<H>", 3))
00939 {
00940 cp += 3;
00941 cp += strspn(cp, " \t");
00942 switch(cp[0])
00943 {
00944 case 's':
00945 {
00946 std::vector<double> hd;
00947
00948 read_vector(hd, cp, "%lf", "Starting point information", ln);
00949 if(_db)
00950 store_point_in_db(hd, _db, _uid, 1U, _la);
00951 }
00952 break;
00953 case 't':
00954 {
00955 std::vector<double> hd(1, 0.);
00956
00957 cp += strspn(cp+1, " \t")+1;
00958 if(coconut_sscanfdouble(&(hd[0]), cp, "%d", &nnum2) != 2)
00959 throw_read("Trace point information");
00960 char *ct = strchr(cp, ',');
00961 if(ct)
00962 {
00963 cp = ct;
00964 read_vector(hd, cp, "%lf", "Trace point information", ln);
00965 }
00966 gid->add_trace_point(nnum2, hd);
00967 }
00968 break;
00969 case 'o':
00970 {
00971 std::vector<double> hd(1, 0.);
00972
00973 cp += strspn(cp+1, " \t")+1;
00974 if(coconut_sscanfdouble(&(hd[0]), cp, "%d", &nnum2) != 2)
00975 throw_read("Optimum information");
00976 char *ct = strchr(cp, ',');
00977 if(ct)
00978 {
00979 cp = ct;
00980 read_vector(hd, cp, "%lf", "Optimum information", ln);
00981 }
00982 gid->add_optimum(nnum2, hd);
00983 }
00984 break;
00985 default:
00986 throw_read("Malformed Helper Information: Wrong type");
00987 break;
00988 }
00989 }
00990 else if((_hlp = coconut_sscanfdouble(&coef, cp, "<E> %u %u", &nnum1, &nnum2)) == 3
00991 || _hlp == 2)
00992 {
00993 add_edge_back(nodes[nnum1], nodes[nnum2]);
00994 remove_edge(nodes[nnum1], sky());
00995 remove_edge(ground(), nodes[nnum2]);
00996 nodes[nnum1]->coeffs.push_back(_hlp == 2 ? 1.0 : coef);
00997 }
00998 else if(sscanf(cp, "<%u>", &nnum1) == 1)
00999 {
01000 #if MODEL_INLINE_DEBUG
01001 std::cerr << "Read a node : nnum = " << nnum1 << std::endl;
01002 #endif
01003 basic_alltype mng(0.0);
01004 semantics _sem;
01005 char _h;
01006
01007 if(nnum1 >= nodes.size())
01008 nodes.insert(nodes.end(), nnum1-nodes.size()+1, ground());
01009 for(cp = strchr(cp, '>')+1; cp; )
01010 {
01011 cq = strsep(&cp, ":");
01012 cq += strspn(cq, " \t");
01013 if(cq[1] != ' ')
01014 _h = ' ';
01015 else
01016 _h = cq[0];
01017 switch(_h)
01018 {
01019 case 'V':
01020 if(sscanf(cq, "V %u", &nnum2) != 1)
01021 throw_read("Variable definition");
01022 else
01023 {
01024 if(nnum2 >= gid->number_of_variables())
01025 new_variables(nnum2+1);
01026
01027 expression_node _en(EXPRINFO_VARIABLE, nnum1);
01028
01029 _en.v_i.reserve(gid->number_of_variables());
01030 _en.v_i.set(nnum2);
01031 _en.params = (int)nnum2;
01032 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
01033
01034 gid->mk_gvarref(nnum2, nodes[nnum1]);
01035 do_mng = 0;
01036 }
01037 break;
01038 case 'C':
01039 if(coconut_sscanfdouble(&coef, cq, "C") != 1)
01040 throw_read("Constant definition");
01041 else
01042 {
01043 expression_node _en(EXPRINFO_CONSTANT, nnum1);
01044 _en.v_i.reserve(gid->number_of_variables());
01045 _en.v_i.clear();
01046 _en.params = coef;
01047
01048 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
01049 do_mng = 0;
01050 }
01051 break;
01052 case 'G':
01053 if(sscanf(cq, "G %c", &_h) != 1 || (_h != 'T' && _h != 'F'))
01054 throw_read("Ghost definition");
01055 else
01056 {
01057 expression_node _en(EXPRINFO_GHOST, nnum1);
01058 _en.v_i.reserve(gid->number_of_variables());
01059 _en.v_i.clear();
01060 _en.params = (_h == 'T' ? true : false);
01061 _en.f_bounds = interval(-COCO_INF,COCO_INF);
01062
01063 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
01064 do_mng = 0;
01065 }
01066 break;
01067 case 'l':
01068 {
01069 std::vector<bool> hd;
01070 char _l;
01071
01072 cq += strspn(cq+1, " \t")+1;
01073 for(; cq; )
01074 {
01075 char *ct;
01076
01077 ct = strsep(&cq, ",");
01078 ct += strspn(ct, " \t");
01079 if(sscanf(ct, "%c", &_l) != 1 || (_l != 'T' && _l != 'F'))
01080 throw_read("Boolean additional definition");
01081 hd.push_back(_l == 'T' ? true : false);
01082 }
01083 if(hd.size() == 1)
01084 mng = hd[0];
01085 else
01086 mng = hd;
01087 found_mng = 1;
01088 }
01089 break;
01090 case 'S':
01091 {
01092 char *ct;
01093
01094 cq += strspn(cq+1, " \t")+1;
01095 if(cq[0] != '\"')
01096 throw_read("String additional definition");
01097 ct = cq+1;
01098 while(1)
01099 {
01100 ct = strchr(ct, '\"');
01101 if(ct == NULL)
01102 throw_read("String additional definition");
01103 if(*(ct-1) != '\\')
01104 break;
01105 ct += 1;
01106 }
01107
01108 *ct = '\0';
01109 mng = cq;
01110 cq = ct+1;
01111 found_mng = 1;
01112 }
01113 break;
01114 case 'd':
01115 {
01116 std::vector<double> hd;
01117
01118 read_vector(hd, cq, "%lf", "Double additional definition", ln);
01119 if(hd.size() == 1)
01120 mng = hd[0];
01121 else
01122 mng = hd;
01123 found_mng = 1;
01124 }
01125 break;
01126 case 'n':
01127 {
01128 std::vector<int> hd;
01129
01130 read_vector(hd, cq, "%d", "Integer additional definition", ln);
01131 if(hd.size() == 1)
01132 mng = hd[0];
01133 else
01134 mng = hd;
01135 found_mng = 1;
01136 }
01137 break;
01138 case 'i':
01139 {
01140 std::vector<interval> hd;
01141
01142 cq += strspn(cq+1, " \t")+1;
01143 for(; cq; )
01144 {
01145 cq += strspn(cq, " \t");
01146 hd.push_back(read_interval(cq, ln));
01147 }
01148 if(hd.size() == 1)
01149 mng = hd[0];
01150 else
01151 mng = hd;
01152 found_mng = 1;
01153 }
01154 break;
01155 case 'm':
01156 if(sscanf(cq, "m %u", &nnum2) != 1)
01157 throw_read("Matrix reference");
01158 else
01159 {
01160 do_mng = 2;
01161 found_mng = nnum2+2;
01162 }
01163 break;
01164 case 'v':
01165 {
01166 std::vector<unsigned int> hd;
01167
01168 read_vector(hd, cq, "%u", "Var index additional definition",
01169 ln);
01170 found_varidx = 1;
01171 v_var_idx = hd;
01172 }
01173 break;
01174 case 'b':
01175 cq += strspn(cq+1, " \t")+1;
01176 hi = read_interval(cq, ln);
01177 break;
01178 case 's':
01179 cq += strspn(cq+1, " \t")+1;
01180 _sem.read(cq);
01181 found_sem = 1;
01182 break;
01183 default:
01184 for(nnum2 = 0; expr_names[nnum2]; nnum2++)
01185 if(!strcmp(expr_names[nnum2], cq))
01186 break;
01187 {
01188 bool have_unknown(expr_names[nnum2] == NULL);
01189 if(have_unknown)
01190 nnum2 = -EXPRINFO_UNDEFINED;
01191 expression_node _en(-(int)nnum2, nnum1);
01192
01193 _en.v_i.reserve(gid->number_of_variables());
01194 _en.v_i.clear();
01195 #if MODEL_INLINE_DEBUG
01196 std::cerr << "Expression node number = " << _en.node_num <<
01197 std::endl;
01198 #endif
01199 nodes[nnum1] = store_node(between_back(ground(), sky(), _en));
01200 #if MODEL_INLINE_DEBUG
01201 std::cerr << "Sky node number = " << sky()->node_num <<
01202 std::endl;
01203 #endif
01204 if(have_unknown)
01205 {
01206 _en.params = std::string(cq);
01207 throw_read("Unknown operator "+cq);
01208 }
01209 }
01210 break;
01211 }
01212 }
01213 if(!found_mng && (nodes[nnum1]->operator_type == EXPRINFO_PROD ||
01214 nodes[nnum1]->operator_type == EXPRINFO_INVERT ||
01215 nodes[nnum1]->operator_type == EXPRINFO_DIV))
01216 {
01217 mng = 1.;
01218 do_mng = 1;
01219 }
01220 if(!found_mng && (nodes[nnum1]->operator_type == EXPRINFO_MAX ||
01221 nodes[nnum1]->operator_type == EXPRINFO_MIN))
01222 {
01223 mng = (double)(nodes[nnum1]->operator_type == EXPRINFO_MIN ?
01224 COCO_INF : -COCO_INF);
01225 do_mng = 1;
01226 }
01227 if(do_mng == 2)
01228 {
01229 int matrix_type;
01230 void* matrix_storage;
01231 std::map<unsigned int,std::pair<int,void*> >::iterator __x;
01232 std::pair<int,void*> x;
01233
01234 nnum2 = found_mng-2;
01235 __x = matrix_def.find(nnum2);
01236 if(__x == matrix_def.end())
01237 throw_read("Matrix reference is referencing undefined matrix");
01238 x = (*__x).second;
01239 matrix_type = x.first;
01240 matrix_storage = x.second;
01241 switch(matrix_type & ~MT_STORED)
01242 {
01243 case MT_DBL:
01244 if(matrix_type & MT_STORED)
01245 nodes[nnum1]->params = *(linalg::matrix<double>*)matrix_storage;
01246 else
01247 nodes[nnum1]->params.set_m((linalg::matrix<double>*)
01248 matrix_storage);
01249 break;
01250 case MT_INTV:
01251 if(matrix_type & MT_STORED)
01252 nodes[nnum1]->params = *(linalg::matrix<interval>*)matrix_storage;
01253 else
01254 nodes[nnum1]->params.set_im((linalg::matrix<interval>*)
01255 matrix_storage);
01256 break;
01257 case MT_INT:
01258 if(matrix_type & MT_STORED)
01259 nodes[nnum1]->params = *(linalg::matrix<int>*)matrix_storage;
01260 else
01261 nodes[nnum1]->params.set_nm((linalg::matrix<int>*)matrix_storage);
01262 break;
01263 }
01264 if(!(matrix_type & MT_STORED))
01265 {
01266 matrix_type |= MT_STORED;
01267 matrix_def.erase(__x);
01268 matrix_def.insert(std::make_pair(nnum2, std::make_pair(matrix_type,
01269 matrix_storage)));
01270 }
01271 }
01272 else if(do_mng)
01273 nodes[nnum1]->params = mng;
01274 if(found_sem)
01275 nodes[nnum1]->sem = _sem;
01276 nodes[nnum1]->set_bounds(hi);
01277 nodes[nnum1]->n_parents = 1;
01278 if(found_varidx)
01279 {
01280 nodes[nnum1]->is_var = v_var_idx.size();
01281 nodes[nnum1]->var_idx = v_var_idx;
01282 }
01283 }
01284 else if(buf[0] != '\0')
01285 throw_read("Unknown input");
01286 }
01287 catch(api_exception ae)
01288 {
01289 #if MODEL_INLINE_DEBUG
01290 std::cerr << "Read Error: " << ae.what() << std::endl;
01291 #endif
01292 error_messages += ae.what();
01293 error_messages += '\n';
01294 }
01295 } while(buf[0] != '\0');
01296 delete [] buf;
01297 clr_sky_ground_link();
01298 if(!error_messages.empty())
01299 {
01300 if(!continue_on_errors)
01301 throw api_exception(apiee_io, std::string("Read Error: \n")+
01302 error_messages);
01303 else
01304 std::cerr << "Read Error: " << error_messages << std::endl;
01305 }
01306 else
01307 {
01308 for(std::map<unsigned int,std::pair<int,void*> >::iterator __x = matrix_def.begin();
01309 __x != matrix_def.end(); ++__x)
01310 {
01311 std::pair<int,void*> x;
01312 x = (*__x).second;
01313 if(!(x.first & MT_STORED))
01314 {
01315 switch(x.first)
01316 {
01317 case MT_DBL:
01318 delete (linalg::matrix<double>*) x.second;
01319 break;
01320 case MT_INTV:
01321 delete (linalg::matrix<interval>*) x.second;
01322 break;
01323 case MT_INT:
01324 delete (linalg::matrix<int>*) x.second;
01325 break;
01326 }
01327 }
01328 }
01329 }
01330 for(int i = node_ref.size()-1; i >= 0; --i)
01331 {
01332 if(node_ref[i] == ground())
01333 {
01334 throw api_exception(apiee_internal, "Undefined node in node_ref!");
01335 }
01336 else
01337 {
01338 walker __w = node_ref[i] << node_ref[i].parent_begin();
01339 if(__w == ground())
01340 node_ref[i]->n_parents = 0;
01341 }
01342 }
01343 #if MODEL_INLINE_DEBUG
01344 std::cerr << "BrYcE : " << sky()->node_num << std::endl;
01345 #endif
01346 return error_messages.empty();
01347 }
01348
01349 bool model::simplify_visitor_0::postorder(expression_node &r)
01350 {
01351
01352 if(flags & SIMPLIFY_0_SKIP_THIS_NODE)
01353 return false;
01354
01355 if(!(*visited)[r.node_num] && r_idx != -1)
01356 {
01357 int ne_del = n-ndel-r_idx-1;
01358 r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01359 r.coeffs.end());
01360 ndel += ne_del;
01361 r_idx = -1;
01362 }
01363 postorder_help(r, n-ndel);
01364 if(!trans_ghosts.empty())
01365 {
01366 std::vector<std::pair<unsigned int,unsigned int> >::iterator tgi;
01367 for(tgi = trans_ghosts.begin(); tgi != trans_ghosts.end(); ++tgi)
01368 transfer_ghost_down(tgi->first, tgi->second);
01369 }
01370 if(!trans_edges.empty())
01371 {
01372 std::vector<std::triple<unsigned int,unsigned int,unsigned int> >::
01373 iterator tti;
01374 #if MODEL_INLINE_DEBUG_SIMPLIFY
01375 std::cerr << "Trans_edges:" << std::endl;
01376 #endif
01377 for(tti = trans_edges.begin(); tti != trans_edges.end(); ++tti)
01378 {
01379 #if MODEL_INLINE_DEBUG_SIMPLIFY
01380 std::cerr << tti->first << " " << tti->second << " " << tti->third
01381 << std::endl;
01382 #endif
01383 walker c(__mod->node(tti->first)), p(__mod->node(tti->second)), cc;
01384 unsigned int idx(tti->third);
01385
01386 __mod->partial_erase_to_parent(c, p, idx);
01387 for(children_iterator _cit = c.child_begin(); _cit != c.child_end();
01388 ++_cit)
01389 {
01390 cc = c >> _cit;
01391 cc->n_parents++;
01392 p->n_children++;
01393 }
01394 p->n_children--;
01395 }
01396 }
01397 if(!(*visited)[r.node_num])
01398 {
01399 (*visited)[r.node_num] = true;
01400
01401 if(r.sem.convexity().t() == 0)
01402 r.sem.convexity(s.convexity());
01403 r.sem.separability(s.separability());
01404 r.sem.degree = s.degree;
01405 r.sem.dim = s.dim;
01406
01407 r.v_i = v_i;
01408 }
01409 if(r.operator_type == EXPRINFO_CONSTANT ||
01410 r.operator_type == EXPRINFO_VARIABLE ||
01411 r.operator_type == EXPRINFO_GHOST)
01412 r.n_children = 0;
01413 else
01414 r.n_children = (__mod->node(r.node_num)).n_children();
01415 return false;
01416 }
01417
01418 void model::simplify_visitor_0::vcollect(const simplify_visitor_0& __s)
01419 {
01420 if(__s.flags & SIMPLIFY_0_SKIP_THIS_NODE)
01421 return;
01422
01423 if((__s.flags & SIMPLIFY_0_IS_CONST))
01424 {
01425 double help = __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01426 __s.m.nd();
01427 walker _n = __mod->node(__s.nnum);
01428 if(!_n->f_bounds.is_entire())
01429 {
01430 if(_n->f_bounds.contains(help))
01431 delnodes_insert(__s.nnum);
01432 }
01433 if(_n == __mod->objective)
01434 {
01435 __mod->ocoeff = 0;
01436 __mod->gid->obj_adj(__mod->gid->obj_adj()+help);
01437 if(_n->operator_type == EXPRINFO_CONSTANT)
01438 _n->params = 0.;
01439 }
01440 }
01441 if((__s.flags & SIMPLIFY_0_IS_SUM &&
01442 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE) ||
01443 (__s.flags & SIMPLIFY_0_IS_PROD &&
01444 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE))
01445 {
01446 walker _n = __mod->node(__s.nnum);
01447 walker _c;
01448 std::vector<unsigned int>::const_iterator _b, _e((*delnodes).end());
01449
01450
01451 for(children_iterator _ci = _n.child_begin(); _ci != _n.child_end(); ++_ci)
01452 {
01453 _c = _n >> _ci;
01454 unsigned int _cnn = _c->node_num;
01455 for(_b = (*delnodes).begin(); _b != _e; ++_b)
01456 if((*_b) == _cnn)
01457 break;
01458 if(_b == _e)
01459 break;
01460 }
01461
01462 if(!_n->f_bounds.is_entire())
01463 {
01464 if(__s.flags & SIMPLIFY_0_IS_SUM)
01465 {
01466 _n->f_bounds -= __s.m.nd();
01467 _n->f_bounds /= (*__s.transfer)[0];
01468 }
01469 else
01470 _n->f_bounds /= __s.m.nd();
01471 _c->f_bounds.intersectwith(_n->f_bounds);
01472 }
01473 if(_n == __mod->objective)
01474 {
01475 double a = __mod->gid->obj_adj(),
01476 m = __mod->gid->obj_mult();
01477 if(__s.flags & SIMPLIFY_0_IS_SUM)
01478 {
01479 a += m * __s.m.nd();
01480 m *= (*__s.transfer)[0];
01481 }
01482 else
01483 m *= __s.m.nd();
01484 __mod->gid->obj_adj(a);
01485 if(m < 0)
01486 {
01487 __mod->ocoeff = -__mod->ocoeff;
01488 __mod->gid->obj_adj(-__mod->obj_adj());
01489 m = -m;
01490 }
01491 __mod->gid->obj_mult(m);
01492 }
01493
01494
01495
01496 delnodes_insert(__s.nnum);
01497 }
01498 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01499
01500 {
01501 walker _n = __mod->node(__s.nnum);
01502 double help = __s.m.nd();
01503 _n->f_bounds /= help;
01504 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01505 _n->params = 1.;
01506 if(_n == __mod->objective &&
01507 !(__s.flags & SIMPLIFY_0_IS_PROD &&
01508 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE))
01509 {
01510 if(help < 0)
01511 {
01512 __mod->ocoeff = -__mod->ocoeff;
01513 __mod->gid->obj_adj(-__mod->obj_adj());
01514 help = -help;
01515 }
01516 help *= __mod->gid->obj_mult();
01517 __mod->gid->obj_mult(help);
01518 }
01519 }
01520 }
01521
01522 void model::simplify_visitor_0::collect(expression_node &r,
01523 const simplify_visitor_0& __s)
01524 {
01525 if(__s.flags & SIMPLIFY_0_SKIP_THIS_NODE)
01526 {
01527 n++;
01528 return;
01529 }
01530
01531 nnum = r.node_num;
01532 if(r.operator_type < 0)
01533 {
01534 switch(r.operator_type)
01535 {
01536 case EXPRINFO_CONSTANT:
01537 case EXPRINFO_VARIABLE:
01538 case EXPRINFO_GHOST:
01539
01540 break;
01541 case EXPRINFO_SUM:
01542 if(n == ndel)
01543 {
01544 if(r.coeffs[0] == 0)
01545 {
01546 r.coeffs.erase(r.coeffs.begin());
01547 (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01548 ndel++;
01549 }
01550 s.degree = __s.s.degree;
01551 s.property_flags = __s.s.property_flags;
01552 if(r.coeffs[0] < 0)
01553 s.property_flags.c_info == -s.property_flags.c_info;
01554 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01555 is_integer(r.params.nd()))
01556 s.annotation_flags.integer = true;
01557 r_idx = -1;
01558 }
01559 else
01560 {
01561 if(s.degree == -1 || __s.s.degree == -1)
01562 s.degree = -1;
01563 else if(__s.s.degree > s.degree)
01564 s.degree = __s.s.degree;
01565 s.property_flags.c_info = convex_e();
01566 if(s.property_flags.separable != t_true ||
01567 __s.s.property_flags.separable != t_true)
01568 s.property_flags.separable = t_maybe;
01569 if(s.annotation_flags.integer &&
01570 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n-ndel])))
01571 s.annotation_flags.integer = false;
01572 if(r.coeffs[n-ndel] == 0)
01573 {
01574 r.coeffs.erase(r.coeffs.begin()+(n-ndel));
01575 (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01576 ndel++;
01577 }
01578 else if(l_nnum == __s.nnum)
01579 {
01580 if(r_idx == -1)
01581 r_idx = n-ndel-1;
01582 r.coeffs[r_idx] += r.coeffs[n-ndel];
01583 (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01584 }
01585 else if(r_idx != -1)
01586 {
01587 int ne_del = n-ndel-r_idx-1;
01588 r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01589 r.coeffs.begin()+n-ndel);
01590 ndel += ne_del;
01591 r_idx = -1;
01592 }
01593 }
01594 if(__s.flags & SIMPLIFY_0_IS_CONST)
01595 {
01596 double help =
01597 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01598 __s.m.nd();
01599 model::walker _node = __mod->node(__s.nnum);
01600
01601 r.params = r.params.nd() + r.coeffs[n-ndel] * help;
01602 r.coeffs.erase(r.coeffs.begin() + n-ndel);
01603 if(_node->n_parents == 1)
01604 delnodes_insert(__s.nnum);
01605 else
01606 {
01607 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01608 n-ndel-ncorr));
01609 _node->n_parents--;
01610 }
01611 ndel++;
01612 if(ndel >= (int)r.n_children)
01613 r.operator_type = EXPRINFO_CONSTANT;
01614 }
01615 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01616 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01617 {
01618 r.coeffs[n-ndel] *= __s.m.nd();
01619 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01620 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01621 else
01622 {
01623 model::walker _node = __mod->node(__s.nnum);
01624 if(_node->n_parents == 1)
01625 delnodes_insert(__s.nnum);
01626 else
01627 {
01628 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01629 n-ndel-ncorr));
01630 _node->n_parents--;
01631 }
01632 }
01633 }
01634 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01635 {
01636 model::walker _node = __mod->node(__s.nnum);
01637 if(_node->n_parents == 1)
01638 {
01639 r.coeffs[n-ndel] *= __s.m.nd();
01640 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01641 _node->params = 1.;
01642 }
01643 }
01644 else if(__s.flags & SIMPLIFY_0_IS_SUM)
01645 {
01646 double help = r.coeffs[n-ndel];
01647 std::vector<double>::const_iterator b = __s.transfer->begin();
01648
01649 r.params = r.params.nd() + help*__s.m.nd();
01650 r.coeffs[n-ndel] = *b * help;
01651 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01652 {
01653 for(++b; b != __s.transfer->end(); ++b)
01654 r.coeffs.push_back(*b * help);
01655 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01656 }
01657 else
01658 {
01659 model::walker _node = __mod->node(__s.nnum);
01660 int i;
01661 for(i=n-ndel+1, ++b; b != __s.transfer->end(); ++b, ++i)
01662 r.coeffs.insert(r.coeffs.begin()+i, *b * help);
01663 if(_node->n_parents == 1)
01664 {
01665 ncorr += __s.transfer->size() - 1;
01666 delnodes_insert(__s.nnum);
01667 }
01668 else
01669 {
01670 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01671 n-ndel-ncorr));
01672 _node->n_parents--;
01673 }
01674 ndel -= __s.transfer->size()-1;
01675 }
01676 }
01677 break;
01678 case EXPRINFO_MEAN:
01679 if(n == 0)
01680 {
01681 s.degree = __s.s.degree;
01682 s.property_flags = __s.s.property_flags;
01683 if(r.coeffs[0] < 0)
01684 {
01685 r.operator_type = EXPRINFO_SUM;
01686 s.property_flags.c_info == -s.property_flags.c_info;
01687 }
01688 r_idx = -1;
01689 }
01690 else
01691 {
01692 if(s.degree == -1 || __s.s.degree == -1)
01693 s.degree = -1;
01694 else if(__s.s.degree > s.degree)
01695 s.degree = __s.s.degree;
01696 s.property_flags.c_info = convex_e();
01697 if(s.property_flags.separable != t_true ||
01698 __s.s.property_flags.separable != t_true)
01699 s.property_flags.separable = t_maybe;
01700 if(l_nnum == __s.nnum)
01701 {
01702 if(r_idx == -1)
01703 r_idx = n-ndel-1;
01704 r.coeffs[r_idx] += r.coeffs[n-ndel];
01705 (*deledges).push_back(std::make_pair(nnum, __s.nnum));
01706 }
01707 else if(r_idx != -1)
01708 {
01709 int ne_del = n-ndel-r_idx-1;
01710 r.coeffs.erase(r.coeffs.begin()+r_idx+1,
01711 r.coeffs.begin()+n-ndel);
01712 ndel += ne_del;
01713 r_idx = -1;
01714 }
01715 }
01716 if(__s.flags & SIMPLIFY_0_IS_CONST)
01717 {
01718 double help =
01719 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01720 __s.m.nd();
01721 r.operator_type = EXPRINFO_SUM;
01722 r.params = r.params.nd() + r.coeffs[n-ndel] * help;
01723 r.coeffs.erase(r.coeffs.begin() + n);
01724 {
01725 model::walker _node = __mod->node(__s.nnum);
01726 if(_node->n_parents == 1)
01727 delnodes_insert(__s.nnum);
01728 else
01729 {
01730 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
01731 _node->n_parents--;
01732 }
01733 }
01734 ndel++;
01735 }
01736 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
01737 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
01738 {
01739 r.operator_type = EXPRINFO_SUM;
01740 r.coeffs[n-ndel] *= __s.m.nd();
01741 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01742 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01743 else
01744 {
01745 model::walker _node = __mod->node(__s.nnum);
01746 if(_node->n_parents == 1)
01747 delnodes_insert(__s.nnum);
01748 else
01749 {
01750 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
01751 _node->n_parents--;
01752 }
01753 }
01754 }
01755 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01756 {
01757 r.operator_type = EXPRINFO_SUM;
01758 r.coeffs[n-ndel] *= __s.m.nd();
01759 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01760 __mod->node(__s.nnum)->params = 1.;
01761 }
01762 else if(__s.flags & SIMPLIFY_0_IS_SUM)
01763 {
01764 double help = r.coeffs[n-ndel];
01765
01766 r.operator_type = EXPRINFO_SUM;
01767 r.params = r.params.nd() + __s.m.nd();
01768 r.coeffs.erase(r.coeffs.begin()+(n-ndel));
01769 ndel++;
01770 for(std::vector<double>::const_iterator b = __s.transfer->begin();
01771 b != __s.transfer->end(); ++b)
01772 r.coeffs.push_back(*b * help);
01773 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01774 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01775 else
01776 {
01777 model::walker _node = __mod->node(__s.nnum);
01778 if(_node->n_parents == 1)
01779 delnodes_insert(__s.nnum);
01780 else
01781 {
01782 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
01783 _node->n_parents--;
01784 }
01785 }
01786 n += __s.transfer->size();
01787 }
01788 break;
01789 case EXPRINFO_PROD:
01790 if(n == 0)
01791 {
01792 s.degree = __s.s.degree;
01793 s.property_flags = __s.s.property_flags;
01794 m = 1.;
01795 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01796 is_integer(r.params.nd()))
01797 s.annotation_flags.integer = true;
01798 }
01799 else
01800 {
01801 if(__s.s.degree == -1 || s.degree == -1)
01802 s.degree = -1;
01803 else
01804 s.degree += __s.s.degree;
01805 s.property_flags.c_info = convex_e();
01806 s.property_flags.separable = t_maybe;
01807 if(s.annotation_flags.integer &&
01808 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01809 s.annotation_flags.integer = false;
01810 }
01811 if(r.coeffs[n-ndel] != 1)
01812 {
01813 r.params = r.params.nd() * r.coeffs[n-ndel];
01814 r.coeffs[n-ndel] = 1;
01815 }
01816 if(__s.flags & SIMPLIFY_0_IS_CONST)
01817 {
01818 double help =
01819 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01820 __s.m.nd();
01821 r.params = r.params.nd() * help;
01822 r.coeffs.pop_back();
01823 {
01824 model::walker _node = __mod->node(__s.nnum);
01825 if(_node->n_parents == 1)
01826 delnodes_insert(__s.nnum);
01827 else
01828 {
01829 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01830 n-ndel-ncorr));
01831 _node->n_parents--;
01832 }
01833 }
01834 ndel++;
01835 if(ndel >= (int)r.n_children)
01836 r.operator_type = EXPRINFO_CONSTANT;
01837 }
01838 else if(__s.flags & SIMPLIFY_0_IS_PROD)
01839 {
01840 r.params = r.params.nd() * __s.m.nd();
01841 r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
01842 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01843 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01844 else
01845 {
01846 model::walker _node = __mod->node(__s.nnum);
01847 if(_node->n_parents == 1)
01848 {
01849 delnodes_insert(__s.nnum);
01850 ncorr += __s.transfer->size()-1;
01851 }
01852 else
01853 {
01854 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01855 n-ndel-ncorr));
01856 _node->n_parents--;
01857 }
01858 }
01859 ndel -= __s.transfer->size()-1;
01860 }
01861 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01862 {
01863 r.params = r.params.nd() * __s.m.nd();
01864 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01865 __mod->node(__s.nnum)->params = 1.;
01866 }
01867 else if(__s.flags & SIMPLIFY_0_IS_SUM &&
01868 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE &&
01869 __s.m.nd() == 0)
01870 {
01871 r.params = r.params.nd() * (*__s.transfer)[0];
01872 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01873 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01874 else
01875 {
01876 model::walker _node = __mod->node(__s.nnum);
01877 if(_node->n_parents == 1)
01878 delnodes_insert(__s.nnum);
01879 else
01880 {
01881 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num,
01882 n-ndel-ncorr));
01883 _node->n_parents--;
01884 }
01885 }
01886 }
01887 if(r.operator_type != EXPRINFO_CONSTANT && r.params.nd() != 1)
01888 {
01889 flags |= SIMPLIFY_0_IS_MULTIPLICATIVE;
01890 }
01891 break;
01892 case EXPRINFO_MONOME:
01893 if(n == 0)
01894 {
01895 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.n()[0];
01896 s.property_flags = __s.s.property_flags;
01897 s.property_flags.c_info = convex_e();
01898 m = 1.;
01899 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
01900 s.annotation_flags.integer = true;
01901 }
01902 else
01903 {
01904 if(__s.s.degree == -1 || s.degree == -1)
01905 s.degree = -1;
01906 else
01907 s.degree += __s.s.degree*r.params.n()[n];
01908 s.property_flags.c_info = convex_e();
01909 s.property_flags.separable = t_maybe;
01910 if(s.annotation_flags.integer &&
01911 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01912 s.annotation_flags.integer = false;
01913 }
01914 if(__s.flags & SIMPLIFY_0_IS_CONST)
01915 {
01916 double help =
01917 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
01918 __s.m.nd();
01919 m = m.nd() * std::pow(help, r.params.n()[n]);
01920 r.coeffs.pop_back();
01921 {
01922 model::walker _node = __mod->node(__s.nnum);
01923 if(_node->n_parents == 1)
01924 delnodes_insert(__s.nnum);
01925 else
01926 {
01927 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
01928 _node->n_parents--;
01929 }
01930 }
01931 ndel++;
01932 }
01933 else if(__s.flags & SIMPLIFY_0_IS_PROD)
01934 {
01935 m = m.nd() * std::pow(__s.m.nd(), r.params.n()[n]);
01936 r.coeffs.insert(r.coeffs.end(), __s.transfer->size()-1, 1.0);
01937 r.params.n().insert(r.params.n().begin()+n, __s.transfer->size()-1,
01938 r.params.n()[n]);
01939 if(__s.flags & SIMPLIFY_0_IS_GHOST)
01940 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
01941 else
01942 {
01943 model::walker _node = __mod->node(__s.nnum);
01944 if(_node->n_parents == 1)
01945 delnodes_insert(__s.nnum);
01946 else
01947 {
01948 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
01949 _node->n_parents--;
01950 }
01951 }
01952 n += __s.transfer->size()-1;
01953 }
01954 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01955 {
01956 m = m.nd() * std::pow(__s.m.nd(), r.params.n()[n]);
01957 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01958 __mod->node(__s.nnum)->params = 1.;
01959 }
01960 if(m.nd() != 1)
01961 {
01962 flags |= (SIMPLIFY_0_IS_MULTIPLICATIVE | SIMPLIFY_0_IS_CORRECTEDMULT);
01963 }
01964 break;
01965 case EXPRINFO_MAX:
01966 case EXPRINFO_MIN:
01967 if(n == 0)
01968 {
01969 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
01970 is_integer(r.params.nd()))
01971 s.annotation_flags.integer = true;
01972 }
01973 else if(s.annotation_flags.integer &&
01974 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
01975 s.annotation_flags.integer = false;
01976 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
01977 {
01978 r.coeffs[n] *= __s.m.nd();
01979 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
01980 __mod->node(__s.nnum)->params = 1.;
01981 }
01982 break;
01983 case EXPRINFO_SCPROD:
01984 if(n == 0)
01985 {
01986 s.property_flags.c_info = convex_e();
01987 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
01988 s.annotation_flags.integer = true;
01989 }
01990 else if(n & 1)
01991 {
01992 r.coeffs[n-1] *= r.coeffs[n];
01993 r.coeffs[n] = 1.;
01994 if(s.degree == -1 || __s.s.degree == -1 || l_s.degree == -1)
01995 s.degree = -1;
01996 else if(__s.s.degree+l_s.degree > s.degree)
01997 s.degree = __s.s.degree+l_s.degree;
01998 s.property_flags.separable = t_maybe;
01999 if(s.annotation_flags.integer &&
02000 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n-1])))
02001 s.annotation_flags.integer = false;
02002 }
02003 else
02004 {
02005 if(s.annotation_flags.integer &&
02006 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02007 s.annotation_flags.integer = false;
02008 }
02009 if(__s.flags & SIMPLIFY_0_IS_PROD &&
02010 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
02011 {
02012 r.coeffs[n-ndel] *= __s.m.nd();
02013 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02014 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02015 else
02016 {
02017 model::walker _node = __mod->node(__s.nnum);
02018 if(_node->n_parents == 1)
02019 delnodes_insert(__s.nnum);
02020 else
02021 {
02022 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02023 _node->n_parents--;
02024 }
02025 }
02026 }
02027 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02028 {
02029 r.coeffs[n-ndel] *= __s.m.nd();
02030 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02031 __mod->node(__s.nnum)->params = 1.;
02032 }
02033 break;
02034 case EXPRINFO_NORM:
02035 if(n == 0)
02036 {
02037 s.degree = -1;
02038 s.property_flags = __s.s.property_flags;
02039 s.property_flags.c_info = convex_e();
02040 s.annotation_flags.integer = false;
02041 }
02042 else
02043 {
02044 if(s.property_flags.separable != t_true ||
02045 __s.s.property_flags.separable != t_true)
02046 s.property_flags.separable = t_maybe;
02047 }
02048 if(__s.flags & SIMPLIFY_0_IS_PROD &&
02049 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
02050 {
02051 r.coeffs[n-ndel] *= std::pow(std::fabs(__s.m.nd()), r.params.nd());
02052 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02053 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02054 else
02055 {
02056 model::walker _node = __mod->node(__s.nnum);
02057 if(_node->n_parents == 1)
02058 delnodes_insert(__s.nnum);
02059 else
02060 {
02061 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02062 _node->n_parents--;
02063 }
02064 }
02065 }
02066 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02067 {
02068 r.coeffs[n-ndel] *= std::pow(std::fabs(__s.m.nd()), r.params.nd());
02069 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02070 __mod->node(__s.nnum)->params = 1.;
02071 }
02072 break;
02073 case EXPRINFO_POW:
02074 {
02075 bool spupd = false;
02076 if(n == 0)
02077 {
02078 if(__s.flags & SIMPLIFY_0_IS_CONST)
02079 {
02080 double help =
02081 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02082 __s.m.nd();
02083 r.operator_type = EXPRINFO_EXP;
02084 r.coeffs[0] = std::log(r.coeffs[0] * help) * r.coeffs[1];
02085 r.coeffs.pop_back();
02086 {
02087 model::walker _node = __mod->node(__s.nnum);
02088 if(_node->n_parents == 1)
02089 delnodes_insert(__s.nnum);
02090 else
02091 {
02092 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02093 _node->n_parents--;
02094 }
02095 }
02096 s.degree = -1;
02097 ndel++;
02098 }
02099 else
02100 s.degree = __s.s.degree;
02101 if((__s.flags & SIMPLIFY_0_IS_SUM &&
02102 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE) ||
02103 (__s.flags & SIMPLIFY_0_IS_PROD &&
02104 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE))
02105 {
02106 transfer = __s.transfer;
02107 m = __s.m;
02108 nnum = __s.nnum;
02109 flags = __s.flags;
02110
02111 }
02112 else
02113 transfer = NULL;
02114 }
02115 if(n != 0 && r.params.nd() == 0 &&
02116 __s.flags & SIMPLIFY_0_IS_CONST &&
02117 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER)
02118 {
02119 double help = __s.m.nn()*r.coeffs[n];
02120 r.coeffs[n] = 1.;
02121 long int helpl = lrint(help);
02122 if(helpl - help == 0 && helpl < MAXINT && helpl > -MAXINT)
02123 {
02124 switch(helpl)
02125 {
02126 case 0:
02127 r.operator_type = EXPRINFO_CONSTANT;
02128 r.params = 1.;
02129 r.coeffs.erase(r.coeffs.begin(),r.coeffs.end());
02130 s.degree = 0;
02131 ndel++;
02132
02133 {
02134 model::walker _node = __mod->node(__s.nnum);
02135 if(_node->n_parents == 1)
02136 delnodes_insert(__s.nnum);
02137 else
02138 {
02139 trans_edges.push_back(std::make_triple(__s.nnum,
02140 r.node_num, 1));
02141 _node->n_parents--;
02142 }
02143 _node = __mod->node(r.node_num);
02144 _node >>= _node.child_begin();
02145 if(_node->n_parents == 1)
02146 delnodes_insert(_node->node_num);
02147 else
02148 {
02149 trans_edges.push_back(std::make_triple(_node->node_num,
02150 r.node_num, 0));
02151 _node->n_parents--;
02152 }
02153 }
02154 break;
02155 case 1:
02156 {
02157 model::walker _node = __mod->node(__s.nnum);
02158 if(_node->n_parents == 1)
02159 delnodes_insert(__s.nnum);
02160 else
02161 {
02162 trans_edges.push_back(std::make_triple(__s.nnum,
02163 r.node_num, 1));
02164 _node->n_parents--;
02165 }
02166 delnodes_insert(r.node_num);
02167 }
02168 break;
02169 case 2:
02170 r.operator_type = EXPRINFO_SQUARE;
02171 {
02172 model::walker _node = __mod->node(__s.nnum);
02173 if(_node->n_parents == 1)
02174 delnodes_insert(__s.nnum);
02175 else
02176 {
02177 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02178 _node->n_parents--;
02179 }
02180 }
02181 s.degree = s.degree == -1 ? -1 : s.degree*2;
02182 r.coeffs.pop_back();
02183 ndel++;
02184 spupd = true;
02185 break;
02186 case -1:
02187 r.params = r.coeffs[0];
02188 r.coeffs[0] = 1.;
02189 r.operator_type = EXPRINFO_INVERT;
02190 {
02191 model::walker _node = __mod->node(__s.nnum);
02192 if(_node->n_parents == 1)
02193 delnodes_insert(__s.nnum);
02194 else
02195 {
02196 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02197 _node->n_parents--;
02198 }
02199 }
02200 s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
02201 flags = SIMPLIFY_0_IS_MULTIPLICATIVE;
02202 r.coeffs.pop_back();
02203 ndel++;
02204 break;
02205 default:
02206 r.params = (int) helpl;
02207 r.operator_type = EXPRINFO_INTPOWER;
02208 {
02209 model::walker _node = __mod->node(__s.nnum);
02210 if(_node->n_parents == 1)
02211 delnodes_insert(__s.nnum);
02212 else
02213 {
02214 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02215 _node->n_parents--;
02216 }
02217 }
02218 s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
02219 r.coeffs.pop_back();
02220 ndel++;
02221 break;
02222 }
02223 }
02224
02225
02226 }
02227
02228
02229 if(spupd)
02230 simple_sum_prod_update(r, *this);
02231 if(n != 0)
02232 {
02233 if(flags != SIMPLIFY_0_IS_MULTIPLICATIVE)
02234 flags = 0;
02235 nnum = r.node_num;
02236 }
02237 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02238 {
02239 r.coeffs[n] *= __s.m.nd();
02240 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02241 __mod->node(__s.nnum)->params = 1.;
02242 }
02243 s.property_flags.c_info = convex_e();
02244 s.property_flags.separable = t_maybe;
02245 }
02246 break;
02247 case EXPRINFO_SQUARE:
02248 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*2;
02249 if(__s.flags & SIMPLIFY_0_IS_CONST)
02250 {
02251 double help =
02252 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02253 __s.m.nd();
02254 r.operator_type = EXPRINFO_CONSTANT;
02255 help *= r.coeffs[0];
02256 help += r.params.nd();
02257 r.params = help*help;
02258 {
02259 model::walker _node = __mod->node(__s.nnum);
02260 if(_node->n_parents == 1)
02261 delnodes_insert(__s.nnum);
02262 else
02263 {
02264 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02265 _node->n_parents--;
02266 }
02267 }
02268 s.degree = 0;
02269 }
02270 else
02271 simple_sum_prod_update(r, __s);
02272 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
02273 is_integer(r.params.nd()))
02274 s.annotation_flags.integer = true;
02275 break;
02276 case EXPRINFO_SQROOT:
02277 if(__s.flags & SIMPLIFY_0_IS_CONST)
02278 {
02279 double help =
02280 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02281 __s.m.nd();
02282 r.operator_type = EXPRINFO_CONSTANT;
02283 help *= r.coeffs[0];
02284 help += r.params.nd();
02285 r.params = std::sqrt(help);
02286 {
02287 model::walker _node = __mod->node(__s.nnum);
02288 if(_node->n_parents == 1)
02289 delnodes_insert(__s.nnum);
02290 else
02291 {
02292 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02293 _node->n_parents--;
02294 }
02295 }
02296 s.degree = 0;
02297 }
02298 else
02299 simple_sum_prod_update(r, __s);
02300 break;
02301 case EXPRINFO_ABS:
02302 if(__s.flags & SIMPLIFY_0_IS_CONST)
02303 {
02304 double help =
02305 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02306 __s.m.nd();
02307 r.operator_type = EXPRINFO_CONSTANT;
02308 help *= r.coeffs[0];
02309 help += r.params.nd();
02310 r.params = std::fabs(help);
02311 {
02312 model::walker _node = __mod->node(__s.nnum);
02313 if(_node->n_parents == 1)
02314 delnodes_insert(__s.nnum);
02315 else
02316 {
02317 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02318 _node->n_parents--;
02319 }
02320 }
02321 s.degree = 0;
02322 }
02323 else
02324 simple_sum_prod_update(r, __s);
02325 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
02326 is_integer(r.params.nd()))
02327 s.annotation_flags.integer = true;
02328 break;
02329 case EXPRINFO_EXP:
02330 if(__s.flags & SIMPLIFY_0_IS_CONST)
02331 {
02332 double help =
02333 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02334 __s.m.nd();
02335 r.operator_type = EXPRINFO_CONSTANT;
02336 help *= r.coeffs[0];
02337 help += r.params.nd();
02338 r.params = std::exp(help);
02339 {
02340 model::walker _node = __mod->node(__s.nnum);
02341 if(_node->n_parents == 1)
02342 delnodes_insert(__s.nnum);
02343 else
02344 {
02345 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02346 _node->n_parents--;
02347 }
02348 }
02349 s.degree = 0;
02350 }
02351 else
02352 simple_sum_prod_update(r, __s);
02353 break;
02354 case EXPRINFO_LOG:
02355 if(__s.flags & SIMPLIFY_0_IS_CONST)
02356 {
02357 double help =
02358 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02359 __s.m.nd();
02360 r.operator_type = EXPRINFO_CONSTANT;
02361 help *= r.coeffs[0];
02362 help += r.params.nd();
02363 r.params = std::log(help);
02364 {
02365 model::walker _node = __mod->node(__s.nnum);
02366 if(_node->n_parents == 1)
02367 delnodes_insert(__s.nnum);
02368 else
02369 {
02370 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02371 _node->n_parents--;
02372 }
02373 }
02374 s.degree = 0;
02375 }
02376 else
02377 simple_sum_prod_update(r, __s);
02378 break;
02379 case EXPRINFO_SIN:
02380 if(__s.flags & SIMPLIFY_0_IS_CONST)
02381 {
02382 double help =
02383 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02384 __s.m.nd();
02385 r.operator_type = EXPRINFO_CONSTANT;
02386 help *= r.coeffs[0];
02387 help += r.params.nd();
02388 r.params = std::sin(help);
02389 {
02390 model::walker _node = __mod->node(__s.nnum);
02391 if(_node->n_parents == 1)
02392 delnodes_insert(__s.nnum);
02393 else
02394 {
02395 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02396 _node->n_parents--;
02397 }
02398 }
02399 s.degree = 0;
02400 }
02401 else
02402 simple_sum_prod_update(r, __s);
02403 break;
02404 case EXPRINFO_COS:
02405 if(__s.flags & SIMPLIFY_0_IS_CONST)
02406 {
02407 double help =
02408 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02409 __s.m.nd();
02410 r.operator_type = EXPRINFO_CONSTANT;
02411 help *= r.coeffs[0];
02412 help += r.params.nd();
02413 r.params = std::cos(help);
02414 {
02415 model::walker _node = __mod->node(__s.nnum);
02416 if(_node->n_parents == 1)
02417 delnodes_insert(__s.nnum);
02418 else
02419 {
02420 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02421 _node->n_parents--;
02422 }
02423 }
02424 s.degree = 0;
02425 }
02426 else
02427 simple_sum_prod_update(r, __s);
02428 break;
02429 case EXPRINFO_ATAN2:
02430 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02431 {
02432 r.coeffs[n] *= __s.m.nd();
02433 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02434 __mod->node(__s.nnum)->params = 1.;
02435 }
02436 break;
02437 case EXPRINFO_GAUSS:
02438 if(__s.flags & SIMPLIFY_0_IS_CONST)
02439 {
02440 double help =
02441 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02442 __s.m.nd();
02443 r.operator_type = EXPRINFO_CONSTANT;
02444 help *= r.coeffs[0];
02445 help -= r.params.d()[0];
02446 help /= r.params.d()[1];
02447 r.params = std::exp(-help*help);
02448 {
02449 model::walker _node = __mod->node(__s.nnum);
02450 if(_node->n_parents == 1)
02451 delnodes_insert(__s.nnum);
02452 else
02453 {
02454 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02455 _node->n_parents--;
02456 }
02457 }
02458 s.degree = 0;
02459 }
02460 else if(__s.flags & SIMPLIFY_0_IS_SUM &&
02461 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
02462 {
02463 std::vector<double> m = r.params.d();
02464
02465 m[0] -= r.coeffs[0]*__s.m.nd();
02466 r.params = m;
02467 r.coeffs[0] *= (*__s.transfer)[0];
02468 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02469 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02470 else
02471 {
02472 model::walker _node = __mod->node(__s.nnum);
02473 if(_node->n_parents == 1)
02474 delnodes_insert(__s.nnum);
02475 else
02476 {
02477 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02478 _node->n_parents--;
02479 }
02480 }
02481 }
02482 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
02483 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
02484 {
02485 r.coeffs[0] *= __s.m.nd();
02486 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02487 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02488 else
02489 {
02490 model::walker _node = __mod->node(__s.nnum);
02491 if(_node->n_parents == 1)
02492 delnodes_insert(__s.nnum);
02493 else
02494 {
02495 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02496 _node->n_parents--;
02497 }
02498 }
02499 }
02500 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02501 {
02502 r.coeffs[0] *= __s.m.nd();
02503 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02504 __mod->node(__s.nnum)->params = 1.;
02505 }
02506 break;
02507 case EXPRINFO_INVERT:
02508 if(r.coeffs[0] != 1)
02509 {
02510 r.params = r.params.nd() / r.coeffs[0];
02511 r.coeffs[0] = 1.;
02512 }
02513 if(__s.flags & SIMPLIFY_0_IS_CONST)
02514 {
02515 double help =
02516 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02517 __s.m.nd();
02518 r.operator_type = EXPRINFO_CONSTANT;
02519 r.params = r.params.nd() / help;
02520 {
02521 model::walker _node = __mod->node(__s.nnum);
02522 if(_node->n_parents == 1)
02523 delnodes_insert(__s.nnum);
02524 else
02525 {
02526 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02527 _node->n_parents--;
02528 }
02529 }
02530 s.degree = 0;
02531 }
02532 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02533 {
02534 r.params = r.params.nd() / __s.m.nd();
02535 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02536 __mod->node(__s.nnum)->params = 1.;
02537 }
02538 break;
02539 case EXPRINFO_DIV:
02540 if(n == 0 && __s.flags & SIMPLIFY_0_IS_CONST)
02541 {
02542 double help =
02543 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02544 __s.m.nd();
02545 r.operator_type = EXPRINFO_INVERT;
02546 r.params = help*r.coeffs[0];
02547 r.coeffs.erase(r.coeffs.begin());
02548 {
02549 model::walker _node = __mod->node(__s.nnum);
02550 if(_node->n_parents == 1)
02551 delnodes_insert(__s.nnum);
02552 else
02553 {
02554 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02555 _node->n_parents--;
02556 }
02557 }
02558 s.degree = __s.s.degree;
02559 ndel++;
02560 }
02561 else if(n == 0)
02562 {
02563 r.params = r.coeffs[0];
02564 r.coeffs[0] = 1;
02565 }
02566 if(n != 0)
02567 {
02568 if(__s.flags & SIMPLIFY_0_IS_CONST)
02569 {
02570 double help =
02571 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02572 __s.m.nd();
02573 r.operator_type = EXPRINFO_PROD;
02574 r.params = 1./help;
02575 r.coeffs.pop_back();
02576 {
02577 model::walker _node = __mod->node(__s.nnum);
02578 if(_node->n_parents == 1)
02579 delnodes_insert(__s.nnum);
02580 else
02581 {
02582 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02583 _node->n_parents--;
02584 }
02585 }
02586 ndel++;
02587 }
02588 else
02589 {
02590 r.params = r.params.nd() / r.coeffs[1];
02591 r.coeffs[1] = 1;
02592 s.degree = -1;
02593 }
02594 }
02595 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02596 {
02597 if(n == 0)
02598 r.params = r.params.nd() * __s.m.nd();
02599 else
02600 r.params = r.params.nd() / __s.m.nd();
02601 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02602 __mod->node(__s.nnum)->params = 1.;
02603 }
02604 break;
02605 case EXPRINFO_INTPOWER:
02606 if(r.params.nn() > 0)
02607 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.nn();
02608 else
02609 s.degree = -1;
02610 if(__s.flags & SIMPLIFY_0_IS_CONST)
02611 {
02612 double help =
02613 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02614 __s.m.nd();
02615 r.operator_type = EXPRINFO_CONSTANT;
02616 r.params = std::pow(help, r.params.nn());
02617 {
02618 model::walker _node = __mod->node(__s.nnum);
02619 if(_node->n_parents == 1)
02620 delnodes_insert(__s.nnum);
02621 else
02622 {
02623 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, 0));
02624 _node->n_parents--;
02625 }
02626 }
02627 s.degree = 0;
02628 }
02629 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02630 {
02631 r.coeffs[0] *= __s.m.nd();
02632 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02633 __mod->node(__s.nnum)->params = 1.;
02634 }
02635 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
02636 s.annotation_flags.integer = true;
02637 break;
02638 case EXPRINFO_IN:
02639 if(n == 0)
02640 r_idx = -1;
02641 else
02642 {
02643 if(l_nnum == __s.nnum)
02644 {
02645 if(r_idx == -1)
02646 r_idx = n-ndel-1;
02647 r.params.i()[n-ndel] /= r.coeffs[n-ndel];
02648 r.coeffs[n-ndel] = 1.;
02649 r.params.i()[r_idx].intersectwith(r.params.i()[n-ndel]);
02650 (*deledges).push_back(std::make_pair(nnum, __s.nnum));
02651 }
02652 else if(r_idx != -1)
02653 {
02654 int ne_del = n-ndel-r_idx-1;
02655 r.coeffs.erase(r.coeffs.begin()+r_idx+1,
02656 r.coeffs.begin()+n-ndel);
02657 r.params.i().erase(r.params.i().begin()+r_idx+1,
02658 r.params.i().begin()+n-ndel);
02659 ndel += ne_del;
02660 r_idx = -1;
02661 }
02662 }
02663 if(__s.flags & SIMPLIFY_0_IS_CONST)
02664 {
02665 double help =
02666 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER ? __s.m.nn() :
02667 __s.m.nd();
02668 help *= r.coeffs[n-ndel];
02669 if(r.params.i()[n-ndel].contains(help))
02670 {
02671 r.params.i().erase(r.params.i().begin()+n-ndel);
02672 {
02673 model::walker _node = __mod->node(__s.nnum);
02674 if(_node->n_parents == 1)
02675 delnodes_insert(__s.nnum);
02676 else
02677 {
02678 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02679 _node->n_parents--;
02680 }
02681 }
02682 ndel++;
02683 }
02684 }
02685 else if(__s.flags & SIMPLIFY_0_IS_PROD &&
02686 __s.flags & SIMPLIFY_0_PROD_IS_SIMPLE)
02687 {
02688 r.coeffs[n-ndel] *= __s.m.nd();
02689 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02690 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02691 else
02692 {
02693 model::walker _node = __mod->node(__s.nnum);
02694 if(_node->n_parents == 1)
02695 delnodes_insert(__s.nnum);
02696 else
02697 {
02698 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02699 _node->n_parents--;
02700 }
02701 }
02702 }
02703 else if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02704 {
02705 r.coeffs[n-ndel] *= __s.m.nd();
02706 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02707 __mod->node(__s.nnum)->params = 1.;
02708 }
02709 else if(__s.flags & SIMPLIFY_0_IS_SUM &&
02710 __s.flags & SIMPLIFY_0_SUM_IS_SIMPLE)
02711 {
02712 double help = r.coeffs[n-ndel]*__s.m.nd();
02713 r.params.i()[n-ndel] -= help;
02714 r.coeffs[n-ndel] *= (*__s.transfer)[0];
02715 if(__s.flags & SIMPLIFY_0_IS_GHOST)
02716 trans_ghosts.push_back(std::make_pair(__s.nnum, r.node_num));
02717 else
02718 {
02719 model::walker _node = __mod->node(__s.nnum);
02720 if(_node->n_parents == 1)
02721 delnodes_insert(__s.nnum);
02722 else
02723 {
02724 trans_edges.push_back(std::make_triple(__s.nnum, r.node_num, n));
02725 _node->n_parents--;
02726 }
02727 }
02728 }
02729 if(r.coeffs[n-ndel] != 1)
02730 {
02731 r.params.i()[n-ndel] /= r.coeffs[n-ndel];
02732 r.coeffs[n-ndel] = 1.;
02733 }
02734 break;
02735 case EXPRINFO_POLY:
02736 case EXPRINFO_IF:
02737 case EXPRINFO_AND:
02738 case EXPRINFO_OR:
02739 case EXPRINFO_NOT:
02740 case EXPRINFO_IMPLIES:
02741 case EXPRINFO_COUNT:
02742 case EXPRINFO_ALLDIFF:
02743 case EXPRINFO_LEVEL:
02744 case EXPRINFO_NEIGHBOR:
02745 case EXPRINFO_NOGOOD:
02746 if(__s.flags & SIMPLIFY_0_IS_MULTIPLICATIVE)
02747 {
02748 r.coeffs[n] *= __s.m.nd();
02749 if(!(__s.flags & SIMPLIFY_0_IS_CORRECTEDMULT))
02750 __mod->node(__s.nnum)->params = 1.;
02751 }
02752 break;
02753 case EXPRINFO_EXPECTATION:
02754 case EXPRINFO_INTEGRAL:
02755 throw nyi_exception("simplify_visitor_0: Integral Operations");
02756 break;
02757 case EXPRINFO_LOOKUP:
02758 case EXPRINFO_PWLIN:
02759 case EXPRINFO_SPLINE:
02760 case EXPRINFO_PWCONSTLC:
02761 case EXPRINFO_PWCONSTRC:
02762 throw nyi_exception("simplify_visitor_0: Table Operations");
02763 break;
02764 case EXPRINFO_DET:
02765 case EXPRINFO_COND:
02766 case EXPRINFO_PSD:
02767 case EXPRINFO_MPROD:
02768 case EXPRINFO_FEM:
02769 throw nyi_exception("simplify_visitor_0: Matrix Operations");
02770 break;
02771 case EXPRINFO_RE:
02772 case EXPRINFO_IM:
02773 case EXPRINFO_ARG:
02774 case EXPRINFO_CPLXCONJ:
02775 throw nyi_exception("simplify_visitor_0: Complex Operations");
02776 break;
02777 case EXPRINFO_CMPROD:
02778 case EXPRINFO_CGFEM:
02779 throw nyi_exception("simplify_visitor_0: Const Matrix Operations");
02780 break;
02781 case EXPRINFO_LIN:
02782 break;
02783 case EXPRINFO_QUAD:
02784 break;
02785 default:
02786 if(!__mod->has_read_errors)
02787 throw api_exception(apiee_internal,
02788 std::string("simplify_visitor_0: unknown function type ")+
02789 convert_to_str(r.operator_type));
02790 break;
02791 }
02792 }
02793 else if(r.operator_type > 0)
02794 {
02795 ;
02796 }
02797 n++;
02798 v_i.set_all(__s.v_i);
02799 l_nnum = __s.nnum;
02800 l_flags = __s.flags;
02801 l_s = __s.s;
02802 }
02803
02804 bool model::simplify_visitor_m::postorder(expression_node &r)
02805 {
02806 if(!(*visited)[r.node_num] && r_idx != -1)
02807 {
02808 int ne_del = n-ndel-r_idx-1;
02809 r.coeffs.erase(r.coeffs.begin()+r_idx+1,
02810 r.coeffs.end());
02811 ndel += ne_del;
02812 r_idx = -1;
02813 }
02814 postorder_help(r, n-ndel);
02815 if(!(*visited)[r.node_num])
02816 {
02817 (*visited)[r.node_num] = true;
02818
02819 if(r.sem.convexity().t() == 0)
02820 r.sem.convexity(s.convexity());
02821 r.sem.separability(s.separability());
02822 r.sem.degree = s.degree;
02823 r.sem.dim = s.dim;
02824
02825 r.v_i = v_i;
02826 if(r.operator_type == EXPRINFO_CONSTANT ||
02827 r.operator_type == EXPRINFO_VARIABLE ||
02828 r.operator_type == EXPRINFO_GHOST)
02829 r.n_children = 0;
02830 else
02831 r.n_children = n - ndel;
02832 }
02833 return false;
02834 }
02835
02836 void model::simplify_visitor_m::collect(expression_node &r,
02837 const simplify_visitor_m& __s)
02838 {
02839 nnum = r.node_num;
02840 if(r.operator_type < 0)
02841 {
02842 switch(r.operator_type)
02843 {
02844 case EXPRINFO_CONSTANT:
02845 case EXPRINFO_VARIABLE:
02846 case EXPRINFO_GHOST:
02847
02848 break;
02849 case EXPRINFO_SUM:
02850 if(n == 0)
02851 {
02852 s.degree = __s.s.degree;
02853 s.property_flags = __s.s.property_flags;
02854 if(r.coeffs[0] < 0)
02855 s.property_flags.c_info == -s.property_flags.c_info;
02856 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
02857 is_integer(r.params.nd()))
02858 s.annotation_flags.integer = true;
02859 r_idx = -1;
02860 }
02861 else
02862 {
02863 if(s.degree == -1 || __s.s.degree == -1)
02864 s.degree = -1;
02865 else if(__s.s.degree > s.degree)
02866 s.degree = __s.s.degree;
02867 s.property_flags.c_info = convex_e();
02868 if(s.property_flags.separable != t_true ||
02869 __s.s.property_flags.separable != t_true)
02870 s.property_flags.separable = t_maybe;
02871 if(s.annotation_flags.integer &&
02872 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02873 s.annotation_flags.integer = false;
02874 }
02875 break;
02876 case EXPRINFO_MEAN:
02877 if(n == 0)
02878 {
02879 s.degree = __s.s.degree;
02880 s.property_flags = __s.s.property_flags;
02881 if(r.coeffs[0] < 0)
02882 {
02883 r.operator_type = EXPRINFO_SUM;
02884 s.property_flags.c_info == -s.property_flags.c_info;
02885 }
02886 r_idx = -1;
02887 }
02888 else
02889 {
02890 if(s.degree == -1 || __s.s.degree == -1)
02891 s.degree = -1;
02892 else if(__s.s.degree > s.degree)
02893 s.degree = __s.s.degree;
02894 s.property_flags.c_info = convex_e();
02895 if(s.property_flags.separable != t_true ||
02896 __s.s.property_flags.separable != t_true)
02897 s.property_flags.separable = t_maybe;
02898 }
02899 break;
02900 case EXPRINFO_PROD:
02901 if(n == 0)
02902 {
02903 s.degree = __s.s.degree;
02904 s.property_flags = __s.s.property_flags;
02905 m = 1.;
02906 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
02907 is_integer(r.params.nd()))
02908 s.annotation_flags.integer = true;
02909 }
02910 else
02911 {
02912 if(__s.s.degree == -1 || s.degree == -1)
02913 s.degree = -1;
02914 else
02915 s.degree += __s.s.degree;
02916 s.property_flags.c_info = convex_e();
02917 s.property_flags.separable = t_maybe;
02918 if(s.annotation_flags.integer &&
02919 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02920 s.annotation_flags.integer = false;
02921 }
02922 break;
02923 case EXPRINFO_MONOME:
02924 if(n == 0)
02925 {
02926 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.n()[0];
02927 s.property_flags = __s.s.property_flags;
02928 s.property_flags.c_info = convex_e();
02929 m = 1.;
02930 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
02931 s.annotation_flags.integer = true;
02932 }
02933 else
02934 {
02935 if(__s.s.degree == -1 || s.degree == -1)
02936 s.degree = -1;
02937 else
02938 s.degree += __s.s.degree*r.params.n()[n];
02939 s.property_flags.c_info = convex_e();
02940 s.property_flags.separable = t_maybe;
02941 if(s.annotation_flags.integer &&
02942 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02943 s.annotation_flags.integer = false;
02944 }
02945 break;
02946 case EXPRINFO_MAX:
02947 case EXPRINFO_MIN:
02948 if(n == 0)
02949 {
02950 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
02951 is_integer(r.params.nd()))
02952 s.annotation_flags.integer = true;
02953 }
02954 else if(s.annotation_flags.integer &&
02955 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02956 s.annotation_flags.integer = false;
02957 break;
02958 case EXPRINFO_SCPROD:
02959 if(n == 0)
02960 {
02961 s.property_flags.c_info = convex_e();
02962 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
02963 s.annotation_flags.integer = true;
02964 }
02965 else if(n & 1)
02966 {
02967 r.coeffs[n-1] *= r.coeffs[n];
02968 r.coeffs[n] = 1.;
02969 if(s.degree == -1 || __s.s.degree == -1 || l_s.degree == -1)
02970 s.degree = -1;
02971 else if(__s.s.degree+l_s.degree > s.degree)
02972 s.degree = __s.s.degree+l_s.degree;
02973 s.property_flags.separable = t_maybe;
02974 if(s.annotation_flags.integer &&
02975 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n-1])))
02976 s.annotation_flags.integer = false;
02977 }
02978 else
02979 {
02980 if(s.annotation_flags.integer &&
02981 !(__s.s.annotation_flags.integer && is_integer(r.coeffs[n])))
02982 s.annotation_flags.integer = false;
02983 }
02984 break;
02985 case EXPRINFO_NORM:
02986 if(n == 0)
02987 {
02988 s.degree = -1;
02989 s.property_flags = __s.s.property_flags;
02990 s.property_flags.c_info = convex_e();
02991 s.annotation_flags.integer = false;
02992 }
02993 else
02994 {
02995 if(s.property_flags.separable != t_true ||
02996 __s.s.property_flags.separable != t_true)
02997 s.property_flags.separable = t_maybe;
02998 }
02999 break;
03000 case EXPRINFO_POW:
03001 {
03002 bool spupd = false;
03003 if(n != 0 && r.params.nd() == 0 &&
03004 __s.flags & SIMPLIFY_0_IS_CONST &&
03005 __s.flags & SIMPLIFY_0_CONST_IS_INTEGER)
03006 {
03007 double help = __s.m.nn()*r.coeffs[n];
03008 r.coeffs[n] = 1.;
03009 long int helpl = lrint(help);
03010 if(helpl - help == 0 && helpl < MAXINT && helpl > -MAXINT)
03011 {
03012 switch(helpl)
03013 {
03014 #if 0
03015
03016 case 0:
03017 r.operator_type = EXPRINFO_CONSTANT;
03018 r.params = 1.;
03019 r.coeffs.erase(r.coeffs.begin(),r.coeffs.end());
03020 delnodes_insert(__s.nnum);
03021 s.degree = 0;
03022 ndel++;
03023 break;
03024 case 1:
03025 delnodes_insert(__s.nnum);
03026 delnodes_insert(r.node_num);
03027 break;
03028 #endif
03029 case 2:
03030 r.operator_type = EXPRINFO_SQUARE;
03031 delnodes_insert(__s.nnum);
03032 s.degree = s.degree == -1 ? -1 : s.degree*2;
03033 r.coeffs.pop_back();
03034 ndel++;
03035 spupd = true;
03036 break;
03037 case -1:
03038 r.params = r.coeffs[0];
03039 r.coeffs[0] = 1.;
03040 r.operator_type = EXPRINFO_INVERT;
03041 delnodes_insert(__s.nnum);
03042 s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
03043 flags = SIMPLIFY_0_IS_MULTIPLICATIVE;
03044 r.coeffs.pop_back();
03045 ndel++;
03046 break;
03047 default:
03048 r.params = (int) helpl;
03049 r.operator_type = EXPRINFO_INTPOWER;
03050 delnodes_insert(__s.nnum);
03051 s.degree = s.degree == -1 ? -1 : s.degree*__s.m.nn();
03052 r.coeffs.pop_back();
03053 ndel++;
03054 break;
03055 }
03056 }
03057
03058
03059 }
03060
03061
03062 s.property_flags.c_info = convex_e();
03063 s.property_flags.separable = t_maybe;
03064 }
03065 break;
03066 case EXPRINFO_SQUARE:
03067 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*2;
03068 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
03069 is_integer(r.params.nd()))
03070 s.annotation_flags.integer = true;
03071 break;
03072 case EXPRINFO_SQROOT:
03073 break;
03074 case EXPRINFO_ABS:
03075 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]) &&
03076 is_integer(r.params.nd()))
03077 s.annotation_flags.integer = true;
03078 break;
03079 case EXPRINFO_EXP:
03080 case EXPRINFO_LOG:
03081 case EXPRINFO_SIN:
03082 case EXPRINFO_COS:
03083 case EXPRINFO_ATAN2:
03084 case EXPRINFO_GAUSS:
03085 case EXPRINFO_INVERT:
03086 case EXPRINFO_DIV:
03087 break;
03088 case EXPRINFO_INTPOWER:
03089 if(r.params.nn() > 0)
03090 s.degree = __s.s.degree == -1 ? -1 : __s.s.degree*r.params.nn();
03091 else
03092 s.degree = -1;
03093 if(__s.s.annotation_flags.integer && is_integer(r.coeffs[0]))
03094 s.annotation_flags.integer = true;
03095 break;
03096 case EXPRINFO_IN:
03097 case EXPRINFO_POLY:
03098 case EXPRINFO_IF:
03099 case EXPRINFO_AND:
03100 case EXPRINFO_OR:
03101 case EXPRINFO_NOT:
03102 case EXPRINFO_IMPLIES:
03103 case EXPRINFO_COUNT:
03104 case EXPRINFO_ALLDIFF:
03105 case EXPRINFO_LEVEL:
03106 case EXPRINFO_NEIGHBOR:
03107 case EXPRINFO_NOGOOD:
03108 break;
03109 case EXPRINFO_EXPECTATION:
03110 case EXPRINFO_INTEGRAL:
03111 throw nyi_exception("simplify_visitor_m: Integral Operations");
03112 break;
03113 case EXPRINFO_LOOKUP:
03114 case EXPRINFO_PWLIN:
03115 case EXPRINFO_SPLINE:
03116 case EXPRINFO_PWCONSTLC:
03117 case EXPRINFO_PWCONSTRC:
03118 throw nyi_exception("simplify_visitor_m: Table Operations");
03119 break;
03120 case EXPRINFO_DET:
03121 case EXPRINFO_COND:
03122 case EXPRINFO_PSD:
03123 case EXPRINFO_MPROD:
03124 case EXPRINFO_FEM:
03125 throw nyi_exception("simplify_visitor_m: Matrix Operations");
03126 break;
03127 case EXPRINFO_RE:
03128 case EXPRINFO_IM:
03129 case EXPRINFO_ARG:
03130 case EXPRINFO_CPLXCONJ:
03131 throw nyi_exception("simplify_visitor_m: Complex Operations");
03132 break;
03133 case EXPRINFO_CMPROD:
03134 case EXPRINFO_CGFEM:
03135 throw nyi_exception("simplify_visitor_m: Const Matrix Operations");
03136 break;
03137 case EXPRINFO_LIN:
03138 break;
03139 case EXPRINFO_QUAD:
03140 break;
03141 default:
03142 throw api_exception(apiee_internal,
03143 std::string("simplify_visitor_m: unknown function type ")+
03144 convert_to_str(r.operator_type));
03145 break;
03146 }
03147 }
03148 else if(r.operator_type > 0)
03149 {
03150 ;
03151 }
03152 n++;
03153 v_i.set_all(__s.v_i);
03154 l_nnum = __s.nnum;
03155 l_flags = __s.flags;
03156 l_s = __s.s;
03157 }
03158
03159 void model::del_nodes_and_edges(const std::vector<unsigned int>& delnodes,
03160 const std::vector<std::pair<unsigned int,unsigned int> >& deledges,
03161 const std::vector<unsigned int>& delghosts)
03162 {
03163 for(std::vector<std::pair<unsigned int,unsigned int> >::const_iterator b =
03164 deledges.begin(); b != deledges.end(); ++b)
03165 remove_edge(node((*b).first), node((*b).second));
03166 for(std::vector<unsigned int>::const_iterator b = delnodes.begin();
03167 b != delnodes.end(); ++b)
03168 remove_node(*b);
03169 for(std::vector<unsigned int>::const_iterator b = delghosts.begin();
03170 b != delghosts.end(); ++b)
03171 remove_node(ghost(*b), *b);
03172 }
03173
03174 bool model::micro_simplify()
03175 {
03176 bool result = false;
03177 std::vector<unsigned int> delnodes;
03178 std::vector<std::pair<unsigned int,unsigned int> > deledges;
03179 std::vector<bool> visited(gid->number_of_nodes(), false);
03180 simplify_visitor_m w(gid->number_of_variables(), &delnodes, &deledges,
03181 &visited, this);
03182
03183 recursive_walk_if(ground(), w);
03184 result = !delnodes.empty() || !deledges.empty();
03185 if(result)
03186 del_nodes_and_edges(delnodes, deledges, std::vector<unsigned int>());
03187 set_counters();
03188 return result;
03189 }
03190
03191 bool model::basic_simplify_0()
03192 {
03193 std::vector<unsigned int> delnodes;
03194 std::vector<unsigned int> delghosts;
03195 std::vector<std::pair<unsigned int,unsigned int> > deledges;
03196 std::vector<bool> visited(gid->number_of_nodes(), false);
03197 simplify_visitor_0 w(gid->number_of_variables(), &delnodes, &delghosts,
03198 &deledges, &visited, this);
03199 bool result = false;
03200
03201 recursive_safe_walk_if(ground(), w);
03202 result = !delnodes.empty() || !deledges.empty();
03203 if(result)
03204 del_nodes_and_edges(delnodes, deledges, delghosts);
03205 return result;
03206 }
03207
03208 bool model::basic_simplify_1_merge(walker __s, std::list<walker>& _todo,
03209 std::vector<int>& _combined,
03210 std::vector<bool>& _fld,
03211 std::vector<int>& _sorted)
03212 {
03213 std::map<unsigned int,walker> dew;
03214 walker _ew, _fw;
03215 parents_iterator _p, _q;
03216 bool result = false;
03217 unsigned int snn = __s == sky() ? number_of_nodes() : __s->node_num;
03218
03219 if(_sorted[snn] <= 0)
03220 {
03221 _sorted[snn] += 2;
03222 sort_parent_edges(__s, expression_node::parents_compare());
03223 }
03224 for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
03225 {
03226 _ew = __s << _p;
03227 if(_combined[_ew->node_num] != (int)_ew->n_children)
03228 continue;
03229 if(std::abs(_sorted[_ew->node_num]) != 1)
03230 {
03231 _sorted[_ew->node_num]--;
03232 if(_ew->operator_type == EXPRINFO_SUM ||
03233 _ew->operator_type == EXPRINFO_PROD ||
03234 _ew->operator_type == EXPRINFO_MAX ||
03235 _ew->operator_type == EXPRINFO_MIN ||
03236 _ew->operator_type == EXPRINFO_MONOME ||
03237 _ew->operator_type == EXPRINFO_NORM ||
03238 _ew->operator_type == EXPRINFO_MEAN)
03239 {
03240
03241
03242
03243 std::map<std::pair<unsigned int, unsigned int>,
03244 std::pair<double, int> > __nr_c_ref;
03245 std::map<std::pair<unsigned int, unsigned int>,
03246 std::pair<double, int> >::iterator __f;
03247 children_iterator _c;
03248 int n;
03249
03250 for(_c = _ew.child_begin(), n=0; _c != _ew.child_end(); ++_c, ++n)
03251 {
03252 unsigned int cnn = (_ew >> _c)->node_num, _h;
03253 for(_h = 0; ; _h++)
03254 {
03255 __f = __nr_c_ref.find(std::make_pair(cnn, _h));
03256 if(__f == __nr_c_ref.end())
03257 break;
03258 }
03259 if(_ew->operator_type == EXPRINFO_MONOME)
03260 __nr_c_ref.insert(std::make_pair(std::make_pair(cnn, _h),
03261 std::make_pair(_ew->coeffs[n],_ew->params.n()[n])));
03262 else
03263 __nr_c_ref.insert(std::make_pair(std::make_pair(cnn, _h),
03264 std::make_pair(_ew->coeffs[n],0)));
03265 }
03266 sort_child_edges(_ew, expression_node::children_compare());
03267 for(_c = _ew.child_begin(), n=0; _c != _ew.child_end(); ++_c, ++n)
03268 {
03269 unsigned int cnn = (_ew >> _c)->node_num, _h;
03270
03271 for(_h = 0; ; _h++)
03272 {
03273 __f = __nr_c_ref.find(std::make_pair(cnn, _h));
03274 #if 0
03275 if(__f == __nr_c_ref.end())
03276 {
03277 std::cerr << "FATAL Error: This can't happen ;) in basic_simplify_1_merge"
03278 << std::endl;
03279 exit(-42);
03280 }
03281 #endif
03282 if(__f != __nr_c_ref.end())
03283 break;
03284 }
03285 _ew->coeffs[n] = __f->second.first;
03286 if(_ew->operator_type == EXPRINFO_MONOME)
03287 _ew->params.n()[n] = __f->second.second;
03288 __nr_c_ref.erase(__f);
03289 }
03290 }
03291 }
03292 }
03293 for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
03294 {
03295 _ew = __s << _p;
03296 if(_combined[_ew->node_num] == (int)_ew->n_children)
03297 break;
03298 }
03299 while(_p != __s.parent_end())
03300 {
03301 for(_q = __s.parent_begin(); _q != __s.parent_end(); ++_q)
03302 {
03303 _ew = __s << _q;
03304 if(_combined[_ew->node_num] == (int)_ew->n_children)
03305 break;
03306 }
03307 for(++_p; _p != __s.parent_end(); ++_p)
03308 {
03309 _fw = __s << _p;
03310 if(_combined[_fw->node_num] != (int)_fw->n_children)
03311 continue;
03312 if(_ew.node() == _fw.node())
03313 {
03314 _q = _p;
03315 _ew = __s << _q;
03316 continue;
03317 }
03318 if(expression_node::parents_compare_eq()(*_ew, *_fw) &&
03319 children_eq(_ew, _fw))
03320
03321 dew[_fw->node_num] = _fw;
03322 else
03323 {
03324 if(!dew.empty())
03325
03326 break;
03327 else
03328 {
03329
03330 if(!_fld[_ew->node_num])
03331 {
03332 _fld[_ew->node_num] = true;
03333 basic_simplify_1_flood(_ew, _combined);
03334 if(_ew->operator_type != EXPRINFO_CONSTANT)
03335 _todo.push_back(_ew);
03336 }
03337 _q = _p;
03338 _ew = __s << _q;
03339 }
03340 }
03341 }
03342 if(dew.empty())
03343 {
03344 if(!_fld[_ew->node_num])
03345 {
03346 _fld[_ew->node_num] = true;
03347 basic_simplify_1_flood(_ew, _combined);
03348 if(_ew->operator_type != EXPRINFO_CONSTANT)
03349 _todo.push_back(_ew);
03350 }
03351 break;
03352 }
03353
03354
03355 for(std::map<unsigned int,walker>::iterator _b = dew.begin();
03356 _b != dew.end(); ++_b)
03357 {
03358 walker _bw((*_b).second);
03359 std::list<walker>::iterator _hlp;
03360
03361 free_node_num(_bw->node_num);
03362
03363 for(_hlp = _todo.begin(); _hlp != _todo.end(); ++_hlp)
03364 {
03365 if(*_hlp == _bw)
03366 {
03367 _todo.erase(_hlp);
03368 break;
03369 }
03370 }
03371
03372 if(objective == _bw)
03373 objective = _ew;
03374
03375
03376 unsigned int cn;
03377 if(get_const_num(_bw->node_num, cn))
03378 {
03379 unsigned int cc;
03380 if(get_const_num(_ew->node_num, cc))
03381 {
03382 gid->unused_constr(const_name(cn));
03383 gid->remove_const_id(cn);
03384 }
03385 else
03386 {
03387
03388 gid->remove_const_ref(cn);
03389 gid->make_const_back_ref(_ew->node_num, cn);
03390 }
03391
03392
03393 for(std::vector<walker>::iterator __x = constraints.begin();
03394 __x != constraints.end(); ++__x)
03395 if(*__x == _bw)
03396 {
03397 constraints.erase(__x);
03398 break;
03399 }
03400 }
03401
03402 #if MODEL_INLINE_DEBUG_SIMPLIFY
03403 std::cerr << "Merging " << _ew->node_num << " and " <<
03404 (*_b).first << std::endl;
03405 #endif
03406 merge(_ew, _bw, false);
03407 result = true;
03408 }
03409 for(children_iterator _c = _ew.child_begin(); _c != _ew.child_end(); ++_c)
03410 {
03411 walker _wc = _ew >> _c;
03412 _wc->n_parents = _wc.n_parents();
03413 }
03414 _ew->n_parents = _ew.is_root() ? 0 : _ew.n_parents();
03415 dew.clear();
03416 if(_ew->operator_type == EXPRINFO_VARIABLE)
03417 store_variable(_ew);
03418 else if(_ew->operator_type == EXPRINFO_GHOST)
03419 store_ghost(_ew);
03420
03421
03422 if(!_fld[_ew->node_num])
03423 {
03424 _fld[_ew->node_num] = true;
03425 basic_simplify_1_flood(_ew, _combined);
03426 if(_ew->operator_type != EXPRINFO_CONSTANT)
03427 _todo.push_back(_ew);
03428 }
03429 for(_p = __s.parent_begin(); _p != __s.parent_end(); ++_p)
03430 {
03431 _fw = __s << _p;
03432 if(_combined[_fw->node_num] == (int)_fw->n_children)
03433 break;
03434 }
03435 }
03436 return result;
03437 }
03438
03439 bool model::basic_simplify_1()
03440 {
03441 std::vector<int> _combined(number_of_nodes(), 0);
03442 std::vector<bool> _fld(number_of_nodes(), false);
03443 std::vector<int> _sorted(number_of_nodes()+1, 0);
03444 std::list<walker> _todo(1, sky());
03445 std::list<walker>::iterator __xxcl, __help;
03446 bool result = false;
03447
03448 while(!_todo.empty())
03449 {
03450 for(__xxcl = _todo.begin(); __xxcl != _todo.end(); __xxcl = __help)
03451 {
03452 #if MODEL_INLINE_DEBUG_SIMPLIFY
03453 for(std::list<walker>::const_iterator __rr = _todo.begin();
03454 __rr != _todo.end(); ++__rr)
03455 std::cerr << (*__rr)->node_num << ", ";
03456 std::cerr << std::endl;
03457 #endif
03458 __help = __xxcl;
03459 ++__help;
03460 if((*__xxcl).is_ground()||(*__xxcl).is_root())
03461
03462 _todo.erase(__xxcl);
03463 else if((*__xxcl).is_sky() ||
03464 basic_simplify_1_is_ready(*__xxcl, _combined, false))
03465 {
03466 result = basic_simplify_1_merge(*__xxcl, _todo, _combined, _fld,
03467 _sorted) || result;
03468 if(basic_simplify_1_is_ready(*__xxcl, _combined, true))
03469
03470 _todo.erase(__xxcl);
03471 }
03472 }
03473 }
03474 return result;
03475 }
03476
03477 bool model::basic_simplify_2(std::set<std::pair<unsigned int, unsigned int> >&
03478 trf_gh_set, std::map<unsigned int, unsigned int>& gh_new_map)
03479 {
03480 bool ret(false);
03481 unsigned int n, ncoeffs, nn;
03482 std::vector<walker>::iterator _nrc, _nre;
03483 bool is_ghost(false);
03484 std::vector<walker> nodews;
03485 std::vector<walker> ghostws;
03486 std::vector<walker>::iterator nit, net;
03487 std::list<unsigned int> gnums;
03488
03489 _nre = node_ref.end();
03490 for(_nrc = node_ref.begin(); _nrc != _nre; ++_nrc)
03491 nodews.push_back(*_nrc);
03492 _nre = ghost_ref.end();
03493 for(_nrc = ghost_ref.begin(); _nrc != _nre; ++_nrc)
03494 ghostws.push_back(*_nrc);
03495
03496 do
03497 {
03498 bool gisroot;
03499
03500 net = is_ghost ? ghostws.end() : nodews.end();
03501 nit = is_ghost ? ghostws.begin() : nodews.begin();
03502 for(; nit != net; ++nit)
03503 {
03504 walker _g(*nit);
03505 nn = _g->node_num;
03506 gisroot = _g.is_root();
03507
03508 if(_g->f_bounds.is_thin() && (is_ghost || !gisroot))
03509 {
03510 std::list<walker> plist;
03511 parents_iterator _p;
03512 #if MODEL_INLINE_DEBUG_SIMPLIFY
03513 std::cerr << "Node " << nn << " has thin bounds: " <<
03514 _g->f_bounds.inf() << std::endl;
03515 #endif
03516 if(!gisroot)
03517 for(_p = _g.parent_begin(); _p != _g.parent_end(); ++_p)
03518 plist.push_back(_g << _p);
03519
03520 if(!plist.empty())
03521 {
03522 expression_node _en(EXPRINFO_CONSTANT, next_num());
03523 _en.v_i.reserve(number_of_variables());
03524 _en.v_i.clear();
03525 _en.params = _g->f_bounds.sup();
03526
03527 walker __r = between_back(ground(), sky(), _en);
03528 store_node(__r);
03529
03530 for(std::list<walker>::iterator _pwit = plist.begin();
03531 _pwit != plist.end(); ++_pwit)
03532 replace_edge_to_child(*_pwit, _g, __r);
03533
03534 ret = true;
03535 }
03536 if(is_ghost)
03537 {
03538 walker _n = node(nn);
03539
03540 for(_p = _n.parent_begin(); _p != _n.parent_end(); ++_p)
03541 {
03542 walker _pw(_n << _p), __r;
03543 unsigned int _pwnum(_pw->node_num);
03544
03545 ref_iterator __x;
03546 __x = lower_bound(ghost_ref.begin(), ghost_ref.end(), _pwnum,
03547 __docompare_nodes());
03548 if(__x != ghost_ref.end() && (*__x)->node_num == _pwnum)
03549 {
03550 std::set<std::pair<unsigned int, unsigned int> >::iterator gsi;
03551 gsi = trf_gh_set.find(std::make_pair(nn, _pwnum));
03552 if(gsi == trf_gh_set.end())
03553 {
03554 walker _rgh(*__x);
03555 #if MODEL_INLINE_DEBUG_SIMPLIFY
03556 std::cerr << "Need to shift ghost number " << _pwnum <<
03557 " because of ghost number " << nn << std::endl;
03558 std::cerr << "f_bounds are " << _rgh->f_bounds << std::endl;
03559 #endif
03560 trf_gh_set.insert(std::make_pair(nn, _pwnum));
03561
03562 expression_node _en(*_pw);
03563 _en.node_num = next_num();
03564 if(_rgh->f_bounds.is_entire())
03565 gnums.push_back(_pwnum);
03566 else
03567 _en.f_bounds.intersectwith(_rgh->f_bounds);
03568 __r = between_back(ground(), sky(), _en);
03569 store_node(__r);
03570 if(!_en.f_bounds.is_entire())
03571 store_constraint(__r);
03572 ret = true;
03573
03574 children_iterator _pwc;
03575 for(_pwc = _pw.child_begin(); _pwc != _pw.child_end(); ++_pwc)
03576 {
03577 walker _pwcw(_pw >> _pwc);
03578 walker _gh;
03579 if(_pwcw->node_num != nn)
03580 {
03581 std::map<unsigned int, unsigned int>::iterator gmi;
03582 gmi = gh_new_map.find(_pwcw->node_num);
03583 if(gmi != gh_new_map.end())
03584 {
03585 unsigned int rpnn((*gmi).second);
03586 ref_iterator __x2;
03587 __x2 = lower_bound(node_ref.begin(), node_ref.end(), rpnn,
03588 __docompare_nodes());
03589 if(__x2 != node_ref.end() && (*__x2)->node_num == rpnn)
03590 _gh = *__x2;
03591 else
03592 {
03593 _gh = ghost(_pwcw->node_num);
03594 gh_new_map.erase(gmi);
03595 }
03596 }
03597 else
03598 _gh = ghost(_pwcw->node_num);
03599 }
03600 else
03601 {
03602 expression_node _en(EXPRINFO_CONSTANT, next_num());
03603 _en.v_i.reserve(number_of_variables());
03604 _en.v_i.clear();
03605 _en.params = _g->f_bounds.sup();
03606 _gh = between_back(ground(), sky(), _en);
03607 store_node(_gh);
03608 }
03609 add_edge_back(__r, _gh);
03610 }
03611
03612 gh_new_map[_pwnum] = __r->node_num;
03613 parents_iterator _rghp;
03614 std::list<walker> _rghplist;
03615 for(_rghp = _rgh.parent_begin(); _rghp != _rgh.parent_end();
03616 ++_rghp)
03617 {
03618 walker _rghpw(_rgh << _rghp);
03619 _rghplist.push_back(_rghpw);
03620 }
03621 for(std::list<walker>::iterator _rghpi = _rghplist.begin();
03622 _rghpi != _rghplist.end(); ++_rghpi)
03623 replace_edge_to_child(*_rghpi, _rgh, __r);
03624 #if 0
03625 expression_node _en(EXPRINFO_CONSTANT, next_num());
03626 _en.v_i.reserve(number_of_variables());
03627 _en.v_i.clear();
03628 _en.params = _n->f_bounds.sup();
03629 __r = between_back(ground(), sky(), _en);
03630 replace_edge_to_child(_pw, _g, __r);
03631 store_node(__r);
03632 #endif
03633 }
03634 }
03635 }
03636 }
03637 }
03638 else if(!is_ghost)
03639 {
03640 std::list<walker> deledges;
03641 std::list<walker> delnodes;
03642 unsigned int ndel(0);
03643
03644 if((_g->operator_type == EXPRINFO_SUM ||
03645 _g->operator_type == EXPRINFO_MEAN ||
03646 _g->operator_type == EXPRINFO_PROD)
03647 && _g->n_children == 1)
03648 {
03649 children_iterator __c(_g.child_begin());
03650 walker _chl(_g >> __c);
03651
03652 if(_chl->n_children == 1 &&
03653 (_chl->operator_type == EXPRINFO_SUM ||
03654 _chl->operator_type == EXPRINFO_MEAN ||
03655 _chl->operator_type == EXPRINFO_PROD))
03656 ret = true;
03657 if((_chl->operator_type == EXPRINFO_CONSTANT ||
03658 _chl->operator_type == EXPRINFO_VARIABLE) && _g.is_root())
03659 ret = true;
03660 }
03661 ncoeffs = _g->coeffs.size();
03662 for(n=0; n<ncoeffs-ndel;)
03663 {
03664 if(_g->coeffs[n] == 0)
03665 {
03666 #if MODEL_INLINE_DEBUG_SIMPLIFY
03667 std::cerr << "Node " << nn << " has " << n <<
03668 "th coefficient 0!"
03669 << std::endl;
03670 #endif
03671 children_iterator __c(_g.child_begin()+n);
03672 walker _chl(_g >> __c);
03673 #if MODEL_INLINE_DEBUG_SIMPLIFY
03674 std::cerr << "Edge from " << _chl->node_num << " to " <<
03675 nn << " needs to be removed!" << std::endl;
03676 #endif
03677 deledges.push_back(_chl);
03678 _g->coeffs[n] = 1;
03679 }
03680 else
03681 ++n;
03682 }
03683 if(!deledges.empty())
03684 {
03685 expression_node _en(EXPRINFO_CONSTANT, next_num());
03686 _en.v_i.reserve(number_of_variables());
03687 _en.v_i.clear();
03688 _en.params = 0.;
03689 walker __r = between_back(ground(), sky(), _en);
03690 store_node(__r);
03691
03692 for(std::list<walker>::iterator de = deledges.begin();
03693 de != deledges.end(); ++de)
03694 replace_edge_to_child(_g, *de, __r);
03695 ret = true;
03696 }
03697 }
03698 }
03699 is_ghost = !is_ghost;
03700 } while(is_ghost);
03702 for(std::list<unsigned int>::iterator _glit = gnums.begin();
03703 _glit != gnums.end(); ++_glit)
03704 remove_node(ghost(*_glit), *_glit);
03705
03706 return ret;
03707 }
03708
03709 void model::prepare_after_read()
03710 {
03711 walker _w;
03712 unsigned int cnum;
03713
03714 compress_numbers();
03715 for(ref_iterator _x = node_ref.begin(); _x != node_ref.end(); ++_x)
03716 {
03717 _w = *_x;
03718 if(_w->f_bounds.inf() != -COCO_INF || _w->f_bounds.sup() != COCO_INF)
03719 {
03720 constraints.insert(constraints.end(), _w);
03721 if(!gid->get_const_num(_w->node_num, cnum))
03722 cnum = next_constraint_num();
03723 gid->mk_gconstref(cnum, _w);
03724 }
03725 }
03726
03727 arrange_constraints();
03728 }
03729
03730 bool model::basic_simplify()
03731 {
03732 bool have_simplified = false, first = true;
03733 int have_simp;
03734 std::set<std::pair<unsigned int, unsigned int> > trf_gh_set;
03735 std::map<unsigned int, unsigned int> gh_new_map;
03736
03737 have_simp = 7;
03738
03739 do
03740 {
03741 check_counters(true);
03742 have_simp &= ~1;
03743 #if MODEL_INLINE_DEBUG_SIMPLIFY
03744 std::cerr << "Before basic_simplify_0: " << std::endl;
03745 gid->print_const_back_ref();
03746 write();
03747 #endif
03748 if((first || have_simp) && basic_simplify_0())
03749 have_simp |= 1;
03750 check_counters(true);
03751 #if MODEL_INLINE_DEBUG_SIMPLIFY
03752 #if DEBUG_EXPRESSIONS
03753 consistency_test(*this);
03754 #endif
03755 std::cerr << "After basic_simplify_0, before basic_simplify_1: " << std::endl;
03756 gid->print_const_back_ref();
03757 write();
03758 #endif
03759 have_simp &= ~2;
03760 if((first || have_simp) && basic_simplify_1())
03761 have_simp |= 2;
03762 #if MODEL_INLINE_DEBUG_SIMPLIFY
03763 check_counters(false);
03764 #if DEBUG_EXPRESSIONS
03765 consistency_test(*this);
03766 #endif
03767 std::cerr << "After basic_simplify_1, before basic_simplify_2: " << std::endl;
03768 gid->print_const_back_ref();
03769 write();
03770 #endif
03771 have_simp &= ~4;
03772 if((first || have_simp) && basic_simplify_2(trf_gh_set, gh_new_map))
03773 have_simp |= 4;
03774 #if MODEL_INLINE_DEBUG_SIMPLIFY
03775 check_counters(false);
03776 #if DEBUG_EXPRESSIONS
03777 consistency_test(*this);
03778 #endif
03779 std::cerr << "After basic_simplify_2: " << std::endl;
03780 gid->print_const_back_ref();
03781 write();
03782 #endif
03783 have_simplified = have_simplified || (have_simp != 0);
03784 first = false;
03785 } while(have_simp != 0);
03786
03787 #if MODEL_INLINE_DEBUG_SIMPLIFY
03788 check_counters(false);
03789 #endif
03790 #if MODEL_INLINE_DEBUG_SIMPLIFY
03791 std::cerr << "After basic_simplify: " << std::endl;
03792 gid->print_const_back_ref();
03793 write();
03794 #endif
03795 return have_simplified;
03796 }
03797
03798 void model::write(std::ostream &o) const
03799 {
03800 std::vector<bool> _nprinted(number_of_nodes(), false);
03801 expression_print_visitor p(_nprinted, o);
03802 int precsave = o.precision(18);
03803
03804 if(model_name() != "%model")
03805 o << "<N> m '" << model_name() << '\'' << std::endl;
03806 o << "<N> V " << gid->number_of_variables() << std::endl;
03807 for(children_iterator b = ground().child_begin(); b != ground().child_end();
03808 b++)
03809 {
03810 recursive_preorder_walk_if(ground() >> b, p);
03811 }
03812 o << "<N> M ";
03813 if((const_walker) objective != ground())
03814 o << objective->node_num;
03815 else
03816 o << '0';
03817 o << ' ';
03818 if(ocoeff == -1)
03819 o << "max";
03820 else if(ocoeff == 1)
03821 o << "min";
03822 else
03823 o << "m00";
03824 o << std::endl;
03825
03826 for(unsigned int i=0; i < number_of_variables(); ++i)
03827 o << "<N> N " << i << " '" << gid->var_name(i) << "'" << std::endl;
03828 for(unsigned int i=0; i < gid->n_fixed_vars(); ++i)
03829 o << "<N> F '" << gid->fixed_var(i).first << "' "
03830 << gid->fixed_var(i).second << std::endl;
03831 for(unsigned int i=0; i < gid->n_unused_vars(); ++i)
03832 o << "<N> U '" << gid->unused_var(i) << "'" << std::endl;
03833 for(unsigned int i=0; i < gid->n_unused_constrs(); ++i)
03834 o << "<N> S '" << gid->unused_constr(i) << "'" << std::endl;
03835 for(std::vector<walker>::const_iterator __b = constraints.begin();
03836 __b != constraints.end(); ++__b)
03837 {
03838 unsigned int cn;
03839 if(!gid->get_const_num((*__b)->node_num, cn))
03840 {
03841 throw api_exception(apiee_internal,
03842 std::string("FATAL in write: Could not get constraint number for node ")+
03843 convert_to_str((*__b)->node_num));
03844 }
03845 o << "<N> c " << cn << " " << (*__b)->node_num << std::endl;
03846 o << "<N> C " << cn << " '" << const_name(cn) << "'" << std::endl;
03847 }
03848 #if 0
03849 for(unsigned int i=0; i < gid->number_of_constraints(); ++i)
03850 {
03851 if(constraint(i) == (const walker&) ground()) continue;
03852 o << "<N> c " << i << " " << constraint(i)->node_num << std::endl;
03853 o << "<N> C " << i << " '" << const_name(i) << "'" << std::endl;
03854 }
03855 #endif
03856 if(ocoeff != 0 || gid->obj_adj() != 0)
03857 {
03858 if(ocoeff == 0) gid->obj_mult(1);
03859 o << "<N> O '" << gid->obj_name() << "'";
03860 if(gid->obj_adj() != 0 || gid->obj_mult() != 1)
03861 o << ": d " << gid->obj_adj();
03862 if(gid->obj_mult() != 1)
03863 o << ", " << gid->obj_mult();
03864 o << std::endl;
03865 }
03866 for(std::map<int, std::vector<double> >::const_iterator __x =
03867 gid->trace_points().begin(); __x != gid->trace_points().end(); ++__x)
03868 {
03869 const std::vector<double>& pt((*__x).second);
03870 o << "<H> t " << (*__x).first << ' ' << pt << std::endl;
03871 }
03872 for(std::map<int, std::vector<double> >::const_iterator __x =
03873 gid->optima().begin(); __x != gid->optima().end(); ++__x)
03874 {
03875 const std::vector<double>& pt((*__x).second);
03876 o << "<H> o " << (*__x).first << ' ' << pt << std::endl;
03877 }
03878 o.precision(precsave);
03879 }
03880
03881 model::walker model::variable(unsigned int _vnum)
03882 {
03883 bool make_new(false);
03884 walker __r(ground());
03885 ref_iterator __x(var_ref.end());
03886
03887 if(!gid->have_gvar_ref(_vnum))
03888 {
03889 new_variables(_vnum+1);
03890 make_new = true;
03891 }
03892 else
03893 {
03894 __x = lower_bound(var_ref.begin(), var_ref.end(), _vnum,
03895 __docompare_variables());
03896 if(__x != var_ref.end() && (*__x)->params.nn() == (int)_vnum)
03897 {
03898 __r = *__x;
03899 make_new = false;
03900 }
03901 else if(gid->empty(var(_vnum)))
03902 make_new = true;
03903 }
03904 if(make_new)
03905 {
03906 expression_node _en(EXPRINFO_VARIABLE, next_num());
03907 _en.v_i.reserve(gid->number_of_variables());
03908 _en.v_i.set(_vnum);
03909 _en.params = (int)_vnum;
03910 __r = between_back(ground(), sky(), _en);
03911 var_ref.insert(__x, __r);
03912 return store_node(__r);
03913 }
03914 else if(__r == ground())
03915 {
03916 __r = var(_vnum);
03917 __r = ghost(__r->node_num);
03918
03919 return __r;
03920 }
03921 else
03922 return __r;
03923 }
03924
03925 model::walker model::vnary(int expr_type, ...)
03926 {
03927 va_list _a_list;
03928 expression_node _en(expr_type, next_num());
03929 std::vector<walker> _args;
03930 const walker* _e;
03931 int __i;
03932
03933 va_start(_a_list, expr_type);
03934 for(__i=0;;__i++)
03935 {
03936 _e = va_arg(_a_list, const walker*);
03937 if(_e == EXPR_LASTARG) break;
03938 _args.push_back(*_e);
03939 _en.v_i.set_all((*_e)->v_i);
03940 }
03941 va_end(_a_list);
03942 _en.coeffs.insert(_en.coeffs.end(),__i,1.0);
03943 if(expr_type == EXPRINFO_PROD)
03944 _en.params = 1.;
03945 else
03946 _en.params = 0.;
03947 return store_node(split_back(ground(), _args, _en));
03948 }
03949
03950 model::walker model::vxnary(const basic_alltype& _params, int expr_type, ...)
03951 {
03952 va_list _a_list;
03953 expression_node _en(expr_type, next_num());
03954 _en.params = _params;
03955 std::vector<walker> _args;
03956 const walker* _e;
03957 const double *_c;
03958 int __i;
03959
03960 va_start(_a_list, expr_type);
03961 for(__i=0;;__i++)
03962 {
03963 _e = va_arg(_a_list, const walker*);
03964 if(_e == EXPR_LASTARG) break;
03965 _args.push_back(*_e);
03966 _en.v_i.set_all((*_e)->v_i);
03967 _c = va_arg(_a_list, const double *);
03968 if(_c == EXPR_LASTARG)
03969 {
03970 _en.coeffs.push_back(1.0);
03971 break;
03972 }
03973 else
03974 _en.coeffs.push_back(*_c);
03975 }
03976 va_end(_a_list);
03977 return store_node(split_back(ground(), _args, _en));
03978 }
03979
03980 void model::detect_0chain()
03981 {
03982 unsigned int f = 1;
03983 unsigned int n = number_of_nodes();
03984 std::vector<unsigned int> t(n,0);
03985 std::vector<unsigned int> depth(n,0);
03986 std::vector<unsigned int> base;
03987
03988 detect_0chain_visitor d(t, depth, base, f);
03989
03990 evaluate(d, (const_walker) ground());
03991 for(unsigned int i = 0; i < n; ++i)
03992 {
03993 if(gid->empty(gid->node(i)))
03994 continue;
03995 if(t[i] == 0)
03996 {
03997 gid->node(i)->sem.info_flags.has_0chnbase = t_false;
03998 gid->node(i)->sem._0chnbase = i;
03999 continue;
04000 }
04001 if(base[t[i]-1] == i)
04002 gid->node(i)->sem.info_flags.has_0chnbase = t_false;
04003 else
04004 gid->node(i)->sem.info_flags.has_0chnbase =
04005 (depth[i] == 1 ? t_maybe : t_true);
04006 gid->node(i)->sem._0chnbase = base[t[i]-1];
04007 }
04008 }
04009
04010 #if MODEL_INLINE_DEBUG
04011 void model::dbg_write() const
04012 {
04013 write();
04014 }
04015 #endif
04016
04017 void model::check_counters(bool reset) const
04018 {
04019 std::vector<walker>::const_iterator __x, __e(node_ref.end());
04020 #if MODEL_INLINE_DEBUG_SIMPLIFY
04021 std::cerr << "In check_counters. Node numbers in node_ref:" << std::endl;
04022 for(__x = node_ref.begin(); __x != __e; ++__x)
04023 std::cerr << " " << (*__x)->node_num << std::endl;
04024 #endif
04025 for(__x = node_ref.begin(); __x != __e; ++__x)
04026 {
04027 walker _w = *__x;
04028 if(_w.is_root() && _w.is_leaf())
04029 {
04030 if(0 != (*_w).n_parents)
04031 {
04032 #if MODEL_INLINE_DEBUG_SIMPLIFY
04033 std::cerr << "INCONSISTENCY: Root&Leaf Node " << _w->node_num <<
04034 " has parents: " << _w->n_parents << std::endl;
04035 #endif
04036 if(reset) (*_w).n_parents = 0;
04037 }
04038 if(0 != (*_w).n_children)
04039 {
04040 #if MODEL_INLINE_DEBUG_SIMPLIFY
04041 std::cerr << "INCONSISTENCY: Root&Leaf Node " << _w->node_num <<
04042 " has children: " << _w->n_children << std::endl;
04043 #endif
04044 if(reset)
04045 (*_w).n_children = 0;
04046 }
04047 }
04048 else if(_w.is_root())
04049 {
04050 if(0 != (*_w).n_parents)
04051 {
04052 #if MODEL_INLINE_DEBUG_SIMPLIFY
04053 std::cerr << "INCONSISTENCY: Root Node " << _w->node_num <<
04054 " has parents: " << _w->n_parents << std::endl;
04055 #endif
04056 if(reset) (*_w).n_parents = 0;
04057 }
04058 if(_w.n_children() != (*_w).n_children)
04059 {
04060 #if MODEL_INLINE_DEBUG_SIMPLIFY
04061 std::cerr << "INCONSISTENCY: Root Node " << _w->node_num <<
04062 " children number mismatch (t/p): " << _w.n_children() << " != "
04063 << _w->n_children << std::endl;
04064 #endif
04065 if(reset)
04066 (*_w).n_children = _w.n_children();
04067 }
04068 }
04069 else if(_w.is_leaf())
04070 {
04071 if(_w.n_parents() != (*_w).n_parents)
04072 {
04073 #if MODEL_INLINE_DEBUG_SIMPLIFY
04074 std::cerr << "INCONSISTENCY: Leaf Node " << _w->node_num <<
04075 " parents number mismatch (t/p): " << _w.n_parents() << " != "
04076 << _w->n_parents << std::endl;
04077 #endif
04078 if(reset) (*_w).n_parents = _w.n_parents();
04079 }
04080 if(0 != (*_w).n_children)
04081 {
04082 #if MODEL_INLINE_DEBUG_SIMPLIFY
04083 std::cerr << "INCONSISTENCY: Leaf Node " << _w->node_num <<
04084 " has children: " << _w->n_children << std::endl;
04085 #endif
04086 if(reset)
04087 (*_w).n_children = 0;
04088 }
04089 }
04090 else
04091 {
04092 if(_w.n_parents() != (*_w).n_parents)
04093 {
04094 #if MODEL_INLINE_DEBUG_SIMPLIFY
04095 std::cerr << "INCONSISTENCY: Node " << _w->node_num <<
04096 " parents number mismatch (t/p): " << _w.n_parents() << " != "
04097 << _w->n_parents << std::endl;
04098 #endif
04099 if(reset) (*_w).n_parents = _w.n_parents();
04100 }
04101 if(_w.n_children() != (*_w).n_children)
04102 {
04103 #if MODEL_INLINE_DEBUG_SIMPLIFY
04104 std::cerr << "INCONSISTENCY: Node " << _w->node_num <<
04105 " children number mismatch (t/p): " << _w.n_children() << " != "
04106 << _w->n_children << std::endl;
04107 #endif
04108 if(reset) (*_w).n_children = _w.n_children();
04109 }
04110 }
04111 }
04112 }
04113
04114 }