48 const std::vector<std::vector<double>>& z_samples) {
49 const size_t n = state.
mean.size();
50 std::vector<std::vector<double>> offspring;
51 offspring.reserve(z_samples.size());
52 for (
const auto& z : z_samples) {
54 throw std::invalid_argument(
"AskGivenSamples: every z_sample must match state.mean's dimension");
56 std::vector<double> x(n);
57 for (
size_t j = 0; j < n; ++j) {
60 offspring.push_back(std::move(x));
75 const std::vector<std::vector<double>>& offspring,
76 const std::vector<double>& fitness,
double step_size_learning_rate,
77 double scale_learning_rate) {
78 if (z_samples.size() != offspring.size() || z_samples.size() != fitness.size()) {
79 throw std::invalid_argument(
"TellGivenSamples: z_samples, offspring, and fitness must be the same size");
81 if (z_samples.size() < 2) {
82 throw std::invalid_argument(
"TellGivenSamples: need at least 2 samples");
85 const size_t n = state.
mean.size();
86 const size_t lambda = z_samples.size();
87 const size_t mu = std::max<size_t>(1, lambda / 2);
89 std::vector<size_t> order(lambda);
90 std::iota(order.begin(), order.end(),
size_t{0});
91 std::sort(order.begin(), order.end(), [&](
size_t a,
size_t b) { return fitness[a] > fitness[b]; });
93 std::vector<double> y(n, 0.0);
94 std::vector<double> y_squared(n, 0.0);
95 for (
size_t rank = 0; rank < mu; ++rank) {
96 const auto& z = z_samples[order[rank]];
97 for (
size_t j = 0; j < n; ++j) {
98 double y_ij = std::sqrt(state.
variances[j]) * z[j];
100 y_squared[j] += y_ij * y_ij;
103 for (
size_t j = 0; j < n; ++j) {
104 y[j] /=
static_cast<double>(mu);
105 y_squared[j] /=
static_cast<double>(mu);
110 for (
size_t j = 0; j < n; ++j) {
115 for (
size_t j = 0; j < n; ++j) {
116 y_norm += y[j] * y[j];
118 y_norm = std::sqrt(y_norm);
119 double expected_norm = std::sqrt(
static_cast<double>(n));
120 next.
sigma = state.
sigma * std::exp(step_size_learning_rate * (y_norm / expected_norm - 1.0));
123 for (
size_t j = 0; j < n; ++j) {
124 next.
variances[j] = (1.0 - scale_learning_rate) * state.
variances[j] + scale_learning_rate * y_squared[j];
140 CMAES(std::vector<double> initial_mean,
double initial_sigma,
size_t lambda,
141 double step_size_learning_rate = 0.3,
double scale_learning_rate = 0.3)
143 step_size_learning_rate_(step_size_learning_rate),
144 scale_learning_rate_(scale_learning_rate) {
145 if (initial_mean.empty()) {
146 throw std::invalid_argument(
"CMAES: initial_mean must not be empty");
148 if (initial_sigma <= 0.0) {
149 throw std::invalid_argument(
"CMAES: initial_sigma must be positive");
152 throw std::invalid_argument(
"CMAES: lambda must be >= 2");
154 state_.
mean = std::move(initial_mean);
155 state_.
sigma = initial_sigma;
161 template <
typename RNG>
162 std::vector<std::vector<double>>
Ask(RNG& rng) {
163 std::normal_distribution<double> dist(0.0, 1.0);
164 last_z_samples_.assign(lambda_, std::vector<double>(state_.
mean.size()));
165 for (
auto& z : last_z_samples_) {
166 for (
double& v : z) {
179 void Tell(
const std::vector<std::vector<double>>& offspring,
const std::vector<double>& fitness) {
180 if (last_z_samples_.empty()) {
181 throw std::invalid_argument(
"CMAES::Tell: called before any Ask()");
183 state_ =
TellGivenSamples(state_, last_z_samples_, offspring, fitness, step_size_learning_rate_,
184 scale_learning_rate_);
187 [[nodiscard]]
const std::vector<double>&
mean()
const {
return state_.
mean; }
194 double step_size_learning_rate_;
195 double scale_learning_rate_;
196 std::vector<std::vector<double>> last_z_samples_;
RNG-driven ask-tell wrapper: caches the z-samples an Ask() call draws so a matching Tell() call can r...
Definition cma_es.hpp:134
void Tell(const std::vector< std::vector< double > > &offspring, const std::vector< double > &fitness)
Updates the internal state from the most recent Ask() call's offspring and their fitness values (maxi...
Definition cma_es.hpp:179
CMAES(std::vector< double > initial_mean, double initial_sigma, size_t lambda, double step_size_learning_rate=0.3, double scale_learning_rate=0.3)
Definition cma_es.hpp:140
const std::vector< double > & variances() const
Definition cma_es.hpp:189
std::vector< std::vector< double > > Ask(RNG &rng)
Draws lambda fresh offspring from the current state, caching the standard- normal samples used for th...
Definition cma_es.hpp:162
const std::vector< double > & mean() const
Definition cma_es.hpp:187
double sigma() const
Definition cma_es.hpp:188
Definition acquisition_functions.hpp:16
std::vector< std::vector< double > > AskGivenSamples(const CMAESState &state, const std::vector< std::vector< double > > &z_samples)
Pure core: decodes an explicit set of standard-normal sample vectors into offspring points,...
Definition cma_es.hpp:47
CMAESState TellGivenSamples(const CMAESState &state, const std::vector< std::vector< double > > &z_samples, const std::vector< std::vector< double > > &offspring, const std::vector< double > &fitness, double step_size_learning_rate, double scale_learning_rate)
Pure core: given the offspring AskGivenSamples produced (same order), their maximization-convention f...
Definition cma_es.hpp:74
This algorithm's full adaptive state: the search mean, the global step size, and each dimension's own...
Definition cma_es.hpp:36
std::vector< double > variances
Definition cma_es.hpp:39
double sigma
Definition cma_es.hpp:38
std::vector< double > mean
Definition cma_es.hpp:37