00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00027 #ifndef _INTERVAL_EVALUATOR_H_
00028 #define _INTERVAL_EVALUATOR_H_
00029
00030 #include <coconut_config.h>
00031 #include <evaluator.h>
00032 #include <expression.h>
00033 #include <model.h>
00034 #include <eval_main.h>
00035 #include <linalg.h>
00036 #include <math.h>
00037
00038 using namespace vgtl;
00039
00040 typedef interval (*interval_evaluator)(const std::vector<interval>* __x,
00041 const variable_indicator& __v);
00042
00043 struct interval_eval_type
00044 {
00045 const std::vector<interval>* x;
00046 std::vector<interval>* cache;
00047 const model* mod;
00048 union { void *p; interval_st d; int info; } u;
00049 interval r;
00050 unsigned int n;
00051 bool do_intersect;
00052 };
00053
00054 class interval_eval : public
00055 cached_forward_evaluator_base<interval_eval_type,expression_node,interval,
00056 model::walker>
00057 {
00058 private:
00059 typedef cached_forward_evaluator_base<interval_eval_type,expression_node,
00060 interval,model::walker> _Base;
00061
00062 protected:
00063 bool is_cached(const node_data_type& __data)
00064 {
00065 if(__data.operator_type == EXPRINFO_LIN ||
00066 __data.operator_type == EXPRINFO_QUAD)
00067 return true;
00068 else
00069 return false;
00070 #if 0
00071 if(eval_data.cache && __data.n_parents > 1 && __data.n_children > 0)
00072 return true;
00073 else
00074 return false;
00075 #endif
00076 }
00077
00078 private:
00079 interval __power(double __coeff, interval __x, int __exp)
00080 {
00081 if(__exp == 0)
00082 return 1.;
00083 else
00084 {
00085 interval k = __coeff*__x;
00086 switch(__exp)
00087 {
00088 case 1:
00089 return k;
00090 break;
00091 case 2:
00092 return sqr(k);
00093 break;
00094 case -1:
00095 return 1./k;
00096 break;
00097 case -2:
00098 return 1./sqr(k);
00099 break;
00100 default:
00101 return ipow(k, __exp);
00102 break;
00103 }
00104 }
00105 return 0;
00106 }
00107
00108 public:
00109 interval_eval(const std::vector<interval>& __x, const variable_indicator& __v,
00110 const model& __m, std::vector<interval>* __c, bool do_i = true)
00111 : _Base()
00112 {
00113 eval_data.x = &__x;
00114 eval_data.cache = __c;
00115 eval_data.mod = &__m;
00116 eval_data.u.d = 0.;
00117 v_ind = &__v;
00118 eval_data.n = 0;
00119 eval_data.do_intersect = do_i;
00120 }
00121
00122 interval_eval(const interval_eval& __v) : _Base(__v) {}
00123
00124 ~interval_eval() {}
00125
00126 model::walker short_cut_to(const expression_node& __data)
00127 { return eval_data.mod->node(0); }
00128
00129 void initialize() { return; }
00130
00131 int initialize(const expression_node& __data)
00132 {
00133 eval_data.n = 0;
00134 if(__data.ev && (*__data.ev)[FUNC_RANGE])
00135
00136 {
00137 eval_data.r =
00138 (*(interval_evaluator)(*__data.ev)[FUNC_RANGE])(eval_data.x,
00139 *v_ind);
00140 return 0;
00141 }
00142 else
00143 {
00144 switch(__data.operator_type)
00145 {
00146 case EXPRINFO_SUM:
00147 case EXPRINFO_PROD:
00148 case EXPRINFO_MAX:
00149 case EXPRINFO_MIN:
00150 case EXPRINFO_INVERT:
00151 case EXPRINFO_DIV:
00152 eval_data.r = __data.params.nd();
00153 break;
00154 case EXPRINFO_MONOME:
00155 case EXPRINFO_IN:
00156 case EXPRINFO_AND:
00157 case EXPRINFO_NOGOOD:
00158 eval_data.r = 1.;
00159 break;
00160 case EXPRINFO_ALLDIFF:
00161 eval_data.u.p = (void*) new std::vector<interval>;
00162 ((std::vector<interval>*)eval_data.u.p)->reserve(__data.n_children);
00163
00164 case EXPRINFO_MEAN:
00165 case EXPRINFO_IF:
00166 case EXPRINFO_OR:
00167 case EXPRINFO_NOT:
00168 case EXPRINFO_COUNT:
00169 case EXPRINFO_SCPROD:
00170 case EXPRINFO_NORM:
00171 case EXPRINFO_LEVEL:
00172 eval_data.r = 0.;
00173 break;
00174 case EXPRINFO_DET:
00175 case EXPRINFO_PSD:
00176
00177 break;
00178 case EXPRINFO_COND:
00179 case EXPRINFO_FEM:
00180 case EXPRINFO_MPROD:
00181
00182 break;
00183 }
00184 return 1;
00185 }
00186 }
00187
00188 void calculate(const expression_node& __data)
00189 {
00190 if(__data.operator_type > 0)
00191 {
00192 eval_data.r = __data.i_evaluate(-1, __data.params.nn(), *eval_data.x,
00193 *v_ind, eval_data.r, interval(0,0), NULL);
00194 }
00195 if(eval_data.do_intersect)
00196 eval_data.r.intersect(__data.f_bounds);
00197 }
00198
00199 void retrieve_from_cache(const expression_node& __data)
00200 {
00201 if(__data.operator_type == EXPRINFO_LIN)
00202 {
00203 const matrix<double>::Row& lrw(eval_data.mod->lin[__data.params.nn()]);
00204 matrix<double>::Row::const_iterator _x, _e;
00205
00206 eval_data.r = interval(0.);
00207 for(_x = lrw.begin(); _x != _e; ++_x)
00208 eval_data.r += (*eval_data.x)[_x.index()] * *_x;
00209 }
00210 else if(__data.operator_type == EXPRINFO_QUAD)
00211 {
00212 throw "Interval Evaluation of QUAD: NYI!";
00213 }
00214 else
00215 eval_data.r = (*eval_data.cache)[__data.node_num];
00216 }
00217
00218 int update(const interval& __rval)
00219 {
00220 eval_data.r = __rval;
00221 return 0;
00222 }
00223
00224 int update(const expression_node& __data, const interval& __rval)
00225 {
00226 interval __x;
00227 int ret = 0;
00228 if(__data.operator_type < 0)
00229 {
00230 switch(__data.operator_type)
00231 {
00232 case EXPRINFO_CONSTANT:
00233 eval_data.r = __data.params.nd();
00234 break;
00235 case EXPRINFO_VARIABLE:
00236 eval_data.r = (*eval_data.x)[__data.params.nn()];
00237 break;
00238 case EXPRINFO_SUM:
00239 case EXPRINFO_MEAN:
00240 eval_data.r += __data.coeffs[eval_data.n++]*__rval;
00241 break;
00242 case EXPRINFO_PROD:
00243
00244 eval_data.r *= __rval;
00245 if(eval_data.r == 0.) ret = -1;
00246 break;
00247 case EXPRINFO_MONOME:
00248
00249 eval_data.r *= __power(__data.coeffs[eval_data.n], __rval,
00250 __data.params.n()[eval_data.n]);
00251 if(eval_data.r == 0.) ret = -1;
00252 eval_data.n++;
00253 break;
00254 case EXPRINFO_MAX:
00255 { interval h = __rval * __data.coeffs[eval_data.n++];
00256 eval_data.r = imax(eval_data.r, h);
00257 }
00258 break;
00259 case EXPRINFO_MIN:
00260 { interval h = __rval * __data.coeffs[eval_data.n++];
00261 eval_data.r = imin(eval_data.r, h);
00262 }
00263 break;
00264 case EXPRINFO_SCPROD:
00265 { interval h = __data.coeffs[eval_data.n]*__rval;
00266
00267
00268 if(eval_data.n & 1)
00269 eval_data.r += __data.coeffs[eval_data.n]*__rval*h;
00270 else
00271 eval_data.u.d = h;
00272 }
00273 eval_data.n++;
00274 break;
00275 case EXPRINFO_NORM:
00276 if(__data.params.nd() == INFINITY)
00277 {
00278 interval h = abs(__rval * __data.coeffs[eval_data.n]);
00279 eval_data.r = imax(eval_data.r, h);
00280 }
00281 else
00282 {
00283 interval h = abs(__data.coeffs[eval_data.n]*__rval);
00284 eval_data.r += pow(h, interval(__data.params.nd()));
00285 }
00286 ++eval_data.n;
00287 if(eval_data.n == __data.n_children)
00288 eval_data.r = pow(eval_data.r, interval(1.)/__data.params.nd());
00289 break;
00290 case EXPRINFO_INVERT:
00291 eval_data.r /= __rval;
00292 break;
00293 case EXPRINFO_DIV:
00294
00295
00296 if(eval_data.n == 0)
00297 eval_data.r *= __rval;
00298 else
00299 eval_data.r /= __rval;
00300 ++eval_data.n;
00301 break;
00302 case EXPRINFO_SQUARE:
00303 { interval h = __data.coeffs[0]*__rval+__data.params.nd();
00304 eval_data.r = sqr(h);
00305 }
00306 break;
00307 case EXPRINFO_INTPOWER:
00308 eval_data.r = __power(__data.coeffs[0], __rval, __data.params.nn());
00309 break;
00310 case EXPRINFO_SQROOT:
00311 eval_data.r = sqrt(__data.coeffs[0]*__rval+__data.params.nd());
00312 break;
00313 case EXPRINFO_ABS:
00314 eval_data.r = abs(__data.coeffs[0]*__rval+__data.params.nd());
00315 break;
00316 case EXPRINFO_POW:
00317 { interval h = __rval * __data.coeffs[eval_data.n];
00318 if(eval_data.n == 0)
00319 eval_data.r = h+__data.params.nd();
00320 else
00321 eval_data.r = pow(eval_data.r, h);
00322 }
00323 ++eval_data.n;
00324 break;
00325 case EXPRINFO_EXP:
00326 eval_data.r = exp(__rval*__data.coeffs[0]+__data.params.nd());
00327 break;
00328 case EXPRINFO_LOG:
00329 eval_data.r = log(__rval*__data.coeffs[0]+__data.params.nd());
00330 break;
00331 case EXPRINFO_SIN:
00332 eval_data.r = sin(__rval*__data.coeffs[0]+__data.params.nd());
00333 break;
00334 case EXPRINFO_COS:
00335 eval_data.r = cos(__rval*__data.coeffs[0]+__data.params.nd());
00336 break;
00337 case EXPRINFO_ATAN2:
00338 { interval h = __rval * __data.coeffs[eval_data.n];
00339 if(eval_data.n == 0)
00340 eval_data.r = h;
00341 else
00342 eval_data.r = atan2(eval_data.r, h);
00343 ++eval_data.n;
00344 }
00345 break;
00346 case EXPRINFO_GAUSS:
00347 { interval h = (__data.coeffs[0]*__rval-__data.params.d()[0])/
00348 __data.params.d()[1];
00349 eval_data.r = gauss(h);
00350 }
00351 break;
00352 case EXPRINFO_POLY:
00353 std::cerr << "Polynomes NYI" << std::endl;
00354 throw "NYI";
00355 break;
00356 case EXPRINFO_LIN:
00357 case EXPRINFO_QUAD:
00358
00359 break;
00360 case EXPRINFO_IN:
00361 {
00362 __x = __data.coeffs[eval_data.n]*__rval;
00363 const interval& i(__data.params.i()[eval_data.n]);
00364 if(i.disjoint(__x))
00365 {
00366 eval_data.r = -1.;
00367 ret = -1;
00368 }
00369 else if(eval_data.r != interval(-1.))
00370 {
00371 if(!i.superset(__x))
00372 {
00373 if(i.sup() == __x.inf() || i.inf() == __x.sup())
00374
00375 eval_data.r = interval(-1.,0.);
00376 else if(eval_data.r.sup() > 0)
00377 eval_data.r = interval(-1.,1.);
00378 }
00379 else if(i.inf() == __x.inf() || i.sup() == __x.sup())
00380
00381
00382 {
00383 if(eval_data.r.inf() == 1.)
00384 {
00385 if(__x.is_thin())
00386 eval_data.r = 0.;
00387 else
00388 eval_data.r = interval(0.,1.);
00389 }
00390 else if(__x.is_thin() && eval_data.r.inf() == 0.)
00391 eval_data.r = 0.;
00392 }
00393
00394 }
00395 }
00396 eval_data.n++;
00397 break;
00398 case EXPRINFO_IF:
00399 __x = __rval * __data.coeffs[eval_data.n];
00400 if(eval_data.n == 0)
00401 {
00402 const interval& i(__data.params.ni());
00403 if(i.superset(__x))
00404 eval_data.u.info = 0;
00405 else if(i.disjoint(__x))
00406 {
00407 eval_data.u.info = 1;
00408 ret = 1;
00409 }
00410 else
00411 eval_data.u.info = 2;
00412 }
00413 else if(eval_data.n == 1)
00414 {
00415 eval_data.r = __x;
00416 if(eval_data.u.info == 0)
00417 ret = -1;
00418 }
00419 else
00420 {
00421 if(eval_data.u.info == 1)
00422 eval_data.r = __x;
00423 else
00424 eval_data.r = eval_data.r.hull(__x);
00425 }
00426 eval_data.n += ret+1;
00427 break;
00428 case EXPRINFO_AND:
00429 { __x = __data.coeffs[eval_data.n]*__rval;
00430 const interval& i(__data.params.i()[eval_data.n]);
00431 if(eval_data.r != 0.)
00432 {
00433 if(i.disjoint(__x))
00434 {
00435 eval_data.r = 0;
00436 ret = -1;
00437 }
00438 else if(!i.superset(__x))
00439 eval_data.r = interval(0.,1.);
00440
00441 }
00442 }
00443 eval_data.n++;
00444 break;
00445 case EXPRINFO_OR:
00446 { __x = __data.coeffs[eval_data.n]*__rval;
00447 const interval& i(__data.params.i()[eval_data.n]);
00448 if(eval_data.r != 1.)
00449 {
00450 if(i.superset(__x))
00451 {
00452 eval_data.r = 1;
00453 ret = -1;
00454 }
00455 else if(!i.disjoint(__x))
00456 eval_data.r = interval(0.,1.);
00457 }
00458 }
00459 eval_data.n++;
00460 break;
00461 case EXPRINFO_NOT:
00462 { __x = __data.coeffs[0]*__rval;
00463 const interval& i(__data.params.ni());
00464 if(i.superset(__x))
00465 eval_data.r = 0;
00466 else if(i.disjoint(__x))
00467 eval_data.r = 1;
00468 else
00469 eval_data.r = interval(0.,1.);
00470 }
00471 break;
00472 case EXPRINFO_IMPLIES:
00473 { const interval& i(__data.params.i()[eval_data.n]);
00474 __x = __rval * __data.coeffs[eval_data.n];
00475 if(eval_data.n == 0)
00476 {
00477 if(i.disjoint(__x))
00478 {
00479 eval_data.r = 1.;
00480 ret = -1;
00481 }
00482 else if(!i.superset(__x))
00483 eval_data.r = interval(0.,1.);
00484 else
00485 eval_data.r = interval(0.);
00486 }
00487 else
00488 {
00489 if(i.superset(__x))
00490 eval_data.r = 1.;
00491 else if(!i.disjoint(__x))
00492 eval_data.r = interval(0.,1.);
00493
00494 }
00495 ++eval_data.n;
00496 }
00497 break;
00498 case EXPRINFO_COUNT:
00499 { __x = __data.coeffs[eval_data.n]*__rval;
00500 const interval& i(__data.params.i()[eval_data.n]);
00501 if(i.superset(__x))
00502 eval_data.r += 1;
00503 else if(!i.disjoint(__x))
00504 eval_data.r += interval(0.,1.);
00505 }
00506 eval_data.n++;
00507 break;
00508 case EXPRINFO_ALLDIFF:
00509 { __x = __data.coeffs[eval_data.n]*__rval;
00510 for(std::vector<interval>::const_iterator _b =
00511 ((std::vector<interval>*)eval_data.u.p)->begin();
00512 _b != ((std::vector<interval>*)eval_data.u.p)->end(); ++_b)
00513 {
00514 interval __h = abs(__x-*_b);
00515 if(__h.sup() <= __data.params.nd())
00516 {
00517 eval_data.r = 0;
00518 ret = -1;
00519 break;
00520 }
00521 else if(__h.inf() <= __data.params.nd())
00522 eval_data.r = interval(0.,1.);
00523 }
00524 if(ret != -1)
00525 ((std::vector<interval>*) eval_data.u.p)->push_back(__x);
00526 }
00527 eval_data.n++;
00528 if(eval_data.n == __data.n_children || ret == -1)
00529 delete (std::vector<interval>*) eval_data.u.p;
00530 break;
00531 case EXPRINFO_HISTOGRAM:
00532 std::cerr << "int_evaluator: histogram NYI" << std::endl;
00533 throw "NYI";
00534 break;
00535 case EXPRINFO_LEVEL:
00536 { int lo = (int)eval_data.r.inf();
00537 int hi = (int)eval_data.r.sup();
00538 __x = __data.coeffs[eval_data.n]*__rval;
00539 interval _h;
00540
00541
00542 if(hi != INT_MAX)
00543 {
00544 while(hi < __data.params.im().nrows())
00545 {
00546 _h = __data.params.im()[hi][eval_data.n];
00547 if(_h.superset(__x))
00548 break;
00549 hi++;
00550 }
00551 if(hi == __data.params.im().nrows())
00552 hi = INT_MAX;
00553 }
00554
00555 if(lo != INT_MAX)
00556 {
00557 while(lo < __data.params.im().nrows())
00558 {
00559 _h = __data.params.im()[lo][eval_data.n];
00560 if(!_h.disjoint(__x))
00561 break;
00562 lo++;
00563 }
00564 if(lo == __data.params.im().nrows())
00565 lo = INT_MAX;
00566 }
00567 if(hi == INT_MAX && lo == INT_MAX)
00568 {
00569 eval_data.r = INT_MAX;
00570 ret = -1;
00571 }
00572 else
00573 eval_data.r = interval(lo+0.,hi+0.);
00574 }
00575 eval_data.n++;
00576 break;
00577 case EXPRINFO_NEIGHBOR:
00578
00579
00580
00581 if(eval_data.n == 0)
00582 eval_data.r = __data.coeffs[0]*__rval;
00583 else
00584 {
00585 interval h = eval_data.r;
00586 eval_data.r = 0;
00587 __x = __data.coeffs[1]*__rval;
00588 for(unsigned int i = 0; i < __data.params.n().size(); i+=2)
00589 {
00590 if(h == __data.params.n()[i]+0. &&
00591 __x == __data.params.n()[i+1]+0.)
00592 {
00593 eval_data.r = 1;
00594 break;
00595 }
00596 else if(h.contains(__data.params.n()[i]+0.) &&
00597 __x.contains(__data.params.n()[i+1]+0.))
00598 {
00599 eval_data.r = interval(0.,1.);
00600 break;
00601 }
00602 }
00603 }
00604 eval_data.n++;
00605 break;
00606 case EXPRINFO_NOGOOD:
00607 __x = __data.coeffs[eval_data.n]*__rval;
00608 if(eval_data.r != 0.)
00609 {
00610 if(!__x.contains(__data.params.n()[eval_data.n]+0.))
00611 {
00612 eval_data.r = 0.;
00613 ret = -1;
00614 }
00615 else if(__x != __data.params.n()[eval_data.n]+0.)
00616 eval_data.r = interval(0.,1.);
00617 }
00618 eval_data.n++;
00619 break;
00620 case EXPRINFO_EXPECTATION:
00621 std::cerr << "int_evaluator: E NYI" << std::endl;
00622 throw "NYI";
00623 break;
00624 case EXPRINFO_INTEGRAL:
00625 std::cerr << "int_evaluator: INT NYI" << std::endl;
00626 throw "NYI";
00627 break;
00628 case EXPRINFO_LOOKUP:
00629 case EXPRINFO_PWLIN:
00630 case EXPRINFO_SPLINE:
00631 case EXPRINFO_PWCONSTLC:
00632 case EXPRINFO_PWCONSTRC:
00633 std::cerr << "int_evaluator: Table Operations NYI" << std::endl;
00634 throw "NYI";
00635 break;
00636 case EXPRINFO_DET:
00637 case EXPRINFO_COND:
00638 case EXPRINFO_PSD:
00639 case EXPRINFO_MPROD:
00640 case EXPRINFO_FEM:
00641 std::cerr << "int_evaluator: Matrix Operations NYI" << std::endl;
00642 throw "NYI";
00643 break;
00644 case EXPRINFO_RE:
00645 case EXPRINFO_IM:
00646 case EXPRINFO_ARG:
00647 case EXPRINFO_CPLXCONJ:
00648 std::cerr << "int_evaluator: Complex Numbers NYI" << std::endl;
00649 throw "NYI";
00650 break;
00651 case EXPRINFO_CMPROD:
00652 case EXPRINFO_CGFEM:
00653 std::cerr << "int_evaluator: Const Matrix Operations NYI" << std::endl;
00654 throw "NYI";
00655 break;
00656 default:
00657 std::cerr << "int_evaluator: unknown function type " <<
00658 __data.operator_type << std::endl;
00659 throw "Programming error";
00660 break;
00661 }
00662 }
00663 else if(__data.operator_type > 0)
00664
00665 eval_data.r = __data.i_evaluate(eval_data.n++, __data.params.nn(),
00666 *eval_data.x, *v_ind, eval_data.r, __rval, NULL);
00667
00668
00669 if(eval_data.cache)
00670 (*eval_data.cache)[__data.node_num] = eval_data.r;
00671 return ret;
00672 }
00673
00674 interval calculate_value(bool eval_all)
00675 {
00676 return eval_data.r;
00677 }
00678 };
00679
00680 #endif