00001 
00002 
00008 #if !defined(__numerical_Opt_h__)
00009 #define __numerical_Opt_h__
00010 
00011 
00012 #if defined(DEBUG_numerical) && !defined(DEBUG_Opt)
00013 #define DEBUG_Opt
00014 #endif
00015 
00016 #include "Exception.h"
00017 
00018 #include "../derivative/centered_difference.h"
00019 
00020 #include "../../ads/array/FixedArray.h"
00021 
00022 BEGIN_NAMESPACE_NUMERICAL
00023 
00025 
00031 template<int N, class Function, typename T = typename Function::result_type,
00032          typename Point = typename Function::argument_type>
00033 class Opt {
00034 protected:
00035 
00036   
00037   
00038   
00039   
00041   typedef Function function_type;
00042 
00044   typedef T number_type;
00045 
00047   typedef Point point_type;
00048 
00049   
00050   
00051   
00052 
00053 protected:
00054 
00056   const function_type& _function;
00057 
00059   int _max_function_calls;
00060 
00062   int _num_function_calls;
00063 
00065   bool _are_checking_function_calls;
00066 
00067   
00068   
00069   
00070   
00071 private:
00072 
00073   
00074   Opt();
00075 
00076   
00077   Opt(const Opt&);
00078 
00079   
00080   Opt&
00081   operator=(const Opt&);
00082 
00083 protected:
00084 
00085   
00091   
00092 
00094   Opt(const function_type& function, 
00095       const int max_function_calls = 10000,
00096       const bool are_checking_function_calls = true) :
00097     _function(function),
00098     _max_function_calls(max_function_calls),
00099     
00100     _num_function_calls(std::numeric_limits<int>::max()),
00101     _are_checking_function_calls(are_checking_function_calls)
00102   {}
00103 
00105   virtual
00106   ~Opt()
00107   {}
00108 
00109   
00110   
00112   
00113 
00115 
00118   number_type
00119   evaluate_function(const point_type& x) {
00120     increment_function_calls(x);
00121     return _function(x);
00122   }
00123 
00125 
00128   void
00129   evaluate_gradient(const point_type& x, point_type& gradient) {
00130     increment_function_calls(x);
00131     _function.gradient(x, gradient);
00132   }
00133 
00135 
00138   void
00139   evaluate_numeric_gradient(const point_type& x, 
00140                             point_type& gradient,
00141                             const number_type delta = 0.0) {
00142     increment_function_calls(x, 2 * N);
00143     if (delta != 0.0) {
00144       numerical::gradient_centered_difference<N,function_type,number_type>
00145         (_function, x, gradient, delta);
00146     }
00147     else {
00148       numerical::gradient_centered_difference<N,function_type,number_type>
00149         (_function, x, gradient);
00150     }
00151   }
00152 
00153   
00154 
00155 public:
00156 
00157   
00159   
00160 
00162   static
00163   int
00164   dimension() {
00165     return N;
00166   }
00167 
00169   const function_type&
00170   function() const {
00171     return _function;
00172   }
00173 
00175   int 
00176   max_function_calls() {
00177     return _max_function_calls;
00178   }
00179 
00181   int
00182   num_function_calls() const {
00183     return _num_function_calls;
00184   }
00185 
00186   
00187   
00189   
00190 
00192   void
00193   set_max_function_calls(const int max_function_calls) {
00194     _max_function_calls = max_function_calls;
00195   }
00196 
00198   void
00199   reset_num_function_calls() {
00200     _num_function_calls = 0;
00201   }
00202 
00204   void
00205   set_are_checking_function_calls(const bool are_checking) {
00206     _are_checking_function_calls = are_checking;
00207   }
00208 
00209   
00210   
00211 private:
00212 
00213   
00214   void
00215   increment_function_calls(const point_type& x, const int increment = 1) {
00216     _num_function_calls += increment;
00217     if (_are_checking_function_calls &&
00218         _num_function_calls > _max_function_calls) {
00219       OptimizationException<N,number_type,point_type>
00220         ex("In Opt: max function calls exceeded.",
00221             x, _function(x), _num_function_calls);
00222       ex.print();
00223       throw ex;
00224     }
00225   }
00226 
00227 };
00228 
00229 END_NAMESPACE_NUMERICAL
00230 
00231 #endif