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