12 #ifndef DIGNEA_MAP_ELITES_H
13 #define DIGNEA_MAP_ELITES_H
48 using Key = std::array<float, 8>;
50 using Bins = nc::NdArray<float>;
65 template <
typename IP,
typename IS,
typename OP,
typename OS>
70 using Grid = std::map<Key, Value>;
78 [[nodiscard]] json to_json()
const override;
82 [[nodiscard]]
string getName()
const override {
return "MapElites"; };
84 virtual Front<IS> getResults()
const override;
86 void setFeaturesInfo(
const Features &f);
89 void createInitialPopulation()
override;
91 void evaluatePopulation(vector<IS> &individuals)
override;
94 void mapToGrid(vector<IS> &individuals);
96 Key constructKey(
const vector<float> &features);
98 vector<IS> gridToVector();
113 template <
typename IP,
typename IS,
typename OP,
typename OS>
115 :
EIG<IP, IS, OP, OS>(), features(), grid(), bins() {
116 this->weightedFitness =
nullptr;
129 template <
typename IP,
typename IS,
typename OP,
typename OS>
132 std::transform(this->grid.begin(), this->grid.end(), std::back_inserter(v),
133 [](
auto &entry) { return entry.second; });
145 template <
typename IP,
typename IS,
typename OP,
typename OS>
147 this->population.reserve(this->populationSize);
148 this->population = this->instProb->createSolutions(this->populationSize);
149 this->evaluatePopulation(this->population);
150 this->mapToGrid(this->population);
151 this->updateEvolution(this->population);
152 this->initProgress();
163 template <
typename IP,
typename IS,
typename OP,
typename OS>
165 if (this->features.empty()) {
166 throw std::logic_error(
"Features not set in MapElites::run");
168 if (this->instProb) {
170 std::cout <<
"Running MapElites" << std::endl;
172 this->createInitialPopulation();
173 this->startTime = chrono::system_clock::now();
174 while (!this->isStoppingConditionReached()) {
176 std::cout <<
"Performing Generation " << this->performedEvaluations
179 vector<IS> offspring(this->populationSize);
180 vector pop = this->gridToVector();
182 pop = this->population;
185 for (
int i = 0; i < this->populationSize; i++) {
186 IS child = this->selection->select(pop);
189 this->mutation->run(child, this->mutationRate,
190 this->instProb.get());
191 offspring[i] = child;
194 this->evaluatePopulation(offspring);
195 this->mapToGrid(offspring);
198 this->updateEvolution(this->population);
199 this->updateProgress();
201 this->endTime = chrono::system_clock::now();
202 this->finishProgress();
205 throw std::logic_error(
"Problem not set in MapElites::run");
209 this->population.clear();
210 this->population = gridToVector();
223 template <
typename IP,
typename IS,
typename OP,
typename OS>
227 for (
int i = 0; i < 8; i++) {
228 auto [start, stop, num] = this->features[i];
229 bins[i] = nc::linspace(start, stop, num);
244 template <
typename IP,
typename IS,
typename OP,
typename OS>
248 for (
unsigned int i = 0; i < descriptor.size(); i++) {
250 const nc::NdArray<float> x = {descriptor[i]};
251 const nc::NdArray<float> bin = this->bins[i];
253 const auto uniqueBins = unique(bin);
254 auto result = nc::NdArray<float>(1, x.size());
257 typename decltype(result)::size_type idx{0};
258 std::for_each(x.begin(), x.end(),
259 [&uniqueBins, &result, &idx](
const auto value) {
260 const auto upperBin = std::upper_bound(
261 uniqueBins.begin(), uniqueBins.end(), value);
262 result[idx++] = static_cast<float>(
263 std::distance(uniqueBins.begin(), upperBin));
281 template <
typename IP,
typename IS,
typename OP,
typename OS>
284 for (IS &ind : individuals) {
286 if (ind.getFitness() > 0) {
287 vector descriptor = ind.getFeatures();
288 Key key = this->constructKey(descriptor);
291 if (!this->grid.contains(key)) {
292 this->grid.insert({key, ind});
294 }
else if (ind.getFitness() > this->grid[key].getFitness()) {
295 this->grid[key] = ind;
311 template <
typename IP,
typename IS,
typename OP,
typename OS>
313 this->instProb->beforeEvaluation(individuals);
314 for (IS &individual : individuals) {
316 shared_ptr<OP> optProblem = this->instProb->genOptProblem(individual);
318 vector<float> avgBestFitEAs;
319 avgBestFitEAs.reserve(this->algPortfolio.size());
320 vector<vector<float>> bestSolsEAs;
322 for (unique_ptr<Alg> &config : this->algPortfolio) {
323 vector<float> bestF(this->repetitions, 0.0);
325 for (
int rep = 0; rep < this->repetitions; rep++) {
326 config->setProblem(optProblem);
330 OS bestSolution = this->bestFitness.getBestSolution(front);
331 bestF[rep] = bestSolution.getFitness();
334 float averageBestFitness = this->averageFitness.computeValue(bestF);
335 avgBestFitEAs.push_back(averageBestFitness);
337 bestSolsEAs.push_back(bestF);
341 individual.setConfigFitness(bestSolsEAs);
342 individual.setAvgConfigFitness(avgBestFitEAs);
345 auto f = this->instanceFitness->compute(avgBestFitEAs);
346 individual.setBiasedFitness(f);
347 individual.setFitness(f);
351 this->instProb->afterEvaluation(individuals);
363 template <
typename IP,
typename IS,
typename OP,
typename OS>
376 template <
typename IP,
typename IS,
typename OP,
typename OS>
379 Evolution copy = this->evolution;
380 AvgEvolution avgCopy = this->avgEvolution;
381 data[
"name"] = this->getName();
382 data[
"max_generations"] = this->getMaxEvaluations();
383 data[
"repetitions"] = this->repetitions;
384 data[
"pop_size"] = this->populationSize;
385 data[
"mutation"] = this->mutation->getName();
386 data[
"crossover"] = this->crossover->getName();
387 data[
"mutation_rate"] = this->mutationRate;
388 data[
"crossover_rate"] = this->crossoverRate;
389 data[
"elapsed_time"] = this->elapsedTime;
390 data[
"evolution"] = copy.results();
391 data[
"avg_evolution"] = avgCopy.results();
394 for (
const unique_ptr<Alg> &config : this->algPortfolio) {
395 data[
"portfolio"][i] = config->to_json();
396 data[
"portfolio"][i][
"isTarget"] = target;
400 data[
"features_info"] = this->features;
std::tuple< float, float, int > FeatureInfo
FeatureInfo defines the information for a specific feature.
Definition: MapElites.h:38
std::map< int, FeatureInfo > Features
Features defines the information a feature.
Definition: MapElites.h:46
Class to define an Abstract Evolutionary Algorithm. This is the base skeleton for future extensions.
Definition: AbstractEA.h:42
Instance Generation Algorithm. Known as Meta-Evolutionary Algorithm (EIG). This algorithm uses a Weig...
Definition: EIG.h:55
unique_ptr< NoveltySearch< IS > > noveltySearch
Definition: EIG.h:255
Front class which stores the final results of an EA execution.
Definition: Front.h:26
Instance Generation Algorithm. Known as Meta-Evolutionary Algorithm (MapElites). This algorithm uses ...
Definition: MapElites.h:66
void evaluatePopulation(vector< IS > &individuals) override
Evaluates the population of individuals with all the algorithms in the portfolio.
Definition: MapElites.h:312
void createInitialPopulation() override
Creates a initial population of Problem Instances of the OP type. Uses the IP method "createSolutions...
Definition: MapElites.h:146
void run() override
Interface to run the MapElites for generating a set of instances for the optimisation problem defined...
Definition: MapElites.h:164
virtual Front< IS > getResults() const override
Returns a set of individuals as a result of the evolutionary method. The individual are instances for...
Definition: MapElites.h:364
string getName() const override
Get the name of the algorithm.
Definition: MapElites.h:82
json to_json() const override
Creates the JSON representation of the MapElites.
Definition: MapElites.h:377
MapElites()
Creates a default MapElites with only the evaluation as EasyInstances.
Definition: MapElites.h:114
void setFeaturesInfo(const Features &f)
Creates the pre-defined bins for each feature in the domain Creates the linspace with nBins different...
Definition: MapElites.h:224