MC++
|
00001 // Copyright (C) 2009-2013 Benoit Chachuat, Imperial College London. 00002 // All Rights Reserved. 00003 00378 #ifndef MC__TMODEL_H 00379 #define MC__TMODEL_H 00380 00381 #include <iostream> 00382 #include <iomanip> 00383 #include <typeinfo> 00384 #include <sstream> 00385 #include <string> 00386 #include <stdarg.h> 00387 #include <cassert> 00388 #include <climits> 00389 #include <stdlib.h> 00390 #include <complex> 00391 00392 #include "mcfunc.hpp" 00393 #include "mcop.hpp" 00394 00395 #undef MC__TMODEL_DEBUG 00396 #undef MC__TMODEL_DEBUG_SCALE 00397 #define MC__TMODEL_CHECK 00398 #undef MC__TVAR_DEBUG_EXP 00399 #undef MC__TVAR_DEBUG_EIGEN 00400 #undef MC__TVAR_DEBUG_BERSTEIN 00401 #undef MC__TVAR_HYBRID_EIGEN 00402 00403 extern "C" void dsyev_ 00404 ( const char*jobz, const char*uplo, const unsigned int*n, double*a, 00405 const unsigned int*lda, double*w, double*work, const int*lwork, int*info ); 00406 00407 namespace mc 00408 { 00409 00410 template <typename T> class TVar; 00411 typedef unsigned long long TM_size; 00412 00420 template <typename T> 00421 class TModel 00423 { 00424 friend class TVar<T>; 00425 template <typename U> friend class TModel; 00426 00427 template <typename U> friend TVar<U> inv 00428 ( const TVar<U>& ); 00429 template <typename U> friend TVar<U> sqrt 00430 ( const TVar<U>& ); 00431 template <typename U> friend TVar<U> log 00432 ( const TVar<U>& ); 00433 template <typename U> friend TVar<U> exp 00434 ( const TVar<U>& ); 00435 template <typename U> friend TVar<U> pow 00436 ( const TVar<U>&, const int ); 00437 00438 public: 00439 00443 00444 TModel 00445 ( const unsigned int nvar, const unsigned int nord ) 00446 { _size( nvar, nord ); } 00448 00449 ~TModel() 00450 { _cleanup(); } 00451 00453 unsigned int nvar() const 00454 { return _nvar; }; 00455 00457 unsigned int nord() const 00458 { return _nord; }; 00459 00461 unsigned int nmon() const 00462 { return _nmon; }; 00463 00465 const T* bndmon() const 00466 { return _bndmon; }; 00467 00469 const unsigned int* expmon() const 00470 { return _expmon; }; 00471 00473 unsigned int loc_expmon 00474 ( const unsigned int *iexp ) const 00475 { return _loc_expmon( iexp ); } 00476 00478 class Exceptions 00479 { 00480 public: 00482 enum TYPE{ 00483 DIV=1, 00484 EIGEN, 00485 BERNSTEIN, 00486 SIZE=-1, 00487 INIT=-2, 00488 INCON=-3, 00489 TMODEL=-4, 00490 MAXSIZE=-5, 00491 UNDEF=-33 00492 }; 00494 Exceptions( TYPE ierr ) : _ierr( ierr ){} 00496 int ierr(){ return _ierr; } 00498 std::string what(){ 00499 switch( _ierr ){ 00500 case DIV: 00501 return "mc::TModel\t Division by zero scalar"; 00502 case EIGEN: 00503 return "mc::TModel\t Range bounder with eigenvalue decomposition failed"; 00504 case BERNSTEIN: 00505 return "mc::TModel\t Bernstein remainder evalution failed"; 00506 case SIZE: 00507 return "mc::TModel\t Inconsistent Taylor model dimension"; 00508 case INIT: 00509 return "mc::TModel\t Taylor variable initialization failed"; 00510 case INCON: 00511 return "mc::TModel\t Inconsistent bounds with template parameter arithmetic"; 00512 case TMODEL: 00513 return "mc::TModel\t Operation between Taylor variables in different Taylor model environment not allowed"; 00514 case MAXSIZE: 00515 return "mc::TModel\t Maximum size in Taylor model reached"; 00516 case UNDEF: 00517 return "mc::Specbnd\t Feature not yet implemented in mc::Specbnd class"; 00518 default: 00519 return "mc::TModel\t Undocument error"; 00520 } 00521 } 00522 return "mc::TModel\t Undocument error"; 00523 } 00524 00525 private: 00526 TYPE _ierr; 00527 }; 00528 00530 struct Options 00531 { 00533 Options(): 00534 BOUNDER_TYPE(LSB), BOUNDER_ORDER(0), PROPAGATE_BNDT(false), 00535 INTER_WITH_BNDT(false), SCALE_VARIABLES(false), CENTER_REMAINDER(false), 00536 REF_MIDPOINT(true), REF_POLY(0.), BERNSTEIN_USE(false), 00537 BERNSTEIN_OPT(true), BERNSTEIN_MAXIT(100), BERNSTEIN_TOL(1e-10), 00538 DISPLAY_DIGITS(5) 00539 {} 00541 template <typename U> Options 00542 ( U&options ) 00543 : BOUNDER_TYPE( options.BOUNDER_TYPE ), 00544 BOUNDER_ORDER( options.BOUNDER_ORDER ), 00545 PROPAGATE_BNDT( options.PROPAGATE_BNDT ), 00546 INTER_WITH_BNDT( options.INTER_WITH_BNDT ), 00547 SCALE_VARIABLES( options.SCALE_VARIABLES ), 00548 CENTER_REMAINDER( options.CENTER_REMAINDER ), 00549 REF_MIDPOINT( options.REF_MIDPOINT ), 00550 REF_POLY(options.REF_POLY), 00551 BERNSTEIN_USE(options.BERNSTEIN_USE), 00552 BERNSTEIN_OPT(options.BERNSTEIN_OPT), 00553 BERNSTEIN_MAXIT(options.BERNSTEIN_MAXIT), 00554 BERNSTEIN_TOL(options.BERNSTEIN_TOL), 00555 DISPLAY_DIGITS(options.DISPLAY_DIGITS) 00556 {} 00558 template <typename U> Options& operator = 00559 ( U&options ){ 00560 BOUNDER_TYPE = options.BOUNDER_TYPE; 00561 BOUNDER_ORDER = options.BOUNDER_ORDER; 00562 PROPAGATE_BNDT = options.PROPAGATE_BNDT; 00563 INTER_WITH_BNDT = options.INTER_WITH_BNDT; 00564 SCALE_VARIABLES = options.SCALE_VARIABLES; 00565 CENTER_REMAINDER = options.CENTER_REMAINDER; 00566 REF_MIDPOINT = options.REF_MIDPOINT, 00567 REF_POLY = options.REF_POLY, 00568 BERNSTEIN_USE = options.BERNSTEIN_USE, 00569 BERNSTEIN_OPT = options.BERNSTEIN_OPT, 00570 BERNSTEIN_MAXIT = options.BERNSTEIN_MAXIT, 00571 BERNSTEIN_TOL = options.BERNSTEIN_TOL, 00572 DISPLAY_DIGITS = options.DISPLAY_DIGITS; 00573 return *this; 00574 } 00576 enum BOUNDER{ 00577 NAIVE=0, 00578 LSB, 00579 EIGEN, 00580 BERNSTEIN, 00581 HYBRID 00582 }; 00584 int BOUNDER_TYPE; 00586 unsigned int BOUNDER_ORDER; 00588 static const std::string BOUNDER_NAME[5]; 00590 bool PROPAGATE_BNDT; 00592 bool INTER_WITH_BNDT; 00594 bool SCALE_VARIABLES; 00596 bool CENTER_REMAINDER; 00598 bool REF_MIDPOINT; 00600 double REF_POLY; 00602 unsigned int BERNSTEIN_ORDER; 00604 bool BERNSTEIN_USE; 00606 bool BERNSTEIN_OPT; 00608 unsigned int BERNSTEIN_MAXIT; 00610 double BERNSTEIN_TOL; 00612 unsigned int DISPLAY_DIGITS; 00613 } options; 00616 00617 static void pause(); 00618 00619 private: 00621 unsigned int _nord; 00623 unsigned int _nvar; 00625 unsigned int _nmon; 00627 unsigned int *_posord; 00629 unsigned _posord_size; 00631 unsigned int *_expmon; 00633 unsigned _expmon_size; 00635 unsigned int **_prodmon; 00637 T *_bndmon; 00639 bool _modvar; 00641 TM_size *_binom; 00643 std::pair<unsigned int, unsigned int> _binom_size; 00645 T **_bndpow; 00647 double *_refpoint; 00649 double *_scaling; 00651 double *_cbern; 00652 00654 TVar<T>* _TV; 00655 00657 void _size 00658 ( const unsigned int nvar, const unsigned int nord ); 00659 00661 void _set_bndpow 00662 ( const unsigned int ivar, const T&X, const double Xref, 00663 const double scaling ); 00664 00666 void _set_bndmon(); 00667 00669 void _set_posord 00670 ( const unsigned int nord ); 00671 00673 void _ext_posord 00674 ( const unsigned int maxord ); 00675 00677 void _set_expmon 00678 ( const unsigned int nord ); 00679 00681 void _ext_expmon 00682 ( const unsigned int maxord, const bool full=false ); 00683 00685 void _next_expmon 00686 ( unsigned int *iexp, const unsigned int iord ) const; 00687 00689 void _set_prodmon(); 00690 00692 unsigned int _loc_expmon 00693 ( const unsigned int *iexp ) const; 00694 00696 void _set_binom 00697 ( const unsigned int nord ); 00698 00700 void _ext_binom 00701 ( const unsigned int nord ); 00702 00704 TM_size _get_binom 00705 ( const unsigned int n, const unsigned int k ) const; 00706 00708 void _scale 00709 ( const unsigned int ivar, double*coef ) const; 00710 00712 void _reset(); 00713 00715 void _cleanup(); 00716 00718 template< typename U > static void _display 00719 ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda, 00720 const std::string&stra, std::ostream&os ); 00721 00723 typedef double (puniv) 00724 ( const double x, const double*rusr, const int*iusr ); 00725 00727 typedef double (punivopt) 00728 ( const double x, const double*rusr, const int*iusr, puniv df, 00729 const T&I, const std::pair<unsigned int,const double*>&bern ); 00730 00732 typedef T (punivext) 00733 ( const T&x, const double*rusr, const int*iusr ); 00734 00736 TVar<T> _univ_bernstein 00737 ( const TVar<T>&TV, puniv f, puniv df, punivext If, 00738 punivext d2If, const double*rusr, const int*iusr ); 00739 00741 static double _gap_bernstein 00742 ( const double x, const double*rusr, const int*iusr, puniv df, 00743 const T&I, const std::pair<unsigned int,const double*>&bern ); 00744 00746 static double _dgap_bernstein 00747 ( const double x, const double*rusr, const int*iusr, puniv df, 00748 const T&I, const std::pair<unsigned int,const double*>&bern ); 00749 00751 double _goldsect 00752 ( const double xL, const double xU, punivopt fopt, const double*rusr, 00753 const int*iusr, puniv df, const T&Ix, 00754 const std::pair<unsigned int,const double*>&bern ); 00755 00757 double _goldsect_iter 00758 ( const bool init, const double a, const double fa, const double b, 00759 const double fb, const double c, const double fc, punivopt fopt, 00760 const double*rusr, const int*iusr, puniv df, const T&Ix, 00761 const std::pair<unsigned int,const double*>&bern ); 00762 00764 TVar<T> _intpow 00765 ( const TVar<T>&TV, const int n ); 00766 00768 TVar<T> _inv_taylor 00769 ( const TVar<T>&TV ); 00770 00772 TVar<T> _inv_bernstein 00773 ( const TVar<T>&TV ); 00774 00776 TVar<T> _sqrt_taylor 00777 ( const TVar<T>&TV ); 00778 00780 TVar<T> _sqrt_bernstein 00781 ( const TVar<T>&TV ); 00782 00784 TVar<T> _exp_taylor 00785 ( const TVar<T>&TV ); 00786 00788 TVar<T> _exp_bernstein 00789 ( const TVar<T>&TV ); 00790 00792 TVar<T> _log_taylor 00793 ( const TVar<T>&TV ); 00794 00796 TVar<T> _log_bernstein 00797 ( const TVar<T>&TV ); 00798 00800 static double* _eigen 00801 ( const unsigned int n, double*a ); 00802 } ; 00803 00804 template <typename T> const std::string TModel<T>::Options::BOUNDER_NAME[5] 00805 = { "NAIVE", "LSB", "EIGEN", "BERNSTEIN", "HYBRID" }; 00806 00813 template <typename T> 00814 class TVar 00816 { 00817 template <typename U> friend class TVar; 00818 template <typename U> friend class TModel; 00819 00820 template <typename U> friend TVar<U> operator+ 00821 ( const TVar<U>& ); 00822 template <typename U, typename V> friend TVar<U> operator+ 00823 ( const TVar<U>&, const TVar<V>& ); 00824 template <typename U, typename V> friend TVar<U> operator+ 00825 ( const TVar<U>&, const V& ); 00826 template <typename U, typename V> friend TVar<U> operator+ 00827 ( const V&, const TVar<U>& ); 00828 template <typename U> friend TVar<U> operator+ 00829 ( const double, const TVar<U>& ); 00830 template <typename U> friend TVar<U> operator+ 00831 ( const TVar<U>&, const double ); 00832 template <typename U> friend TVar<U> operator- 00833 ( const TVar<U>& ); 00834 template <typename U, typename V> friend TVar<U> operator- 00835 ( const TVar<U>&, const TVar<V>& ); 00836 template <typename U, typename V> friend TVar<U> operator- 00837 ( const TVar<U>&, const V& ); 00838 template <typename U, typename V> friend TVar<U> operator- 00839 ( const V&, const TVar<U>& ); 00840 template <typename U> friend TVar<U> operator- 00841 ( const double, const TVar<U>& ); 00842 template <typename U> friend TVar<U> operator- 00843 ( const TVar<U>&, const double ); 00844 template <typename U> friend TVar<U> operator* 00845 ( const TVar<U>&, const TVar<U>& ); 00846 template <typename U> friend TVar<U> operator* 00847 ( const double, const TVar<U>& ); 00848 template <typename U> friend TVar<U> operator* 00849 ( const TVar<U>&, const double ); 00850 template <typename U> friend TVar<U> operator* 00851 ( const U&, const TVar<U>& ); 00852 template <typename U> friend TVar<U> operator* 00853 ( const TVar<U>&, const U& ); 00854 template <typename U> friend TVar<U> operator/ 00855 ( const TVar<U>&, const TVar<U>& ); 00856 template <typename U> friend TVar<U> operator/ 00857 ( const double, const TVar<U>& ); 00858 template <typename U> friend TVar<U> operator/ 00859 ( const TVar<U>&, const double ); 00860 template <typename U> friend std::ostream& operator<< 00861 ( std::ostream&, const TVar<U>& ); 00862 00863 template <typename U> friend TVar<U> inv 00864 ( const TVar<U>& ); 00865 template <typename U> friend TVar<U> sqr 00866 ( const TVar<U>& ); 00867 template <typename U> friend TVar<U> sqrt 00868 ( const TVar<U>& ); 00869 template <typename U> friend TVar<U> exp 00870 ( const TVar<U>& ); 00871 template <typename U> friend TVar<U> log 00872 ( const TVar<U>& ); 00873 template <typename U> friend TVar<U> xlog 00874 ( const TVar<U>& ); 00875 template <typename U> friend TVar<U> pow 00876 ( const TVar<U>&, const int ); 00877 template <typename U> friend TVar<U> pow 00878 ( const TVar<U>&, const double ); 00879 template <typename U> friend TVar<U> pow 00880 ( const double, const TVar<U>& ); 00881 template <typename U> friend TVar<U> pow 00882 ( const TVar<U>&, const TVar<U>& ); 00883 template <typename U> friend TVar<U> monomial 00884 ( const unsigned int, const TVar<U>*, const int* ); 00885 template <typename U> friend TVar<U> cos 00886 ( const TVar<U>& ); 00887 template <typename U> friend TVar<U> sin 00888 ( const TVar<U>& ); 00889 template <typename U> friend TVar<U> tan 00890 ( const TVar<U>& ); 00891 template <typename U> friend TVar<U> acos 00892 ( const TVar<U>& ); 00893 template <typename U> friend TVar<U> asin 00894 ( const TVar<U>& ); 00895 template <typename U> friend TVar<U> atan 00896 ( const TVar<U>& ); 00897 template <typename U> friend TVar<U> hull 00898 ( const TVar<U>&, const TVar<U>& ); 00899 template <typename U> friend bool inter 00900 ( TVar<U>&, const TVar<U>&, const TVar<U>& ); 00901 00902 private: 00904 TModel<T> *_TM; 00906 TVar<T>* _TV() const 00907 { return _TM->_TV; }; 00909 unsigned int _nord() const 00910 { return _TM->_nord; }; 00912 unsigned int _nvar() const 00913 { return _TM->_nvar; }; 00915 unsigned int _nmon() const 00916 { return _TM->_nmon; }; 00918 unsigned int _posord 00919 ( const unsigned int iord ) const 00920 { return _TM->_posord[iord]; }; 00922 const unsigned int* _expmon 00923 ( const unsigned int imon ) const 00924 { return _TM->_expmon+imon*_TM->_nvar; }; 00926 unsigned int _prodmon 00927 ( const unsigned int imon, const unsigned int jmon ) const 00928 { return _TM->_prodmon[imon][jmon]; }; 00930 const T& _bndmon 00931 ( const unsigned int imon ) const 00932 { return _TM->_bndmon[imon]; }; 00934 double _refpoint 00935 ( const unsigned int ivar ) const 00936 { return _TM->_refpoint[ivar]; }; 00938 double _scaling 00939 ( const unsigned int ivar ) const 00940 { return _TM->_scaling[ivar]; }; 00941 00942 public: 00946 00947 TVar 00948 ( const double d=0. ); 00950 TVar 00951 ( const T&B ); 00953 TVar 00954 ( TModel<T>*TM, const unsigned int ix, const T&X, 00955 const double Xref ); 00957 TVar 00958 ( TModel<T>*TM, const unsigned int ix, const T&X ); 00960 TVar 00961 ( const TVar<T>&TV ); 00963 template <typename U> TVar 00964 ( TModel<T>*&TM, const TVar<U>&TV ); 00966 template <typename U> TVar 00967 ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const ); 00969 template <typename U> TVar 00970 ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) ); 00971 00973 ~TVar() 00974 { delete [] _coefmon; delete [] _bndord; } 00975 00977 TVar<T>& set 00978 ( TModel<T>*TM, const unsigned int ix, const T&X ) 00979 { *this = TVar( TM, ix, X ); return *this; } 00980 00982 TVar<T>& set 00983 ( TModel<T>*TM, const unsigned int ix, const T&X, 00984 const double Xref ) 00985 { *this = TVar( TM, ix, X, Xref ); return *this; } 00986 00988 TVar<T>& set 00989 ( TModel<T>*env ) 00990 { *this = TVar( env ); return *this; } 00991 00993 TVar<T>& set 00994 ( const double*coefmon ) 00995 { for( unsigned int imon=0; imon<(_TM?_nmon():1); imon++ ) 00996 _coefmon[imon] = coefmon[imon]; 00997 _update_bndord(); return *this; } 00998 01000 TVar<T>& set 01001 ( std::pair<unsigned int, const double*> coefmon ) 01002 { for( unsigned int imon=0; imon<(_TM?_nmon():1); imon++ ) 01003 _coefmon[imon] = ( imon<coefmon.first && coefmon.second? 01004 coefmon.second[imon]: 0. ); 01005 _update_bndord(); return *this; } 01006 01008 TVar<T>& set 01009 ( const T&bndrem ) 01010 { *_bndrem = bndrem; _update_bndord(); return *this; } 01011 01013 TVar<T>& set 01014 ( TVar<T>& TV, const bool reset=true ) 01015 { if( !_TM || !TV._TM || _nvar() < TV._nvar() || _nord() < TV._nord() ) 01016 return *this; 01017 // Reset coefficients to 0 01018 for( unsigned int imon=0; reset && imon<_nmon(); imon++ ) 01019 _coefmon[imon] = 0.; 01020 // Copy coefficients from TV --> *this 01021 unsigned int*iexp = new unsigned int[_nvar()]; 01022 for( unsigned int jmon=0; jmon<TV._nmon(); jmon++ ){ 01023 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 01024 iexp[ivar] = (ivar<TV._nvar()? TV._TM->_expmon[jmon*TV._nvar()+ivar]: 0); 01025 _coefmon[_TM->_loc_expmon(iexp)] = TV._coefmon[jmon]; 01026 } 01027 delete[] iexp; 01028 *_bndrem = *TV._bndrem; _update_bndord(); return *this; } 01029 01031 TVar<T>& get 01032 ( TVar<T>&TV, const bool reset=false ) 01033 { if( !_TM ){ 01034 TV._coefmon[0] = _coefmon[0]; 01035 // Reset coefficients to 0 01036 if( reset ) _coefmon[0] = 0.; 01037 return *this; 01038 } 01039 if( !TV._TM || _nvar() < TV._nvar() || _nord() < TV._nord() ) 01040 return *this; 01041 // Copy coefficients from *this --> TV 01042 unsigned int*iexp = new unsigned int[_nvar()]; 01043 for( unsigned int jmon=0; jmon<(TV._TM?TV._nmon():1); jmon++ ){ 01044 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 01045 iexp[ivar] = (ivar<TV._nvar()? TV._TM->_expmon[jmon*TV._nvar()+ivar]: 0); 01046 TV._coefmon[jmon] = _coefmon[_TM->_loc_expmon(iexp)]; 01047 // Reset coefficients to 0 01048 if( reset ) _coefmon[_TM->_loc_expmon(iexp)] = 0.; 01049 } 01050 delete[] iexp; 01051 if( reset ) _update_bndord(); 01052 *TV._bndrem = 0.; TV._update_bndord(); return *this; } 01053 01055 TModel<T>* env() const 01056 { return _TM; } 01057 01059 T bound 01060 ( const unsigned int iord ) const 01061 { return (!iord || (_TM && iord<=_nord()))? _bndord[iord]: 0.; } 01062 01064 T bound() const 01065 { T bndmod; return _bound( bndmod ); } 01066 01068 const T& boundT() const 01069 { return _bndT; } 01070 01072 T remainder() const 01073 { return( *_bndrem ); } 01074 01076 TVar<T>& center() 01077 { _center_TM(); return *this; } 01078 01080 TVar<T> polynomial() const 01081 { TVar<T> TV = *this; *(TV._bndrem) = 0.; return TV; } 01082 01084 double polynomial 01085 ( const double*x ) const; 01086 01088 T B 01089 ( const unsigned int iord ) const 01090 { return iord<=_nord()? _bndord[iord]: 0.; } 01091 01093 T B() const 01094 { T bndmod; return _bound( bndmod ); } 01095 01097 T R() const 01098 { return remainder(); } 01099 01101 TVar<T>& C() 01102 { return center(); } 01103 01105 TVar<T> P() const 01106 { return polynomial(); } 01107 01109 double P 01110 ( const double*x ) const 01111 { return polynomial( x ); } 01112 01114 double* reference() const; 01115 01117 double constant() const; 01118 01120 double* linear() const; 01121 01123 double linear 01124 ( const unsigned int ivar, const bool reset=false ); 01125 01127 double coefmon 01128 ( const unsigned int*iexp ) const; 01129 01131 std::pair<unsigned int, const double*> coefmon() const; 01132 01134 std::pair<unsigned int, const unsigned int*> expmon() const; 01137 TVar<T>& operator = 01138 ( const double ); 01139 TVar<T>& operator = 01140 ( const TVar<T>& ); 01141 TVar<T>& operator = 01142 ( const T& ); 01143 template <typename U> TVar<T>& operator += 01144 ( const TVar<U>& ); 01145 template <typename U> TVar<T>& operator += 01146 ( const U& ); 01147 TVar<T>& operator += 01148 ( const double ); 01149 template <typename U> TVar<T>& operator -= 01150 ( const TVar<U>& ); 01151 template <typename U> TVar<T>& operator -= 01152 ( const U& ); 01153 TVar<T>& operator -= 01154 ( const double ); 01155 TVar<T>& operator *= 01156 ( const TVar<T>& ); 01157 TVar<T>& operator *= 01158 ( const double ); 01159 TVar<T>& operator *= 01160 ( const T& ); 01161 TVar<T>& operator /= 01162 ( const TVar<T>& ); 01163 TVar<T>& operator /= 01164 ( const double ); 01165 01166 private: 01167 01169 TVar 01170 ( TModel<T>*TM, const double d=0. ); 01172 TVar 01173 ( TModel<T>*TM, const T&B ); 01174 01176 double *_coefmon; 01178 T * _bndord; 01180 T * _bndrem; 01182 T _bndT; 01183 01185 void _update_bndord(); 01187 void _center_TM(); 01188 01190 T& _bound 01191 ( T& bndmod ) const; 01193 T& _bound_naive 01194 ( T& bndmod ) const; 01196 T& _bound_LSB 01197 ( T& bndmod ) const; 01199 T& _bound_eigen 01200 ( T& bndmod ) const; 01202 T& _bound_bernstein 01203 ( T& bndmod ) const; 01205 double _coef_bernstein 01206 ( const double*coefmon, const unsigned int*jexp, 01207 const unsigned int jmon, const unsigned int maxord ) const; 01208 01210 void _init(); 01212 void _reinit(); 01214 void _clean(); 01215 01216 }; 01217 01219 01220 template <typename T> inline void 01221 TModel<T>::_size 01222 ( const unsigned int nvar, const unsigned int nord ) 01223 { 01224 if( !nvar ) throw Exceptions( Exceptions::SIZE ); 01225 01226 //_cleanup(); 01227 _nvar = nvar; 01228 _nord = nord; 01229 _binom = new TM_size[(nvar+nord-1)*(nord+1)]; 01230 _binom_size = std::make_pair( nvar+nord-1, nord+1 ); 01231 _set_binom( nord ); 01232 _posord = new unsigned int[nord+2]; 01233 _posord_size = nord; 01234 _set_posord( nord ); 01235 _nmon = _posord[_nord+1]; 01236 _expmon = new unsigned int[_nmon*nvar]; 01237 _expmon_size = _nmon; 01238 _set_expmon( nord ); 01239 _set_prodmon(); 01240 _bndpow = new T*[_nvar]; 01241 for( unsigned int i=0; i<_nvar; i++ ) _bndpow[i] = 0; 01242 _bndmon = new T[_nmon]; 01243 _refpoint = new double[_nvar]; 01244 _scaling = new double[_nvar]; 01245 _modvar = true; 01246 _cbern = new double[_nord+1]; 01247 01248 _TV = new TVar<T>( this ); 01249 } 01250 01251 template <typename T> inline void 01252 TModel<T>::_set_bndpow 01253 ( const unsigned int ivar, const T&X, const double Xref, 01254 const double scaling ) 01255 { 01256 if( ivar>=_nvar ) throw Exceptions( Exceptions::INIT ); 01257 01258 delete[] _bndpow[ivar]; 01259 _bndpow[ivar] = new T [_nord+1]; 01260 _refpoint[ivar] = Xref/scaling; 01261 _scaling[ivar] = scaling; 01262 T Xr = X/scaling - _refpoint[ivar]; 01263 _bndpow[ivar][0] = 1.; 01264 for( unsigned int i=1; i<=_nord; i++ ){ 01265 _bndpow[ivar][i] = Op<T>::pow(Xr,(int)i); 01266 } 01267 _modvar = true; 01268 } 01269 01270 template <typename T> inline void 01271 TModel<T>::_set_bndmon() 01272 { 01273 if( !_modvar ) return; 01274 01275 _bndmon[0] = 1.; 01276 for( unsigned int i=1; i<_nmon; i++ ){ 01277 _bndmon[i] = 1.; 01278 for( unsigned int j=0; j<_nvar; j++) 01279 if( _bndpow[j] ) _bndmon[i] *= _bndpow[j][_expmon[i*_nvar+j]]; 01280 } 01281 _modvar = false; 01282 01283 #ifdef MC__TMODEL_DEBUG 01284 _display( 1, _nmon, _bndmon, 1, "_bndmon", std::cout ); 01285 #endif 01286 } 01287 01288 template <typename T> inline void 01289 TModel<T>::_set_posord 01290 ( const unsigned int nord ) 01291 { 01292 _posord[0] = 0; 01293 _posord[1] = 1; 01294 for( unsigned int i=1; i<=nord; i++ ){ 01295 TM_size _posord_next = _posord[i] + _get_binom( _nvar+i-1, i ); 01296 if( _posord_next > UINT_MAX ) 01297 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::MAXSIZE ); 01298 _posord[i+1] = _posord_next; 01299 } 01300 01301 #ifdef MC__TMODEL_DEBUG 01302 _display( 1, nord+2, _posord, 1, "_posord", std::cout ); 01303 #endif 01304 } 01305 01306 template <typename T> inline void 01307 TModel<T>::_ext_posord 01308 ( const unsigned int maxord ) 01309 { 01310 if( maxord < _posord_size ) return; 01311 delete[] _posord; 01312 _posord = new unsigned int[maxord+2]; 01313 _posord_size = maxord; 01314 _set_posord( maxord ); 01315 } 01316 01317 template <typename T> inline void 01318 TModel<T>::_set_expmon 01319 ( const unsigned int nord ) 01320 { 01321 unsigned int *iexp = new unsigned int[_nvar] ; 01322 for( unsigned int k=0; k<_nvar; k++ ) _expmon[k] = 0; 01323 for( unsigned int i=1; i<=nord; i++ ){ 01324 for( unsigned int j=0; j<_nvar; j++ ) iexp[j] = 0; 01325 for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){ 01326 _next_expmon( iexp, i ); 01327 for( unsigned int k=0; k<_nvar; k++ ) 01328 _expmon[j*_nvar+k] = iexp[k]; 01329 } 01330 } 01331 delete[] iexp; 01332 01333 #ifdef MC__TMODEL_DEBUG 01334 _display( _nvar, _expmon_size, _expmon, _nvar, "_expmon", std::cout ); 01335 #endif 01336 } 01337 01338 template <typename T> inline void 01339 TModel<T>::_next_expmon 01340 ( unsigned int *iexp, const unsigned int iord ) const 01341 { 01342 unsigned int curord; 01343 do{ 01344 iexp[_nvar-1] += iord; 01345 unsigned int j = _nvar; 01346 while( j > 0 && iexp[j-1] > iord ){ 01347 iexp[j-1] -= iord + 1; 01348 j-- ; 01349 iexp[j-1]++; 01350 } 01351 curord = 0; 01352 for( unsigned int i=0; i<_nvar; i++ ) curord += iexp[i]; 01353 } while( curord != iord ); 01354 } 01355 01356 template <typename T> inline void 01357 TModel<T>::_ext_expmon 01358 ( const unsigned int maxord, const bool full ) 01359 { 01360 _ext_binom( maxord ); 01361 _ext_posord( maxord ); 01362 delete[] _expmon; 01363 if( full ) _expmon_size = std::pow(maxord+1,_nvar); 01364 else _expmon_size = _posord[maxord+1]; 01365 _expmon = new unsigned int[ _expmon_size*_nvar]; 01366 _set_expmon( maxord ); 01367 if( !full ) return; 01368 01369 unsigned int *iexp = new unsigned int[_nvar]; 01370 for( unsigned int iord=maxord+1, jmon=_posord[maxord+1]; 01371 jmon<_expmon_size; iord++ ){ 01372 _ext_binom( iord ); 01373 _ext_posord( iord ); 01374 if( _posord[iord] >= _posord[iord+1] ) 01375 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::MAXSIZE ); 01376 for( unsigned int ivar=0; ivar<_nvar; ivar++ ) iexp[ivar] = 0; 01377 for( unsigned int kmon=_posord[iord]; kmon<_posord[iord+1]; kmon++ ){ 01378 _next_expmon( iexp, iord ); 01379 bool lt_maxord = true; 01380 for( unsigned int ivar=0; ivar<_nvar; ivar++ ){ 01381 if( iexp[ivar] > maxord ){ lt_maxord = false; break; } 01382 _expmon[jmon*_nvar+ivar] = iexp[ivar]; 01383 } 01384 if( lt_maxord ){ 01385 #ifdef MC__TMODEL_DEBUG 01386 std::cout << jmon << ":"; 01387 for( unsigned int ivar=0; ivar<_nvar; ivar++ ) 01388 std::cout << " " << _expmon[jmon*_nvar+ivar]; 01389 std::cout << std::endl; 01390 #endif 01391 jmon++; 01392 } 01393 } 01394 } 01395 delete[] iexp; 01396 return; 01397 } 01398 01399 template <typename T> inline void 01400 TModel<T>::_set_prodmon() 01401 { 01402 _prodmon = new unsigned int*[_nmon]; 01403 _prodmon[0] = new unsigned int[_nmon+1]; 01404 _prodmon[0][0] = _nmon; 01405 for( unsigned int i=1; i<=_nmon; i++ ) _prodmon[0][i] = i-1; 01406 #ifdef MC__TMODEL_DEBUG 01407 std::ostringstream ohead0; 01408 ohead0 << "_prodmon[" << 0 << "]"; 01409 _display( 1, _nmon+1, _prodmon[0], 1, ohead0.str(), std::cout ); 01410 #endif 01411 01412 unsigned int *iexp = new unsigned int[_nvar]; 01413 for( unsigned int i=1; i<_nord; i++ ){ 01414 for( unsigned int j=_posord[i]; j<_posord[i+1]; j++ ){ 01415 _prodmon[j] = new unsigned int [_posord[_nord+1-i]+1]; 01416 _prodmon[j][0] = _posord[_nord+1-i]; 01417 for( unsigned int k=0; k<_posord[_nord+1-i]; k++ ){ 01418 for( unsigned int in=0; in<_nvar; in++ ) 01419 iexp[in] = _expmon[j*_nvar+in] + _expmon[k*_nvar+in] ; 01420 _prodmon[j][k+1] = _loc_expmon( iexp ); 01421 } 01422 #ifdef MC__TMODEL_DEBUG 01423 std::ostringstream oheadj; 01424 oheadj << "_prodmon[" << j << "]"; 01425 _display( 1, _posord[_nord+1-i]+1, _prodmon[j], 1, oheadj.str(), std::cout ); 01426 #endif 01427 } 01428 } 01429 delete[] iexp; 01430 01431 for( unsigned int i=_posord[_nord]; i<_nmon; i++ ){ 01432 _prodmon[i] = new unsigned int[2]; 01433 _prodmon[i][0] = 1; 01434 _prodmon[i][1] = i; 01435 #ifdef MC__TMODEL_DEBUG 01436 std::ostringstream oheadi; 01437 oheadi << "_prodmon[" << i << "]"; 01438 _display( 1, 2, _prodmon[i], 1, oheadi.str(), std::cout ); 01439 #endif 01440 } 01441 } 01442 01443 template <typename T> inline unsigned int 01444 TModel<T>::_loc_expmon 01445 ( const unsigned int *iexp ) const 01446 { 01447 unsigned int ord = 0; 01448 for( unsigned int i=0; i<_nvar; i++ ) ord += iexp[i]; 01449 assert( ord<_nord+2 ); 01450 unsigned int pos = _posord[ord]; 01451 01452 unsigned int p = _nvar ; 01453 for( unsigned int i=0; i<_nvar-1; i++ ){ 01454 p--; 01455 for( unsigned int j=0; j<iexp[i]; j++ ) 01456 pos += _get_binom( p-1+ord-j, ord-j ); 01457 ord -= iexp[i]; 01458 } 01459 01460 return pos; 01461 } 01462 01463 template <typename T> inline void 01464 TModel<T>::_set_binom 01465 ( const unsigned int nord ) 01466 { 01467 TM_size *p; 01468 unsigned int k; 01469 for( unsigned int i=0; i<_nvar+nord-1; i++ ){ 01470 p = &_binom[i*(nord+1)]; 01471 *p = 1; 01472 p++; 01473 *p = i+1; 01474 p++; 01475 k = ( i+1<nord? i+1: nord ); 01476 for( unsigned int j=2; j<=k; j++, p++ ) *p = *(p-1) * (i+2-j)/j; 01477 for( unsigned int j=k+1; j<=nord; j++, p++ ) *p = 0.; 01478 } 01479 #ifdef MC__TMODEL_DEBUG 01480 _display( _binom_size.second, _binom_size.first, _binom, 01481 _binom_size.second, "_binom", std::cout ); 01482 #endif 01483 } 01484 01485 template <typename T> inline void 01486 TModel<T>::_ext_binom 01487 ( const unsigned int maxord ) 01488 { 01489 if( maxord < _binom_size.second ) return; 01490 delete[] _binom; 01491 _binom = new TM_size[(_nvar+maxord-1)*(maxord+1)]; 01492 _binom_size = std::make_pair( _nvar+maxord-1, maxord+1 ); 01493 _set_binom( maxord ); 01494 } 01495 01496 template <typename T> inline TM_size 01497 TModel<T>::_get_binom 01498 ( const unsigned int n, const unsigned int k ) const 01499 { 01500 #ifdef MC__TMODEL_CHECK 01501 assert( n<=_binom_size.first ); 01502 assert( k<=_binom_size.second ); 01503 assert( k<=n ); 01504 #endif 01505 return( n? _binom[(n-1)*_binom_size.second+k]: 1. ); 01506 } 01507 01508 template <typename T> inline void 01509 TModel<T>::_scale 01510 ( const unsigned int ivar, double*coef ) const 01511 { 01512 if( ivar>=_nvar || !_nord ) return; 01513 double dscale = Op<T>::diam(_bndpow[ivar][1]); 01514 double fscale = Op<T>::l(_bndpow[ivar][1]) / dscale; 01515 unsigned int iexp[_nvar]; 01516 for( unsigned int imon=0; imon<_nmon; imon++ ){ 01517 unsigned int iord = 0; 01518 for( unsigned int jvar=0; jvar<_nvar; jvar++ ){ 01519 iexp[jvar] = _expmon[imon*_nvar+jvar]; 01520 iord += iexp[jvar]; 01521 } 01522 double coefmod = coef[imon] * std::pow(dscale,iexp[ivar]); 01523 iexp[ivar]++; 01524 for( unsigned int k=1; k<=_nord-iord; k++, iexp[ivar]++ ){ 01525 coefmod += coef[_loc_expmon(iexp)] 01526 * _get_binom(iexp[ivar],k) * std::pow(fscale,k) 01527 * std::pow(dscale,iexp[ivar]); 01528 } 01529 #ifdef MC__TMODEL_DEBUG_SCALE 01530 std::cout << " a" << std::left << std::setw(3) << imon << " = " 01531 << std::right << std::setw(12) << coef[imon] 01532 << std::right << std::setw(14) << coefmod << std::endl; 01533 #endif 01534 coef[imon] = coefmod; 01535 } 01536 return; 01537 } 01538 01539 template <typename T> inline TVar<T> 01540 TModel<T>::_univ_bernstein 01541 ( const TVar<T>&TV, puniv f, puniv df, punivext If, 01542 punivext d2If, const double*rusr, const int*iusr ) 01543 { 01544 assert( TV._TM == this ); 01545 01546 const T B( TV.B() ); 01547 const TVar<T> TVs( (TV-Op<T>::l(B))/Op<T>::diam(B) ); 01548 TVar<T> TV2( this, 0. ), MON( 1. ); 01549 for( unsigned int j=0; j<=_nord; j++ ){ 01550 double sign = ( j%2? -1.: 1. ); 01551 _cbern[j] = sign * _get_binom(_nord,j) * f( Op<T>::l(B), rusr, iusr ); 01552 for( unsigned int i=1; i<=j; i++ ){ 01553 sign *= -1.; 01554 _cbern[j] += sign * _get_binom(_nord,i) * _get_binom(_nord-i,j-i) 01555 * f( Op<T>::l(B)+(double)i/(double)_nord*Op<T>::diam(B), rusr, iusr ); 01556 } 01557 TV2 += _cbern[j] * MON; 01558 MON *= TVs; 01559 } 01560 01561 T R( - d2If( B, rusr, iusr ) * sqr(Op<T>::diam(B)) / 2. / _nord ); 01562 if( Op<T>::l( R ) * Op<T>::u( R ) < 0 ) 01563 return TV2 + Op<T>::zeroone() * R; 01564 01565 if( !options.BERNSTEIN_OPT ){ 01566 T R0( If(B,rusr,iusr) ); 01567 R = Op<T>::zeroone() * ( Op<T>::u(R) <= 0.? 01568 -std::min( Op<T>::diam(R0), -Op<T>::l(R) ): 01569 std::min( Op<T>::diam(R0), Op<T>::u(R) ) ); 01570 return TV2 + R; 01571 } 01572 01573 std::pair<unsigned int,const double*> bern = std::make_pair(_nord+1,_cbern); 01574 double xopt = _goldsect( 0., 1., _dgap_bernstein, rusr, iusr, df, B, bern ); 01575 R = Op<T>::zeroone() * _gap_bernstein( xopt, rusr, iusr, f, B, bern ); 01576 return TV2 + R; 01577 } 01578 01579 template <typename T> inline double 01580 TModel<T>::_dgap_bernstein 01581 ( const double x, const double*rusr, const int*iusr, puniv df, 01582 const T&B, const std::pair<unsigned int,const double*>&bern ) 01583 { 01584 double phi = df(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr)*Op<T>::diam(B); 01585 for( unsigned int j=1; j<bern.first; j++ ) 01586 phi -= j * bern.second[j] * std::pow(x,j-1); 01587 return phi; 01588 } 01589 01590 template <typename T> inline double 01591 TModel<T>::_gap_bernstein 01592 ( const double x, const double*rusr, const int*iusr, puniv f, 01593 const T&B, const std::pair<unsigned int,const double*>&bern ) 01594 { 01595 double phi = f(Op<T>::l(B)+x*Op<T>::diam(B),rusr,iusr); 01596 for( unsigned int j=0; j<bern.first; j++ ) 01597 phi -= bern.second[j] * std::pow(x,j); 01598 return phi; 01599 } 01600 01601 template <typename T> inline double 01602 TModel<T>::_goldsect 01603 ( const double xL, const double xU, punivopt fopt, const double*rusr, 01604 const int*iusr, puniv df, const T&Ix, 01605 const std::pair<unsigned int,const double*>&bern ) 01606 { 01607 const double phi = 2.-(1.+std::sqrt(5.))/2.; 01608 const double fL = fopt( xL, rusr, iusr, df, Ix, bern ), 01609 fU = fopt( xU, rusr, iusr, df, Ix, bern ); 01610 if( fL*fU > 0 ) throw Exceptions( Exceptions::BERNSTEIN ); 01611 const double xm = xU-phi*(xU-xL), 01612 fm = fopt( xm, rusr, iusr, df, Ix, bern ); 01613 return _goldsect_iter( true, xL, fL, xm, fm, xU, fU, fopt, rusr, iusr, 01614 df, Ix, bern ); 01615 } 01616 01617 template <typename T> inline double 01618 TModel<T>::_goldsect_iter 01619 ( const bool init, const double a, const double fa, const double b, 01620 const double fb, const double c, const double fc, punivopt fopt, 01621 const double*rusr, const int*iusr, puniv df, const T&Ix, 01622 const std::pair<unsigned int,const double*>&bern ) 01623 // a and c are the current bounds; the minimum is between them. 01624 // b is a center point 01625 { 01626 static unsigned int iter; 01627 iter = ( init? 1: iter+1 ); 01628 const double phi = 2.-(1.+std::sqrt(5.))/2.; 01629 bool b_then_x = ( c-b > b-a ); 01630 double x = ( b_then_x? b+phi*(c-b): b-phi*(b-a) ); 01631 if( std::fabs(c-a) < options.BERNSTEIN_TOL*(std::fabs(b)+std::fabs(x)) 01632 || iter > options.BERNSTEIN_MAXIT ) return (c+a)/2.; 01633 double fx = fopt( x, rusr, iusr, df, Ix, bern ); 01634 if( b_then_x ) 01635 return( fa*fx<0? 01636 _goldsect_iter( false, a, fa, b, fb, x, fx, fopt, rusr, iusr, df, Ix, bern ): 01637 _goldsect_iter( false, b, fb, x, fx, c, fc, fopt, rusr, iusr, df, Ix, bern ) ); 01638 return( fa*fb<0? 01639 _goldsect_iter( false, a, fa, x, fx, b, fb, fopt, rusr, iusr, df, Ix, bern ): 01640 _goldsect_iter( false, x, fx, b, fb, c, fc, fopt, rusr, iusr, df, Ix, bern ) ); 01641 } 01642 01643 template <typename T> inline void 01644 TModel<T>::_reset() 01645 { 01646 for( unsigned int i=0; i<_nvar; i++ ){ 01647 delete[] _bndpow[i]; 01648 _bndpow[i] = 0; 01649 } 01650 } 01651 01652 template <typename T> inline void 01653 TModel<T>::_cleanup() 01654 { 01655 for( unsigned int i=0; i<_nmon; i++ ) delete[] _prodmon[i]; 01656 delete[] _prodmon; 01657 delete[] _expmon; 01658 delete[] _posord; 01659 for( unsigned int i=0; i<_nvar; i++ ) delete[] _bndpow[i]; 01660 delete[] _bndpow; 01661 delete[] _bndmon; 01662 delete[] _refpoint; 01663 delete[] _scaling; 01664 delete[] _cbern; 01665 delete[] _binom; 01666 delete _TV; 01667 } 01668 01669 template <typename T> template< typename U > inline void 01670 TModel<T>::_display 01671 ( const unsigned int m, const unsigned int n, U*&a, const unsigned int lda, 01672 const std::string&stra, std::ostream&os ) 01673 { 01674 os << stra << " =" << std::endl << std::scientific 01675 << std::setprecision(5); 01676 for( unsigned int im=0; a && im<m; im++ ){ 01677 for( unsigned int in=0; in<n; in++ ){ 01678 os << a[in*lda+im] << " "; 01679 } 01680 os << std::endl; 01681 } 01682 os << std::endl; 01683 01684 if( os == std::cout || os == std::cerr ) pause(); 01685 } 01686 01687 template <typename T> void 01688 TModel<T>::pause() 01689 { 01690 double tmp; 01691 std::cout << "ENTER <1> TO CONTINUE" << std::endl; 01692 std::cin >> tmp; 01693 } 01694 01696 01697 template <typename T> inline 01698 TVar<T>::TVar 01699 ( const double d ) 01700 : _TM( 0 ), _bndT( d ) 01701 { 01702 _init(); 01703 _coefmon[0] = d; 01704 _bndord[0] = 0.; 01705 } 01706 01707 template <typename T> inline TVar<T>& 01708 TVar<T>::operator = 01709 ( const double d ) 01710 { 01711 if( _TM ){ _TM = 0; _reinit(); } 01712 _coefmon[0] = d; 01713 _bndord[0] = 0.; 01714 return *this; 01715 } 01716 01717 template <typename T> inline 01718 TVar<T>::TVar 01719 ( TModel<T>*TM, const double d ) 01720 : _TM( TM ) 01721 { 01722 if( !_TM ){ 01723 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01724 } 01725 _init(); 01726 _coefmon[0] = d; 01727 for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.; 01728 _bndord[0] = d; 01729 for( unsigned int i=1; i<_nord()+2; i++) _bndord[i] = 0.; 01730 if( _TM->options.PROPAGATE_BNDT ) _bndT = d; 01731 } 01732 01733 template <typename T> inline 01734 TVar<T>::TVar 01735 ( const T&B ) 01736 : _TM( 0 ), _bndT( B ) 01737 { 01738 _init(); 01739 _coefmon[0] = 0.; 01740 _bndord[0] = B; 01741 } 01742 01743 template <typename T> inline TVar<T>& 01744 TVar<T>::operator = 01745 ( const T&B ) 01746 { 01747 if( _TM ){ _TM = 0; _reinit(); } 01748 _coefmon[0] = 0.; 01749 _bndord[0] = B; 01750 return *this; 01751 } 01752 01753 template <typename T> inline 01754 TVar<T>::TVar 01755 ( TModel<T>*TM, const T&B ) 01756 : _TM( TM ) 01757 { 01758 if( !_TM ) throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01759 _init(); 01760 for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = 0.; 01761 for( unsigned int i=0; i<_nord()+1; i++) _bndord[i] = 0.; 01762 *_bndrem = B; 01763 if( _TM->options.PROPAGATE_BNDT ) _bndT = B; 01764 if( _TM->options.CENTER_REMAINDER ) _center_TM(); 01765 } 01766 01767 template <typename T> inline 01768 TVar<T>::TVar 01769 ( const TVar<T>&TV ) 01770 : _TM(0) 01771 { 01772 _init(); 01773 *this = TV; 01774 } 01775 01776 template <typename T> inline TVar<T>& 01777 TVar<T>::operator = 01778 ( const TVar<T>&TV ) 01779 { 01780 // Same TVar 01781 if( this == &TV ) return *this; 01782 01783 // Reinitialization needed? 01784 if( _TM != TV._TM ){ _TM = TV._TM; _reinit(); } 01785 01786 // Set to TVar not linked to TModel (either scalar or range) 01787 if( !_TM ){ 01788 _coefmon[0] = TV._coefmon[0]; 01789 _bndord[0] = TV._bndord[0]; 01790 return *this; 01791 } 01792 // Set to TVar linked to TModel 01793 for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] = TV._coefmon[i]; 01794 for( unsigned int i=0; i<_nord()+2; i++) _bndord[i] = TV._bndord[i]; 01795 if( _TM->options.PROPAGATE_BNDT ) _bndT = TV._bndT; 01796 return *this; 01797 } 01798 01799 template <typename T> template <typename U> inline 01800 TVar<T>::TVar 01801 ( TModel<T>*&TM, const TVar<U>&TV ) 01802 : _TM(TM), _coefmon(0), _bndord(0), _bndrem(0) 01803 { 01804 _init(); 01805 TVar<U> TVtrunc( TV ); 01806 _coefmon[0] = TVtrunc._coefmon[0]; 01807 TVtrunc._coefmon[0] = 0. ; 01808 for( unsigned int i=1; _TM && i<_nmon(); i++ ){ 01809 if( TVtrunc._TM && i < TVtrunc._nmon() ){ 01810 _coefmon[i] = TVtrunc._coefmon[i]; 01811 TVtrunc._coefmon[i] = 0.; 01812 } 01813 else 01814 _coefmon[i] = 0.; 01815 } 01816 TVtrunc._update_bndord(); 01817 *_bndrem = T( TVtrunc.B() ); 01818 if( !_TM ) return; 01819 _update_bndord(); 01820 if( _TM->options.PROPAGATE_BNDT ) _bndT = T( TV._bndT ); 01821 return; 01822 } 01823 01824 template <typename T> template <typename U> inline 01825 TVar<T>::TVar 01826 ( TModel<T>*&TM, const TVar<U>&TV, T (*method)( const U& ) ) 01827 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 ) 01828 { 01829 if( !method ) 01830 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01831 _init(); 01832 TVar<U> TVtrunc( TV ); 01833 _coefmon[0] = TVtrunc._coefmon[0]; 01834 TVtrunc._coefmon[0] = 0. ; 01835 for( unsigned int i=1; _TM && i<_nmon(); i++ ){ 01836 if( TVtrunc._TM && i < TVtrunc._nmon() ){ 01837 _coefmon[i] = TVtrunc._coefmon[i]; 01838 TVtrunc._coefmon[i] = 0.; 01839 } 01840 else 01841 _coefmon[i] = 0.; 01842 } 01843 TVtrunc._update_bndord(); 01844 *_bndrem = (*method)( TVtrunc.B() ); 01845 if( !_TM ) return; 01846 _update_bndord(); 01847 if( _TM->options.PROPAGATE_BNDT ) _bndT = (*method)( TV._bndT ); 01848 return; 01849 } 01850 01851 template <typename T> template <typename U> inline 01852 TVar<T>::TVar 01853 ( TModel<T>*&TM, const TVar<U>&TV, const T& (U::*method)() const ) 01854 : _TM(TM), _coefmon(0), _bndord(0), _bndrem( 0 ) 01855 { 01856 if( !method ) 01857 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01858 _init(); 01859 TVar<U> TVtrunc( TV ); 01860 _coefmon[0] = TVtrunc._coefmon[0]; 01861 TVtrunc._coefmon[0] = 0. ; 01862 for( unsigned int i=1; _TM && i<_nmon(); i++ ){ 01863 if( TVtrunc._TM && i < TVtrunc._nmon() ){ 01864 _coefmon[i] = TVtrunc._coefmon[i]; 01865 TVtrunc._coefmon[i] = 0.; 01866 } 01867 else 01868 _coefmon[i] = 0.; 01869 } 01870 TVtrunc._update_bndord(); 01871 *_bndrem = (TVtrunc.B().*method)(); 01872 if( !_TM ) return; 01873 _update_bndord(); 01874 if( _TM->options.PROPAGATE_BNDT ) _bndT = (TV._bndT.*method)(); 01875 return; 01876 } 01877 01878 template <typename T> inline 01879 TVar<T>::TVar 01880 ( TModel<T>*TM, const unsigned int ivar, const T&X ) 01881 : _TM( TM ) 01882 { 01883 if( !TM ){ 01884 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01885 } 01886 01887 // Scale variables and keep track of them in TModel 01888 double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. ); 01889 if( isequal( scaling, 0. ) ) scaling = 1.; 01890 _TM->_set_bndpow( ivar, X, Op<T>::mid(X), scaling ); 01891 _TM->_set_bndmon(); 01892 _init(); 01893 01894 // Populate _coefmon w/ TVar coefficients 01895 _coefmon[0] = Op<T>::mid(X); 01896 for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.; 01897 if( _nord() > 0 ) _coefmon[_nvar()-ivar] = scaling; 01898 01899 // Populate _bndord w/ bounds on TVar terms 01900 _bndord[0] = _coefmon[0]; 01901 _bndord[1] = X-_coefmon[0]; 01902 for( unsigned int i=2; i<_nord()+2; i++) _bndord[i] = 0.; 01903 if( _TM->options.PROPAGATE_BNDT ) _bndT = X; 01904 } 01905 01906 template <typename T> inline 01907 TVar<T>::TVar 01908 ( TModel<T>*TM, const unsigned int ivar, const T&X, const double Xref ) 01909 : _TM( TM ) 01910 { 01911 if( !TM ){ 01912 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INIT ); 01913 } 01914 01915 // Scale variables and keep track of them in TModel 01916 double scaling = ( _TM->options.SCALE_VARIABLES? Op<T>::diam(X)/2.: 1. ); 01917 if( isequal( scaling, 0. ) ) scaling = 1.; 01918 _TM->_set_bndpow( ivar, X, Xref, scaling ); 01919 _TM->_set_bndmon(); 01920 _init(); 01921 01922 // Populate _coefmon w/ TVar coefficients 01923 _coefmon[0] = Xref; 01924 for( unsigned int i=1; i<_nmon(); i++ ) _coefmon[i] = 0.; 01925 if( _nord() > 0 ) _coefmon[_nvar()-ivar] = scaling; 01926 01927 // Populate _bndord w/ bounds on TVar terms 01928 _bndord[0] = _coefmon[0]; 01929 _bndord[1] = X-_coefmon[0]; 01930 for( unsigned int i=2; i<_nord()+2; i++) _bndord[i] = 0.; 01931 if( _TM->options.PROPAGATE_BNDT ) _bndT = X; 01932 } 01933 01934 template <typename T> inline void 01935 TVar<T>::_init() 01936 { 01937 if( !_TM ){ 01938 _coefmon = new double[1]; 01939 _bndord = new T[1]; 01940 _bndrem = _bndord; 01941 return; 01942 } 01943 _coefmon = new double[_nmon()]; 01944 _bndord = new T[_nord()+2]; 01945 _bndrem = _bndord + _nord()+1; 01946 } 01947 01948 template <typename T> inline void 01949 TVar<T>::_clean() 01950 { 01951 delete [] _coefmon; delete [] _bndord; 01952 _coefmon = 0; _bndord = _bndrem = 0; 01953 } 01954 01955 template <typename T> inline void 01956 TVar<T>::_reinit() 01957 { 01958 _clean(); _init(); 01959 } 01960 01961 template <typename T> inline void 01962 TVar<T>::_update_bndord() 01963 { 01964 if( !_TM ) return; 01965 _TM->_set_bndmon(); 01966 _bndord[0] = _coefmon[0]; 01967 for( unsigned int i=1; i<=_nord(); i++ ){ 01968 _bndord[i] = 0.; 01969 for( unsigned int j=_posord(i); j<_posord(i+1); j++ ) 01970 _bndord[i] += _coefmon[j] * _bndmon(j); 01971 } 01972 } 01973 01974 template <typename T> inline void 01975 TVar<T>::_center_TM() 01976 { 01977 const double remmid = Op<T>::mid(*_bndrem); 01978 _coefmon[0] += remmid; 01979 if( _TM ) _bndord[0] = _coefmon[0]; 01980 *_bndrem -= remmid; 01981 } 01982 01983 template <typename T> inline double* 01984 TModel<T>::_eigen 01985 ( const unsigned int n, double*a ) 01986 { 01987 int info; 01988 double*d = new double[n]; 01989 #ifdef MC__TVAR_DEBUG_EIGEN 01990 TModel<T>::_display( n, n, a, n, "Matrix Q", std::cout ); 01991 #endif 01992 01993 // get optimal size 01994 char JOBZ = 'V', UPLO = 'U'; 01995 double worktmp; 01996 int lwork = -1; 01997 dsyev_( &JOBZ, &UPLO, &n, a, &n, d, &worktmp, &lwork, &info ); 01998 01999 // perform eigenvalue decomposition 02000 lwork = (int)worktmp; 02001 double*work = new double[lwork]; 02002 dsyev_( &JOBZ, &UPLO, &n, a, &n, d, work, &lwork, &info ); 02003 #ifdef MC__TVAR_DEBUG_EIGEN 02004 TModel<T>::_display( n, n, a, n, "Matrix U", std::cout ); 02005 TModel<T>::_display( 1, n, d, 1, "Matrix D", std::cout ); 02006 #endif 02007 delete[] work; 02008 02009 #ifdef MC__TVAR_DEBUG_EIGEN 02010 std::cout << "INFO: " << info << std::endl; 02011 TModel<T>::pause(); 02012 #endif 02013 if( info ){ delete[] d; return 0; } 02014 return d; 02015 } 02016 02017 template <typename T> inline T& 02018 TVar<T>::_bound_eigen 02019 ( T& bndmod ) const 02020 { 02021 static const double TOL = 1e-8; 02022 02023 bndmod = _coefmon[0]; 02024 if( _nord() == 1 ) bndmod += _bndord[1]; 02025 02026 else if( _nord() > 1 ){ 02027 double*U = new double[_nvar()*_nvar()]; 02028 for( unsigned int i=0; i<_nvar(); i++ ){ 02029 for( unsigned int j=0; j<i; j++ ){ 02030 U[_nvar()*(_nvar()-i-1)+_nvar()-j-1] = 0.; 02031 U[_nvar()*(_nvar()-j-1)+_nvar()-i-1] = _coefmon[_prodmon(i+1,j+2)]/2.; 02032 } 02033 U[(_nvar()+1)*(_nvar()-i-1)] = _coefmon[_prodmon(i+1,i+2)]; 02034 } 02035 double*D = TModel<T>::_eigen( _nvar(), U ); 02036 if( !D ){ 02037 delete[] U; 02038 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::EIGEN ); 02039 } 02040 02041 #ifdef MC__TVAR_HYBRID_EIGEN 02042 T bndtype1(0.); 02043 #endif 02044 T bndtype2(0.); 02045 for( unsigned int i=0; i<_nvar(); i++ ){ 02046 double linaux = 0.; 02047 T bndaux(0.); 02048 for( unsigned int k=0; k<_nvar(); k++ ){ 02049 linaux += U[i*_nvar()+k] * _coefmon[_nvar()-k]; 02050 bndaux += U[i*_nvar()+k] * _bndmon(_nvar()-k); 02051 } 02052 #ifdef MC__TVAR_DEBUG_EIGEN 02053 std::cout << i << ": LINAUX = " << linaux 02054 << " BNDAUX = " << bndaux << std::endl; 02055 #endif 02056 #ifdef MC__TVAR_HYBRID_EIGEN 02057 bndtype1 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux ); 02058 #endif 02059 #ifdef MC__TVAR_DEBUG_EIGEN 02060 std::cout << std::endl << "BNDTYPE1: " << bndtype1 << std::endl; 02061 #endif 02062 if( std::fabs(D[i]) > TOL ) 02063 bndtype2 += D[i] * Op<T>::sqr( linaux/D[i]/2. + bndaux ) 02064 - linaux*linaux/D[i]/4.; 02065 else 02066 //bndtype2 += _coefmon[i+1] * _bndmon(i+1) + D[i] * Op<T>::sqr( bndaux ); 02067 bndtype2 += linaux * bndaux + D[i] * Op<T>::sqr( bndaux ); 02068 #ifdef MC__TVAR_DEBUG_EIGEN 02069 std::cout << "BNDTYPE2: " << bndtype2 << std::endl; 02070 #endif 02071 } 02072 delete[] U; 02073 delete[] D; 02074 02075 #ifdef MC__TVAR_HYBRID_EIGEN 02076 if( !Op<T>::inter( bndtype1, bndtype1, bndtype2 ) ){ 02077 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON ); 02078 #ifdef MC__TVAR_DEBUG_EIGEN 02079 std::cout << "BNDTYPE3: " << bndtype1 << std::endl; 02080 #endif 02081 } 02082 bndmod += bndtype1; 02083 #else 02084 bndmod += bndtype2; 02085 #endif 02086 } 02087 #ifdef MC__TVAR_DEBUG_EIGEN 02088 int tmp; std::cin >> tmp; 02089 #endif 02090 02091 for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i]; 02092 bndmod += *_bndrem; 02093 02094 return bndmod; 02095 } 02096 02097 template <typename T> inline T& 02098 TVar<T>::_bound_LSB 02099 ( T& bndmod ) const 02100 { 02101 static const double TOL = 1e-8; 02102 bndmod = _coefmon[0]; 02103 if( _nord() == 1 ) bndmod += _bndord[1]; 02104 else if( _nord() > 1 ){ 02105 for( unsigned int i=1; i<=_nvar(); i++ ){ 02106 // linear and diagonal quadratic terms 02107 unsigned int ii = _prodmon(i,i+1); 02108 if( std::fabs(_coefmon[ii]) > TOL ) 02109 bndmod += _coefmon[ii] * Op<T>::sqr( _coefmon[i]/_coefmon[ii]/2. 02110 + _bndmon(i) ) - _coefmon[i]*_coefmon[i]/_coefmon[ii]/4.; 02111 else 02112 bndmod += _coefmon[i] * _bndmon(i) + _coefmon[ii] * _bndmon(ii); 02113 // off-diagonal quadratic terms 02114 for( unsigned int k=i+1; k<=_nvar(); k++ ){ 02115 unsigned int ik = _prodmon(i,k+1) ; 02116 bndmod += _coefmon[ik] * _bndmon(ik); 02117 } 02118 } 02119 } 02120 // higher-order terms 02121 for( unsigned int i=3; i<=_nord(); i++ ) bndmod += _bndord[i]; 02122 bndmod += *_bndrem; 02123 return bndmod; 02124 } 02125 02126 template <typename T> inline T& 02127 TVar<T>::_bound_bernstein 02128 ( T& bndmod ) const 02129 { 02130 // Scale Taylor model in unit hypercube with reference point at the origin 02131 double *coeftrans = new double[_nmon()]; 02132 for( unsigned int imon=0; imon<_nmon(); imon++ ) 02133 coeftrans[imon] = _coefmon[imon]; 02134 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 02135 _TM->_scale( ivar, coeftrans ); 02136 02137 // Expand binomial coefficient and exponent arrays if needed 02138 const unsigned int maxord = (_TM->options.BOUNDER_ORDER>_nord()? 02139 _TM->options.BOUNDER_ORDER: _nord() ); 02140 const unsigned int maxmon = std::pow(maxord+1,_nvar()); 02141 _TM->_ext_expmon( maxord, true ); 02142 02143 // Compute min/max amongst all Bernstein coefficients 02144 bndmod = coeftrans[0]; 02145 #ifdef MC__TVAR_DEBUG_BERSTEIN 02146 std::cout << "\n0: " << bndmod << std::endl; 02147 #endif 02148 for( unsigned int jmon=1; jmon<maxmon; jmon++ ){ 02149 const unsigned int*jexp = _TM->_expmon + jmon*_nvar(); 02150 const double coefbern = _coef_bernstein( coeftrans, jexp, jmon, maxord ); 02151 bndmod = Op<T>::hull( bndmod, coefbern ); 02152 #ifdef MC__TVAR_DEBUG_BERNSTEIN 02153 std::cout << jmon << " ["; 02154 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 02155 std::cout << std::setw(3) << jexp[ivar]; 02156 std::cout << "] : " << coefbern << " : " << bndmod << std::endl; 02157 #endif 02158 } 02159 02160 delete[] coeftrans; 02161 bndmod += *_bndrem; 02162 return bndmod; 02163 } 02164 02165 template <typename T> inline double 02166 TVar<T>::_coef_bernstein 02167 ( const double*coefmon, const unsigned int*jexp, 02168 const unsigned int jmon, const unsigned int maxord ) const 02169 { 02170 // Compute bernstein coefficient with variables indices <tt>jexp</tt> 02171 double coefbern = coefmon[0]; 02172 for( unsigned int imon=1; imon<=std::min(jmon,_nmon()-1); imon++ ){ 02173 const unsigned int*iexp = _TM->_expmon + imon*_nvar(); 02174 // Only append term if monomial degrees are lower 02175 bool inrange = true; 02176 for( unsigned int ivar=0; ivar<_nvar() && inrange; ivar++ ) 02177 if( iexp[ivar] > jexp[ivar] ) inrange = false; 02178 if( !inrange ) continue; 02179 double termbern = coefmon[imon]; 02180 #ifdef MC__TVAR_DEBUG_BERSTEIN 02181 std::cout << " ["; 02182 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 02183 std::cout << std::setw(3) << iexp[ivar]; 02184 std::cout << "]"; 02185 #endif 02186 for( unsigned int ivar=0; ivar<_nvar(); ivar++ ) 02187 termbern *= (double)_TM->_get_binom(jexp[ivar],iexp[ivar]) 02188 / (double)_TM->_get_binom(maxord,iexp[ivar]); 02189 coefbern += termbern; 02190 } 02191 #ifdef MC__TVAR_DEBUG_BERSTEIN 02192 std::cout << std::endl; 02193 #endif 02194 return coefbern; 02195 } 02196 02197 template <typename T> inline T& 02198 TVar<T>::_bound_naive 02199 ( T& bndmod ) const 02200 { 02201 bndmod = _coefmon[0]; 02202 for( unsigned int i=1; i<=_nord()+1; i++ ) bndmod += _bndord[i]; 02203 return bndmod; 02204 } 02205 02206 template <typename T> inline T& 02207 TVar<T>::_bound 02208 ( T& bndmod ) const 02209 { 02210 if( !_TM ){ bndmod = _coefmon[0] + _bndord[0]; return bndmod; } 02211 02212 switch( _TM->options.BOUNDER_TYPE ){ 02213 case TModel<T>::Options::NAIVE: bndmod = _bound_naive(bndmod); break; 02214 case TModel<T>::Options::LSB: bndmod = _bound_LSB(bndmod); break; 02215 case TModel<T>::Options::EIGEN: bndmod = _bound_eigen(bndmod); break; 02216 case TModel<T>::Options::BERNSTEIN: bndmod = _bound_bernstein(bndmod); break; 02217 case TModel<T>::Options::HYBRID: default:{ 02218 T bndlsb(0.), bndeig(0.); 02219 if( !Op<T>::inter( bndmod, _bound_LSB(bndlsb), _bound_eigen(bndeig) ) ) 02220 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON ); 02221 } 02222 } 02223 02224 if( _TM->options.PROPAGATE_BNDT && _TM->options.INTER_WITH_BNDT 02225 && !Op<T>::inter( bndmod, bndmod, _bndT ) ) 02226 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::INCON ); 02227 02228 return bndmod; 02229 } 02230 02231 template <typename T> inline double 02232 TVar<T>::polynomial 02233 ( const double*x ) const 02234 { 02235 if( !_TM ) return _coefmon[0]; 02236 double Pval = _coefmon[0]; 02237 for( unsigned int i=1; i<_nmon(); i++ ){ 02238 double valmon = 1.; 02239 for( unsigned int k=0; k<_nvar(); k++ ) 02240 valmon *= std::pow( x[k]/_scaling(k)-_refpoint(k), _expmon(i)[k] ); 02241 Pval += _coefmon[i] * valmon; 02242 } 02243 return Pval; 02244 } 02245 02246 template <typename T> inline double* 02247 TVar<T>::reference() const 02248 { 02249 if( !_TM ) return 0; 02250 if( _nvar() < 1 ) return 0; 02251 double*pref = new double[_nvar()]; 02252 for( unsigned int i=0; i<_nvar(); i++ ) pref[i] = _refpoint(i)*_scaling(i); 02253 return pref; 02254 } 02255 02256 template <typename T> inline double 02257 TVar<T>::constant() const 02258 { 02259 return _coefmon[0]; 02260 } 02261 02262 template <typename T> inline double* 02263 TVar<T>::linear() const 02264 { 02265 if( !_TM || !_nvar() || !_nord() ) return 0; 02266 02267 double*plin = new double[_nvar()]; 02268 for( unsigned int i=0; i<_nvar(); i++ ) 02269 plin[i] = _coefmon[_nvar()-i] / _scaling(i); 02270 return plin; 02271 } 02272 02273 template <typename T> inline double 02274 TVar<T>::linear 02275 ( const unsigned int ivar, const bool reset ) 02276 { 02277 if( !_TM || ivar>=_nvar() || !_nord() ) return 0.; 02278 const double coeflin = _coefmon[_nvar()-ivar] / _scaling(ivar); 02279 if( reset ){ _coefmon[_nvar()-ivar] = 0.; _update_bndord(); } 02280 return coeflin; 02281 } 02282 02283 template <typename T> inline double 02284 TVar<T>::coefmon 02285 ( const unsigned int*iexp ) const 02286 { 02287 if( !_TM ) return 0; 02288 const unsigned int imon = _TM->_loc_expmon( iexp ); 02289 return( imon<_nmon()? _coefmon[imon]: 0. ); 02290 } 02291 02292 template <typename T> inline std::pair<unsigned int, const double*> 02293 TVar<T>::coefmon() const 02294 { 02295 return std::make_pair( (_TM?_nmon():1), _coefmon ); 02296 } 02297 02298 template <typename T> inline std::pair<unsigned int, const unsigned int*> 02299 TVar<T>::expmon() const 02300 { 02301 return std::make_pair( (_TM?_nmon()*_nvar():1), _TM->_expmon ); 02302 } 02303 02304 template <typename T> inline std::ostream& 02305 operator << 02306 ( std::ostream&out, const TVar<T>&TV ) 02307 { 02308 out << std::endl 02309 << std::scientific << std::setprecision(5) 02310 << std::right; 02311 02312 // Constant model 02313 if( !TV._TM ){ 02314 out << " a0 = " << std::right << std::setw(12) << TV._coefmon[0] 02315 << " 0 0" 02316 << std::endl 02317 << " R = " << *(TV._bndrem) << std::endl; 02318 } 02319 02320 // Monomial term coefficients and corresponding exponents 02321 else{ 02322 out << std::setprecision(TV._TM->options.DISPLAY_DIGITS); 02323 for( unsigned int i=0; i<TV._nmon(); i++ ){ 02324 double scal = 1.; 02325 for( unsigned int k=0; k<TV._nvar(); k++ ) 02326 scal *= std::pow( TV._scaling(k), TV._expmon(i)[k] ); 02327 out << " a" << std::left << std::setw(4) << i << " = " 02328 << std::right << std::setw(TV._TM->options.DISPLAY_DIGITS+7) 02329 << TV._coefmon[i]*scal << " "; 02330 for( unsigned int k=0; k<TV._nvar(); k++ ) 02331 out << std::setw(3) << TV._expmon(i)[k]; 02332 out << std::endl; 02333 } 02334 // Remainder term 02335 out << std::right << " R = " << *(TV._bndrem) 02336 << std::endl; 02337 } 02338 02339 // Range bounder 02340 out << std::right << " B = " << TV.B() 02341 << std::endl; 02342 02343 return out; 02344 } 02345 02346 template <typename T> inline TVar<T> 02347 operator + 02348 ( const TVar<T>&TV ) 02349 { 02350 return TV; 02351 } 02352 02353 template <typename T> template <typename U> inline TVar<T>& 02354 TVar<T>::operator += 02355 ( const TVar<U>&TV ) 02356 { 02357 if( !TV._TM ){ 02358 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT; 02359 _coefmon[0] += TV._coefmon[0]; 02360 *_bndrem += *(TV._bndrem); 02361 } 02362 else if( !_TM ){ 02363 TVar<T> TV2(*this); 02364 *this = TV; *this += TV2; 02365 } 02366 else{ 02367 if( _TM != TV._TM ) 02368 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL ); 02369 if( _TM->options.PROPAGATE_BNDT ) _bndT += TV._bndT; 02370 for( unsigned int i=0; i<_nmon(); i++ ) 02371 _coefmon[i] += TV._coefmon[i]; 02372 *_bndrem += *(TV._bndrem); 02373 _update_bndord(); 02374 } 02375 if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM(); 02376 return *this; 02377 } 02378 02379 template <typename T, typename U> inline TVar<T> 02380 operator + 02381 ( const TVar<T>&TV1, const TVar<U>&TV2 ) 02382 { 02383 TVar<T> TV3( TV1 ); 02384 TV3 += TV2; 02385 return TV3; 02386 } 02387 02388 template <typename T> inline TVar<T>& 02389 TVar<T>::operator += 02390 ( const double c ) 02391 { 02392 _coefmon[0] += c; 02393 if( _TM ) _bndord[0] = _coefmon[0]; 02394 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += c; 02395 return *this; 02396 } 02397 02398 template <typename T> inline TVar<T> 02399 operator + 02400 ( const TVar<T>&TV1, const double c ) 02401 { 02402 TVar<T> TV3( TV1 ); 02403 TV3 += c; 02404 return TV3; 02405 } 02406 02407 template <typename T> inline TVar<T> 02408 operator + 02409 ( const double c, const TVar<T>&TV2 ) 02410 { 02411 TVar<T> TV3( TV2 ); 02412 TV3 += c; 02413 return TV3; 02414 } 02415 02416 template <typename T> template <typename U> inline TVar<T>& 02417 TVar<T>::operator += 02418 ( const U&I ) 02419 { 02420 *_bndrem += I; 02421 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT += I; 02422 if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM(); 02423 return *this; 02424 } 02425 02426 template <typename T, typename U> inline TVar<T> 02427 operator + 02428 ( const TVar<T>&TV1, const U&I ) 02429 { 02430 TVar<T> TV3( TV1 ); 02431 TV3 += I; 02432 return TV3; 02433 } 02434 02435 template <typename T, typename U> inline TVar<T> 02436 operator + 02437 ( const U&I, const TVar<T>&TV2 ) 02438 { 02439 TVar<T> TV3( TV2 ); 02440 TV2 += I; 02441 return TV3; 02442 } 02443 02444 template <typename T> inline TVar<T> 02445 operator - 02446 ( const TVar<T>&TV ) 02447 { 02448 if( !TV._TM ){ 02449 TVar<T> TV2; 02450 TV2._coefmon[0] = -TV._coefmon[0]; 02451 TV2._bndord[0] = -TV._bndord[0]; 02452 return TV2; 02453 } 02454 TVar<T>& TV2 = *TV._TV(); 02455 //TVar<T> TV2( TV._TM ); 02456 for( unsigned int i=0; i<TV._nmon(); i++ ) TV2._coefmon[i] = -TV._coefmon[i]; 02457 for( unsigned int i=0; i<TV._nord()+2; i++ ) TV2._bndord[i] = -TV._bndord[i]; 02458 if( TV._TM->options.PROPAGATE_BNDT ) TV2._bndT = -TV._bndT; 02459 if( TV._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02460 return TV2; 02461 } 02462 02463 template <typename T> template <typename U> inline TVar<T>& 02464 TVar<T>::operator -= 02465 ( const TVar<U>&TV ) 02466 { 02467 if( !TV._TM ){ 02468 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT; 02469 _coefmon[0] -= TV._coefmon[0]; 02470 *_bndrem -= *(TV._bndrem); 02471 } 02472 else if( !_TM ){ 02473 TVar<T> TV2(*this); 02474 *this = -TV; *this += TV2; 02475 } 02476 else{ 02477 if( _TM != TV._TM ) 02478 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL ); 02479 if( _TM->options.PROPAGATE_BNDT ) _bndT -= TV._bndT; 02480 for( unsigned int i=0; i<_nmon(); i++ ) 02481 _coefmon[i] -= TV._coefmon[i]; 02482 *_bndrem -= *(TV._bndrem); 02483 _update_bndord(); 02484 } 02485 if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM(); 02486 return *this; 02487 } 02488 02489 template <typename T, typename U> inline TVar<T> 02490 operator- 02491 ( const TVar<T>&TV1, const TVar<U>&TV2 ) 02492 { 02493 TVar<T> TV3( TV1 ); 02494 TV3 -= TV2; 02495 return TV3; 02496 } 02497 02498 template <typename T> inline TVar<T>& 02499 TVar<T>::operator -= 02500 ( const double c ) 02501 { 02502 _coefmon[0] -= c; 02503 if( _TM ) _bndord[0] = _coefmon[0]; 02504 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= c; 02505 return *this; 02506 } 02507 02508 template <typename T> inline TVar<T> 02509 operator - 02510 ( const TVar<T>&TV1, const double c ) 02511 { 02512 TVar<T> TV3( TV1 ); 02513 TV3 -= c; 02514 return TV3; 02515 } 02516 02517 template <typename T> inline TVar<T> 02518 operator - 02519 ( const double c, const TVar<T>&TV2 ) 02520 { 02521 TVar<T> TV3( -TV2 ); 02522 TV3 += c; 02523 return TV3; 02524 } 02525 02526 template <typename T> template <typename U> inline TVar<T>& 02527 TVar<T>::operator -= 02528 ( const U&I ) 02529 { 02530 *_bndrem -= I; 02531 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT -= I; 02532 if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM(); 02533 return *this; 02534 } 02535 02536 template <typename T, typename U> inline TVar<T> 02537 operator - 02538 ( const TVar<T>&TV1, const U&I ) 02539 { 02540 TVar<T> TV3( TV1 ); 02541 TV3 -= I; 02542 return TV3; 02543 } 02544 02545 template <typename T, typename U> inline TVar<T> 02546 operator - 02547 ( const U&I, const TVar<T>&TV2 ) 02548 { 02549 TVar<T> TV3( -TV2 ); 02550 TV3 += I; 02551 return TV3; 02552 } 02553 02554 template <typename T> inline TVar<T>& 02555 TVar<T>::operator *= 02556 ( const TVar<T>&TV ) 02557 { 02558 TVar<T> TV2( *this ); 02559 *this = TV * TV2; 02560 return *this; 02561 } 02562 02563 template <typename T> inline TVar<T> 02564 operator * 02565 ( const TVar<T>&TV1, const TVar<T>&TV2 ) 02566 { 02567 if( !TV2._TM ) return( TV1 * TV2._coefmon[0] + TV1 * *(TV2._bndrem) ); 02568 else if( !TV1._TM ) return( TV2 * TV1._coefmon[0] + TV2 * *(TV1._bndrem) ); 02569 02570 if( TV1._TM != TV2._TM ) 02571 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL ); 02572 TVar<T>& TV3 = *TV1._TV(); 02573 for( unsigned int i=0; i<TV3._nmon(); i++ ) TV3._coefmon[i] = 0.; 02574 //TVar<T> TV3( TV1._TM, 0. ); 02575 02576 // Populate _coefmon for product term 02577 for( unsigned int i=0; i<TV3._posord(TV3._nord()/2+1); i++){ 02578 TV3._coefmon[TV3._prodmon(i,i+1)] += TV1._coefmon[i] * TV2._coefmon[i]; 02579 for( unsigned int j=i+1; j<TV3._prodmon(i,0); j++ ) 02580 TV3._coefmon[TV3._prodmon(i,j+1)] += TV1._coefmon[i] * TV2._coefmon[j] 02581 + TV1._coefmon[j] * TV2._coefmon[i]; 02582 } 02583 // Calculate remainder term _bndrem for product term 02584 T s1 = 0., s2 = 0.; 02585 for( unsigned int i=0; i<=TV3._nord()+1; i++ ){ 02586 T r1 = 0., r2 = 0.; 02587 for( unsigned int j=TV3._nord()+1-i; j<=TV3._nord()+1; j++ ){ 02588 r1 += TV1._bndord[j]; 02589 r2 += TV2._bndord[j]; 02590 } 02591 s1 += TV2._bndord[i] * r1 ; 02592 s2 += TV1._bndord[i] * r2 ; 02593 } 02594 if( !Op<T>::inter( *(TV3._bndrem), s1, s2) ){ 02595 *(TV3._bndrem) = s1; 02596 //throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::SQUARE ); 02597 } 02598 // Populate _bndord for product term (except remainder term) 02599 TV3._update_bndord(); 02600 if( TV3._TM->options.PROPAGATE_BNDT ) TV3._bndT = TV1._bndT * TV2._bndT; 02601 if( TV3._TM->options.CENTER_REMAINDER ) TV3._center_TM(); 02602 return TV3; 02603 } 02604 02605 template <typename T> inline TVar<T> 02606 sqr 02607 ( const TVar<T>&TV ) 02608 { 02609 if( !TV._TM ){ 02610 TVar<T> TV2( TV ); 02611 TV2._coefmon[0] *= TV2._coefmon[0]; 02612 *(TV2._bndrem) *= 2. + *(TV2._bndrem); 02613 return TV2; 02614 } 02615 02616 // Populate _coefmon for product term 02617 TVar<T> TV2( TV._TM, 0. ); 02618 for( unsigned int i=0; i<TV2._posord(TV2._nord()/2+1); i++){ 02619 TV2._coefmon[TV2._prodmon(i,i+1)] += TV._coefmon[i] * TV._coefmon[i]; 02620 for( unsigned int j=i+1; j<TV2._prodmon(i,0); j++ ) 02621 TV2._coefmon[TV2._prodmon(i,j+1)] += TV._coefmon[i] * TV._coefmon[j] * 2.; 02622 } 02623 02624 T s = 0.; 02625 for( unsigned int i=0; i<=TV2._nord()+1; i++ ){ 02626 unsigned int k = std::max(TV2._nord()+1-i, i+1); 02627 T r = 0.; 02628 for( unsigned int j=k; j<=TV2._nord()+1; j++ ) 02629 r += TV._bndord[j]; 02630 s += TV._bndord[i] * r; 02631 } 02632 02633 T r = 0.; 02634 for( unsigned int i=TV2._nord()/2+1; i<=TV2._nord()+1; i++ ) 02635 r += Op<T>::sqr(TV._bndord[i]) ; 02636 *(TV2._bndrem) = 2. * s + r; 02637 02638 // Populate _bndord for product term (except remainder term) 02639 TV2._update_bndord(); 02640 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqr( TV._bndT ); 02641 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02642 return TV2; 02643 } 02644 02645 template <typename T> inline TVar<T>& 02646 TVar<T>::operator *= 02647 ( const double c ) 02648 { 02649 if( !_TM ){ 02650 _coefmon[0] *= c; 02651 *(_bndrem) *= c; 02652 } 02653 else{ 02654 for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= c; 02655 for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= c; 02656 if( _TM->options.PROPAGATE_BNDT ) _bndT *= c; 02657 } 02658 return *this; 02659 } 02660 02661 template <typename T> inline TVar<T> 02662 operator * 02663 ( const TVar<T>&TV1, const double c ) 02664 { 02665 TVar<T> TV3( TV1 ); 02666 TV3 *= c; 02667 return TV3; 02668 } 02669 02670 template <typename T> inline TVar<T> 02671 operator * 02672 ( const double c, const TVar<T>&TV2 ) 02673 { 02674 TVar<T> TV3( TV2 ); 02675 TV3 *= c; 02676 return TV3; 02677 } 02678 02679 template <typename T> inline TVar<T>& 02680 TVar<T>::operator *= 02681 ( const T&I ) 02682 { 02683 if( !_TM ){ 02684 *(_bndrem) += _coefmon[0]; 02685 _coefmon[0] = 0.; 02686 *(_bndrem) *= I; 02687 } 02688 else{ 02689 const double Imid = Op<T>::mid(I); 02690 T Icur = bound(); 02691 for( unsigned int i=0; i<_nmon(); i++ ) _coefmon[i] *= Imid; 02692 for( unsigned int i=0; i<_nord()+2; i++ ) _bndord[i] *= Imid; 02693 *_bndrem += (I-Imid)*Icur; 02694 } 02695 if( _TM && _TM->options.CENTER_REMAINDER ) _center_TM(); 02696 if( _TM && _TM->options.PROPAGATE_BNDT ) _bndT *= I; 02697 return (*this); 02698 } 02699 02700 template <typename T> inline TVar<T> 02701 operator * 02702 ( const TVar<T>&TV1, const T&I ) 02703 { 02704 TVar<T> TV3( TV1 ); 02705 TV3 *= I; 02706 return TV3; 02707 } 02708 02709 template <typename T> inline TVar<T> 02710 operator * 02711 ( const T&I, const TVar<T>&TV2 ) 02712 { 02713 TVar<T> TV3( TV2 ); 02714 TV3 *= I; 02715 return TV3; 02716 } 02717 02718 template <typename T> inline TVar<T>& 02719 TVar<T>::operator /= 02720 ( const TVar<T>&TV ) 02721 { 02722 *this *= inv(TV); 02723 return *this; 02724 } 02725 02726 template <typename T> inline TVar<T> 02727 operator / 02728 ( const TVar<T>&TV1, const TVar<T>&TV2 ) 02729 { 02730 return TV1 * inv(TV2); 02731 } 02732 02733 template <typename T> inline TVar<T>& 02734 TVar<T>::operator /= 02735 ( const double c ) 02736 { 02737 if ( isequal( c, 0. )) 02738 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV ); 02739 *this *= (1./c); 02740 return *this; 02741 } 02742 02743 template <typename T> inline TVar<T> 02744 operator / 02745 ( const TVar<T>&TV, const double c ) 02746 { 02747 if ( isequal( c, 0. )) 02748 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::DIV ); 02749 return TV * (1./c); 02750 } 02751 02752 template <typename T> inline TVar<T> 02753 operator / 02754 ( const double c, const TVar<T>&TV ) 02755 { 02756 return inv(TV) * c; 02757 } 02758 02759 template <typename T> inline TVar<T> 02760 inv 02761 ( const TVar<T>&TV ) 02762 { 02763 if( !TV._TM ){ 02764 TVar<T> TV2( TV ); 02765 TV2._coefmon[0] = 0.; 02766 *(TV2._bndrem) = Op<T>::inv(TV._coefmon[0] + *(TV._bndrem)); 02767 TV2._update_bndord(); 02768 return TV2; 02769 } 02770 02771 TVar<T> TV2 = TV._TM->_inv_taylor( TV ); 02772 if( TV2._TM->options.BERNSTEIN_USE ){ 02773 TVar<T> TV2b = TV._TM->_inv_bernstein( TV ); 02774 if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) ) 02775 TV2 = TV2b; 02776 } 02777 02778 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::inv( TV._bndT ); 02779 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02780 return TV2; 02781 } 02782 02783 template <typename T> inline TVar<T> 02784 TModel<T>::_inv_taylor 02785 ( const TVar<T>&TV ) 02786 { 02787 const T I( TV.B() ); 02788 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I): 02789 TV._coefmon[0] ); 02790 const TVar<T> TVmx0( TV - x0 ); 02791 const T Imx0( I - x0 ); 02792 02793 TVar<T> TV2( TV._TM, 1. ), MON( 1. ); 02794 for( unsigned int i=1; i<=TV._nord(); i++ ){ 02795 MON *= TVmx0 / (-x0); 02796 TV2 += MON; 02797 } 02798 TV2 /= x0; 02799 TV2 += Op<T>::pow( -Imx0, (int)TV2._nord()+1 ) 02800 / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+2 ); 02801 return TV2; 02802 } 02803 02804 template <typename T> inline TVar<T> 02805 TModel<T>::_inv_bernstein 02806 ( const TVar<T>&TV ) 02807 { 02808 struct loc{ 02809 static double inv 02810 ( const double x, const double*rusr, const int*iusr ) 02811 { return 1./x; } 02812 static double dinv 02813 ( const double x, const double*rusr, const int*iusr ) 02814 { return -1./mc::sqr(x); } 02815 static T Iinv 02816 ( const T&x, const double*rusr, const int*iusr ) 02817 { return Op<T>::inv(x); } 02818 static T d2Iinv 02819 ( const T&x, const double*rusr, const int*iusr ) 02820 { return 2.*Op<T>::pow( Op<T>::inv(x), 3 ); } 02821 }; 02822 return TV._TM->_univ_bernstein( TV, loc::inv, loc::dinv, loc::Iinv, 02823 loc::d2Iinv, 0, 0 ); 02824 } 02825 02826 template <typename T> inline TVar<T> 02827 sqrt 02828 ( const TVar<T>&TV ) 02829 { 02830 if( !TV._TM ){ 02831 TVar<T> TV2( TV ); 02832 TV2._coefmon[0] = 0.; 02833 *(TV2._bndrem) = Op<T>::sqrt(TV._coefmon[0] + *(TV._bndrem)); 02834 TV2._update_bndord(); 02835 return TV2; 02836 } 02837 02838 TVar<T> TV2 = TV._TM->_sqrt_taylor( TV ); 02839 if( TV2._TM->options.BERNSTEIN_USE ){ 02840 TVar<T> TV2b = TV._TM->_sqrt_bernstein( TV ); 02841 if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) ) 02842 TV2 = TV2b; 02843 } 02844 02845 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::sqrt( TV._bndT ); 02846 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02847 return TV2; 02848 } 02849 02850 template <typename T> inline TVar<T> 02851 TModel<T>::_sqrt_taylor 02852 ( const TVar<T>&TV ) 02853 { 02854 const T I( TV.B() ); 02855 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I): 02856 TV._coefmon[0] ); 02857 const TVar<T> TVmx0( TV - x0 ); 02858 const T Imx0( I - x0 ); 02859 02860 double s = 0.5; 02861 TVar<T> TV2( TV._TM, 1. ), MON( 1. ); 02862 for( unsigned int i=1; i<=TV._nord(); i++ ){ 02863 MON *= TVmx0 / x0; 02864 TV2 += MON * s; 02865 s *= -(2.*i-1.)/(2.*i+2.); 02866 } 02867 TV2 *= std::sqrt(x0); 02868 TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 02869 / Op<T>::pow( Op<T>::zeroone()*Imx0+x0, (int)TV2._nord()+1/2 ); 02870 return TV2; 02871 } 02872 02873 template <typename T> inline TVar<T> 02874 TModel<T>::_sqrt_bernstein 02875 ( const TVar<T>&TV ) 02876 { 02877 struct loc{ 02878 static double sqrt 02879 ( const double x, const double*rusr, const int*iusr ) 02880 { return std::sqrt(x); } 02881 static double dsqrt 02882 ( const double x, const double*rusr, const int*iusr ) 02883 { return 1./(2.*std::sqrt(x)); } 02884 static T Isqrt 02885 ( const T&x, const double*rusr, const int*iusr ) 02886 { return Op<T>::sqrt(x); } 02887 static T d2Isqrt 02888 ( const T&x, const double*rusr, const int*iusr ) 02889 { return -Op<T>::inv( 4.*Op<T>::sqrt(Op<T>::pow(x,3)) ); } 02890 }; 02891 return TV._TM->_univ_bernstein( TV, loc::sqrt, loc::dsqrt, loc::Isqrt, 02892 loc::d2Isqrt, 0, 0 ); 02893 } 02894 02895 template <typename T> inline TVar<T> 02896 exp 02897 ( const TVar<T>&TV ) 02898 { 02899 if( !TV._TM ){ 02900 TVar<T> TV2( TV ); 02901 TV2._coefmon[0] = 0.; 02902 *(TV2._bndrem) = Op<T>::exp(TV._coefmon[0] + *(TV._bndrem)); 02903 TV2._update_bndord(); 02904 return TV2; 02905 } 02906 02907 TVar<T> TV2 = TV._TM->_exp_taylor( TV ); 02908 if( TV2._TM->options.BERNSTEIN_USE ){ 02909 TVar<T> TV2b = TV._TM->_exp_bernstein( TV ); 02910 //std::cout << *(TV2b._bndrem) << " <=? " << *(TV2._bndrem) << std::endl; 02911 if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) ) 02912 TV2 = TV2b; 02913 } 02914 02915 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::exp( TV._bndT ); 02916 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02917 return TV2; 02918 } 02919 02920 template <typename T> inline TVar<T> 02921 TModel<T>::_exp_taylor 02922 ( const TVar<T>&TV ) 02923 { 02924 const T I( TV.B() ); 02925 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I): 02926 TV._coefmon[0] ); 02927 const TVar<T> TVmx0( TV - x0 ); 02928 const T Imx0( I - x0 ); 02929 02930 double s = 1.; 02931 TVar<T> TV2( TV._TM, 1. ), MON( 1. ); 02932 for( unsigned int i=1; i<=TV._nord(); i++ ){ 02933 MON *= TVmx0; 02934 TV2 += MON * s; 02935 s /= i+1.; 02936 } 02937 TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 02938 * Op<T>::exp( Op<T>::zeroone()*Imx0 ); 02939 TV2 *= std::exp(x0); 02940 TV2._update_bndord(); 02941 return TV2; 02942 } 02943 02944 template <typename T> inline TVar<T> 02945 TModel<T>::_exp_bernstein 02946 ( const TVar<T>&TV ) 02947 { 02948 struct loc{ 02949 static double exp 02950 ( const double x, const double*rusr, const int*iusr ) 02951 { return std::exp(x); } 02952 static double dexp 02953 ( const double x, const double*rusr, const int*iusr ) 02954 { return std::exp(x); } 02955 static T Iexp 02956 ( const T&x, const double*rusr, const int*iusr ) 02957 { return Op<T>::exp(x); } 02958 static T d2Iexp 02959 ( const T&x, const double*rusr, const int*iusr ) 02960 { return Op<T>::exp(x); } 02961 }; 02962 return TV._TM->_univ_bernstein( TV, loc::exp, loc::dexp, loc::Iexp, 02963 loc::d2Iexp, 0, 0 ); 02964 } 02965 02966 template <typename T> inline TVar<T> 02967 log 02968 ( const TVar<T>&TV ) 02969 { 02970 if( !TV._TM ){ 02971 TVar<T> TV2( TV ); 02972 TV2._coefmon[0] = 0.; 02973 *(TV2._bndrem) = Op<T>::log(TV._coefmon[0] + *(TV._bndrem)); 02974 TV2._update_bndord(); 02975 return TV2; 02976 } 02977 02978 TVar<T> TV2 = TV._TM->_log_taylor( TV ); 02979 if( TV2._TM->options.BERNSTEIN_USE ){ 02980 TVar<T> TV2b = TV._TM->_log_bernstein( TV ); 02981 if( Op<T>::diam(*(TV2b._bndrem)) < Op<T>::diam(*(TV2._bndrem)) ) 02982 TV2 = TV2b; 02983 } 02984 02985 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::log( TV._bndT ); 02986 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 02987 return TV2; 02988 } 02989 02990 template <typename T> inline TVar<T> 02991 TModel<T>::_log_taylor 02992 ( const TVar<T>&TV ) 02993 { 02994 const T I( TV.B() ); 02995 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I): 02996 TV._coefmon[0] ); 02997 const TVar<T> TVmx0( TV - x0 ); 02998 const T Imx0( I - x0 ); 02999 03000 TVar<T> TV2( TV._TM, 0. ), MON( -1. ); 03001 for( unsigned int i=1; i<=TV._nord(); i++ ){ 03002 MON *= TVmx0 / (-x0); 03003 TV2 += MON / (double)i; 03004 } 03005 TV2._coefmon[0] += std::log(x0); 03006 TV2._update_bndord(); 03007 TV2 -= Op<T>::pow( - Imx0 / ( Op<T>::zeroone()*Imx0+x0 ), 03008 (int)TV2._nord()+1 ) / ( TV2._nord()+1. ); 03009 return TV2; 03010 } 03011 03012 template <typename T> inline TVar<T> 03013 TModel<T>::_log_bernstein 03014 ( const TVar<T>&TV ) 03015 { 03016 struct loc{ 03017 static double log 03018 ( const double x, const double*rusr, const int*iusr ) 03019 { return std::log(x); } 03020 static double dlog 03021 ( const double x, const double*rusr, const int*iusr ) 03022 { return 1./x; } 03023 static T Ilog 03024 ( const T&x, const double*rusr, const int*iusr ) 03025 { return Op<T>::log(x); } 03026 static T d2Ilog 03027 ( const T&x, const double*rusr, const int*iusr ) 03028 { return -Op<T>::sqr( Op<T>::inv(x) ); } 03029 }; 03030 return TV._TM->_univ_bernstein( TV, loc::log, loc::dlog, loc::Ilog, 03031 loc::d2Ilog, 0, 0 ); 03032 } 03033 03034 template <typename T> inline TVar<T> 03035 xlog 03036 ( const TVar<T>&TV ) 03037 { 03038 return TV * log( TV ); 03039 } 03040 03041 template <typename T> inline TVar<T> 03042 pow 03043 ( const TVar<T>&TV, const int n ) 03044 { 03045 if( !TV._TM ){ 03046 TVar<T> TV2( TV ); 03047 TV2._coefmon[0] = 0.; 03048 *(TV2._bndrem) = Op<T>::pow(TV._coefmon[0] + *(TV._bndrem), n); 03049 TV2._update_bndord(); 03050 return TV2; 03051 } 03052 03053 if( n < 0 ) return pow( inv( TV ), -n ); 03054 TVar<T> TV2( TV._TM->_intpow( TV, n ) ); 03055 if( TV2._TM && TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::pow( TV._bndT, n ); 03056 if( TV2._TM && TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 03057 return TV2; 03058 } 03059 03060 template <typename T> inline TVar<T> 03061 TModel<T>::_intpow 03062 ( const TVar<T>&TV, const int n ) 03063 { 03064 if( n == 0 ) return 1.; 03065 else if( n == 1 ) return TV; 03066 return n%2 ? sqr( _intpow( TV, n/2 ) ) * TV : sqr( _intpow( TV, n/2 ) ); 03067 } 03068 03069 template <typename T> inline TVar<T> 03070 pow 03071 ( const TVar<T> &TV, const double a ) 03072 { 03073 return exp( a * log( TV ) ); 03074 } 03075 03076 template <typename T> inline TVar<T> 03077 pow 03078 ( const TVar<T> &TV1, const TVar<T> &TV2 ) 03079 { 03080 return exp( TV2 * log( TV1 ) ); 03081 } 03082 03083 template <typename T> inline TVar<T> 03084 pow 03085 ( const double a, const TVar<T> &TV ) 03086 { 03087 return exp( TV * std::log( a ) ); 03088 } 03089 03090 template <typename T> inline TVar<T> 03091 monomial 03092 (const unsigned int n, const TVar<T>*TV, const int*k) 03093 { 03094 if( n == 0 ){ 03095 return 1.; 03096 } 03097 if( n == 1 ){ 03098 return pow( TV[0], k[0] ); 03099 } 03100 return pow( TV[0], k[0] ) * monomial( n-1, TV+1, k+1 ); 03101 } 03102 03103 template <typename T> inline TVar<T> 03104 cos 03105 ( const TVar<T> &TV ) 03106 { 03107 if( !TV._TM ){ 03108 TVar<T> TV2( TV ); 03109 TV2._coefmon[0] = 0.; 03110 *(TV2._bndrem) = Op<T>::cos(TV._coefmon[0] + *(TV._bndrem)); 03111 TV2._update_bndord(); 03112 return TV2; 03113 } 03114 03115 const T I( TV.B() ); 03116 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(I): 03117 TV._coefmon[0] ); 03118 const TVar<T> TVmx0( TV - x0 ); 03119 const T Imx0( I - x0 ); 03120 double s = 1., c; 03121 03122 TVar<T> TV2( TV._TM, 0. ), MON( 1. ); 03123 for( unsigned int i=1; i<=TV._nord(); i++ ){ 03124 switch( i%4 ){ 03125 case 0: c = std::cos(x0); break; 03126 case 1: c = -std::sin(x0); break; 03127 case 2: c = -std::cos(x0); break; 03128 case 3: 03129 default: c = std::sin(x0); break; 03130 } 03131 MON *= TVmx0; 03132 TV2 += c * s * MON; 03133 s /= i+1; 03134 } 03135 03136 TV2._coefmon[0] += std::cos(x0); 03137 TV2._update_bndord(); 03138 switch( (TV2._nord()+1)%4 ){ 03139 case 0: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 03140 * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break; 03141 case 1: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 03142 * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break; 03143 case 2: TV2 -= s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 03144 * Op<T>::cos( Op<T>::zeroone()*Imx0+x0 ); break; 03145 case 3: TV2 += s * Op<T>::pow( Imx0, (int)TV2._nord()+1 ) 03146 * Op<T>::sin( Op<T>::zeroone()*Imx0+x0 ); break; 03147 } 03148 03149 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::cos( TV._bndT ); 03150 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 03151 return TV2; 03152 } 03153 03154 template <typename T> inline TVar<T> 03155 sin 03156 ( const TVar<T> &TV ) 03157 { 03158 return cos( TV - PI/2. ); 03159 } 03160 03161 template <typename T> inline TVar<T> 03162 asin 03163 ( const TVar<T> &TV ) 03164 { 03165 if( !TV._TM ){ 03166 TVar<T> TV2( TV ); 03167 TV2._coefmon[0] = 0.; 03168 *(TV2._bndrem) = Op<T>::asin(TV._coefmon[0] + *(TV._bndrem)); 03169 TV2._update_bndord(); 03170 return TV2; 03171 } 03172 03173 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()): 03174 TV._coefmon[0] ); 03175 double s = 1., t = 1.; 03176 TVar<T> G = TV * std::sqrt(1-x0*x0) - x0 * sqrt(1.-sqr(TV)); 03177 TVar<T> TV2( G ), MON( G ), sqrG( sqr(G) ); 03178 T IG( G.B() ), IG0( IG*Op<T>::zeroone() ), sqrIG0( Op<T>::sqr(IG0) ) ; 03179 T ASIN1, ASIN2( 1./Op<T>::sqrt(1-sqrIG0) ), 03180 ASIN3( IG0*Op<T>::pow(Op<T>::sqrt(1-sqrIG0),-3) ); 03181 for( unsigned int i=1; i<=TV._nord(); i++ ){ 03182 MON *= sqrG; 03183 s *= (double)(2*i-1)*(double)(2*i-1)/(double)(2*i)/(double)(2*i+1); 03184 TV2 += MON * s; 03185 t *= double(i+1); 03186 ASIN1 = ASIN2; ASIN2 = ASIN3; 03187 ASIN3 = ((2*i-1)*IG0*ASIN2+(i-1)*(i-1)*ASIN1)/(1-sqrIG0); 03188 } 03189 TV2._coefmon[0] += std::asin(x0); 03190 TV2._update_bndord(); 03191 TV2 += Op<T>::pow( IG, (int)TV2._nord()+1 ) / t * ASIN2; 03192 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::asin( TV._bndT ); 03193 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 03194 return TV2; 03195 } 03196 03197 template <typename T> inline TVar<T> 03198 acos 03199 ( const TVar<T> &TV ) 03200 { 03201 return PI/2. - asin( TV ); 03202 } 03203 03204 template <typename T> inline TVar<T> 03205 tan 03206 ( const TVar<T> &TV ) 03207 { 03208 return sin(TV) / cos(TV); 03209 } 03210 03211 template <typename T> inline TVar<T> 03212 atan 03213 ( const TVar<T> &TV ) 03214 { 03215 if( !TV._TM ){ 03216 TVar<T> TV2( TV ); 03217 TV2._coefmon[0] = 0.; 03218 *(TV2._bndrem) = Op<T>::atan(TV._coefmon[0] + *(TV._bndrem)); 03219 TV2._update_bndord(); 03220 return TV2; 03221 } 03222 03223 double x0 = ( TV._TM->options.REF_MIDPOINT? Op<T>::mid(TV.B()): 03224 TV._coefmon[0] ); 03225 TVar<T> G = ( TV - x0 ) / ( 1. + x0 * TV ); 03226 TVar<T> TV2( G ), MON( G ), msqrG( -sqr(G) ); 03227 T IG( G.B() ), IG0( IG*Op<T>::zeroone() ); 03228 for( unsigned int i=1; i<=TV._nord(); i++ ){ 03229 MON *= msqrG; 03230 TV2 += MON / (2*i+1); 03231 } 03232 TV2._coefmon[0] += std::atan(x0); 03233 TV2._update_bndord(); 03234 TV2 += Op<T>::pow( IG * Op<T>::cos( Op<T>::atan(IG0) ), 03235 (int)TV2._nord()+1 ) / (double)(TV2._nord()+1) 03236 * sin( (TV2._nord()+1) * (atan(IG0)+PI/2.) ); 03237 if( TV2._TM->options.PROPAGATE_BNDT ) TV2._bndT = Op<T>::asin( TV._bndT ); 03238 if( TV2._TM->options.CENTER_REMAINDER ) TV2._center_TM(); 03239 return TV2; 03240 } 03241 03242 template <typename T> inline TVar<T> 03243 hull 03244 ( const TVar<T>&TV1, const TVar<T>&TV2 ) 03245 { 03246 // Neither operands associated to TModel -- Make intersection in T type 03247 if( !TV1._TM && !TV2._TM ){ 03248 T R1 = TV1._coefmon[0] + TV1._bndord[0]; 03249 T R2 = TV2._coefmon[0] + TV2._bndord[0]; 03250 return Op<T>::hull(R1, R2); 03251 } 03252 03253 // First operand not associated to TModel 03254 else if( !TV1._TM ) 03255 return hull( TV2, TV1 ); 03256 03257 // Second operand not associated to TModel 03258 else if( !TV2._TM ) 03259 return TV1.P() + Op<T>::hull( TV1.R(), TV2._coefmon[0]+TV2._bndord[0]-TV1.B() ); 03260 03261 // TModel for first and second operands are inconsistent 03262 else if( TV1._TM != TV2._TM ) 03263 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL ); 03264 03265 // Perform union 03266 TVar<T> TV1C( TV1 ), TV2C( TV2 ); 03267 const double eta = TV1._TM->options.REF_POLY; 03268 T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 03269 TV1C.set(T(0.)); 03270 TV2C.set(T(0.)); 03271 T BTVD = (TV1C-TV2C).B(); 03272 return (1.-eta)*TV1C + eta*TV2C + Op<T>::hull( R1C+eta*BTVD, R2C+(eta-1.)*BTVD ); 03273 } 03274 03275 template <typename T> inline bool 03276 inter 03277 ( TVar<T>&TVR, const TVar<T>&TV1, const TVar<T>&TV2 ) 03278 { 03279 // Neither operands associated to TModel -- Make intersection in T type 03280 if( !TV1._TM && !TV2._TM ){ 03281 T R1 = TV1._coefmon[0] + TV1._bndord[0]; 03282 T R2 = TV2._coefmon[0] + TV2._bndord[0]; 03283 T RR( 0. ); 03284 bool flag = Op<T>::inter(RR, R1, R2); 03285 TVR = RR; 03286 return flag; 03287 } 03288 03289 // First operand not associated to TModel 03290 else if( !TV1._TM ) 03291 return inter( TVR, TV2, TV1 ); 03292 03293 // Second operand not associated to TModel 03294 else if( !TV2._TM ){ 03295 TVR = TV1.P(); 03296 return( Op<T>::inter(*(TVR._bndrem), TV1.R(), 03297 TV2._coefmon[0]+TV2._bndord[0]-TV1.B())? true: false ); 03298 } 03299 03300 // TModel for first and second operands are inconsistent 03301 else if( TV1._TM != TV2._TM ) 03302 throw typename TModel<T>::Exceptions( TModel<T>::Exceptions::TMODEL ); 03303 03304 // Perform intersection 03305 TVar<T> TV1C( TV1 ), TV2C( TV2 ); 03306 const double eta = TV1._TM->options.REF_POLY; 03307 T R1C = TV1C.C().R(), R2C = TV2C.C().R(); 03308 TV1C.set(T(0.)); 03309 TV2C.set(T(0.)); 03310 TVR = (1.-eta)*TV1C + eta*TV2C; 03311 TV1C -= TV2C; 03312 T BTVD = TV1C.B(); 03313 return( Op<T>::inter( *(TVR._bndrem), R1C+eta*BTVD, R2C+(eta-1.)*BTVD )? 03314 true: false ); 03315 } 03316 03317 } // namespace mc 03318 03319 #include "mcop.hpp" 03320 03321 namespace mc 03322 { 03323 03325 template <> template<typename T> struct Op< mc::TVar<T> > 03326 { 03327 typedef mc::TVar<T> TV; 03328 static TV point( const double c ) { return TV(c); } 03329 static TV zeroone() { return TV( mc::Op<T>::zeroone() ); } 03330 static void I(TV& x, const TV&y) { x = y; } 03331 static double l(const TV& x) { return mc::Op<T>::l(x.B()); } 03332 static double u(const TV& x) { return mc::Op<T>::u(x.B()); } 03333 static double abs (const TV& x) { return mc::Op<T>::abs(x.B()); } 03334 static double mid (const TV& x) { return mc::Op<T>::mid(x.B()); } 03335 static double diam(const TV& x) { return mc::Op<T>::diam(x.B()); } 03336 static TV inv (const TV& x) { return mc::inv(x); } 03337 static TV sqr (const TV& x) { return mc::sqr(x); } 03338 static TV sqrt(const TV& x) { return mc::sqrt(x); } 03339 static TV log (const TV& x) { return mc::log(x); } 03340 static TV xlog(const TV& x) { return x*mc::log(x); } 03341 static TV fabs(const TV& x) { return TV( mc::Op<T>::fabs(x.B()) ); } 03342 static TV exp (const TV& x) { return mc::exp(x); } 03343 static TV sin (const TV& x) { return mc::sin(x); } 03344 static TV cos (const TV& x) { return mc::cos(x); } 03345 static TV tan (const TV& x) { return mc::tan(x); } 03346 static TV asin(const TV& x) { return mc::asin(x); } 03347 static TV acos(const TV& x) { return mc::acos(x); } 03348 static TV atan(const TV& x) { return mc::atan(x); } 03349 static TV erf (const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ) } 03350 static TV erfc(const TV& x) { throw typename mc::TModel<T>::Exceptions( TModel<T>::Exceptions::UNDEF ) } 03351 static TV hull(const TV& x, const TV& y) { return mc::hull(x,y); } 03352 static TV min (const TV& x, const TV& y) { return mc::Op<T>::min(x.B(),y.B()); } 03353 static TV max (const TV& x, const TV& y) { return mc::Op<T>::max(x.B(),y.B()); } 03354 static TV arh (const TV& x, const double k) { return mc::exp(-k/x); } 03355 template <typename X, typename Y> static TV pow(const X& x, const Y& y) { return mc::pow(x,y); } 03356 static TV monomial (const unsigned int n, const T* x, const int* k) { return mc::monomial(n,x,k); } 03357 static bool inter(TV& xIy, const TV& x, const TV& y) { return mc::inter(xIy,x,y); } 03358 static bool eq(const TV& x, const TV& y) { return mc::Op<T>::eq(x.B(),y.B()); } 03359 static bool ne(const TV& x, const TV& y) { return mc::Op<T>::ne(x.B(),y.B()); } 03360 static bool lt(const TV& x, const TV& y) { return mc::Op<T>::lt(x.B(),y.B()); } 03361 static bool le(const TV& x, const TV& y) { return mc::Op<T>::le(x.B(),y.B()); } 03362 static bool gt(const TV& x, const TV& y) { return mc::Op<T>::gt(x.B(),y.B()); } 03363 static bool ge(const TV& x, const TV& y) { return mc::Op<T>::ge(x.B(),y.B()); } 03364 }; 03365 03366 } // namespace mc 03367 03368 #endif