edoSamplerNormalMulti.h
00001 /*
00002 The Evolving Distribution Objects framework (EDO) is a template-based,
00003 ANSI-C++ evolutionary computation library which helps you to write your
00004 own estimation of distribution algorithms.
00005 
00006 This library is free software; you can redistribute it and/or
00007 modify it under the terms of the GNU Lesser General Public
00008 License as published by the Free Software Foundation; either
00009 version 2.1 of the License, or (at your option) any later version.
00010 
00011 This library is distributed in the hope that it will be useful,
00012 but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 Lesser General Public License for more details.
00015 
00016 You should have received a copy of the GNU Lesser General Public
00017 License along with this library; if not, write to the Free Software
00018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020 Copyright (C) 2010 Thales group
00021 */
00022 /*
00023 Authors:
00024     Johann Dréo <johann.dreo@thalesgroup.com>
00025     Caner Candan <caner.candan@thalesgroup.com>
00026 */
00027 
00028 #ifndef _edoSamplerNormalMulti_h
00029 #define _edoSamplerNormalMulti_h
00030 
00031 #include <cmath>
00032 #include <limits>
00033 
00034 #include <edoSampler.h>
00035 
00036 
00037 #ifdef WITH_BOOST
00038 #include <utils/edoCholesky.h>
00039 #include <boost/numeric/ublas/lu.hpp>
00040 #include <boost/numeric/ublas/symmetric.hpp>
00041 namespace ublas = boost::numeric::ublas;
00042 #else
00043 #ifdef WITH_EIGEN
00044 #include <Eigen/Dense>
00045 #endif // WITH_EIGEN
00046 #endif // WITH_BOOST
00047 
00048 
00064 template< typename EOT, typename D = edoNormalMulti< EOT > >
00065 class edoSamplerNormalMulti : public edoSampler< D >
00066 {
00067 
00068 #ifdef WITH_BOOST
00069 
00070 public:
00071     typedef typename EOT::AtomType AtomType;
00072 
00073     edoSamplerNormalMulti( edoRepairer<EOT> & repairer ) 
00074         : edoSampler< D >( repairer)
00075     {}
00076 
00077 
00078     EOT sample( D& distrib )
00079     {
00080         unsigned int size = distrib.size();
00081         assert(size > 0);
00082 
00083         // L = cholesky decomposition of varcovar
00084         const typename cholesky::CholeskyBase<AtomType>::FactorMat& L = _cholesky( distrib.varcovar() );
00085 
00086         // T = vector of size elements drawn in N(0,1)
00087         ublas::vector< AtomType > T( size );
00088         for ( unsigned int i = 0; i < size; ++i ) {
00089             T( i ) = rng.normal();
00090         }
00091 
00092         // LT = L * T
00093         ublas::vector< AtomType > LT = ublas::prod( L, T );
00094 
00095         // solution = means + LT
00096         ublas::vector< AtomType > mean = distrib.mean();
00097         ublas::vector< AtomType > ublas_solution = mean + LT;
00098         EOT solution( size );
00099         std::copy( ublas_solution.begin(), ublas_solution.end(), solution.begin() );
00100 
00101         return solution;
00102     }
00103 
00104 protected:
00105     cholesky::CholeskyLLT<AtomType> _cholesky;
00106 
00107 #else
00108 #ifdef WITH_EIGEN
00109 
00110 public:
00111     typedef typename EOT::AtomType AtomType;
00112 
00113     typedef typename D::Vector Vector;
00114     typedef typename D::Matrix Matrix;
00115 
00116     edoSamplerNormalMulti( edoRepairer<EOT> & repairer ) 
00117         : edoSampler< D >( repairer)
00118     {}
00119 
00120 
00121     EOT sample( D& distrib )
00122     {
00123         unsigned int size = distrib.size();
00124         assert(size > 0);
00125 
00126         // LsD = cholesky decomposition of varcovar
00127 
00128         // Computes L and mD such as V = L mD L^T
00129         Eigen::LDLT<Matrix> cholesky( distrib.varcovar() );
00130         Matrix L = cholesky.matrixL();
00131         assert(L.innerSize() == size);
00132         assert(L.outerSize() == size);
00133 
00134         Matrix mD = cholesky.vectorD().asDiagonal();
00135         assert(mD.innerSize() == size);
00136         assert(mD.outerSize() == size);
00137 
00138         // now compute the final symetric matrix: LsD = L mD^1/2
00139         // remember that V = ( L mD^1/2) ( L mD^1/2)^T
00140         // fortunately, the square root of a diagonal matrix is the square 
00141         // root of all its elements
00142         Matrix sqrtD = mD.cwiseSqrt();
00143         assert(sqrtD.innerSize() == size);
00144         assert(sqrtD.outerSize() == size);
00145 
00146         Matrix LsD = L * sqrtD;
00147         assert(LsD.innerSize() == size);
00148         assert(LsD.outerSize() == size);
00149 
00150         // T = vector of size elements drawn in N(0,1)
00151         Vector T( size );
00152         for ( unsigned int i = 0; i < size; ++i ) {
00153             T( i ) = rng.normal();
00154         }
00155         assert(T.innerSize() == size);
00156         assert(T.outerSize() == 1);
00157 
00158         // LDT = (L mD^1/2) * T
00159         Vector LDT = LsD * T;
00160         assert(LDT.innerSize() == size);
00161         assert(LDT.outerSize() == 1);
00162 
00163         // solution = means + LDT
00164         Vector mean = distrib.mean();
00165         assert(mean.innerSize() == size);
00166         assert(mean.outerSize() == 1);
00167 
00168         Vector typed_solution = mean + LDT;
00169         assert(typed_solution.innerSize() == size);
00170         assert(typed_solution.outerSize() == 1);
00171 
00172         // copy in the EOT structure (more probably a vector)
00173         EOT solution( size );
00174         for( unsigned int i = 0; i < mean.innerSize(); i++ ) {
00175             solution[i]= typed_solution(i);
00176         }
00177         assert( solution.size() == size );
00178 
00179         return solution;
00180     }
00181 #endif // WITH_EIGEN
00182 #endif // WITH_BOOST
00183 }; // class edoNormalMulti
00184 
00185 
00186 #endif // !_edoSamplerNormalMulti_h
 All Classes Functions Variables Typedefs