Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

ider_evaluator.h

Go to the documentation of this file.
00001 // Interval Derivative Evaluator implementation -*- C++ -*-
00002 
00003 // Copyright (C) 2001-2003 Hermann Schichl
00004 //
00005 // This file is part of the COCONUT API.  This library
00006 // is free software; you can redistribute it and/or modify it under the
00007 // terms of the Library GNU General Public License as published by the
00008 // Free Software Foundation; either version 2, or (at your option)
00009 // any later version.
00010 
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 // Library GNU General Public License for more details.
00015 
00016 // As a special exception, you may use this file as part of a free software
00017 // library without restriction.  Specifically, if other files instantiate
00018 // templates or use macros or inline functions from this file, or you compile
00019 // this file and link it with other files to produce an executable, this
00020 // file does not by itself cause the resulting executable to be covered by
00021 // the Library GNU General Public License.  This exception does not however
00022 // invalidate any other reasons why the executable file might be covered by
00023 // the Library GNU General Public License.
00024 
00027 #ifndef _IDER_EVALUATOR_H_
00028 #define _IDER_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 bool (*prep_id_evaluator)();
00041 typedef interval (*func_id_evaluator)(
00042               const std::vector<interval>* __x, const variable_indicator& __v,
00043               std::vector<interval>& __id_data);
00044 typedef std::vector<interval>& (*ider_evaluator)(const std::vector<interval>& __d_dat,
00045                                          const variable_indicator& __v);
00046 
00047 class prep_id_eval : public
00048   cached_forward_evaluator_base<std::vector<std::vector<interval> >*,
00049                                 expression_node, bool, model::walker>
00050 {
00051 private:
00052   typedef cached_forward_evaluator_base<std::vector<std::vector<interval> >*,
00053                                    expression_node,bool,model::walker> _Base;
00054 
00055 public:
00056   prep_id_eval(std::vector<std::vector<interval> >& __d,
00057               unsigned int _num_of_nodes)
00058   {
00059     eval_data = &__d;
00060     if((*eval_data).size() < _num_of_nodes)
00061       (*eval_data).insert((*eval_data).end(),
00062                           _num_of_nodes-(*eval_data).size(), std::vector<interval>());
00063   }
00064 
00065   prep_id_eval(const prep_id_eval& __x) { eval_data = __x.eval_data; }
00066 
00067   ~prep_id_eval() {}
00068 
00069   void initialize() { return; }
00070 
00071   bool is_cached(const expression_node& __data)
00072   {
00073     return (*eval_data)[__data.node_num].size() > 0;
00074   }
00075 
00076   void retrieve_from_cache(const expression_node& __data) { return; }
00077 
00078   int initialize(const expression_node& __data)
00079   {
00080     (*eval_data)[__data.node_num].insert((*eval_data)[__data.node_num].end(),
00081         __data.n_children, interval(0.));
00082     return 1;
00083   }
00084 
00085   void calculate(const expression_node& __data) { return; }
00086 
00087   int update(bool __rval) { return 0; }
00088 
00089   int update(const expression_node& __data, bool __rval)
00090         { return 0; }
00091 
00092   bool calculate_value(bool eval_all) { return true; }
00093 };
00094 
00095 // function evaluation at interval argument + preparation of derivative data
00096 // for later backwards evaluation
00097 
00098 struct func_id_eval_type
00099 {
00100   const std::vector<interval>* x;
00101   const std::vector<interval>* range;
00102   std::vector<interval>* f;
00103   std::vector<std::vector<interval> >* id_data;
00104   const model* mod;
00105   union { void *p; interval_st d; unsigned int info; } u;
00106   interval r;
00107   unsigned int n;
00108 };
00109 
00110 class func_id_eval : public
00111   cached_forward_evaluator_base<func_id_eval_type, expression_node,
00112                                 interval, model::walker>
00113 {
00114 private:
00115   typedef cached_forward_evaluator_base<func_id_eval_type,expression_node,
00116                                         interval, model::walker> _Base;
00117 
00118 protected:
00119   bool is_cached(const node_data_type& __data)
00120   {
00121     if(__data.operator_type == EXPRINFO_LIN ||
00122        __data.operator_type == EXPRINFO_QUAD)
00123       return true;
00124     if(eval_data.f && __data.n_parents > 1 && __data.n_children > 0 &&
00125        v_ind->match(__data.var_indicator()))
00126       return true;
00127     else
00128       return false;
00129   }
00130 
00131 private:
00132   interval __power(double __coeff, interval __x, int __exp)
00133   {
00134     if(__exp == 0)
00135       return 1.;
00136     else
00137     {
00138       interval k = __coeff*__x;
00139       switch(__exp)
00140       {
00141         case 1:
00142           return k;
00143           break;
00144         case 2:
00145           return sqr(k);
00146           break;
00147         case -1:
00148           return 1./k;
00149           break;
00150         case -2:
00151           return 1./sqr(k);
00152           break;
00153         default:
00154           return ipow(k, __exp);
00155           break;
00156       }
00157     }
00158     return 0;           // we never come here!
00159   }
00160 
00161   void __calc_max(const interval& h, const expression_node& __data)
00162   { 
00163     if(h.inf() > eval_data.r.sup())
00164     {
00165       for(unsigned int i = 0; i < eval_data.n; ++i)
00166         (*eval_data.id_data)[__data.node_num][i] = 0;
00167       (*eval_data.id_data)[__data.node_num][eval_data.n] =
00168                           __data.coeffs[eval_data.n];
00169       eval_data.r = h;
00170       eval_data.u.info = eval_data.n;
00171     }
00172     else if(h.sup() < eval_data.r.inf())
00173       (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00174     else
00175     {
00176       (*eval_data.id_data)[__data.node_num][eval_data.n] =
00177                 __data.coeffs[eval_data.n] >= 0 ?
00178                       interval(0.,__data.coeffs[eval_data.n]):
00179                       interval(__data.coeffs[eval_data.n],0.);
00180       (*eval_data.id_data)[__data.node_num][eval_data.u.info] =
00181                 __data.coeffs[eval_data.u.info] >= 0 ?
00182                       interval(0.,__data.coeffs[eval_data.u.info]):
00183                       interval(__data.coeffs[eval_data.u.info],0.);
00184     }
00185   }
00186 
00187 public:
00188   func_id_eval(const std::vector<interval>& __x,
00189                   const std::vector<interval>& __rg,
00190                   const variable_indicator& __v,
00191                   const model& __m,
00192                   std::vector<std::vector<interval> >& __d,
00193                   std::vector<interval>* __c) : _Base()
00194   {
00195     eval_data.x = &__x;
00196     eval_data.f = __c;
00197     eval_data.range = &__rg;
00198     eval_data.mod = &__m;
00199     eval_data.id_data = &__d;
00200     eval_data.n = 0;
00201     eval_data.r = interval(0.);
00202     eval_data.u.d = 0;
00203     v_ind = &__v;
00204   }
00205 
00206   func_id_eval(const func_id_eval& __x) : _Base(__x) {}
00207 
00208   ~func_id_eval() {}
00209 
00210   model::walker short_cut_to(const expression_node& __data)
00211   { return eval_data.mod->node(0); }    // return anything
00212 
00213   void new_box(const std::vector<interval>& __x, const variable_indicator& __v)
00214   {
00215     eval_data.x = &__x;
00216     v_ind = &__v;
00217   }
00218 
00219   void new_range(const std::vector<interval>& __rg, const variable_indicator& __v)
00220   {
00221     eval_data.range = &__rg;
00222     v_ind = &__v;
00223   }
00224 
00225   void initialize() { return; }
00226 
00227   int initialize(const expression_node& __data)
00228   {
00229     eval_data.n = 0;
00230     if(__data.ev != NULL && (*__data.ev)[FUNC_ID_EVALUATOR] != NULL)
00231     // is there a short-cut evaluator defined?
00232     {
00233       eval_data.r =
00234           (*(func_id_evaluator)(*__data.ev)[FUNC_ID_EVALUATOR])(eval_data.range,
00235                                *v_ind, (*eval_data.id_data)[__data.node_num]);
00236       return 0;     // don't perform the remaining graph walk
00237     }
00238     else
00239     {
00240       switch(__data.operator_type)
00241       {
00242         case EXPRINFO_MAX:
00243         case EXPRINFO_MIN:
00244           eval_data.u.info = 0;
00245           // no break == continue
00246         case EXPRINFO_SUM:
00247         case EXPRINFO_INVERT:
00248         case EXPRINFO_PROD:
00249         case EXPRINFO_DIV:
00250           eval_data.r = __data.params.nd();
00251           break;
00252         case EXPRINFO_IN:
00253         case EXPRINFO_AND:
00254         case EXPRINFO_NOGOOD:
00255           eval_data.r = 1.;
00256           break;
00257         case EXPRINFO_ALLDIFF:
00258           eval_data.u.p = (void*) new std::vector<interval>;
00259           ((std::vector<interval>*)eval_data.u.p)->reserve(__data.n_children);
00260           // no break!
00261         case EXPRINFO_MEAN:
00262         case EXPRINFO_IF:
00263         case EXPRINFO_OR:
00264         case EXPRINFO_NOT:
00265         case EXPRINFO_COUNT:
00266         case EXPRINFO_SCPROD:
00267           eval_data.r = 0.;
00268           break;
00269         case EXPRINFO_NORM:
00270           eval_data.u.info = 0;
00271           eval_data.r = 0.;
00272           break;
00273         case EXPRINFO_LEVEL:
00274           eval_data.u.p = (void*) new std::vector<interval>;
00275           ((std::vector<interval>*)eval_data.u.p)->reserve(__data.n_children);
00276           eval_data.r = 0.;
00277           break;
00278         case EXPRINFO_DET:
00279         case EXPRINFO_PSD:
00280           // here construct square interval matrix
00281           break;
00282         case EXPRINFO_COND:
00283         case EXPRINFO_FEM:
00284         case EXPRINFO_MPROD:
00285           // here construct rectangular interval matrix
00286           break;
00287       }
00288       return 1;
00289     }
00290   }
00291 
00292   void calculate(const expression_node& __data)
00293   {
00294     if(__data.operator_type > 0)
00295     {
00296 #if 0
00297       //***** THINK ABOUT THIS LATER !
00298       eval_data.r = __data.f_evaluate(-1, __data.params.nn(), *eval_data.x,
00299                                       *v_ind, eval_data.r, 0,
00300                                       &((*eval_data.id_data)[__data.node_num]));
00301 #endif
00302     }
00303   }
00304 
00305   void retrieve_from_cache(const expression_node& __data)
00306   {
00307     if(__data.operator_type == EXPRINFO_LIN)
00308     {
00309       const matrix<double>::Row&
00310                           lrw(eval_data.mod->lin[__data.params.nn()]);
00311       matrix<double>::Row::const_iterator _x, _e;
00312       eval_data.r = 0.;
00313       _e = lrw.end();
00314       for(_x = lrw.begin(); _x != _e; ++_x)
00315       {
00316         interval _h = (*eval_data.x)[_x.index()];
00317         eval_data.r += *_x * _h;
00318       }
00319       eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00320     }
00321     else if(__data.operator_type == EXPRINFO_QUAD)
00322     {
00323       throw "Interval Evaluation of QUAD: NYI!";
00324     }
00325     else
00326     {
00327     // the parallel ider_cache MUST be initialized, too
00328       eval_data.r = (*eval_data.f)[__data.node_num];
00329       eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00330     }
00331   }
00332 
00333   int update(const interval& __rval)
00334   {
00335     eval_data.r = __rval;
00336     return 0;
00337   }
00338 
00339   int update(const expression_node& __data, const interval& __rval)
00340   {
00341     interval __x;
00342     int ret = 0;
00343     if(__data.operator_type < 0)
00344     {
00345       switch(__data.operator_type)
00346       {
00347         case EXPRINFO_CONSTANT:
00348           eval_data.r = __data.params.nd();
00349           // don't care about id_data, CONSTANTS are ALWAYS leafs
00350           break;
00351         case EXPRINFO_VARIABLE:
00352           eval_data.r = (*eval_data.x)[__data.params.nn()];
00353           eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00354           // don't care about id_data, VARIABLES are ALWAYS leafs
00355           break;
00356         case EXPRINFO_SUM:
00357         case EXPRINFO_MEAN:
00358           { double h = __data.coeffs[eval_data.n];
00359             eval_data.r += h*__rval;
00360             (*eval_data.id_data)[__data.node_num][eval_data.n++] = h;
00361           }
00362           // intersect with the known range
00363           if(eval_data.n == __data.n_children)
00364             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00365           break;
00366         case EXPRINFO_PROD:
00367           if(eval_data.n == 0)
00368           {
00369             eval_data.r *= __rval;
00370             (*eval_data.id_data)[__data.node_num][0] = __data.params.nd();
00371           }
00372           else
00373           {
00374             (*eval_data.id_data)[__data.node_num][eval_data.n] = eval_data.r;
00375             eval_data.r *= __rval;
00376             for(int i = eval_data.n-1; i >= 0; i--)
00377               (*eval_data.id_data)[__data.node_num][i] *= __rval;
00378           }
00379           ++eval_data.n;
00380           // intersect with the known range
00381           if(eval_data.n == __data.n_children)
00382             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00383           break;
00384         case EXPRINFO_MONOME:
00385           if(eval_data.n == 0)
00386           {
00387             int n = __data.params.n()[0];
00388             if(n != 0)
00389             {
00390               eval_data.r = __power(__data.coeffs[0], __rval, n);
00391               (*eval_data.id_data)[__data.node_num][0] =
00392                  (n*__data.coeffs[0])*__power(__data.coeffs[0], __rval, n-1);
00393             }
00394             else
00395             {
00396               eval_data.r = 1;
00397               (*eval_data.id_data)[__data.node_num][0] = 0;
00398             }
00399           }
00400           else
00401           {
00402             int n = __data.params.n()[eval_data.n];
00403             if(n != 0)
00404             {
00405               __x = __power(__data.coeffs[eval_data.n], __rval, n-1)*
00406                                 __data.coeffs[eval_data.n];
00407               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00408                                                         eval_data.r*(n+0.)*__x;
00409               __x = __power(__data.coeffs[eval_data.n], __rval, n);
00410               eval_data.r *= __x;
00411               for(int i = eval_data.n-1; i >= 0; i--)
00412                 (*eval_data.id_data)[__data.node_num][i] *= __x;
00413             }
00414             else
00415               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00416           }
00417           ++eval_data.n;
00418           // intersect with the known range
00419           if(eval_data.n == __data.n_children)
00420             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00421           break;
00422         case EXPRINFO_MAX:
00423           __calc_max(__rval * __data.coeffs[eval_data.n], __data);
00424           ++eval_data.n;
00425           if(eval_data.n == __data.n_children)
00426             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00427           break;
00428         case EXPRINFO_MIN:
00429           { interval h = __rval * __data.coeffs[eval_data.n];
00430             if(h.sup() < eval_data.r.inf())
00431             {
00432               for(unsigned int i = 0; i < eval_data.n; ++i)
00433                 (*eval_data.id_data)[__data.node_num][i] = 0;
00434               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00435                                   __data.coeffs[eval_data.n];
00436               eval_data.r = h;
00437               eval_data.u.info = eval_data.n;
00438             }
00439             else if(h.inf() > eval_data.r.sup())
00440               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00441             else
00442             {
00443               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00444                         __data.coeffs[eval_data.n] >= 0 ?
00445                               interval(0.,__data.coeffs[eval_data.n]):
00446                               interval(__data.coeffs[eval_data.n],0.);
00447               (*eval_data.id_data)[__data.node_num][eval_data.u.info] =
00448                         __data.coeffs[eval_data.u.info] >= 0 ?
00449                               interval(0.,__data.coeffs[eval_data.u.info]):
00450                               interval(__data.coeffs[eval_data.u.info],0.);
00451             }
00452           }
00453           ++eval_data.n;
00454           if(eval_data.n == __data.n_children)
00455             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00456           break;
00457         case EXPRINFO_SCPROD:
00458           { interval h = __data.coeffs[eval_data.n]*__rval;
00459             // if the number of children is odd, the list is implicitly
00460             // lengthened by one null element (i.e. implicitly shortened)
00461             if(eval_data.n & 1) // y_n
00462             {
00463               eval_data.r += interval(eval_data.u.d)*h;
00464               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00465                           interval(eval_data.u.d)*__data.coeffs[eval_data.n-1];
00466               (*eval_data.id_data)[__data.node_num][eval_data.n-1] =
00467                                                   h*__data.coeffs[eval_data.n];
00468             }
00469             else // x_n
00470               eval_data.u.d = h;
00471           }
00472           eval_data.n++;
00473           // intersect with the known range
00474           if(eval_data.n == __data.n_children)
00475             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00476           break;
00477         case EXPRINFO_NORM:
00478           if(__data.params.nd() == INFINITY)
00479             __calc_max(abs(__rval*__data.coeffs[eval_data.n]), __data);
00480           else
00481           { interval h = abs(__data.coeffs[eval_data.n]*__rval);
00482             eval_data.r += pow(h, interval(__data.params.nd()));
00483             (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00484                                 pow(h, interval(__data.params.nd())-1.);
00485           }
00486           eval_data.n++;
00487           // intersect with the known range
00488           if(eval_data.n == __data.n_children)
00489           {
00490             if(__data.params.nd() != INFINITY)
00491             {
00492               interval h = pow(eval_data.r, interval(1.)/__data.params.nd()-1.);
00493               for(unsigned int i = 0; i < eval_data.n; ++i)
00494                 (*eval_data.id_data)[__data.node_num][eval_data.n] *= h;
00495               eval_data.r = pow(eval_data.r, interval(1.)/__data.params.nd());
00496             }
00497             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00498           }
00499           break;
00500         case EXPRINFO_INVERT:
00501           { interval h = 1./__rval;
00502             eval_data.r *= h;
00503             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00504             (*eval_data.id_data)[__data.node_num][0] =
00505                                 -eval_data.r*eval_data.r/__data.params.nd();
00506           }
00507           break;
00508         case EXPRINFO_DIV:  // has two children
00509           if(eval_data.n++ == 0)
00510             eval_data.r = __rval;
00511           else
00512           {
00513             interval h = 1./__rval;
00514             eval_data.r *=
00515                 (*eval_data.id_data)[__data.node_num][0] = __data.params.nd()*h;
00516             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00517             (*eval_data.id_data)[__data.node_num][1] = -eval_data.r*h;
00518           }
00519           break;
00520         case EXPRINFO_SQUARE:
00521           { interval h = __data.coeffs[0]*__rval+__data.params.nd();
00522             eval_data.r = h*h;
00523             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00524             (*eval_data.id_data)[__data.node_num][0] = 2.*h*__data.coeffs[0];
00525           }
00526           break;
00527         case EXPRINFO_INTPOWER:
00528           { int hl = __data.params.nn();
00529             if(hl == 0)
00530             {
00531               eval_data.r = 1;
00532               (*eval_data.id_data)[__data.node_num][0] = 0;
00533             }
00534             else
00535             {
00536               interval kl = __data.coeffs[0]*__rval;
00537               switch(hl)
00538               {
00539                 case 1:
00540                   eval_data.r = kl;
00541                   (*eval_data.id_data)[__data.node_num][0] = __data.coeffs[0];
00542                   break;
00543                 case 2:
00544                   eval_data.r = kl*kl;
00545                   (*eval_data.id_data)[__data.node_num][0] =
00546                         2.*kl*__data.coeffs[0];
00547                   break;
00548                 case -1:
00549                   { interval h = 1./kl;
00550                     eval_data.r = h;
00551                     h = eval_data.r.
00552                                 intersect((*eval_data.range)[__data.node_num]);
00553                     (*eval_data.id_data)[__data.node_num][0] =
00554                                 -h*h/__data.coeffs[0];
00555                   }
00556                   break;
00557                 case -2:
00558                   { interval h = 1./kl;
00559                     interval k = h*h;
00560                     k.intersect((*eval_data.range)[__data.node_num]);
00561                     eval_data.r = k;
00562                     (*eval_data.id_data)[__data.node_num][0] =
00563                                                 -2.*h*k*__data.coeffs[0];
00564                   }
00565                   break;
00566                 default:
00567                   { interval h;
00568                     if(hl < 0)
00569                     {
00570                       h = ipow(kl, hl);
00571                       h.intersect((*eval_data.range)[__data.node_num]);
00572                       eval_data.r = h;
00573                       (*eval_data.id_data)[__data.node_num][0] =
00574                                         (hl+0.)*h*__data.coeffs[0];
00575                     }
00576                     else // hl > 0
00577                     {
00578                       h = ipow(kl, hl-1);
00579                       eval_data.r = ipow(kl, hl);
00580                       (*eval_data.id_data)[__data.node_num][0] =
00581                                         (hl+0.)*h*__data.coeffs[0];
00582                     }
00583                   }
00584                   break;
00585               }
00586             }
00587             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00588           }
00589           break;
00590         case EXPRINFO_SQROOT:
00591           { interval h = sqrt(__data.coeffs[0]*__rval+__data.params.nd());
00592             h.intersect((*eval_data.range)[__data.node_num]);
00593             eval_data.r = h;
00594             (*eval_data.id_data)[__data.node_num][0] = 0.5*__data.coeffs[0]/h;
00595           }
00596           break;
00597         case EXPRINFO_ABS:
00598           { interval h = __data.coeffs[0]*__rval+__data.params.nd();
00599             eval_data.r = abs(h);
00600             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00601             if(h.contains(0))
00602               h = interval(-1.,1.);
00603             else if(h.inf() > 0)
00604               h = 1.;
00605             else
00606               h = -1.;
00607             (*eval_data.id_data)[__data.node_num][0] = h*__data.coeffs[0];
00608           }
00609           break;
00610         case EXPRINFO_POW:
00611           { interval hh = __rval * __data.coeffs[eval_data.n];
00612             if(eval_data.n++ == 0)
00613               eval_data.r = hh+__data.params.nd();
00614             else
00615             { 
00616               if(hh == interval(0.))
00617               {
00618                 (*eval_data.id_data)[__data.node_num][0] = 0;
00619                 (*eval_data.id_data)[__data.node_num][1] =
00620                                   log(eval_data.r)*__data.coeffs[1];
00621                 eval_data.r = 1;
00622               }
00623               else
00624               {
00625                 interval h = pow(eval_data.r, hh);
00626                 h.intersect((*eval_data.range)[__data.node_num]);
00627 
00628                 (*eval_data.id_data)[__data.node_num][0] =
00629                          hh*pow(eval_data.r, hh-1.)*__data.coeffs[0];
00630                 (*eval_data.id_data)[__data.node_num][1] =
00631                                        log(eval_data.r)*h*__data.coeffs[1];
00632                 eval_data.r = h;
00633               }
00634             }
00635           }
00636           break;
00637         case EXPRINFO_EXP:
00638           { interval h = exp(__rval*__data.coeffs[0]+__data.params.nd());
00639             h.intersect((*eval_data.range)[__data.node_num]);
00640             eval_data.r = h;
00641             (*eval_data.id_data)[__data.node_num][0] = h*__data.coeffs[0];
00642           }
00643           break;
00644         case EXPRINFO_LOG:
00645           { interval h = __rval*__data.coeffs[0]+__data.params.nd();
00646             eval_data.r = log(h);
00647             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00648             (*eval_data.id_data)[__data.node_num][0] = __data.coeffs[0]/h;
00649           }
00650           break;
00651         case EXPRINFO_SIN:
00652           { interval h = __rval*__data.coeffs[0]+__data.params.nd();
00653             eval_data.r = sin(h);
00654             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00655             (*eval_data.id_data)[__data.node_num][0] = __data.coeffs[0]*cos(h);
00656           }
00657           break;
00658         case EXPRINFO_COS:
00659           { interval h = __rval*__data.coeffs[0]+__data.params.nd();
00660             eval_data.r = cos(h);
00661             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00662             (*eval_data.id_data)[__data.node_num][0] = -__data.coeffs[0]*sin(h);
00663           }
00664           break;
00665         case EXPRINFO_ATAN2:
00666           { interval hh = __rval * __data.coeffs[eval_data.n];
00667             if(eval_data.n++ == 0)
00668               eval_data.r = hh;
00669             else
00670             { interval h = eval_data.r;
00671               h *= h;
00672               h += hh*hh;
00673               (*eval_data.id_data)[__data.node_num][0] = __data.coeffs[0]*hh/h;
00674               (*eval_data.id_data)[__data.node_num][1] =
00675                                                   -__data.coeffs[1]*eval_data.r/h;
00676               eval_data.r = atan2(eval_data.r,hh);
00677               eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00678             }
00679           }
00680           break;
00681         case EXPRINFO_GAUSS:
00682           { interval h = (__data.coeffs[0]*__rval-__data.params.d()[0])/
00683                                 __data.params.d()[1];
00684             interval k = exp(-h*h);
00685             k.intersect((*eval_data.range)[__data.node_num]);
00686             eval_data.r = k;
00687             (*eval_data.id_data)[__data.node_num][0] =
00688                                  -2*__data.coeffs[0]*k*h/__data.params.d()[1];
00689           }
00690           break;
00691         case EXPRINFO_POLY:
00692           std::cerr << "Polynomes NYI" << std::endl;
00693           throw "NYI";
00694           break;
00695         case EXPRINFO_QUAD:
00696         case EXPRINFO_LIN:
00697           // we will never be here
00698           break;
00699         case EXPRINFO_IN:
00700           {
00701             __x = __data.coeffs[eval_data.n]*__rval;
00702             const interval& i(__data.params.i()[eval_data.n]);
00703             if(i.disjoint(__x))     // it is not in
00704             {
00705               eval_data.r = -1.;
00706               ret = -1;
00707               std::vector<interval>& r((*eval_data.id_data)[__data.node_num]);
00708               r.erase(r.begin(),r.end());
00709               r.insert(r.end(),__data.n_children,interval(0.));
00710             }
00711             else
00712             {
00713               if(!i.superset(__x))  // in and out are possible
00714               {
00715                 if(i.sup() == __x.inf() || i.inf() == __x.sup())
00716                 {
00717                   // intersection is only on the border
00718                   eval_data.r = interval(-1.,0.);
00719                   if(i.sup() == __x.inf())
00720                     (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00721                                                 interval(-INFINITY,0.);
00722                   else
00723                     (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00724                                                 interval(0.,INFINITY);
00725                 }
00726                 else
00727                 {
00728                   // intersection is big
00729                   if(eval_data.r.sup() > 0)
00730                     eval_data.r = interval(-1.,1.);
00731 
00732                   if(i.subset(__x))
00733                     (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00734                                                 interval(-INFINITY,INFINITY);
00735                   else if(__x.contains(i.inf()))
00736                     (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00737                                                 interval(0.,INFINITY);
00738                   else
00739                     (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00740                                                 interval(-INFINITY,0.);
00741                 }
00742               }
00743               else if(i.inf() == __x.inf() || i.sup() == __x.sup())
00744               // they are not disjoint, and i is a superset of __x
00745               // but a border is possible
00746               {
00747                 if(eval_data.r.inf() == 1.)
00748                 {
00749                   if(__x.is_thin())       // only border
00750                     eval_data.r = 0.;
00751                   else                    // interior and border possible
00752                     eval_data.r = interval(0.,1.);
00753                 }
00754                 else if(__x.is_thin() && eval_data.r.inf() == 0.)
00755                   eval_data.r = 0.;
00756                 if(__x.inf() == __x.sup())
00757                   (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00758                 else if(i.inf() == __x.inf() && i.sup() == __x.sup())
00759                   (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00760                                                   interval(-INFINITY,INFINITY);
00761                 else if(i.inf() == __x.inf())
00762                   (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00763                                                   interval(0.,INFINITY);
00764                 else
00765                   (*eval_data.id_data)[__data.node_num][eval_data.n] = 
00766                                                   interval(-INFINITY,0.);
00767               }
00768               else
00769               // if __x is in the interior of i eval_data.r does not change
00770                 (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00771             }
00772           }
00773           eval_data.n++;
00774           break;
00775         case EXPRINFO_IF:
00776           __x = __rval * __data.coeffs[eval_data.n];
00777           if(eval_data.n == 0) // this is the condition
00778           {
00779             const interval& i(__data.params.ni());
00780             if(i.superset(__x))      // always true
00781             {
00782               eval_data.u.info = 0;
00783               (*eval_data.id_data)[__data.node_num][0] = 0;
00784               (*eval_data.id_data)[__data.node_num][2] = 0;
00785             }
00786             else if(i.disjoint(__x)) // never true
00787             {
00788               eval_data.u.info = 1;
00789               (*eval_data.id_data)[__data.node_num][0] = 0;
00790               (*eval_data.id_data)[__data.node_num][1] = 0;
00791               ret = 1;               // skip if part
00792             }
00793             else                     // both is possible
00794               eval_data.u.info = 1;
00795           }
00796           else if(eval_data.n == 1)  // this is either the if or the else part
00797           {
00798             eval_data.r = __x;
00799             (*eval_data.id_data)[__data.node_num][1] = __data.coeffs[1];
00800             if(eval_data.u.info == 0)  // it was always true
00801               ret = -1;                // don't continue walking
00802           }
00803           else // this is the else part if both possibilities could be true
00804           {
00805             if(eval_data.u.info == 1)
00806               eval_data.r = __x;
00807             else
00808             {
00809               eval_data.r = eval_data.r.hull(__x);
00810               (*eval_data.id_data)[__data.node_num][0] =
00811                                                 interval(-INFINITY,INFINITY);
00812             }
00813             (*eval_data.id_data)[__data.node_num][2] = __data.coeffs[2];
00814           }
00815           if(eval_data.n == 2 || ret == -1)
00816             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00817           else
00818             eval_data.n += 1+ret;
00819           break;
00820         case EXPRINFO_AND:
00821           { __x = __data.coeffs[eval_data.n]*__rval;
00822             const interval& i(__data.params.i()[eval_data.n]);
00823             if(i.disjoint(__x))
00824             {
00825               eval_data.r = 0;
00826               std::vector<interval>& r((*eval_data.id_data)[__data.node_num]);
00827               r.erase(r.begin(),r.end());
00828               r.insert(r.end(),__data.n_children,interval(0.));
00829               ret = -1;
00830             }
00831             else if(!i.superset(__x))
00832             {
00833               double lo = 0, hi = 0;
00834               if(eval_data.r != 0)
00835                 eval_data.r = interval(0.,1.);
00836               if(__x.inf() < i.inf())
00837                 hi = INFINITY;
00838               if(__x.sup() > i.sup())
00839                 lo = -INFINITY;
00840               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00841                                                                interval(lo,hi);
00842             }
00843             else
00844               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00845           }
00846           eval_data.n++;
00847           // intersect with the known range
00848           if(eval_data.n == __data.n_children)
00849             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00850           break;
00851         case EXPRINFO_OR:
00852           { __x = __data.coeffs[eval_data.n]*__rval;
00853             const interval& i(__data.params.i()[eval_data.n]);
00854             if(i.superset(__x))
00855             {
00856               eval_data.r = 1;
00857               std::vector<interval>& r((*eval_data.id_data)[__data.node_num]);
00858               r.erase(r.begin(),r.end());
00859               r.insert(r.end(),__data.n_children,interval(0.));
00860               ret = -1;
00861             }
00862             else if(!i.disjoint(__x))
00863             {
00864               if(eval_data.r != 0)
00865                 eval_data.r = interval(0.,1.);
00866               double lo = 0, hi = 0;
00867               if(__x.inf() < i.inf())
00868                 hi = INFINITY;
00869               if(__x.sup() > i.sup())
00870                 lo = -INFINITY;
00871               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00872                                                                interval(lo,hi);
00873             }
00874             else
00875               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00876           }
00877           eval_data.n++;
00878           // intersect with the known range
00879           if(eval_data.n == __data.n_children)
00880             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00881           break;
00882         case EXPRINFO_NOT:
00883           { __x = __data.coeffs[0]*__rval;
00884             const interval& i(__data.params.ni());
00885             if(i.superset(__x))
00886             {
00887               eval_data.r = 0;
00888               (*eval_data.id_data)[__data.node_num][0] = 0;
00889             }
00890             else if(i.disjoint(__x))
00891             {
00892               eval_data.r = 1;
00893               (*eval_data.id_data)[__data.node_num][0] = 0;
00894             }
00895             else
00896             {
00897               eval_data.r = interval(0.,1.);
00898               double lo = 0, hi = 0;
00899               if(__x.inf() < i.inf())
00900                 lo = -INFINITY;
00901               if(__x.sup() > i.sup())
00902                 hi = INFINITY;
00903               (*eval_data.id_data)[__data.node_num][0] = interval(lo,hi);
00904             }
00905             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00906           }
00907           break;
00908         case EXPRINFO_IMPLIES:
00909           { const interval& i(__data.params.i()[eval_data.n]);
00910             __x = __rval * __data.coeffs[eval_data.n];
00911             if(eval_data.n == 0)
00912             {
00913               if(i.disjoint(__x))
00914               {
00915                 eval_data.r = 1.;
00916                 (*eval_data.id_data)[__data.node_num][0] = 0;
00917                 (*eval_data.id_data)[__data.node_num][1] = 0;
00918                 ret = -1;        // ex falso quodlibet
00919               }
00920               else if(!i.superset(__x))
00921               {
00922                 eval_data.r = interval(0.,1.);
00923                 double lo = 0, hi = 0;
00924                 if(__x.inf() < i.inf())
00925                   lo = -INFINITY;
00926                 if(__x.sup() > i.sup())
00927                   hi = INFINITY;
00928                 (*eval_data.id_data)[__data.node_num][0] = interval(lo,hi);
00929               }
00930               else
00931               {
00932                 eval_data.r = interval(0.);
00933                 (*eval_data.id_data)[__data.node_num][0] = 0;
00934               }
00935             }
00936             else // we only get here if first clause might be true
00937             {
00938               if(i.superset(__x)) // true result is always true
00939               {
00940                 eval_data.r = 1.;
00941                 (*eval_data.id_data)[__data.node_num][0] = 0;
00942                 (*eval_data.id_data)[__data.node_num][1] = 0;
00943               }
00944               else if(!i.disjoint(__x))
00945               {
00946                 eval_data.r = interval(0.,1.);
00947                 double lo = 0, hi = 0;
00948                 if(__x.inf() < i.inf())
00949                   hi = INFINITY;
00950                 if(__x.sup() > i.sup())
00951                   lo = -INFINITY;
00952                 (*eval_data.id_data)[__data.node_num][0] = interval(lo,hi);
00953               }
00954               else
00955                 (*eval_data.id_data)[__data.node_num][1] = 0;
00956               eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00957             }
00958             ++eval_data.n;
00959           }
00960           break;
00961         case EXPRINFO_COUNT:
00962           { __x = __data.coeffs[eval_data.n]*__rval;
00963             const interval& i(__data.params.i()[eval_data.n]);
00964             if(i.superset(__x))
00965             {
00966               eval_data.r += 1;
00967               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00968             }
00969             else if(!i.disjoint(__x))
00970             {
00971               eval_data.r += interval(0.,1.);
00972               double lo = 0, hi = 0;
00973               if(__x.inf() < i.inf())
00974                 hi = INFINITY;
00975               if(__x.sup() > i.sup())
00976                 lo = -INFINITY;
00977               (*eval_data.id_data)[__data.node_num][eval_data.n] =
00978                                                                interval(lo,hi);
00979             }
00980             else
00981               (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00982           }
00983           eval_data.n++;
00984           // intersect with the known range
00985           if(eval_data.n == __data.n_children)
00986             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
00987           break;
00988         case EXPRINFO_ALLDIFF:
00989           { int i; 
00990             std::vector<interval>::const_iterator _b;
00991             __x = __data.coeffs[eval_data.n]*__rval;
00992             (*eval_data.id_data)[__data.node_num][eval_data.n] = 0;
00993             for(_b = ((std::vector<interval>*)eval_data.u.p)->begin(), i = 0;
00994                 _b != ((std::vector<interval>*)eval_data.u.p)->end(); ++_b, ++i)
00995             {
00996               interval __h = abs(__x-*_b);
00997               if(__h.sup() <= __data.params.nd())  // they are always equal
00998               {
00999                 eval_data.r = 0;
01000                 std::vector<interval>& r((*eval_data.id_data)[__data.node_num]);
01001                 r.erase(r.begin(),r.end());
01002                 r.insert(r.end(),__data.n_children,interval(0.));
01003                 ret = -1;               // don't continue
01004                 break;
01005               }
01006               else if(__h.inf() <= __data.params.nd()) // they are not always different
01007               {
01008                 eval_data.r = interval(0.,1.);
01009                 (*eval_data.id_data)[__data.node_num][eval_data.n] =
01010                                                 interval(-INFINITY,INFINITY);
01011                 (*eval_data.id_data)[__data.node_num][i] =
01012                                                 interval(-INFINITY,INFINITY);
01013               }
01014             }
01015             if(ret != -1)
01016               ((std::vector<interval>*) eval_data.u.p)->push_back(__x);
01017           }
01018           eval_data.n++;
01019           if(eval_data.n == __data.n_children || ret == -1)
01020           {
01021             if(eval_data.r == 1.)       // all are always different
01022             {
01023               std::vector<interval>& r((*eval_data.id_data)[__data.node_num]);
01024               r.erase(r.begin(),r.end());
01025               r.insert(r.end(),__data.n_children,interval(0.));
01026             }
01027             delete (std::vector<interval>*) eval_data.u.p;
01028             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
01029           }
01030           break;
01031         case EXPRINFO_HISTOGRAM:
01032           std::cerr << "func_id_evaluator: histogram NYI" << std::endl;
01033           throw "NYI";
01034           break;
01035         case EXPRINFO_LEVEL:
01036           { // we have to make this one more complicated than
01037             // in the interval evaluation. For deciding the final
01038             // outcome, we (seemingly) need to know the results
01039             // for all before determining the derivatives
01040             int lo = 0;
01041             int hi = 0;
01042             __x = __data.coeffs[eval_data.n]*__rval;
01043             interval _h;
01044 
01045             // first adjust upper bound
01046             if(hi != INT_MAX)
01047             {
01048               while(hi < __data.params.im().nrows())
01049               { 
01050                 _h = __data.params.im()[hi][eval_data.n];
01051                 if(_h.superset(__x))
01052                   break;
01053                 hi++;
01054               }
01055               if(hi == __data.params.im().nrows())
01056                 hi = INT_MAX;
01057             }
01058             // then adjust lower bound
01059             if(lo != INT_MAX)
01060             {
01061               while(lo < __data.params.im().nrows())
01062               { 
01063                 _h = __data.params.im()[lo][eval_data.n];
01064                 if(!_h.disjoint(__x))
01065                   break;
01066                 lo++;
01067               }
01068               if(lo == __data.params.im().nrows())
01069                 lo = INT_MAX;
01070             }
01071             ((std::vector<interval>*)eval_data.u.p)->
01072                                         push_back(interval(lo+0.,hi+0.));
01073             eval_data.r = interval(std::min(eval_data.r.inf(),lo+0.),
01074                                    std::max(eval_data.r.sup(),hi+0.));
01075           }
01076           eval_data.n++;
01077           if(eval_data.n == __data.n_children)
01078           {
01079             std::vector<interval>& v(*((std::vector<interval>*)eval_data.u.p));
01080             for(unsigned int i = 0; i < __data.n_children; ++i)
01081             {
01082               if(v[i].is_thin() || v[i].sup() < eval_data.r.inf())
01083                 (*eval_data.id_data)[__data.node_num][i] = 0;
01084               else
01085                 (*eval_data.id_data)[__data.node_num][i] =
01086                                                 interval(0.,INFINITY);
01087             }
01088             delete (std::vector<interval>*)eval_data.u.p;
01089             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
01090           }
01091           break;
01092         case EXPRINFO_NEIGHBOR:
01093           // this is suboptimal. It does not take into account
01094           // all the possibilities to proove that the result actually
01095           // EQUALS 1
01096           // furthermore, it sets all derivatives to [-I,I] because
01097           // computing derivatives is nonsense, anyway
01098           (*eval_data.id_data)[__data.node_num][eval_data.n] =
01099                                                 interval(-INFINITY,INFINITY);
01100           if(eval_data.n == 0)
01101             eval_data.r = __data.coeffs[0]*__rval;
01102           else
01103           {
01104             interval h = eval_data.r;
01105             eval_data.r = 0;
01106             __x = __data.coeffs[1]*__rval;
01107             for(unsigned int i = 0; i < __data.params.n().size(); i+=2)
01108             {
01109               if(h == __data.params.n()[i]+0. &&
01110                  __x == __data.params.n()[i+1]+0.)
01111               {
01112                 eval_data.r = 1;
01113                 break;
01114               }
01115               else if(h.contains(__data.params.n()[i]+0.) &&
01116                       __x.contains(__data.params.n()[i+1]+0.))
01117               {
01118                 eval_data.r = interval(0.,1.);
01119                 break;
01120               }
01121             }
01122           }
01123           eval_data.n++;
01124           if(eval_data.n == __data.n_children)
01125             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
01126           break;
01127         case EXPRINFO_NOGOOD:
01128           // derivatives are nonsense here, so set them to [-I,I]
01129           (*eval_data.id_data)[__data.node_num][eval_data.n] =
01130                                                 interval(-INFINITY,INFINITY);
01131           __x = __data.coeffs[eval_data.n]*__rval;
01132           if(eval_data.r != 0.)
01133           { 
01134             if(!__x.contains(__data.params.n()[eval_data.n]+0.))
01135             {
01136               eval_data.r = 0.;
01137               ret = -1;
01138             }
01139             else if(__x != __data.params.n()[eval_data.n]+0.)
01140               eval_data.r = interval(0.,1.);
01141           }
01142           eval_data.n++;
01143           if(eval_data.n == __data.n_children)
01144             eval_data.r.intersect((*eval_data.range)[__data.node_num]);
01145           break;
01146         case EXPRINFO_EXPECTATION:
01147           std::cerr << "func_id_evaluator: E NYI" << std::endl;
01148           throw "NYI";
01149           break;
01150         case EXPRINFO_INTEGRAL:
01151           std::cerr << "func_id_evaluator: INT NYI" << std::endl;
01152           throw "NYI";
01153           break;
01154         case EXPRINFO_LOOKUP:
01155         case EXPRINFO_PWLIN:
01156         case EXPRINFO_SPLINE:
01157         case EXPRINFO_PWCONSTLC:
01158         case EXPRINFO_PWCONSTRC:
01159           std::cerr << "func_id_evaluator: Table Operations NYI" << std::endl;
01160           throw "NYI";
01161           break;
01162         case EXPRINFO_DET:
01163         case EXPRINFO_COND:
01164         case EXPRINFO_PSD:
01165         case EXPRINFO_MPROD:
01166         case EXPRINFO_FEM:
01167           std::cerr << "func_id_evaluator: Matrix Operations NYI" << std::endl;
01168           throw "NYI";
01169           break;
01170         case EXPRINFO_RE:
01171         case EXPRINFO_IM:
01172         case EXPRINFO_ARG:
01173         case EXPRINFO_CPLXCONJ:
01174           std::cerr << "func_id_evaluator: Complex Numbers NYI" << std::endl;
01175           throw "NYI";
01176           break;
01177         case EXPRINFO_CMPROD:
01178         case EXPRINFO_CGFEM:
01179           std::cerr << "func_id_evaluator: Const Matrix Operations NYI" << std::endl;
01180           throw "NYI";
01181           break;
01182         default:
01183           std::cerr << "ider_evaluator: unknown function type " <<
01184                   __data.operator_type << std::endl;
01185           throw "Programming error";
01186           break;
01187       }
01188     }
01189     else if(__data.operator_type > 0)
01190     {
01191 #if 0
01192       // think about this later
01193       // update the function arguments
01194       eval_data.r = __data.f_evaluate(eval_data.n++, __data.params.nn(),
01195                         *eval_data.x, *v_ind, eval_data.r, __rval,
01196                             &(*eval_data.id_data)[__data.node_num]);
01197 #endif
01198     }
01199     // use the cache only if it is worthwhile
01200     if(eval_data.f && __data.n_parents > 1 && __data.n_children > 0)
01201       (*eval_data.f)[__data.node_num] = eval_data.r;
01202     return ret;
01203   }
01204 
01205   interval calculate_value(bool eval_all)
01206   {
01207     return eval_data.r;
01208   }
01209 };
01210 
01211 struct ider_eval_type
01212 {
01213   std::vector<std::vector<interval> >* id_data;
01214   std::vector<std::vector<interval> >* d_cache;
01215   std::vector<interval>* grad_vec;
01216   const std::vector<interval>* x;
01217   const model* mod;
01218   interval mult;
01219   interval mult_trans;
01220   unsigned int child_n;
01221 };
01222 
01223 class ider_eval : public
01224   cached_backward_evaluator_base<ider_eval_type,expression_node,bool,
01225                                  model::walker>
01226 {
01227 private:
01228   typedef cached_backward_evaluator_base<ider_eval_type,expression_node,
01229                                          bool,model::walker> _Base;
01230 
01231 protected:
01232   bool is_cached(const node_data_type& __data)
01233      { 
01234        if(eval_data.d_cache && __data.n_parents > 1 && __data.n_children > 0
01235           && (*eval_data.d_cache)[__data.node_num].size() > 0 &&
01236           v_ind->match(__data.var_indicator()))
01237        {
01238          return true;
01239        }
01240        else
01241          return false;
01242      }
01243                                         
01244 public:
01245   ider_eval(std::vector<interval> __x,
01246       std::vector<std::vector<interval> >& __ider_data, variable_indicator& __v,
01247       const model& __m, std::vector<std::vector<interval > >* __d, 
01248       std::vector<interval>& __grad)
01249   { // __grad MUST BE INITIALIZED WITH 0 AND THE CORRECT LENGTH
01250     eval_data.id_data = &__ider_data;
01251     eval_data.d_cache = __d;
01252     eval_data.mod = &__m;
01253     eval_data.grad_vec = &__grad;
01254     eval_data.mult_trans = 1;
01255     eval_data.mult = 0;
01256     eval_data.x = &__x;
01257     v_ind = &__v;
01258   }
01259 
01260   ider_eval(const ider_eval& __d) { eval_data = __d.eval_data; }
01261 
01262   ~ider_eval() {}
01263 
01264   void new_box(std::vector<std::vector<interval> >& __ider_data,
01265                  const variable_indicator& __v)
01266   {
01267     eval_data.id_data = &__ider_data;
01268     v_ind = &__v;
01269   }
01270 
01271   void new_result(std::vector<interval>& __grad)
01272   {
01273     eval_data.grad_vec = &__grad;
01274   }
01275 
01276   void set_mult(double scal)
01277   {
01278     eval_data.mult_trans = scal;
01279   }
01280 public:
01281 
01282   model::walker short_cut_to(const expression_node& __data)
01283   { return eval_data.mod->node(0); }  // return anything - not needed
01284 
01285   // at virtual nodes (ground, sky)
01286   void initialize()
01287   {
01288     eval_data.child_n = 0;
01289   }
01290 
01291   // before the children are visited
01292   int calculate(const expression_node& __data)
01293   {
01294     if(__data.operator_type == EXPRINFO_CONSTANT)
01295       return 0;
01296     else if(__data.operator_type == EXPRINFO_VARIABLE)
01297     {
01298       // update the gradient
01299       (*eval_data.grad_vec)[__data.params.nn()] += eval_data.mult_trans;
01300       return 0;
01301     }
01302     else if(__data.operator_type == EXPRINFO_LIN)
01303     { // update the gradient
01304       const matrix<double>::Row& lrw(eval_data.mod->lin[__data.params.nn()]);
01305       matrix<double>::Row::const_iterator _x, _e;
01306       _e = lrw.end();
01307       for(_x = lrw.begin(); _x != _e; ++_x)
01308         (*eval_data.grad_vec)[_x.index()] += *_x * eval_data.mult_trans;
01309       return 0;     // don't perform the remaining graph walk
01310     }
01311     else if(__data.operator_type == EXPRINFO_QUAD)
01312     { // update the gradient
01313       throw "ider_evaluator: QUAD is NYI";
01314       return 0;
01315     }
01316     else if(__data.ev && (*__data.ev)[IDER_EVALUATOR])
01317     // is there a short-cut evaluator defined?
01318     {
01319 #if 0
01320       // think about this later
01321       linalg_ssum(*eval_data.grad_vec, eval_data.mult, 
01322           (*(ider_evaluator)(*__data.ev)[IDER_EVALUATOR])(
01323                               (*eval_data.id_data)[__data.node_num], *v_ind));
01324 #endif 
01325       return 0;     // don't perform the remaining graph walk
01326     }
01327     else if(eval_data.mult_trans == interval(0.))
01328     // does not contribute to grad
01329       return 0;
01330     else
01331     {
01332       eval_data.child_n = 1;
01333       eval_data.mult = eval_data.mult_trans;
01334       if(__data.n_parents > 1 && __data.n_children > 0 && eval_data.d_cache)
01335       { 
01336         eval_data.mult_trans = (*eval_data.id_data)[__data.node_num][0];
01337       }
01338       else // set multiplier for first child
01339         eval_data.mult_trans *= (*eval_data.id_data)[__data.node_num][0];
01340       return 1;
01341     }
01342   }
01343 
01344   // after all children have finished
01345   void cleanup(const expression_node& __data)
01346   {
01347     // use the cache only if it is worthwhile
01348     if(__data.n_parents > 1 && __data.n_children > 0 && eval_data.d_cache
01349        && (*eval_data.d_cache)[__data.node_num].size() == 0)
01350     {
01351       (*eval_data.d_cache)[__data.node_num] = *eval_data.grad_vec;
01352       linalg_smult(*eval_data.grad_vec, interval(eval_data.mult));
01353     }
01354   }
01355 
01356   void retrieve_from_cache(const expression_node& __data)
01357   {
01358     // the parallel f_cache MUST be initialized, too
01359     linalg_ssum(*eval_data.grad_vec, interval(eval_data.mult_trans), 
01360           (*eval_data.d_cache)[__data.node_num]);
01361   }
01362 
01363   int update(const bool& __rval)
01364   {
01365     eval_data.child_n++;
01366     return 0;
01367   }
01368 
01369   // after the current child is processed
01370   int update(const expression_node& __data, const bool& __rval)
01371   {
01372     if(__data.n_children == 0)
01373       return 0;
01374     if(__data.n_parents > 1 && __data.n_children > 0 && eval_data.d_cache)
01375     { 
01376       if(eval_data.child_n < __data.n_children)
01377         eval_data.mult_trans =
01378                 (*eval_data.id_data)[__data.node_num][eval_data.child_n];
01379     }
01380     else if(eval_data.child_n < __data.n_children)
01381     { // prepare multiplier for the next child
01382       eval_data.mult_trans = eval_data.mult *
01383                 (*eval_data.id_data)[__data.node_num][eval_data.child_n];
01384     }
01385     eval_data.child_n++;
01386     return 0;
01387   }
01388 
01389   bool calculate_value(bool eval_all)
01390   {
01391     return true;
01392   }
01393 };
01394 
01395 #endif /* _IDER_EVALUATOR_H_ */

Generated on Tue Nov 4 01:57:57 2003 for COCONUT API by doxygen1.2.18