Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 27 additions & 17 deletions include/bounds.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,27 @@ struct Population;
namespace parameters
{
struct Parameters;
struct Settings;
}

namespace bounds
{
using Mask = Eigen::Array<bool, Eigen::Dynamic, 1>;

Mask is_out_of_bounds(const Vector& xi, const Vector& lb, const Vector& ub);
bool any_out_of_bounds(const Vector& xi, const Vector& lb, const Vector& ub);
Mask is_out_of_bounds(const Vector &xi, const Vector &lb, const Vector &ub);
bool any_out_of_bounds(const Vector &xi, const Vector &lb, const Vector &ub);

struct BoundCorrection
{
virtual ~BoundCorrection() = default;
Vector lb, ub, db;
Vector db;
Float diameter;
size_t n_out_of_bounds = 0;
bool has_bounds;

BoundCorrection(const Vector& lb, const Vector& ub) : lb(lb), ub(ub), db(ub - lb),
diameter((ub - lb).norm()),
has_bounds(true)
BoundCorrection(const Vector &lb, const Vector &ub) : db(ub - lb),
diameter((ub - lb).norm()),
has_bounds(true)
{
//! find a better way
if (!std::isfinite(diameter))
Expand All @@ -38,13 +39,22 @@ namespace bounds
}
}

void correct(const Eigen::Index i, parameters::Parameters& p);
void correct(const Eigen::Index i, parameters::Parameters &p);

virtual Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) = 0;
virtual Vector correct_x(
const Vector &xi,
const Mask &oob,
const Float sigma,
const parameters::Settings &settings) = 0;

[[nodiscard]] Mask is_out_of_bounds(const Vector& xi) const;
[[nodiscard]] Mask is_out_of_bounds(
const Vector &xi,
const parameters::Settings &settings) const;

[[nodiscard]] Vector delta_out_of_bounds(const Vector& xi, const Mask& oob) const;
[[nodiscard]] Vector delta_out_of_bounds(
const Vector &xi,
const Mask &oob,
const parameters::Settings &settings) const;

[[nodiscard]] bool any_out_of_bounds() const
{
Expand All @@ -56,7 +66,7 @@ namespace bounds
{
using BoundCorrection::BoundCorrection;

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override
{
return xi;
}
Expand All @@ -73,14 +83,14 @@ namespace bounds

COTN(Eigen::Ref<const Vector> lb, Eigen::Ref<const Vector> ub) : BoundCorrection(lb, ub), sampler(static_cast<size_t>(lb.size()), rng::normal<Float>(0, 1.0 / 3.)) {}

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override;
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override;
};

struct Mirror final : BoundCorrection
{
using BoundCorrection::BoundCorrection;

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override;
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override;
};

struct UniformResample final : BoundCorrection
Expand All @@ -89,24 +99,24 @@ namespace bounds

UniformResample(Eigen::Ref<const Vector> lb, Eigen::Ref<const Vector> ub) : BoundCorrection(lb, ub), sampler(static_cast<size_t>(lb.size())) {}

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override;
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override;
};

struct Saturate final : BoundCorrection
{
using BoundCorrection::BoundCorrection;

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override;
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override;
};

struct Toroidal final : BoundCorrection
{
using BoundCorrection::BoundCorrection;

Vector correct_x(const Vector& xi, const Mask& oob, const Float sigma) override;
Vector correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings) override;
};

inline std::shared_ptr<BoundCorrection> get(const parameters::CorrectionMethod& m, const Vector& lb, const Vector& ub)
inline std::shared_ptr<BoundCorrection> get(const parameters::CorrectionMethod &m, const Vector &lb, const Vector &ub)
{
using namespace parameters;
switch (m)
Expand Down
22 changes: 20 additions & 2 deletions include/es.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "sampling.hpp"
#include "stats.hpp"
#include "bounds.hpp"
#include "settings.hpp"

namespace es
{
Expand All @@ -20,8 +21,15 @@ namespace es
x(x0), f(f0), t(1), budget(budget), target(target),
rejection_sampling(modules.bound_correction == parameters::CorrectionMethod::RESAMPLE),
sampler(sampling::get(d, modules, 1)),
corrector(bounds::get(modules.bound_correction, Vector::Ones(d) * -5.0, Vector::Ones(d) * 5.0))
corrector(bounds::get(modules.bound_correction, Vector::Ones(d) * -5.0, Vector::Ones(d) * 5.0)),
settings{d}
{
settings.modules = modules;
settings.x0 = x0;
settings.budget = budget;
settings.target = target;
settings.lb = Vector::Ones(d) * -5.0;
settings.ub = Vector::Ones(d) * 5.0;
}

Vector sample();
Expand All @@ -40,6 +48,7 @@ namespace es

std::shared_ptr<sampling::Sampler> sampler;
std::shared_ptr<bounds::BoundCorrection> corrector;
parameters::Settings settings;
};

struct MuCommaLambdaES
Expand All @@ -65,10 +74,18 @@ namespace es
sampler(sampling::get(d, modules, lambda)),
sigma_sampler(std::make_shared<sampling::Gaussian>(d)),
rejection_sampling(modules.bound_correction == parameters::CorrectionMethod::RESAMPLE),
corrector(bounds::get(modules.bound_correction, Vector::Ones(d) * -5.0, Vector::Ones(d) * 5.0))
corrector(bounds::get(modules.bound_correction, Vector::Ones(d) * -5.0, Vector::Ones(d) * 5.0)),
settings(d)
{
// tau = 1.0 / sampler->expected_length();
// tau_i = 1.0 / std::sqrt(sampler->expected_length());

settings.modules = modules;
settings.x0 = x0;
settings.budget = budget;
settings.target = target;
settings.lb = Vector::Ones(d) * -5.0;
settings.ub = Vector::Ones(d) * 5.0;
}

Vector sample(const Vector si);
Expand Down Expand Up @@ -100,5 +117,6 @@ namespace es

bool rejection_sampling;
std::shared_ptr<bounds::BoundCorrection> corrector;
parameters::Settings settings;
};
}
51 changes: 24 additions & 27 deletions src/bounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ static Float modulo2(const int x)

namespace bounds
{
Mask is_out_of_bounds(const Vector &xi, const Vector &lb, const Vector &ub)

Mask is_out_of_bounds(const Vector &xi, const Vector &lb, const Vector &ub)
{
return xi.array() < lb.array() || xi.array() > ub.array();
}
Expand All @@ -20,69 +20,66 @@ namespace bounds
return bounds::is_out_of_bounds(xi, lb, ub).any();
}


Mask BoundCorrection::is_out_of_bounds(const Vector& xi) const
Mask BoundCorrection::is_out_of_bounds(const Vector &xi, const parameters::Settings &settings) const
{
return bounds::is_out_of_bounds(xi, lb, ub);
return bounds::is_out_of_bounds(xi, settings.lb, settings.ub);
}

Vector BoundCorrection::delta_out_of_bounds(const Vector& xi, const Mask& oob) const
Vector BoundCorrection::delta_out_of_bounds(const Vector &xi, const Mask &oob, const parameters::Settings &settings) const
{
return (oob).select((xi - lb).cwiseQuotient(db), xi);;
return (oob).select((xi - settings.lb).cwiseQuotient(db), xi);
;
}

void BoundCorrection::correct(const Eigen::Index i, parameters::Parameters& p)
void BoundCorrection::correct(const Eigen::Index i, parameters::Parameters &p)
{
if (!has_bounds)
return;

const auto oob = is_out_of_bounds(p.pop.X.col(i));
const auto oob = is_out_of_bounds(p.pop.X.col(i), p.settings);
if (oob.any())
{
n_out_of_bounds++;
if (p.settings.modules.bound_correction == parameters::CorrectionMethod::NONE)
return;

p.pop.X.col(i) = correct_x(p.pop.X.col(i), oob, p.mutation->sigma);
p.pop.X.col(i) = correct_x(p.pop.X.col(i), oob, p.mutation->sigma, p.settings);
p.pop.Y.col(i) = p.adaptation->invert_x(p.pop.X.col(i), p.pop.s(i));
p.pop.Z.col(i) = p.adaptation->invert_y(p.pop.Y.col(i));
}
}

Vector COTN::correct_x(const Vector& xi, const Mask& oob, const Float sigma)
Vector COTN::correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings)
{
const Vector y = delta_out_of_bounds(xi, oob);
const Vector y = delta_out_of_bounds(xi, oob, settings);
return (oob).select(
lb.array() + db.array() * ((y.array() > 0).cast<Float>() - (sigma * sampler().array().abs())).abs(), y);
settings.lb.array() + db.array() * ((y.array() > 0).cast<Float>() - (sigma * sampler().array().abs())).abs(), y);
}


Vector Mirror::correct_x(const Vector& xi, const Mask& oob, const Float sigma)
Vector Mirror::correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings)
{
const Vector y = delta_out_of_bounds(xi, oob);
const Vector y = delta_out_of_bounds(xi, oob, settings);
return (oob).select(
lb.array() + db.array() * (y.array() - y.array().floor() - y.array().floor().unaryExpr(&modulo2)).
abs(),
settings.lb.array() + db.array() * (y.array() - y.array().floor() - y.array().floor().unaryExpr(&modulo2)).abs(),
y);
}


Vector UniformResample::correct_x(const Vector& xi, const Mask& oob, const Float sigma)
Vector UniformResample::correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings)
{
return (oob).select(lb + sampler().cwiseProduct(db), xi);
return (oob).select(settings.lb + sampler().cwiseProduct(db), xi);
}

Vector Saturate::correct_x(const Vector& xi, const Mask& oob, const Float sigma)
Vector Saturate::correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings)
{
const Vector y = delta_out_of_bounds(xi, oob);
const Vector y = delta_out_of_bounds(xi, oob, settings);
return (oob).select(
lb.array() + db.array() * (y.array() > 0).cast<Float>(), y);
settings.lb.array() + db.array() * (y.array() > 0).cast<Float>(), y);
}

Vector Toroidal::correct_x(const Vector& xi, const Mask& oob, const Float sigma)
Vector Toroidal::correct_x(const Vector &xi, const Mask &oob, const Float sigma, const parameters::Settings &settings)
{
const Vector y = delta_out_of_bounds(xi, oob);
const Vector y = delta_out_of_bounds(xi, oob, settings);
return (oob).select(
lb.array() + db.array() * (y.array() - y.array().floor()).abs(), y);
settings.lb.array() + db.array() * (y.array() - y.array().floor()).abs(), y);
}
}
12 changes: 6 additions & 6 deletions src/es.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ namespace es
const Vector z = (*sampler)();
x1 = x + sigma * z;

const auto mask = corrector->is_out_of_bounds(x1);
const auto mask = corrector->is_out_of_bounds(x, settings);
if (mask.any())
x1 = corrector->correct_x(x1, mask, sigma);
x1 = corrector->correct_x(x1, mask, sigma, settings);

} while (rejection_sampling && n_rej++ < 5*d && bounds::any_out_of_bounds(x1, corrector->lb, corrector->ub) );
} while (rejection_sampling && n_rej++ < 5*d && bounds::any_out_of_bounds(x1, settings.lb, settings.ub) );
return x1;
}

Expand Down Expand Up @@ -49,11 +49,11 @@ namespace es
const Vector z = (*sampler)();
x = m.array() + (si.array() * z.array());

const auto mask = corrector->is_out_of_bounds(x);
const auto mask = corrector->is_out_of_bounds(x, settings);
if (mask.any())
x = corrector->correct_x(x, mask, si.mean());
x = corrector->correct_x(x, mask, si.mean(), settings);

} while (rejection_sampling && n_rej++ < 5*d && bounds::any_out_of_bounds(x, corrector->lb, corrector->ub));
} while (rejection_sampling && n_rej++ < 5*d && bounds::any_out_of_bounds(x, settings.lb, settings.ub));
return x;
}

Expand Down
9 changes: 4 additions & 5 deletions src/interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -745,16 +745,15 @@ void define_bounds(py::module& main)
using namespace bounds;

py::class_<BoundCorrection, std::shared_ptr<BoundCorrection>>(m, "BoundCorrection")
.def_readwrite("lb", &BoundCorrection::lb)
.def_readwrite("ub", &BoundCorrection::ub)
.def_readwrite("db", &BoundCorrection::db)
.def_readwrite("diameter", &BoundCorrection::diameter)
.def_readwrite("has_bounds", &BoundCorrection::has_bounds)
.def_readonly("n_out_of_bounds", &BoundCorrection::n_out_of_bounds)
.def("correct", &BoundCorrection::correct,
py::arg("population"), py::arg("m"))
.def("delta_out_of_bounds", &BoundCorrection::delta_out_of_bounds, py::arg("xi"), py::arg("oob"))
.def("is_out_of_bounds", &BoundCorrection::is_out_of_bounds, py::arg("xi"))
py::arg("index"), py::arg("parameters"))
.def("correct_x", &BoundCorrection::correct_x, py::arg("xi"), py::arg("oob"), py::arg("sigma"), py::arg("settings"))
.def("delta_out_of_bounds", &BoundCorrection::delta_out_of_bounds, py::arg("xi"), py::arg("oob"), py::arg("settings"))
.def("is_out_of_bounds", &BoundCorrection::is_out_of_bounds, py::arg("xi"), py::arg("settings"))
;

py::class_<Resample, BoundCorrection, std::shared_ptr<Resample>>(m, "Resample")
Expand Down
Loading