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

islp_evaluator.h

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

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