164 lines
5.1 KiB
C++
164 lines
5.1 KiB
C++
#pragma once
|
|
|
|
/**
|
|
* @file population.hpp
|
|
* @brief Population management — the evolutionary ecosystem.
|
|
*
|
|
* Manages a population of FuzzyControllers with:
|
|
* - Elitism (protected top-N)
|
|
* - Tournament selection with age weighting
|
|
* - Crossover, mutation, and Phoenix rebirth
|
|
* - Island migration (optional)
|
|
* - Novelty search (optional)
|
|
* - Phase 23 stale elite mitigation strategies
|
|
* - Phase 24 violator synchronization
|
|
*
|
|
* Port of: packages/fces/core/population.py (~1260 LOC)
|
|
*/
|
|
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "controller.hpp"
|
|
|
|
namespace fces {
|
|
|
|
/**
|
|
* Elite selection strategy for stale elite mitigation (Phase 23).
|
|
*/
|
|
enum class EliteStrategy {
|
|
Cumulative, // Raw cumulative fitness
|
|
EMA, // Exponential moving average
|
|
Rolling, // Rolling window average
|
|
Reset, // Periodic reset every 500 steps
|
|
AgePenalty // fitness / log(age + 2)
|
|
};
|
|
|
|
/**
|
|
* Population — manages the ecosystem of FuzzyControllers.
|
|
*/
|
|
class Population {
|
|
public:
|
|
// Configuration constants
|
|
static constexpr int ELITE_COUNT = 2;
|
|
static constexpr float NOVELTY_WEIGHT = 0.1f;
|
|
static constexpr float ISLAND_MIGRATION_RATE = 0.05f;
|
|
static constexpr int BEHAVIORAL_ARCHIVE_SIZE = 100;
|
|
|
|
// ---------------------------------------------------------------
|
|
// Construction
|
|
// ---------------------------------------------------------------
|
|
|
|
explicit Population(int active_size = 75, int repo_size = 10000,
|
|
EliteStrategy elite_strategy = EliteStrategy::Cumulative,
|
|
bool link_mutation = false, bool link_elite = false,
|
|
bool link_violator = false, bool use_fuzzy_pacer = false,
|
|
bool use_fuzzy_importance = false,
|
|
bool direct_construction = false,
|
|
bool use_banach_fission = false);
|
|
|
|
// ---------------------------------------------------------------
|
|
// Core API
|
|
// ---------------------------------------------------------------
|
|
|
|
/// Get the currently active controller (sticky selection)
|
|
FuzzyController &get_active_controller();
|
|
|
|
/// Select a controller via fitness-weighted tournament
|
|
FuzzyController &select_weighted();
|
|
|
|
/// Get the best controller in the active population
|
|
FuzzyController &get_best_active();
|
|
|
|
/// Get the worst non-elite controller
|
|
FuzzyController &get_worst_active();
|
|
|
|
/// Remove a specific controller (unless elite)
|
|
void kill(FuzzyController &controller);
|
|
|
|
/// Update a controller's fitness
|
|
void update_controller_fitness(FuzzyController &controller, float reward,
|
|
bool increment_eval = true);
|
|
|
|
/// Mark a controller as a violator (rollback)
|
|
void mark_violated(FuzzyController &controller);
|
|
|
|
/// Get the effective fitness considering elite strategy and training progress
|
|
float get_effective_fitness(const FuzzyController &controller,
|
|
float training_progress) const;
|
|
|
|
// ---------------------------------------------------------------
|
|
// Evolution
|
|
// ---------------------------------------------------------------
|
|
|
|
/**
|
|
* Evolve the population: select parents, crossover/mutate, replace worst.
|
|
*
|
|
* @param current_loss Current training loss
|
|
* @param velocity Loss velocity
|
|
* @param training_progress Training progress [0, 1]
|
|
*/
|
|
void evolve(float current_loss, float velocity = 0.0f,
|
|
float training_progress = 0.0f);
|
|
|
|
/// Resize the population (dynamic expansion/contraction)
|
|
void resize(int target_size, float training_progress = 0.5f);
|
|
|
|
/// Reduce mutation variance after rollback
|
|
void calm_down();
|
|
|
|
// ---------------------------------------------------------------
|
|
// Accessors
|
|
// ---------------------------------------------------------------
|
|
|
|
int size() const { return static_cast<int>(gladiators_.size()); }
|
|
float global_sigma_modifier() const { return global_sigma_modifier_; }
|
|
|
|
/// Compute diversity index (behavioral spread)
|
|
float get_diversity_index() const;
|
|
|
|
/// Serialization
|
|
// TODO: state_dict / load_state_dict
|
|
|
|
private:
|
|
std::vector<FuzzyController> gladiators_;
|
|
std::vector<FuzzyController> repository_;
|
|
std::vector<FuzzyController> violated_controllers_;
|
|
|
|
float global_sigma_modifier_ = 1.0f;
|
|
|
|
// Sticky controller selection
|
|
FuzzyController *active_controller_ = nullptr;
|
|
int steps_active_ = 0;
|
|
int selection_interval_ = 20;
|
|
|
|
// Configuration
|
|
EliteStrategy elite_strategy_;
|
|
bool link_mutation_;
|
|
bool link_elite_;
|
|
bool link_violator_;
|
|
bool use_fuzzy_pacer_;
|
|
bool use_fuzzy_importance_;
|
|
bool direct_construction_;
|
|
bool use_banach_fission_;
|
|
|
|
// Novelty search
|
|
std::vector<std::vector<float>> behavioral_archive_;
|
|
|
|
// Fitness history for fuzzy pacer
|
|
std::vector<float> fitness_history_;
|
|
|
|
// Phase 23: periodic reset counter
|
|
int reset_step_counter_ = 0;
|
|
|
|
// ---------------------------------------------------------------
|
|
// Internal
|
|
// ---------------------------------------------------------------
|
|
|
|
std::vector<FuzzyController *> get_elites();
|
|
void add_to_repository(const FuzzyController &controller);
|
|
};
|
|
|
|
} // namespace fces
|