Ultra 0.9.4
Loading...
Searching...
No Matches
numerical_refiner.h
Go to the documentation of this file.
1
12
13#if !defined(ULTRA_DE_NUMERICAL_REFINER_H)
14#define ULTRA_DE_NUMERICAL_REFINER_H
15
17#include "kernel/de/search.h"
19#include "kernel/refiner.h"
20
21#include <algorithm>
22#include <cmath>
23#include <cstddef>
24#include <optional>
25#include <vector>
26
27namespace ultra::de
28{
29
31{
47 template<Evaluator E>
49 std::optional<evaluator_fitness_t<E>> operator()(
50 evaluator_individual_t<E> &ind, const E &eva,
51 const parameters::refinement_parameters &params) const
52 {
53 Expects(params.de.min_radius > 0.0);
54 Expects(params.de.rel_radius >= 0.0);
55
56 const auto eval([&eva](const auto &cand)
57 {
58 if constexpr (requires { eva.core(); })
59 return eva.core()(cand);
60 else
61 return eva(cand);
62 });
63
64 auto dv(extract_decision_vector(ind));
65
66 if (dv.empty())
67 return {};
68
69 std::vector<interval<double>> ranges;
70 ranges.reserve(dv.size());
71
72 for (const auto val : dv.values)
73 {
74 const auto delta(std::max(std::abs(val) * params.de.rel_radius,
75 params.de.min_radius));
76 ranges.emplace_back(val - delta, val + delta);
77 }
78
79 problem de_prob(ranges);
80 de_prob.params.population.init_subgroups = 1;
81 de_prob.params.population.individuals = std::max(
83 de_prob.params.evolution.generations = params.de.generations;
84
85 // Reusable working buffer to avoid allocations in the evaluation loop.
86 auto trial(ind);
87
88 const auto de_eva([&](const de::individual &vec)
89 {
90 std::ranges::copy(vec, dv.values.begin());
91 trial.apply_decision_vector(dv);
92
93 return eval(trial);
94 });
95
96 const auto base(eval(ind));
97
98 search de_search(de_prob, de_eva);
99 de_search.messages(params.messages);
100 const auto res(de_search.run());
101
102 if (!res.runs() || res.best_measurements().fitness <= base)
103 return {};
104
105 std::ranges::copy(res.best_individual(), dv.values.begin());
106 ind.apply_decision_vector(dv);
107
108 return res.best_measurements().fitness;
109 }
110};
111
124template<Evaluator E>
126std::optional<evaluator_fitness_t<E>> optimise(const refiner &opt,
127 evaluator_individual_t<E> &ind,
128 const E &eva)
129{
130 return opt.optimise(ind, eva, numerical_refinement_backend());
131}
132
133} // namespace ultra::de
134
135#endif // include guard
search_stats< individual_t, fitness_t > run(unsigned=1, const model_measurements< fitness_t > &={})
Definition search.h:230
Definition de/individual.h:36
Definition de/problem.h:29
Definition de/search.h:28
Definition refiner.h:25
std::optional< evaluator_fitness_t< E > > optimise(evaluator_individual_t< E > &, const E &, Backend &&) const
Definition refiner.h:34
const_iterator begin() const noexcept
Definition vector_individual.h:65
Supports numerical optimisation via decision-vector perturbation.
Definition decision_vector.h:97
std::optional< evaluator_fitness_t< E > > optimise(const refiner &opt, evaluator_individual_t< E > &ind, const E &eva)
Definition numerical_refiner.h:126
Definition numerical_refiner.h:31
std::optional< evaluator_fitness_t< E > > operator()(evaluator_individual_t< E > &ind, const E &eva, const parameters::refinement_parameters &params) const
Definition numerical_refiner.h:49
static constexpr std::size_t min_individuals
Minimum population size required for Differential Evolution.
Definition parameters.h:188
unsigned generations
Definition parameters.h:119
std::size_t individuals
Definition parameters.h:54
std::size_t init_subgroups
Definition parameters.h:68
Parameters controlling numerical optimisation of GP individuals.
Definition parameters.h:203
bool messages
Definition parameters.h:275