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