GCOP  1.0
samplenumericaldiff.h
Go to the documentation of this file.
00001 // -*- coding: utf-8
00002 // vim: set fileencoding=utf-8
00003 
00004 // This file is part of Eigen, a lightweight C++ template library
00005 // for linear algebra.
00006 //
00007 // Copyright (C) 2009 Thomas Capricelli <orzel@freehackers.org>
00008 //
00009 // This Source Code Form is subject to the terms of the Mozilla
00010 // Public License v. 2.0. If a copy of the MPL was not distributed
00011 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
00012 
00013 // Modified to find numerical difference using samples
00014 
00015 // Author2: Gowtham
00016 
00017 #ifndef EIGEN_SAMPLE_NUMERICAL_DIFF_H
00018 #define EIGEN_SAMPLE_NUMERICAL_DIFF_H
00019 
00020 #include <random>
00021 
00022 namespace Eigen { 
00023 
00033 template<typename _Functor>
00034 class SampleNumericalDiff : public _Functor
00035 {
00036 public:
00037     typedef _Functor Functor;
00038     typedef typename Functor::Scalar Scalar;
00039     typedef typename Functor::InputType InputType;
00040     typedef typename Functor::ValueType ValueType;
00041     typedef typename Functor::JacobianType JacobianType;
00042 
00043     SampleNumericalDiff(Scalar _epsfcn=0.) : Functor(), epsfcn(_epsfcn), normal_dist(0,1) {
00044       randgenerator.seed(370212);
00045       }
00046     SampleNumericalDiff(const Functor& f, Scalar _epsfcn=0.) : Functor(f), epsfcn(_epsfcn), normal_dist(0,1) {
00047       randgenerator.seed(370212);
00048       }
00049 
00050     // forward constructors
00051     template<typename T0>
00052         SampleNumericalDiff(const T0& a0) : Functor(a0), epsfcn(0) {}
00053     template<typename T0, typename T1>
00054         SampleNumericalDiff(const T0& a0, const T1& a1) : Functor(a0, a1), epsfcn(0) {}
00055     template<typename T0, typename T1, typename T2>
00056         SampleNumericalDiff(const T0& a0, const T1& a1, const T2& a2) : Functor(a0, a1, a2), epsfcn(0) {}
00057 
00058     enum {
00059         InputsAtCompileTime = Functor::InputsAtCompileTime,
00060         ValuesAtCompileTime = Functor::ValuesAtCompileTime
00061     };
00062 
00066     int df(const InputType& _x, JacobianType &jac)
00067     {
00068       using std::sqrt;
00069       using std::abs;
00070       using std::cout;
00071       using std::endl;
00072       /* Local variables */
00073       Scalar h;
00074       const typename InputType::Index n = _x.size();
00075       int nfev= round(n*1.5);
00076       const Scalar eps = sqrt(((std::max)(epsfcn,NumTraits<Scalar>::epsilon() )));
00077       ValueType val1, val2;
00078       InputType x = _x;
00079       // TODO : we should do this only if the size is not already known
00080       val1.resize(Functor::values());
00081       val2.resize(Functor::values());
00082       MatrixXd dymatrix(Functor::values(), nfev);
00083       MatrixXd dumatrix(n, nfev);
00084 
00085       // initialization
00086       Functor::operator()(x, val1);//Mean input and value
00087 
00088       // Function Body
00089       for(int ns = 0; ns < nfev; ++ns)
00090       {
00091         for (int j = 0; j < n; ++j) {
00092 
00093           /*h = eps * abs(x[j]);
00094           if (h == 0.) {
00095             h = eps;
00096           }
00097           h = eps;
00098           if(bernoulli_dist(randgenerator))
00099           {
00100             dumatrix(j, ns) = h;
00101           }
00102           else
00103           {
00104             dumatrix(j, ns) = -h;
00105           }
00106           */
00107           dumatrix(j, ns) = eps*normal_dist(randgenerator);
00108         }//Do perturbations to the whole vector
00109         x = _x + dumatrix.col(ns);
00110         Functor::operator()(x, val2);//Evaluate at new perturbed vector
00111         dymatrix.col(ns) = val2 - val1;//dY
00112         //cout<<"dumatrix["<<ns<<"]: "<<dumatrix.col(ns).transpose()<<endl;
00113         //getchar();
00114         //cout<<"dymatrix["<<ns<<"]: "<<dymatrix.col(ns).transpose()<<endl;
00115         //getchar();
00116       }
00117       jac = (dumatrix*dumatrix.transpose()).ldlt().solve(dumatrix*dymatrix.transpose()).transpose();
00118       //cout<<"jac: "<<endl<<jac<<endl;
00119       cout<<endl<<"Error_predicted: "<<sqrt((dymatrix - jac*dumatrix).squaredNorm())<<endl;
00120       getchar();
00121       return nfev;
00122     }
00123 private:
00124     Scalar epsfcn;
00125 
00126     SampleNumericalDiff& operator=(const SampleNumericalDiff&);
00127 
00128     std::default_random_engine randgenerator; 
00129 
00130     //default constructor gives p = 0.5 benoulli
00131     //std::bernoulli_distribution bernoulli_dist;     ///< Bernoulli generator for getting perturbations
00132     std::normal_distribution<double> normal_dist;
00133 };
00134 
00135 } // end namespace Eigen
00136 
00137 //vim: ai ts=4 sts=4 et sw=4
00138 #endif // EIGEN_NUMERICAL_DIFF_H
00139