aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--math/num_diff.hpp70
-rw-r--r--math/vector_operation.hpp26
-rw-r--r--methods/lsnewton_cg/lsnewton_cg.hpp238
3 files changed, 306 insertions, 28 deletions
diff --git a/math/num_diff.hpp b/math/num_diff.hpp
index 0bd2937..2d2e67d 100644
--- a/math/num_diff.hpp
+++ b/math/num_diff.hpp
@@ -17,35 +17,60 @@ namespace opt_utilities
/**
calculate the numerical differential of a func_obj
*/
+ template<typename rT,typename pT>
+ class diff_func_obj
+ :public func_obj<rT,pT>
+ {
+ private:
+ virtual pT do_gradient(const pT& p)=0;
+ public:
+ pT gradient(const pT& p)
+ {
+ return do_gradient(p);
+ }
+ };
+
+
+
template <typename rT,typename pT>
- rT gradient(func_obj<rT,pT>& f,const pT& p,size_t n)
+ rT gradient(func_obj<rT,pT>& f,pT& p,size_t n)
{
rT ep=std::sqrt(std::numeric_limits<rT>::epsilon());
rT result;
- pT p2;
- resize(p2,get_size(p));
- pT p1;
- resize(p1,get_size(p));
+ pT p_tmp;
+
+ typename element_type_trait<pT>::element_type old_value=get_element(p,n);
- for(size_t i=0;i<get_size(p);++i)
- {
- set_element(p2,i,get_element(p,i));
- set_element(p1,i,get_element(p,i));
- }
typename element_type_trait<pT>::element_type h=
std::max(get_element(p,n),rT(1))*ep;
- set_element(p2,n,get_element(p,n)+h);
- set_element(p1,n,get_element(p,n)-h);
-
- rT v2=f(p2);
- rT v1=f(p1);
-
+ set_element(p,n,old_value+h);
+ rT v2=f(p);
+ set_element(p,n,old_value-h);
+ rT v1=f(p_tmp);
+ set_element(p,n,old_value);
result=(v2-v1)/h/2;
return result;
}
+ template <typename rT,typename pT>
+ pT gradient(func_obj<rT,pT>& f,pT& p)
+ {
+ diff_func_obj<rT,pT>* pdfo=0;
+ if(pdfo=dynamic_cast<diff_func_obj<rT,pT>*>(&f))
+ {
+ return pdfo->gradient(p);
+ }
+ pT result;
+ resize(result,get_size(p));
+ for(int i=0;i<get_size(p);++i)
+ {
+ set_element(result,i,gradient(f,p,i));
+ }
+ return result;
+ }
+
template <typename rT,typename pT>
rT hessian(func_obj<rT,pT>& f,const pT& p,size_t m,size_t n)
{
@@ -83,6 +108,19 @@ namespace opt_utilities
rT result=(f(p11)+f(p00)-f(p01)-f(p10))/(4*hm*hn);
return result;
}
+
+
+ template<typename rT,typename pT>
+ rT div(func_obj<rT,pT>& f,const pT& p)
+ {
+ rT result=0;
+ for(int i=0;i<get_size(p);++i)
+ {
+ result+=hessian(f,p,i,i);
+ }
+ return result;
+ }
+
}
#endif
diff --git a/math/vector_operation.hpp b/math/vector_operation.hpp
index 481fdef..3f5532c 100644
--- a/math/vector_operation.hpp
+++ b/math/vector_operation.hpp
@@ -1,18 +1,20 @@
#ifndef VECTOR_OPERATION_HPP
#define VECTOR_OPERATION_HPP
#include <core/opt_traits.hpp>
-
-template <typename pT>
-typename element_type_trait<pT>::element_type
-inner_product(const pT& v1,const pT& v2)
+namespace opt_utilities
{
- typename element_type_trait<pT>::element_type result;
- for(int i=0;i<get_size(v1);++i)
- {
- result+=get_element(v1,i)*get_element(v2,i);
- }
- return result;
-}
-
+ template <typename pT>
+ typename element_type_trait<pT>::element_type
+ inner_product(const pT& v1,const pT& v2)
+ {
+ typename element_type_trait<pT>::element_type result(0);
+ for(int i=0;i<get_size(v1);++i)
+ {
+ result+=get_element(v1,i)*get_element(v2,i);
+ }
+ return result;
+ }
+
+}
#endif
diff --git a/methods/lsnewton_cg/lsnewton_cg.hpp b/methods/lsnewton_cg/lsnewton_cg.hpp
new file mode 100644
index 0000000..e1c912a
--- /dev/null
+++ b/methods/lsnewton_cg/lsnewton_cg.hpp
@@ -0,0 +1,238 @@
+#ifndef LSNEWTON_GG_HPP
+#define LSNEWTON_GG_HPP
+#include <core/optimizer.hpp>
+#include <math/num_diff.hpp>
+#include <math/vector_operation.hpp>
+#include <methods/linmin/linmin.hpp>
+#include <cmath>
+
+#include <iostream>
+
+using std::cout;
+using std::cerr;
+using std::endl;
+
+namespace opt_utilities
+{
+
+ template<typename rT,typename pT>
+ void lsnewton_cg_f(func_obj<rT,pT>& foo,pT& x0,const rT& threshold)
+ {
+ for(int k=0;;++k)
+ {
+ cerr<<k<<endl;
+ rT abs_gk=0;
+ pT gk(gradient(foo,x0));
+ abs_gk=inner_product(gk,gk);
+ abs_gk=std::sqrt(abs_gk);
+ rT epsilon=std::min(rT(.5),std::sqrt(abs_gk))*abs_gk;
+ pT zj;
+ pT dj;
+ pT rj;
+ opt_eq(rj,gk);
+ resize(dj,get_size(x0));
+ resize(rj,get_size(x0));
+ resize(zj,get_size(x0));
+ for(int i=0;i!=get_size(gk);++i)
+ {
+ set_element(dj,i,-get_element(gk,i));
+ set_element(zj,i,0);
+ //cerr<<"gk:"<<i<<"\t"<<gk[i]<<endl;
+ }
+ pT p;
+
+ for(int j=0;;++j)
+ {
+ cerr<<j<<endl;
+ rT ep=std::sqrt(std::numeric_limits<rT>::epsilon());
+ rT djBkdj=0;
+ pT Bkdj;
+ resize(Bkdj,get_size(x0));
+ pT x1,x2;
+ typename element_type_trait<pT>::element_type h=1;
+ for(int i=0;i<get_size(x0);++i)
+ {
+ h=max(rT(1),std::abs(get_element(dj,i)));
+ //cerr<<"dj:"<<j<<"\t"<<dj[i]<<endl;
+ }
+ h*=ep;
+
+
+ resize(x1,get_size(x0));
+ resize(x2,get_size(x0));
+
+ for(int i=0;i<get_size(x0);++i)
+ {
+ set_element(x1,i,get_element(x0,i)-h*get_element(dj,i));
+ set_element(x2,i,get_element(x0,i)+h*get_element(dj,i));
+ //cerr<<i<<"\t"<<x1[i]<<"\t"<<x2[i]<<"\t"<<h<<"\t"<<dj[i]<<endl;
+ }
+
+ pT gk1(gradient(foo,x1));
+ pT gk2(gradient(foo,x2));
+
+ for(int i=0;i<get_size(x0);++i)
+ {
+ set_element(Bkdj,i,(get_element(gk2,i)-get_element(gk1,i))/h/2.);
+ djBkdj+=get_element(dj,i)*get_element(Bkdj,i);
+ //std::cerr<<"aa="<<Bkdj[i]<<endl;
+
+ }
+ if(djBkdj<0)
+ {
+ if(j==0)
+ {
+ opt_eq(p,gk);
+ }
+ else
+ {
+ opt_eq(p,zj);
+ }
+ break;
+ }
+ double rjrj=inner_product(rj,rj);
+ cerr<<"rjrj="<<j<<"\t"<<rjrj<<endl;
+
+ if(rjrj<threshold)
+ {
+ cerr<<"fdfa"<<endl;
+ return;
+ }
+ double alpha=rjrj/djBkdj;
+ double beta=0;
+ //cerr<<"alpha="<<alpha<<endl;
+ for(int i=0;i<get_size(x0);++i)
+ {
+ set_element(zj,i,get_element(zj,i)+alpha*get_element(dj,i));
+ set_element(rj,i,get_element(rj,i)+alpha*get_element(Bkdj,i));
+
+ //std::cerr<<"rj:"<<i<<"\t"<<Bkdj[i]<<endl;
+ }
+ double rj1rj1=inner_product(rj,rj);
+ //cerr<<"rj1rj1=\t"<<rj1rj1<<"\t"<<sqrt(rj1rj1)<<endl;
+ if(std::sqrt(rj1rj1)<epsilon)
+ {
+ //cerr<<"afd"<<endl;
+ opt_eq(p,zj);
+ break;
+ }
+ beta=rj1rj1/rjrj;
+ //cerr<<"rj1:\t"<<beta<<endl;
+ for(int i=0;i<get_size(x0);++i)
+ {
+ set_element(dj,i,-get_element(rj,i)+beta*get_element(dj,i));
+ }
+ }
+ rT fret;
+ //std::cerr<<p.size()<<std::endl;
+ linmin(x0,p,fret,foo);
+ for(int i=0;i<get_size(x0);++i)
+ {
+ set_element(x0,i,get_element(x0,i)+fret*get_element(p,i));
+ }
+ }
+ }
+
+
+ template <typename rT,typename pT>
+ class lsnewton_cg
+ :public opt_method<rT,pT>
+ {
+ public:
+ typedef pT array1d_type;
+ typedef rT T;
+ private:
+ func_obj<rT,pT>* p_fo;
+ optimizer<rT,pT>* p_optimizer;
+
+ //typedef blitz::Array<rT,2> array2d_type;
+
+
+ private:
+ array1d_type start_point;
+ array1d_type end_point;
+
+ private:
+ rT threshold;
+ private:
+ rT func(const pT& x)
+ {
+ assert(p_fo!=0);
+ return p_fo->eval(x);
+ }
+
+
+ public:
+ lsnewton_cg()
+ :threshold(1e-4)
+ {}
+
+ virtual ~lsnewton_cg()
+ {
+ };
+
+ lsnewton_cg(const lsnewton_cg<rT,pT>& rhs)
+ :p_fo(rhs.p_fo),p_optimizer(rhs.p_optimizer),
+ start_point(rhs.start_point),
+ end_point(rhs.end_point),
+ threshold(rhs.threshold)
+ {
+ }
+
+ lsnewton_cg<rT,pT>& operator=(const lsnewton_cg<rT,pT>& rhs)
+ {
+ threshold=rhs.threshold;
+ p_fo=rhs.p_fo;
+ p_optimizer=rhs.p_optimizer;
+ opt_eq(start_point,rhs.start_point);
+ opt_eq(end_point,rhs.end_point);
+ }
+
+ opt_method<rT,pT>* do_clone()const
+ {
+ return new lsnewton_cg<rT,pT>(*this);
+ }
+
+ void do_set_start_point(const array1d_type& p)
+ {
+ start_point.resize(get_size(p));
+ opt_eq(start_point,p);
+
+ }
+
+ array1d_type do_get_start_point()const
+ {
+ return start_point;
+ }
+
+ void do_set_precision(rT t)
+ {
+ threshold=t;
+ }
+
+ rT do_get_precision()const
+ {
+ return threshold;
+ }
+
+ void do_set_optimizer(optimizer<rT,pT>& o)
+ {
+ p_optimizer=&o;
+ p_fo=p_optimizer->ptr_func_obj();
+ }
+
+
+
+ pT do_optimize()
+ {
+ lsnewton_cg_f(*p_fo,start_point,threshold);
+ opt_eq(end_point,start_point);
+ return end_point;
+ }
+ };
+
+
+}
+
+#endif
+//EOF