libcmaes 0.10.2
A C++11 library for stochastic optimization with CMA-ES
Loading...
Searching...
No Matches
eigenmvn.h
1
33#ifndef __EIGENMULTIVARIATENORMAL_HPP
34#define __EIGENMULTIVARIATENORMAL_HPP
35
36#include <Eigen/Dense>
37#include <random>
38#include <stdexcept>
39
40/*
41 We need a functor that can pretend it's const,
42 but to be a good random number generator
43 it needs mutable state. The standard Eigen function
44 Random() just calls rand(), which changes a global
45 variable.
46*/
47namespace Eigen {
48 namespace internal {
49 template<typename Scalar>
51 {
52private:
53 void swap(scalar_normal_dist_op &other) {
54 std::swap(rng, other.rng);
55 std::swap(norm, other.norm);
56 }
57public:
58 static std::mt19937 rng; // The uniform pseudo-random algorithm
59 mutable std::normal_distribution<Scalar> norm; // gaussian combinator
60
61 //EIGEN_EMPTY_STRUCT_CTOR(scalar_normal_dist_op)
62 scalar_normal_dist_op() = default;
64 : norm{other.norm}
65 {
66 rng = other.rng;
67 };
68 scalar_normal_dist_op &operator=(const scalar_normal_dist_op &other) {
69 if(this != &other)
70 {
71 scalar_normal_dist_op temp(other);
72 swap(temp);
73 }
74 return *this;
75 };
76
78 {
79 if (this != &other) {
80 swap(other);
81 }
82 return *this;
83 }
84
86 *this = std::move(other);
87 }
88
89 template<typename Index>
90 inline const Scalar operator() (Index, Index = 0) const { return norm(rng); }
91 inline void seed(const uint64_t &s) { rng.seed(s); }
92 };
93
94 template<typename Scalar>
96
97 template<typename Scalar>
98 struct functor_traits<scalar_normal_dist_op<Scalar> >
99 { enum { Cost = 50 * NumTraits<Scalar>::MulCost, PacketAccess = false, IsRepeatable = false }; };
100
101 } // end namespace internal
102
107 template<typename Scalar>
109 {
110 Matrix< Scalar, Dynamic, 1> _mean;
111 internal::scalar_normal_dist_op<Scalar> randN; // Gaussian functor
112 bool _use_cholesky;
113
114 public:
115 void set_covar(const Matrix<Scalar,Dynamic,Dynamic> &covar) { _covar = covar; }
116 void set_transform(const Matrix<Scalar,Dynamic,Dynamic> &transform) { _transform = transform; }
117
118 private:
119 Matrix<Scalar,Dynamic,Dynamic> _covar;
120 Matrix<Scalar,Dynamic,Dynamic> _transform;
121
122 public:
123 SelfAdjointEigenSolver<Matrix<Scalar,Dynamic,Dynamic> > _eigenSolver; // drawback: this creates a useless eigenSolver when using Cholesky decomposition, but it yields access to eigenvalues and vectors
124
125 public:
126 EigenMultivariateNormal(const bool &use_cholesky=false,
127 const uint64_t &seed=std::mt19937::default_seed)
128 :_use_cholesky(use_cholesky)
129 {
130 randN.seed(seed);
131 }
132 EigenMultivariateNormal(const Matrix<Scalar,Dynamic,1>& mean,const Matrix<Scalar,Dynamic,Dynamic>& covar,
133 const bool &use_cholesky=false,const uint64_t &seed=std::mt19937::default_seed)
134 :_use_cholesky(use_cholesky)
135 {
136 randN.seed(seed);
137 setMean(mean);
138 setCovar(covar);
139 }
140
141 void setMean(const Matrix<Scalar,Dynamic,1>& mean) { _mean = mean; }
142 void setCovar(const Matrix<Scalar,Dynamic,Dynamic>& covar)
143 {
144 _covar = covar;
145
146 // Assuming that we'll be using this repeatedly,
147 // compute the transformation matrix that will
148 // be applied to unit-variance independent normals
149
150 if (_use_cholesky)
151 {
152 Eigen::LLT<Eigen::Matrix<Scalar,Dynamic,Dynamic> > cholSolver(_covar);
153 // We can only use the cholesky decomposition if
154 // the covariance matrix is symmetric, pos-definite.
155 // But a covariance matrix might be pos-semi-definite.
156 // In that case, we'll go to an EigenSolver
157 if (cholSolver.info()==Eigen::Success)
158 {
159 // Use cholesky solver
160 _transform = cholSolver.matrixL();
161 }
162 else
163 {
164 throw std::runtime_error("Failed computing the Cholesky decomposition. Use solver instead");
165 }
166 }
167 else
168 {
169 _eigenSolver = SelfAdjointEigenSolver<Matrix<Scalar,Dynamic,Dynamic> >(_covar);
170 _transform = _eigenSolver.eigenvectors()*_eigenSolver.eigenvalues().cwiseMax(0).cwiseSqrt().asDiagonal();
171 }
172 }
173
176 Matrix<Scalar,Dynamic,-1> samples(int nn, double factor)
177 {
178 return ((_transform * Matrix<Scalar,Dynamic,-1>::NullaryExpr(_covar.rows(),nn,randN))*factor).colwise() + _mean;
179 }
180
181 Matrix<Scalar,Dynamic,-1> samples_ind(int nn, double factor)
182 {
183 dMat pop = (Matrix<Scalar,Dynamic,-1>::NullaryExpr(_covar.rows(),nn,randN))*factor;
184 for (int i=0;i<pop.cols();i++)
185 {
186 pop.col(i) = pop.col(i).cwiseProduct(_transform) + _mean;
187 }
188 return pop;
189 }
190
191 Matrix<Scalar,Dynamic,-1> samples_ind(int nn)
192 {
193 return (Matrix<Scalar,Dynamic,-1>::NullaryExpr(_covar.rows(),nn,randN));
194 }
195
196 }; // end class EigenMultivariateNormal
197} // end namespace Eigen
198#endif
Definition eigenmvn.h:109
Matrix< Scalar, Dynamic,-1 > samples(int nn, double factor)
Definition eigenmvn.h:176
Definition eigenmvn.h:47