style: run clang-format and configure pre-commit hooks
This commit is contained in:
51
.pre-commit-config.yaml
Normal file
51
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Pre-commit configuration for FCES-native
|
||||||
|
repos:
|
||||||
|
# 1. Standard hooks for general file cleanliness
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.6.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: check-yaml
|
||||||
|
- id: check-added-large-files
|
||||||
|
|
||||||
|
# 2. C++ Formatting using clang-format (fetched dynamically)
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
|
rev: v18.1.5
|
||||||
|
hooks:
|
||||||
|
- id: clang-format
|
||||||
|
types_or: [c++, c]
|
||||||
|
|
||||||
|
# 3. C++ Static Analysis using local cppcheck
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: cppcheck
|
||||||
|
name: cppcheck
|
||||||
|
entry: cppcheck
|
||||||
|
language: system
|
||||||
|
types_or: [c++, c]
|
||||||
|
args: [
|
||||||
|
"--enable=warning,portability",
|
||||||
|
"--suppress=missingIncludeSystem",
|
||||||
|
"--suppress=unusedFunction",
|
||||||
|
"--suppress=normalCheckLevelMaxBranches",
|
||||||
|
"--inline-suppr",
|
||||||
|
"--error-exitcode=1",
|
||||||
|
"-Iinclude"
|
||||||
|
]
|
||||||
|
|
||||||
|
# 4. Python Linter and Formatter (ruff)
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.4.4
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [ --fix ]
|
||||||
|
- id: ruff-format
|
||||||
|
|
||||||
|
# 5. Python Type Checking (mypy)
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
|
rev: v1.10.0
|
||||||
|
hooks:
|
||||||
|
- id: mypy
|
||||||
|
args: [ "--ignore-missing-imports", "--strict" ]
|
||||||
|
additional_dependencies: [ "types-requests", "pydantic" ]
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
#include <benchmark/benchmark.h>
|
|
||||||
#include "fces/population.hpp"
|
|
||||||
#include "fces/controller.hpp"
|
#include "fces/controller.hpp"
|
||||||
|
#include "fces/population.hpp"
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
static void BM_ControllerDecideUpdate(benchmark::State &state) {
|
static void BM_ControllerDecideUpdate(benchmark::State &state) {
|
||||||
FuzzyController ctrl;
|
FuzzyController ctrl;
|
||||||
std::vector<std::vector<float>> stats(state.range(0), {0.1f, 0.2f, 0.3f, 0.4f, 0.5f});
|
std::vector<std::vector<float>> stats(state.range(0),
|
||||||
|
{0.1f, 0.2f, 0.3f, 0.4f, 0.5f});
|
||||||
|
|
||||||
for (auto _ : state) {
|
for (auto _ : state) {
|
||||||
auto actions = ctrl.decide_update(stats, 0.0f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f);
|
auto actions = ctrl.decide_update(stats, 0.0f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f,
|
||||||
|
1.0f, 0.0f);
|
||||||
benchmark::DoNotOptimize(actions);
|
benchmark::DoNotOptimize(actions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
#include "fces/optimizer.hpp"
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
#include <torch/torch.h>
|
#include <torch/torch.h>
|
||||||
#include "fces/optimizer.hpp"
|
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
static void BM_OptimizerStep(benchmark::State &state) {
|
static void BM_OptimizerStep(benchmark::State &state) {
|
||||||
auto model = torch::nn::Linear(state.range(0), state.range(0) / 2);
|
auto model = torch::nn::Linear(state.range(0), state.range(0) / 2);
|
||||||
std::vector<torch::Tensor> params;
|
std::vector<torch::Tensor> params;
|
||||||
for (auto& p : model->parameters()) params.push_back(p);
|
for (auto &p : model->parameters())
|
||||||
|
params.push_back(p);
|
||||||
|
|
||||||
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* @brief Example: train a small neural network with FCES via libtorch.
|
* @brief Example: train a small neural network with FCES via libtorch.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fces/optimizer.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <torch/torch.h>
|
#include <torch/torch.h>
|
||||||
#include "fces/optimizer.hpp"
|
|
||||||
|
|
||||||
struct TinyNet : torch::nn::Module {
|
struct TinyNet : torch::nn::Module {
|
||||||
torch::nn::Linear fc1{nullptr}, fc2{nullptr};
|
torch::nn::Linear fc1{nullptr}, fc2{nullptr};
|
||||||
@@ -25,15 +25,13 @@ int main() {
|
|||||||
auto model = std::make_shared<TinyNet>();
|
auto model = std::make_shared<TinyNet>();
|
||||||
|
|
||||||
std::vector<torch::Tensor> params;
|
std::vector<torch::Tensor> params;
|
||||||
for (auto& p : model->parameters()) params.push_back(p);
|
for (auto &p : model->parameters())
|
||||||
|
params.push_back(p);
|
||||||
|
|
||||||
fces::FCESOptimizer optimizer(
|
fces::FCESOptimizer optimizer(params, fces::FCESConfig{}
|
||||||
params,
|
|
||||||
fces::FCESConfig{}
|
|
||||||
.set_lr(1.6e-3f)
|
.set_lr(1.6e-3f)
|
||||||
.set_population_size(200)
|
.set_population_size(200)
|
||||||
.set_total_steps(1000)
|
.set_total_steps(1000));
|
||||||
);
|
|
||||||
|
|
||||||
// Generate synthetic regression data
|
// Generate synthetic regression data
|
||||||
auto x_train = torch::randn({100, 10});
|
auto x_train = torch::randn({100, 10});
|
||||||
@@ -48,8 +46,8 @@ int main() {
|
|||||||
optimizer.update_fitness(loss.item<float>());
|
optimizer.update_fitness(loss.item<float>());
|
||||||
|
|
||||||
if (epoch % 10 == 0) {
|
if (epoch % 10 == 0) {
|
||||||
std::cout << "Epoch " << epoch
|
std::cout << "Epoch " << epoch << " | Loss: " << loss.item<float>()
|
||||||
<< " | Loss: " << loss.item<float>() << std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
* @brief Minimal example: optimize a quadratic function with FCES.
|
* @brief Minimal example: optimize a quadratic function with FCES.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "fces/optimizer.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <torch/torch.h>
|
#include <torch/torch.h>
|
||||||
#include "fces/optimizer.hpp"
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// Target: minimize f(x) = ||x - target||^2
|
// Target: minimize f(x) = ||x - target||^2
|
||||||
@@ -23,8 +23,7 @@ int main() {
|
|||||||
optimizer.update_fitness(loss.item<float>());
|
optimizer.update_fitness(loss.item<float>());
|
||||||
|
|
||||||
if (step % 50 == 0) {
|
if (step % 50 == 0) {
|
||||||
std::cout << "Step " << step
|
std::cout << "Step " << step << " | Loss: " << loss.item<float>()
|
||||||
<< " | Loss: " << loss.item<float>()
|
|
||||||
<< " | x: " << x << std::endl;
|
<< " | x: " << x << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
* @brief Example showcasing telemetry instrumentation and model inference.
|
* @brief Example showcasing telemetry instrumentation and model inference.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
|
||||||
#include <torch/torch.h>
|
|
||||||
#include "fces/optimizer.hpp"
|
#include "fces/optimizer.hpp"
|
||||||
#include "fces/telemetry.hpp"
|
#include "fces/telemetry.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <torch/torch.h>
|
||||||
|
|
||||||
// Define a simple neural network for nonlinear regression: y = x^2
|
// Define a simple neural network for nonlinear regression: y = x^2
|
||||||
struct RegressionNet : torch::nn::Module {
|
struct RegressionNet : torch::nn::Module {
|
||||||
@@ -25,7 +25,8 @@ struct RegressionNet : torch::nn::Module {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
fces::Telemetry::get().info("app_start", "Telemetry and Inference demo initialized.");
|
fces::Telemetry::get().info("app_start",
|
||||||
|
"Telemetry and Inference demo initialized.");
|
||||||
|
|
||||||
// 1. Create Model and Data
|
// 1. Create Model and Data
|
||||||
auto model = std::make_shared<RegressionNet>();
|
auto model = std::make_shared<RegressionNet>();
|
||||||
@@ -42,13 +43,11 @@ int main() {
|
|||||||
|
|
||||||
fces::FCESOptimizer optimizer(
|
fces::FCESOptimizer optimizer(
|
||||||
params,
|
params,
|
||||||
fces::FCESConfig{}
|
fces::FCESConfig{}.set_lr(2e-3f).set_population_size(150).set_total_steps(
|
||||||
.set_lr(2e-3f)
|
100));
|
||||||
.set_population_size(150)
|
|
||||||
.set_total_steps(100)
|
|
||||||
);
|
|
||||||
|
|
||||||
fces::Telemetry::get().info("training_start", "Beginning neural net optimization with FCES.");
|
fces::Telemetry::get().info("training_start",
|
||||||
|
"Beginning neural net optimization with FCES.");
|
||||||
|
|
||||||
auto start_train = std::chrono::high_resolution_clock::now();
|
auto start_train = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
@@ -62,19 +61,24 @@ int main() {
|
|||||||
optimizer.update_fitness(loss.item<float>());
|
optimizer.update_fitness(loss.item<float>());
|
||||||
|
|
||||||
if (epoch % 20 == 0) {
|
if (epoch % 20 == 0) {
|
||||||
fces::Telemetry::get().info("epoch_checkpoint",
|
fces::Telemetry::get().info(
|
||||||
"Epoch " + std::to_string(epoch) + " | Loss: " + std::to_string(loss.item<float>()));
|
"epoch_checkpoint", "Epoch " + std::to_string(epoch) + " | Loss: " +
|
||||||
|
std::to_string(loss.item<float>()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end_train = std::chrono::high_resolution_clock::now();
|
auto end_train = std::chrono::high_resolution_clock::now();
|
||||||
double train_duration = std::chrono::duration<double, std::milli>(end_train - start_train).count();
|
double train_duration =
|
||||||
|
std::chrono::duration<double, std::milli>(end_train - start_train)
|
||||||
|
.count();
|
||||||
|
|
||||||
fces::Telemetry::get().info("training_complete",
|
fces::Telemetry::get().info("training_complete",
|
||||||
"Duration: " + std::to_string(train_duration) + " ms");
|
"Duration: " + std::to_string(train_duration) +
|
||||||
|
" ms");
|
||||||
|
|
||||||
// 4. Inference Phase
|
// 4. Inference Phase
|
||||||
fces::Telemetry::get().info("inference_phase_start", "Evaluating model on new test inputs.");
|
fces::Telemetry::get().info("inference_phase_start",
|
||||||
|
"Evaluating model on new test inputs.");
|
||||||
|
|
||||||
// Generate test inputs
|
// Generate test inputs
|
||||||
auto x_test = torch::tensor({-1.5f, -0.5f, 0.0f, 0.5f, 1.5f}).unsqueeze(1);
|
auto x_test = torch::tensor({-1.5f, -0.5f, 0.0f, 0.5f, 1.5f}).unsqueeze(1);
|
||||||
@@ -91,23 +95,31 @@ int main() {
|
|||||||
y_pred = model->forward(x_test);
|
y_pred = model->forward(x_test);
|
||||||
}
|
}
|
||||||
auto end_inf = std::chrono::high_resolution_clock::now();
|
auto end_inf = std::chrono::high_resolution_clock::now();
|
||||||
double inf_duration = std::chrono::duration<double, std::milli>(end_inf - start_inf).count();
|
double inf_duration =
|
||||||
|
std::chrono::duration<double, std::milli>(end_inf - start_inf).count();
|
||||||
|
|
||||||
// Log telemetry for inference performance
|
// Log telemetry for inference performance
|
||||||
fces::Telemetry::get().info("inference_perf",
|
fces::Telemetry::get().info(
|
||||||
"Inputs: " + std::to_string(x_test.size(0)) + " | Latency: " + std::to_string(inf_duration) + " ms");
|
"inference_perf", "Inputs: " + std::to_string(x_test.size(0)) +
|
||||||
|
" | Latency: " + std::to_string(inf_duration) +
|
||||||
|
" ms");
|
||||||
|
|
||||||
// Print predictions and expected values side-by-side
|
// Print predictions and expected values side-by-side
|
||||||
std::cout << "\n================ INFERENCE RESULTS ================" << std::endl;
|
std::cout << "\n================ INFERENCE RESULTS ================"
|
||||||
std::cout << "Input (x) | Predicted (y_pred) | Expected (y_expected)" << std::endl;
|
<< std::endl;
|
||||||
std::cout << "----------------------------------------------------" << std::endl;
|
std::cout << "Input (x) | Predicted (y_pred) | Expected (y_expected)"
|
||||||
|
<< std::endl;
|
||||||
|
std::cout << "----------------------------------------------------"
|
||||||
|
<< std::endl;
|
||||||
for (int i = 0; i < x_test.size(0); ++i) {
|
for (int i = 0; i < x_test.size(0); ++i) {
|
||||||
float x_val = x_test[i][0].item<float>();
|
float x_val = x_test[i][0].item<float>();
|
||||||
float pred_val = y_pred[i][0].item<float>();
|
float pred_val = y_pred[i][0].item<float>();
|
||||||
float exp_val = y_expected[i][0].item<float>();
|
float exp_val = y_expected[i][0].item<float>();
|
||||||
std::printf(" %7.2f | %7.4f | %7.4f\n", x_val, pred_val, exp_val);
|
std::printf(" %7.2f | %7.4f | %7.4f\n", x_val,
|
||||||
|
pred_val, exp_val);
|
||||||
}
|
}
|
||||||
std::cout << "====================================================\n" << std::endl;
|
std::cout << "====================================================\n"
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
fces::Telemetry::get().info("app_finish", "Exiting demo successfully.");
|
fces::Telemetry::get().info("app_finish", "Exiting demo successfully.");
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -72,11 +72,26 @@ struct FCESConfig {
|
|||||||
bool auto_population = false;
|
bool auto_population = false;
|
||||||
|
|
||||||
// Builder pattern
|
// Builder pattern
|
||||||
FCESConfig& set_lr(float v) { lr = v; return *this; }
|
FCESConfig &set_lr(float v) {
|
||||||
FCESConfig& set_population_size(int v) { population_size = v; return *this; }
|
lr = v;
|
||||||
FCESConfig& set_total_steps(int v) { total_steps = v; return *this; }
|
return *this;
|
||||||
FCESConfig& set_grokking_coefficient(float v) { grokking_coefficient = v; return *this; }
|
}
|
||||||
FCESConfig& set_direct_construction(bool v) { direct_construction = v; return *this; }
|
FCESConfig &set_population_size(int v) {
|
||||||
|
population_size = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FCESConfig &set_total_steps(int v) {
|
||||||
|
total_steps = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FCESConfig &set_grokking_coefficient(float v) {
|
||||||
|
grokking_coefficient = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
FCESConfig &set_direct_construction(bool v) {
|
||||||
|
direct_construction = v;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fces
|
} // namespace fces
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ constexpr int GENOME_INPUT_DIM = 14;
|
|||||||
constexpr int GENOME_HIDDEN_DIM = 8;
|
constexpr int GENOME_HIDDEN_DIM = 8;
|
||||||
// Controller output dimension: [multiplier, sign_gate, wd_mult]
|
// Controller output dimension: [multiplier, sign_gate, wd_mult]
|
||||||
constexpr int GENOME_OUTPUT_DIM = 3;
|
constexpr int GENOME_OUTPUT_DIM = 3;
|
||||||
// Total genome size: input->hidden weights + hidden biases + hidden->output weights + output biases
|
// Total genome size: input->hidden weights + hidden biases + hidden->output
|
||||||
|
// weights + output biases
|
||||||
constexpr int GENOME_SIZE =
|
constexpr int GENOME_SIZE =
|
||||||
(GENOME_INPUT_DIM * GENOME_HIDDEN_DIM) + // input -> hidden weights
|
(GENOME_INPUT_DIM * GENOME_HIDDEN_DIM) + // input -> hidden weights
|
||||||
GENOME_HIDDEN_DIM + // hidden biases
|
GENOME_HIDDEN_DIM + // hidden biases
|
||||||
@@ -109,17 +110,12 @@ public:
|
|||||||
* @param projected_drift Projected loss drift
|
* @param projected_drift Projected loss drift
|
||||||
* @return Tensor of shape [num_groups, 3] — (mult, sign_gate, wd_mult)
|
* @return Tensor of shape [num_groups, 3] — (mult, sign_gate, wd_mult)
|
||||||
*/
|
*/
|
||||||
torch::Tensor decide_update(
|
torch::Tensor
|
||||||
const std::vector<std::vector<float>>& layer_stats,
|
decide_update(const std::vector<std::vector<float>> &layer_stats,
|
||||||
float loss_trend,
|
float loss_trend, float step_pct, float rollback_rate,
|
||||||
float step_pct,
|
float grad_stability, float spectral_alpha,
|
||||||
float rollback_rate,
|
float stagnation_intensity, float kzm_damping,
|
||||||
float grad_stability,
|
float projected_drift);
|
||||||
float spectral_alpha,
|
|
||||||
float stagnation_intensity,
|
|
||||||
float kzm_damping,
|
|
||||||
float projected_drift
|
|
||||||
);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Evolutionary Operators
|
// Evolutionary Operators
|
||||||
@@ -129,13 +125,15 @@ public:
|
|||||||
FuzzyController mutate(float current_loss, float sigma_scale = 1.0f) const;
|
FuzzyController mutate(float current_loss, float sigma_scale = 1.0f) const;
|
||||||
|
|
||||||
/// Crossover with another controller
|
/// Crossover with another controller
|
||||||
FuzzyController crossover(const FuzzyController& partner, bool use_alignment = true) const;
|
FuzzyController crossover(const FuzzyController &partner,
|
||||||
|
bool use_alignment = true) const;
|
||||||
|
|
||||||
/// Create an orthogonal counter-strategy (Phoenix Rebirth)
|
/// Create an orthogonal counter-strategy (Phoenix Rebirth)
|
||||||
FuzzyController create_orthogonal_child(float intensity = 1.0f) const;
|
FuzzyController create_orthogonal_child(float intensity = 1.0f) const;
|
||||||
|
|
||||||
/// Banach-Tarski fission: split into two complementary children
|
/// Banach-Tarski fission: split into two complementary children
|
||||||
std::pair<FuzzyController, FuzzyController> banach_tarski_fission(float intensity = 1.0f) const;
|
std::pair<FuzzyController, FuzzyController>
|
||||||
|
banach_tarski_fission(float intensity = 1.0f) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::atomic<uint64_t> next_id_;
|
static std::atomic<uint64_t> next_id_;
|
||||||
|
|||||||
@@ -21,23 +21,16 @@ namespace fces {
|
|||||||
*/
|
*/
|
||||||
class EvolutionManager {
|
class EvolutionManager {
|
||||||
public:
|
public:
|
||||||
explicit EvolutionManager(
|
explicit EvolutionManager(Population &population, int selection_interval = 50,
|
||||||
Population& population,
|
|
||||||
int selection_interval = 50,
|
|
||||||
bool auto_population = false,
|
bool auto_population = false,
|
||||||
bool direct_construction = false
|
bool direct_construction = false);
|
||||||
);
|
|
||||||
|
|
||||||
/// Get the currently active controller
|
/// Get the currently active controller
|
||||||
FuzzyController &get_active_controller();
|
FuzzyController &get_active_controller();
|
||||||
|
|
||||||
/// Update population dynamics based on current training state
|
/// Update population dynamics based on current training state
|
||||||
void update_population_dynamics(
|
void update_population_dynamics(float loss_velocity, float ema_loss,
|
||||||
float loss_velocity,
|
int step_counter, int total_steps);
|
||||||
float ema_loss,
|
|
||||||
int step_counter,
|
|
||||||
int total_steps
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Steps the active controller has been in control
|
/// Steps the active controller has been in control
|
||||||
int steps_active = 0;
|
int steps_active = 0;
|
||||||
|
|||||||
@@ -2,14 +2,15 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @file fitness.hpp
|
* @file fitness.hpp
|
||||||
* @brief Fitness evaluation — loss signal processing and multi-objective evaluation.
|
* @brief Fitness evaluation — loss signal processing and multi-objective
|
||||||
|
* evaluation.
|
||||||
*
|
*
|
||||||
* Port of: packages/fces/core/fitness_engine.py + fitness.py
|
* Port of: packages/fces/core/fitness_engine.py + fitness.py
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
@@ -48,7 +49,8 @@ public:
|
|||||||
* @param mode "relative" or "absolute"
|
* @param mode "relative" or "absolute"
|
||||||
* @return Velocity signal (negative = improving)
|
* @return Velocity signal (negative = improving)
|
||||||
*/
|
*/
|
||||||
float calculate_loss_signal(float current_loss, float ema_loss, const std::string& mode = "relative") const;
|
float calculate_loss_signal(float current_loss, float ema_loss,
|
||||||
|
const std::string &mode = "relative") const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute Kibble-Zurek Mechanism damping factor.
|
* Compute Kibble-Zurek Mechanism damping factor.
|
||||||
@@ -112,7 +114,8 @@ struct FitnessMetrics {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FuzzyFitnessEvaluator — multi-objective fitness evaluation with fuzzy weighting.
|
* FuzzyFitnessEvaluator — multi-objective fitness evaluation with fuzzy
|
||||||
|
* weighting.
|
||||||
*/
|
*/
|
||||||
class FuzzyFitnessEvaluator {
|
class FuzzyFitnessEvaluator {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -5,17 +5,17 @@
|
|||||||
* @brief FCESOptimizer — the main entry point. libtorch-compatible optimizer.
|
* @brief FCESOptimizer — the main entry point. libtorch-compatible optimizer.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <torch/torch.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <torch/torch.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "population.hpp"
|
|
||||||
#include "fitness.hpp"
|
|
||||||
#include "evolution.hpp"
|
#include "evolution.hpp"
|
||||||
#include "spectral.hpp"
|
#include "fitness.hpp"
|
||||||
#include "oscillation.hpp"
|
#include "oscillation.hpp"
|
||||||
|
#include "population.hpp"
|
||||||
|
#include "spectral.hpp"
|
||||||
#include "telemetry.hpp"
|
#include "telemetry.hpp"
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
@@ -24,7 +24,8 @@ namespace fces {
|
|||||||
* FCESOptimizer — Fuzzy Controlled Evolutionary Search V49.0 (C++ Port).
|
* FCESOptimizer — Fuzzy Controlled Evolutionary Search V49.0 (C++ Port).
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* auto optimizer = FCESOptimizer(model->parameters(), FCESConfig{}.set_lr(1.6e-3));
|
* auto optimizer = FCESOptimizer(model->parameters(),
|
||||||
|
* FCESConfig{}.set_lr(1.6e-3));
|
||||||
* // In training loop:
|
* // In training loop:
|
||||||
* optimizer.zero_grad();
|
* optimizer.zero_grad();
|
||||||
* auto loss = model->forward(input);
|
* auto loss = model->forward(input);
|
||||||
@@ -32,7 +33,8 @@ namespace fces {
|
|||||||
* optimizer.step();
|
* optimizer.step();
|
||||||
* optimizer.update_fitness(loss.item<float>());
|
* optimizer.update_fitness(loss.item<float>());
|
||||||
*/
|
*/
|
||||||
struct FCESOptimizerOptions : public torch::optim::OptimizerCloneableOptions<FCESOptimizerOptions> {
|
struct FCESOptimizerOptions
|
||||||
|
: public torch::optim::OptimizerCloneableOptions<FCESOptimizerOptions> {
|
||||||
explicit FCESOptimizerOptions(double lr = 0.01) : lr_(lr) {}
|
explicit FCESOptimizerOptions(double lr = 0.01) : lr_(lr) {}
|
||||||
|
|
||||||
double get_lr() const override { return lr_; }
|
double get_lr() const override { return lr_; }
|
||||||
@@ -43,10 +45,8 @@ struct FCESOptimizerOptions : public torch::optim::OptimizerCloneableOptions<FCE
|
|||||||
|
|
||||||
class FCESOptimizer : public torch::optim::Optimizer {
|
class FCESOptimizer : public torch::optim::Optimizer {
|
||||||
public:
|
public:
|
||||||
explicit FCESOptimizer(
|
explicit FCESOptimizer(std::vector<torch::Tensor> params,
|
||||||
std::vector<torch::Tensor> params,
|
FCESConfig config = FCESConfig{});
|
||||||
FCESConfig config = FCESConfig{}
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Perform a single optimization step
|
/// Perform a single optimization step
|
||||||
torch::Tensor step(LossClosure closure = nullptr) override;
|
torch::Tensor step(LossClosure closure = nullptr) override;
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::vector<float> loss_history_;
|
std::vector<float> loss_history_;
|
||||||
static std::vector<float> detrend(const std::vector<float> &signal);
|
static std::vector<float> detrend(const std::vector<float> &signal);
|
||||||
static std::vector<float> compute_power_spectrum(const std::vector<float>& signal);
|
static std::vector<float>
|
||||||
|
compute_power_spectrum(const std::vector<float> &signal);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace fces
|
} // namespace fces
|
||||||
|
|||||||
@@ -16,9 +16,9 @@
|
|||||||
* Port of: packages/fces/core/population.py (~1260 LOC)
|
* Port of: packages/fces/core/population.py (~1260 LOC)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
#include "controller.hpp"
|
#include "controller.hpp"
|
||||||
|
|
||||||
@@ -50,18 +50,13 @@ public:
|
|||||||
// Construction
|
// Construction
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
explicit Population(
|
explicit Population(int active_size = 75, int repo_size = 10000,
|
||||||
int active_size = 75,
|
|
||||||
int repo_size = 10000,
|
|
||||||
EliteStrategy elite_strategy = EliteStrategy::Cumulative,
|
EliteStrategy elite_strategy = EliteStrategy::Cumulative,
|
||||||
bool link_mutation = false,
|
bool link_mutation = false, bool link_elite = false,
|
||||||
bool link_elite = false,
|
bool link_violator = false, bool use_fuzzy_pacer = false,
|
||||||
bool link_violator = false,
|
|
||||||
bool use_fuzzy_pacer = false,
|
|
||||||
bool use_fuzzy_importance = false,
|
bool use_fuzzy_importance = false,
|
||||||
bool direct_construction = false,
|
bool direct_construction = false,
|
||||||
bool use_banach_fission = false
|
bool use_banach_fission = false);
|
||||||
);
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Core API
|
// Core API
|
||||||
@@ -83,13 +78,15 @@ public:
|
|||||||
void kill(FuzzyController &controller);
|
void kill(FuzzyController &controller);
|
||||||
|
|
||||||
/// Update a controller's fitness
|
/// Update a controller's fitness
|
||||||
void update_controller_fitness(FuzzyController& controller, float reward, bool increment_eval = true);
|
void update_controller_fitness(FuzzyController &controller, float reward,
|
||||||
|
bool increment_eval = true);
|
||||||
|
|
||||||
/// Mark a controller as a violator (rollback)
|
/// Mark a controller as a violator (rollback)
|
||||||
void mark_violated(FuzzyController &controller);
|
void mark_violated(FuzzyController &controller);
|
||||||
|
|
||||||
/// Get the effective fitness considering elite strategy and training progress
|
/// Get the effective fitness considering elite strategy and training progress
|
||||||
float get_effective_fitness(const FuzzyController& controller, float training_progress) const;
|
float get_effective_fitness(const FuzzyController &controller,
|
||||||
|
float training_progress) const;
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// Evolution
|
// Evolution
|
||||||
@@ -102,7 +99,8 @@ public:
|
|||||||
* @param velocity Loss velocity
|
* @param velocity Loss velocity
|
||||||
* @param training_progress Training progress [0, 1]
|
* @param training_progress Training progress [0, 1]
|
||||||
*/
|
*/
|
||||||
void evolve(float current_loss, float velocity = 0.0f, float training_progress = 0.0f);
|
void evolve(float current_loss, float velocity = 0.0f,
|
||||||
|
float training_progress = 0.0f);
|
||||||
|
|
||||||
/// Resize the population (dynamic expansion/contraction)
|
/// Resize the population (dynamic expansion/contraction)
|
||||||
void resize(int target_size, float training_progress = 0.5f);
|
void resize(int target_size, float training_progress = 0.5f);
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#include <pybind11/stl.h>
|
#include <pybind11/stl.h>
|
||||||
#include <torch/extension.h>
|
#include <torch/extension.h>
|
||||||
|
|
||||||
#include "fces/optimizer.hpp"
|
|
||||||
#include "fces/config.hpp"
|
#include "fces/config.hpp"
|
||||||
|
#include "fces/optimizer.hpp"
|
||||||
|
|
||||||
namespace py = pybind11;
|
namespace py = pybind11;
|
||||||
|
|
||||||
@@ -26,13 +26,14 @@ PYBIND11_MODULE(fces_native, m) {
|
|||||||
.def_readwrite("lr", &fces::FCESConfig::lr)
|
.def_readwrite("lr", &fces::FCESConfig::lr)
|
||||||
.def_readwrite("population_size", &fces::FCESConfig::population_size)
|
.def_readwrite("population_size", &fces::FCESConfig::population_size)
|
||||||
.def_readwrite("total_steps", &fces::FCESConfig::total_steps)
|
.def_readwrite("total_steps", &fces::FCESConfig::total_steps)
|
||||||
.def_readwrite("grokking_coefficient", &fces::FCESConfig::grokking_coefficient)
|
.def_readwrite("grokking_coefficient",
|
||||||
.def_readwrite("direct_construction", &fces::FCESConfig::direct_construction);
|
&fces::FCESConfig::grokking_coefficient)
|
||||||
|
.def_readwrite("direct_construction",
|
||||||
|
&fces::FCESConfig::direct_construction);
|
||||||
|
|
||||||
py::class_<fces::FCESOptimizer>(m, "FCESOptimizer")
|
py::class_<fces::FCESOptimizer>(m, "FCESOptimizer")
|
||||||
.def(py::init<std::vector<torch::Tensor>, fces::FCESConfig>(),
|
.def(py::init<std::vector<torch::Tensor>, fces::FCESConfig>(),
|
||||||
py::arg("params"),
|
py::arg("params"), py::arg("config") = fces::FCESConfig{})
|
||||||
py::arg("config") = fces::FCESConfig{})
|
|
||||||
.def("step", &fces::FCESOptimizer::step)
|
.def("step", &fces::FCESOptimizer::step)
|
||||||
.def("update_fitness", &fces::FCESOptimizer::update_fitness)
|
.def("update_fitness", &fces::FCESOptimizer::update_fitness)
|
||||||
.def("backup_to_ram", &fces::FCESOptimizer::backup_to_ram)
|
.def("backup_to_ram", &fces::FCESOptimizer::backup_to_ram)
|
||||||
|
|||||||
@@ -29,11 +29,11 @@ Genome Genome::clone() const {
|
|||||||
// FuzzyController
|
// FuzzyController
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
|
|
||||||
FuzzyController::FuzzyController()
|
FuzzyController::FuzzyController() : id(next_id_++), origin("random") {
|
||||||
: id(next_id_++), origin("random") {
|
|
||||||
genome.randomize(rng_);
|
genome.randomize(rng_);
|
||||||
// Bias output toward acceleration (V2.1 insight)
|
// Bias output toward acceleration (V2.1 insight)
|
||||||
// Set output biases (last GENOME_OUTPUT_DIM elements) to +2.0, -1.0, 0.0 with noise
|
// Set output biases (last GENOME_OUTPUT_DIM elements) to +2.0, -1.0, 0.0 with
|
||||||
|
// noise
|
||||||
constexpr int bias_start = GENOME_SIZE - GENOME_OUTPUT_DIM;
|
constexpr int bias_start = GENOME_SIZE - GENOME_OUTPUT_DIM;
|
||||||
std::normal_distribution<float> bias_noise(0.0f, 0.5f);
|
std::normal_distribution<float> bias_noise(0.0f, 0.5f);
|
||||||
genome.weights[bias_start] = 2.0f + bias_noise(rng_);
|
genome.weights[bias_start] = 2.0f + bias_noise(rng_);
|
||||||
@@ -51,16 +51,10 @@ FuzzyController::FuzzyController(Genome genome)
|
|||||||
: id(next_id_++), genome(std::move(genome)), origin("constructed") {}
|
: id(next_id_++), genome(std::move(genome)), origin("constructed") {}
|
||||||
|
|
||||||
torch::Tensor FuzzyController::decide_update(
|
torch::Tensor FuzzyController::decide_update(
|
||||||
const std::vector<std::vector<float>>& layer_stats,
|
const std::vector<std::vector<float>> &layer_stats, float loss_trend,
|
||||||
float loss_trend,
|
float step_pct, float rollback_rate, float grad_stability,
|
||||||
float step_pct,
|
float spectral_alpha, float stagnation_intensity, float kzm_damping,
|
||||||
float rollback_rate,
|
float projected_drift) {
|
||||||
float grad_stability,
|
|
||||||
float spectral_alpha,
|
|
||||||
float stagnation_intensity,
|
|
||||||
float kzm_damping,
|
|
||||||
float projected_drift
|
|
||||||
) {
|
|
||||||
const int num_groups = static_cast<int>(layer_stats.size());
|
const int num_groups = static_cast<int>(layer_stats.size());
|
||||||
auto actions = torch::zeros({num_groups, GENOME_OUTPUT_DIM});
|
auto actions = torch::zeros({num_groups, GENOME_OUTPUT_DIM});
|
||||||
|
|
||||||
@@ -70,11 +64,14 @@ torch::Tensor FuzzyController::decide_update(
|
|||||||
// Layer 1: input -> hidden
|
// Layer 1: input -> hidden
|
||||||
const float *W1 = w; // [(GENOME_INPUT_DIM + 1) x GENOME_HIDDEN_DIM]
|
const float *W1 = w; // [(GENOME_INPUT_DIM + 1) x GENOME_HIDDEN_DIM]
|
||||||
// Layer 2: hidden -> output
|
// Layer 2: hidden -> output
|
||||||
const float* W2 = w + ((GENOME_INPUT_DIM + 1) * GENOME_HIDDEN_DIM); // [(GENOME_HIDDEN_DIM + 1) x GENOME_OUTPUT_DIM]
|
const float *W2 =
|
||||||
|
w + ((GENOME_INPUT_DIM + 1) *
|
||||||
|
GENOME_HIDDEN_DIM); // [(GENOME_HIDDEN_DIM + 1) x GENOME_OUTPUT_DIM]
|
||||||
|
|
||||||
for (int g = 0; g < num_groups; ++g) {
|
for (int g = 0; g < num_groups; ++g) {
|
||||||
// One-Hot Layer Type: Clamp to 5 to avoid overflow for new categories
|
// One-Hot Layer Type: Clamp to 5 to avoid overflow for new categories
|
||||||
float layer_type_val = (layer_stats[g].size() >= 3) ? layer_stats[g][2] : 5.0f;
|
float layer_type_val =
|
||||||
|
(layer_stats[g].size() >= 3) ? layer_stats[g][2] : 5.0f;
|
||||||
int type_idx = std::min(5, static_cast<int>(layer_type_val));
|
int type_idx = std::min(5, static_cast<int>(layer_type_val));
|
||||||
std::array<float, 5> type_onehot{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
std::array<float, 5> type_onehot{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
|
||||||
if (type_idx >= 0 && type_idx < 5) {
|
if (type_idx >= 0 && type_idx < 5) {
|
||||||
@@ -87,19 +84,26 @@ torch::Tensor FuzzyController::decide_update(
|
|||||||
float sp = (layer_stats[g].size() >= 2) ? layer_stats[g][1] : 0.0f;
|
float sp = (layer_stats[g].size() >= 2) ? layer_stats[g][1] : 0.0f;
|
||||||
|
|
||||||
// Sanitization matching nan_to_num
|
// Sanitization matching nan_to_num
|
||||||
if (!std::isfinite(gn) || std::isnan(gn)) gn = 0.0f;
|
if (!std::isfinite(gn) || std::isnan(gn))
|
||||||
if (gn > 10.0f) gn = 10.0f;
|
gn = 0.0f;
|
||||||
if (gn < 0.0f) gn = 0.0f;
|
if (gn > 10.0f)
|
||||||
|
gn = 10.0f;
|
||||||
|
if (gn < 0.0f)
|
||||||
|
gn = 0.0f;
|
||||||
|
|
||||||
if (!std::isfinite(sp) || std::isnan(sp)) sp = 0.0f;
|
if (!std::isfinite(sp) || std::isnan(sp))
|
||||||
if (sp > 1.0f) sp = 1.0f;
|
sp = 0.0f;
|
||||||
if (sp < 0.0f) sp = 0.0f;
|
if (sp > 1.0f)
|
||||||
|
sp = 1.0f;
|
||||||
|
if (sp < 0.0f)
|
||||||
|
sp = 0.0f;
|
||||||
|
|
||||||
input[0] = gn;
|
input[0] = gn;
|
||||||
input[1] = sp;
|
input[1] = sp;
|
||||||
input[2] = loss_trend;
|
input[2] = loss_trend;
|
||||||
input[3] = step_pct;
|
input[3] = step_pct;
|
||||||
input[4] = (num_groups > 1) ? static_cast<float>(g) / (num_groups - 1.0f) : 0.0f;
|
input[4] =
|
||||||
|
(num_groups > 1) ? static_cast<float>(g) / (num_groups - 1.0f) : 0.0f;
|
||||||
input[5] = rollback_rate;
|
input[5] = rollback_rate;
|
||||||
input[6] = grad_stability;
|
input[6] = grad_stability;
|
||||||
input[7] = spectral_alpha;
|
input[7] = spectral_alpha;
|
||||||
@@ -178,7 +182,8 @@ torch::Tensor FuzzyController::decide_update(
|
|||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuzzyController FuzzyController::mutate(float current_loss, float sigma_scale) const {
|
FuzzyController FuzzyController::mutate(float current_loss,
|
||||||
|
float sigma_scale) const {
|
||||||
Genome child_genome = genome.clone();
|
Genome child_genome = genome.clone();
|
||||||
std::normal_distribution<float> std_normal(0.0f, 1.0f);
|
std::normal_distribution<float> std_normal(0.0f, 1.0f);
|
||||||
|
|
||||||
@@ -207,7 +212,8 @@ FuzzyController FuzzyController::mutate(float current_loss, float sigma_scale) c
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuzzyController FuzzyController::crossover(const FuzzyController& partner, bool /*use_alignment*/) const {
|
FuzzyController FuzzyController::crossover(const FuzzyController &partner,
|
||||||
|
bool /*use_alignment*/) const {
|
||||||
Genome child_genome;
|
Genome child_genome;
|
||||||
std::uniform_real_distribution<float> u_dist(0.0f, 1.0f);
|
std::uniform_real_distribution<float> u_dist(0.0f, 1.0f);
|
||||||
|
|
||||||
@@ -234,15 +240,18 @@ FuzzyController FuzzyController::crossover(const FuzzyController& partner, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child_genome.sigma_gene = (genome.sigma_gene + partner.genome.sigma_gene) * 0.5f;
|
child_genome.sigma_gene =
|
||||||
child_genome.plasticity = (genome.plasticity + partner.genome.plasticity) * 0.5f;
|
(genome.sigma_gene + partner.genome.sigma_gene) * 0.5f;
|
||||||
|
child_genome.plasticity =
|
||||||
|
(genome.plasticity + partner.genome.plasticity) * 0.5f;
|
||||||
|
|
||||||
FuzzyController child(child_genome);
|
FuzzyController child(child_genome);
|
||||||
child.origin = "crossover";
|
child.origin = "crossover";
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
FuzzyController FuzzyController::create_orthogonal_child(float intensity) const {
|
FuzzyController
|
||||||
|
FuzzyController::create_orthogonal_child(float intensity) const {
|
||||||
Genome child_genome;
|
Genome child_genome;
|
||||||
std::normal_distribution<float> norm_dist(0.0f, 1.0f);
|
std::normal_distribution<float> norm_dist(0.0f, 1.0f);
|
||||||
|
|
||||||
@@ -262,7 +271,8 @@ FuzzyController FuzzyController::create_orthogonal_child(float intensity) const
|
|||||||
std::array<float, GENOME_SIZE> orthogonal_vec{};
|
std::array<float, GENOME_SIZE> orthogonal_vec{};
|
||||||
float norm_ortho = 0.0f;
|
float norm_ortho = 0.0f;
|
||||||
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
||||||
float projection = (dot_product / (norm_elite * norm_elite)) * genome.weights[i];
|
float projection =
|
||||||
|
(dot_product / (norm_elite * norm_elite)) * genome.weights[i];
|
||||||
orthogonal_vec[i] = random_vec[i] - projection;
|
orthogonal_vec[i] = random_vec[i] - projection;
|
||||||
norm_ortho += orthogonal_vec[i] * orthogonal_vec[i];
|
norm_ortho += orthogonal_vec[i] * orthogonal_vec[i];
|
||||||
}
|
}
|
||||||
@@ -294,7 +304,8 @@ FuzzyController FuzzyController::create_orthogonal_child(float intensity) const
|
|||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<FuzzyController, FuzzyController> FuzzyController::banach_tarski_fission(float intensity) const {
|
std::pair<FuzzyController, FuzzyController>
|
||||||
|
FuzzyController::banach_tarski_fission(float intensity) const {
|
||||||
Genome plus_genome;
|
Genome plus_genome;
|
||||||
Genome minus_genome;
|
Genome minus_genome;
|
||||||
|
|
||||||
@@ -321,13 +332,15 @@ std::pair<FuzzyController, FuzzyController> FuzzyController::banach_tarski_fissi
|
|||||||
std::array<float, GENOME_SIZE> fission_vec{};
|
std::array<float, GENOME_SIZE> fission_vec{};
|
||||||
float norm_fission = 0.0f;
|
float norm_fission = 0.0f;
|
||||||
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
||||||
fission_vec[i] = noise[i] - (dot_product / (norm_parent * norm_parent)) * genome.weights[i];
|
fission_vec[i] = noise[i] - (dot_product / (norm_parent * norm_parent)) *
|
||||||
|
genome.weights[i];
|
||||||
norm_fission += fission_vec[i] * fission_vec[i];
|
norm_fission += fission_vec[i] * fission_vec[i];
|
||||||
}
|
}
|
||||||
norm_fission = std::sqrt(norm_fission) + 1e-9f;
|
norm_fission = std::sqrt(norm_fission) + 1e-9f;
|
||||||
|
|
||||||
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
for (size_t i = 0; i < GENOME_SIZE; ++i) {
|
||||||
float scaled_fission = fission_vec[i] * (norm_parent / norm_fission) * 0.1f * intensity;
|
float scaled_fission =
|
||||||
|
fission_vec[i] * (norm_parent / norm_fission) * 0.1f * intensity;
|
||||||
plus_genome.weights[i] = genome.weights[i] + scaled_fission;
|
plus_genome.weights[i] = genome.weights[i] + scaled_fission;
|
||||||
minus_genome.weights[i] = genome.weights[i] - scaled_fission;
|
minus_genome.weights[i] = genome.weights[i] - scaled_fission;
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
EvolutionManager::EvolutionManager(
|
EvolutionManager::EvolutionManager(Population &population,
|
||||||
Population& population, int selection_interval,
|
int selection_interval, bool auto_population,
|
||||||
bool auto_population, bool direct_construction
|
bool direct_construction)
|
||||||
)
|
: population_(population), selection_interval(selection_interval),
|
||||||
: population_(population),
|
|
||||||
selection_interval(selection_interval),
|
|
||||||
auto_population_(auto_population),
|
auto_population_(auto_population),
|
||||||
direct_construction_(direct_construction) {}
|
direct_construction_(direct_construction) {}
|
||||||
|
|
||||||
@@ -15,17 +13,14 @@ FuzzyController& EvolutionManager::get_active_controller() {
|
|||||||
return population_.get_active_controller();
|
return population_.get_active_controller();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvolutionManager::update_population_dynamics(
|
void EvolutionManager::update_population_dynamics(float loss_velocity,
|
||||||
float loss_velocity, float ema_loss, int step_counter, int total_steps
|
float ema_loss,
|
||||||
) {
|
int step_counter,
|
||||||
|
int total_steps) {
|
||||||
float progress = static_cast<float>(step_counter) / std::max(1, total_steps);
|
float progress = static_cast<float>(step_counter) / std::max(1, total_steps);
|
||||||
|
|
||||||
if (step_counter % 20 == 0) {
|
if (step_counter % 20 == 0) {
|
||||||
population_.evolve(
|
population_.evolve(std::abs(loss_velocity), loss_velocity, progress);
|
||||||
std::abs(loss_velocity),
|
|
||||||
loss_velocity,
|
|
||||||
progress
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!auto_population_ || step_counter % 50 != 0) {
|
if (!auto_population_ || step_counter % 50 != 0) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "fces/fitness.hpp"
|
#include "fces/fitness.hpp"
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <algorithm>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
@@ -20,12 +20,14 @@ void RunningStats::update(float value) {
|
|||||||
|
|
||||||
float RunningStats::z_score(float value) const {
|
float RunningStats::z_score(float value) const {
|
||||||
float s = get_std();
|
float s = get_std();
|
||||||
if (s < 1e-8f) return 0.0f;
|
if (s < 1e-8f)
|
||||||
|
return 0.0f;
|
||||||
return (value - mean_) / s;
|
return (value - mean_) / s;
|
||||||
}
|
}
|
||||||
|
|
||||||
float RunningStats::get_std() const {
|
float RunningStats::get_std() const {
|
||||||
if (count_ < 2) return 1.0f;
|
if (count_ < 2)
|
||||||
|
return 1.0f;
|
||||||
return std::sqrt(m2_ / static_cast<float>(count_ - 1));
|
return std::sqrt(m2_ / static_cast<float>(count_ - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,8 +44,10 @@ void RunningStats::reset() {
|
|||||||
FitnessEngine::FitnessEngine(float grokking_coefficient)
|
FitnessEngine::FitnessEngine(float grokking_coefficient)
|
||||||
: grokking_coefficient_(grokking_coefficient) {}
|
: grokking_coefficient_(grokking_coefficient) {}
|
||||||
|
|
||||||
float FitnessEngine::calculate_loss_signal(float current_loss, float ema_loss, const std::string& mode) const {
|
float FitnessEngine::calculate_loss_signal(float current_loss, float ema_loss,
|
||||||
if (ema_loss < 1e-8f) return 0.0f;
|
const std::string &mode) const {
|
||||||
|
if (ema_loss < 1e-8f)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
if (mode == "relative") {
|
if (mode == "relative") {
|
||||||
return (current_loss - ema_loss) / (ema_loss + 1e-8f);
|
return (current_loss - ema_loss) / (ema_loss + 1e-8f);
|
||||||
@@ -68,7 +72,8 @@ FuzzyFitnessEvaluator::FuzzyFitnessEvaluator() noexcept
|
|||||||
consistency_set_("Consistent", -1.0f, 0.0f, 0.02f, 0.1f),
|
consistency_set_("Consistent", -1.0f, 0.0f, 0.02f, 0.1f),
|
||||||
rank_set_("LowRank", -1.0f, 0.0f, 5.0f, 20.0f) {}
|
rank_set_("LowRank", -1.0f, 0.0f, 5.0f, 20.0f) {}
|
||||||
|
|
||||||
float FuzzyFitnessEvaluator::evaluate(const FitnessMetrics& metrics) const noexcept {
|
float FuzzyFitnessEvaluator::evaluate(
|
||||||
|
const FitnessMetrics &metrics) const noexcept {
|
||||||
float m_stability = stability_set_.membership(metrics.grad_cv);
|
float m_stability = stability_set_.membership(metrics.grad_cv);
|
||||||
float m_train = train_set_.membership(metrics.training_advantage);
|
float m_train = train_set_.membership(metrics.training_advantage);
|
||||||
float m_val = val_set_.membership(metrics.validation_advantage);
|
float m_val = val_set_.membership(metrics.validation_advantage);
|
||||||
@@ -76,15 +81,12 @@ float FuzzyFitnessEvaluator::evaluate(const FitnessMetrics& metrics) const noexc
|
|||||||
float m_consistency = consistency_set_.membership(metrics.consistency_gap);
|
float m_consistency = consistency_set_.membership(metrics.consistency_gap);
|
||||||
float m_rank = rank_set_.membership(metrics.stable_rank);
|
float m_rank = rank_set_.membership(metrics.stable_rank);
|
||||||
|
|
||||||
float weighted_score =
|
float weighted_score = m_stability * w_stability_ + m_train * w_train_ +
|
||||||
m_stability * w_stability_ +
|
m_val * w_val_ + m_sparsity * w_sparsity_ +
|
||||||
m_train * w_train_ +
|
m_consistency * w_consistency_ + m_rank * w_rank_;
|
||||||
m_val * w_val_ +
|
|
||||||
m_sparsity * w_sparsity_ +
|
|
||||||
m_consistency * w_consistency_ +
|
|
||||||
m_rank * w_rank_;
|
|
||||||
|
|
||||||
float total_weight = w_stability_ + w_train_ + w_val_ + w_sparsity_ + w_consistency_ + w_rank_;
|
float total_weight =
|
||||||
|
w_stability_ + w_train_ + w_val_ + w_sparsity_ + w_consistency_ + w_rank_;
|
||||||
if (total_weight > 0.0f) {
|
if (total_weight > 0.0f) {
|
||||||
weighted_score /= total_weight;
|
weighted_score /= total_weight;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "fces/optimizer.hpp"
|
#include "fces/optimizer.hpp"
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
@@ -31,8 +31,10 @@ int classify_layer_by_shape(const torch::Tensor& p) {
|
|||||||
return 5; // Other
|
return 5; // Other
|
||||||
}
|
}
|
||||||
|
|
||||||
torch::Tensor apply_trust_clipping(const torch::Tensor& p, torch::Tensor update, float trust_region_clip) {
|
torch::Tensor apply_trust_clipping(const torch::Tensor &p, torch::Tensor update,
|
||||||
if (torch::isnan(update).any().item<bool>() || torch::isinf(update).any().item<bool>()) {
|
float trust_region_clip) {
|
||||||
|
if (torch::isnan(update).any().item<bool>() ||
|
||||||
|
torch::isinf(update).any().item<bool>()) {
|
||||||
return torch::zeros_like(update);
|
return torch::zeros_like(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,14 +52,16 @@ torch::Tensor apply_trust_clipping(const torch::Tensor& p, torch::Tensor update,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torch::isnan(update).any().item<bool>() || torch::isinf(update).any().item<bool>()) {
|
if (torch::isnan(update).any().item<bool>() ||
|
||||||
|
torch::isinf(update).any().item<bool>()) {
|
||||||
return torch::zeros_like(update);
|
return torch::zeros_like(update);
|
||||||
}
|
}
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
float calculate_parasitic_reward(const torch::Tensor& p, float mult, const RunningStats& grad_norm_tracker) {
|
float calculate_parasitic_reward(const torch::Tensor &p, float mult,
|
||||||
|
const RunningStats &grad_norm_tracker) {
|
||||||
if (!p.grad().defined()) {
|
if (!p.grad().defined()) {
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
@@ -66,31 +70,26 @@ float calculate_parasitic_reward(const torch::Tensor& p, float mult, const Runni
|
|||||||
return z_g * (mult - 1.0f);
|
return z_g * (mult - 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<torch::optim::OptimizerOptions> make_optimizer_options(double lr) {
|
std::unique_ptr<torch::optim::OptimizerOptions>
|
||||||
|
make_optimizer_options(double lr) {
|
||||||
return std::make_unique<FCESOptimizerOptions>(lr);
|
return std::make_unique<FCESOptimizerOptions>(lr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
FCESOptimizer::FCESOptimizer(
|
FCESOptimizer::FCESOptimizer(std::vector<torch::Tensor> params,
|
||||||
std::vector<torch::Tensor> params,
|
FCESConfig config)
|
||||||
FCESConfig config
|
|
||||||
)
|
|
||||||
: torch::optim::Optimizer(
|
: torch::optim::Optimizer(
|
||||||
{torch::optim::OptimizerParamGroup(std::move(params))},
|
{torch::optim::OptimizerParamGroup(std::move(params))},
|
||||||
make_optimizer_options(config.lr)
|
make_optimizer_options(config.lr)),
|
||||||
),
|
|
||||||
config_(std::move(config)),
|
config_(std::move(config)),
|
||||||
population_(config_.population_size, 10000,
|
population_(config_.population_size, 10000, EliteStrategy::Cumulative,
|
||||||
EliteStrategy::Cumulative,
|
|
||||||
false, false, false, false, false,
|
false, false, false, false, false,
|
||||||
config_.direct_construction,
|
config_.direct_construction, config_.use_banach_fission),
|
||||||
config_.use_banach_fission),
|
|
||||||
fitness_engine_(config_.grokking_coefficient) {
|
fitness_engine_(config_.grokking_coefficient) {
|
||||||
|
|
||||||
evolution_manager_ = std::make_unique<EvolutionManager>(
|
evolution_manager_ = std::make_unique<EvolutionManager>(
|
||||||
population_, 50, config_.auto_population, config_.direct_construction
|
population_, 50, config_.auto_population, config_.direct_construction);
|
||||||
);
|
|
||||||
|
|
||||||
spectral_sensor_ = std::make_unique<SpectralSensor>();
|
spectral_sensor_ = std::make_unique<SpectralSensor>();
|
||||||
|
|
||||||
@@ -98,7 +97,8 @@ FCESOptimizer::FCESOptimizer(
|
|||||||
backup_to_ram();
|
backup_to_ram();
|
||||||
|
|
||||||
Telemetry::get().info("optimizer_initialized",
|
Telemetry::get().info("optimizer_initialized",
|
||||||
"version=0.1.0 pop_size=" + std::to_string(config_.population_size));
|
"version=0.1.0 pop_size=" +
|
||||||
|
std::to_string(config_.population_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
||||||
@@ -118,35 +118,45 @@ torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
|||||||
auto &active_controller = evolution_manager_->get_active_controller();
|
auto &active_controller = evolution_manager_->get_active_controller();
|
||||||
|
|
||||||
// 3. Decision: Neural Decisions from Controllers
|
// 3. Decision: Neural Decisions from Controllers
|
||||||
float current_loss_val = (loss.defined()) ? loss.item<float>() : last_step_loss_;
|
float current_loss_val =
|
||||||
|
(loss.defined()) ? loss.item<float>() : last_step_loss_;
|
||||||
|
|
||||||
// Emergency Brake - NaN/Inf Detection
|
// Emergency Brake - NaN/Inf Detection
|
||||||
if (std::isnan(current_loss_val) || !std::isfinite(current_loss_val)) {
|
if (std::isnan(current_loss_val) || !std::isfinite(current_loss_val)) {
|
||||||
Telemetry::get().error("emergency_brake_nan", "NaN/Inf loss detected in step " + std::to_string(step_counter_));
|
Telemetry::get().error("emergency_brake_nan",
|
||||||
|
"NaN/Inf loss detected in step " +
|
||||||
|
std::to_string(step_counter_));
|
||||||
handle_rollback();
|
handle_rollback();
|
||||||
return loss;
|
return loss;
|
||||||
}
|
}
|
||||||
|
|
||||||
float loss_velocity = fitness_engine_.calculate_loss_signal(current_loss_val, ema_loss_, config_.signal_mode);
|
float loss_velocity = fitness_engine_.calculate_loss_signal(
|
||||||
|
current_loss_val, ema_loss_, config_.signal_mode);
|
||||||
last_loss_velocity_ = loss_velocity;
|
last_loss_velocity_ = loss_velocity;
|
||||||
|
|
||||||
float progress = std::min(1.0f, static_cast<float>(step_counter_) / std::max(1, config_.total_steps));
|
float progress = std::min(1.0f, static_cast<float>(step_counter_) /
|
||||||
float grad_cv = grad_norm_tracker_.get_std() / (grad_norm_tracker_.get_mean() + 1e-8f);
|
std::max(1, config_.total_steps));
|
||||||
|
float grad_cv =
|
||||||
|
grad_norm_tracker_.get_std() / (grad_norm_tracker_.get_mean() + 1e-8f);
|
||||||
|
|
||||||
float csr_factor = 1.0f;
|
float csr_factor = 1.0f;
|
||||||
if (config_.csr_enabled) {
|
if (config_.csr_enabled) {
|
||||||
if (step_counter_ < config_.csr_warmup_steps) {
|
if (step_counter_ < config_.csr_warmup_steps) {
|
||||||
csr_factor = 0.0f;
|
csr_factor = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
float steps_since_warmup = static_cast<float>(step_counter_ - config_.csr_warmup_steps);
|
float steps_since_warmup =
|
||||||
csr_factor = std::min(1.0f, steps_since_warmup / std::max(1.0f, static_cast<float>(config_.csr_ramp_steps)));
|
static_cast<float>(step_counter_ - config_.csr_warmup_steps);
|
||||||
|
csr_factor = std::min(
|
||||||
|
1.0f, steps_since_warmup /
|
||||||
|
std::max(1.0f, static_cast<float>(config_.csr_ramp_steps)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update spectral sensing rank
|
// Update spectral sensing rank
|
||||||
float spectral_alpha = 0.0f;
|
float spectral_alpha = 0.0f;
|
||||||
if (config_.grokking_coefficient > 0.0f && spectral_sensor_) {
|
if (config_.grokking_coefficient > 0.0f && spectral_sensor_) {
|
||||||
if (step_counter_ % config_.spectral_frequency == 0 || last_spectral_rank_ == 0.0f) {
|
if (step_counter_ % config_.spectral_frequency == 0 ||
|
||||||
|
last_spectral_rank_ == 0.0f) {
|
||||||
int param_idx = 0;
|
int param_idx = 0;
|
||||||
for (auto &group : param_groups()) {
|
for (auto &group : param_groups()) {
|
||||||
for (auto &p : group.params()) {
|
for (auto &p : group.params()) {
|
||||||
@@ -164,31 +174,28 @@ torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
|||||||
|
|
||||||
float effective_alpha = spectral_alpha * csr_factor;
|
float effective_alpha = spectral_alpha * csr_factor;
|
||||||
float kzm_damping = fitness_engine_.compute_kzm_damping(effective_alpha);
|
float kzm_damping = fitness_engine_.compute_kzm_damping(effective_alpha);
|
||||||
float stagnation_intensity = std::min(1.0f, static_cast<float>(stagnation_counter_) / 500.0f);
|
float stagnation_intensity =
|
||||||
|
std::min(1.0f, static_cast<float>(stagnation_counter_) / 500.0f);
|
||||||
float log_spectral_alpha = std::log(effective_alpha + 1e-6f);
|
float log_spectral_alpha = std::log(effective_alpha + 1e-6f);
|
||||||
|
|
||||||
// Call decide_update
|
// Call decide_update
|
||||||
auto actions = active_controller.decide_update(
|
auto actions = active_controller.decide_update(
|
||||||
layer_stats_,
|
layer_stats_, loss_velocity, progress, rollback_ema_, grad_cv,
|
||||||
loss_velocity,
|
log_spectral_alpha, stagnation_intensity, kzm_damping, loss_velocity);
|
||||||
progress,
|
|
||||||
rollback_ema_,
|
|
||||||
grad_cv,
|
|
||||||
log_spectral_alpha,
|
|
||||||
stagnation_intensity,
|
|
||||||
kzm_damping,
|
|
||||||
loss_velocity
|
|
||||||
);
|
|
||||||
|
|
||||||
// Bandit-style Early Stopping
|
// Bandit-style Early Stopping
|
||||||
if (step_counter_ % 5 == 0 && loss_velocity > 0.05f) {
|
if (step_counter_ % 5 == 0 && loss_velocity > 0.05f) {
|
||||||
Telemetry::get().warning("early_stopping_poor_controller",
|
Telemetry::get().warning(
|
||||||
"controller_id=" + std::to_string(active_controller.id) + " velocity=" + std::to_string(loss_velocity));
|
"early_stopping_poor_controller",
|
||||||
|
"controller_id=" + std::to_string(active_controller.id) +
|
||||||
|
" velocity=" + std::to_string(loss_velocity));
|
||||||
evolution_manager_->steps_active = evolution_manager_->selection_interval;
|
evolution_manager_->steps_active = evolution_manager_->selection_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (torch::isnan(actions).any().item<bool>()) {
|
if (torch::isnan(actions).any().item<bool>()) {
|
||||||
Telemetry::get().error("controller_nan_actions", "NaN actions returned by controller ID " + std::to_string(active_controller.id));
|
Telemetry::get().error("controller_nan_actions",
|
||||||
|
"NaN actions returned by controller ID " +
|
||||||
|
std::to_string(active_controller.id));
|
||||||
population_.kill(active_controller);
|
population_.kill(active_controller);
|
||||||
auto &new_controller = evolution_manager_->get_active_controller();
|
auto &new_controller = evolution_manager_->get_active_controller();
|
||||||
actions = torch::zeros_like(actions);
|
actions = torch::zeros_like(actions);
|
||||||
@@ -203,11 +210,7 @@ torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
|||||||
// 5. Evolution & Maintenance
|
// 5. Evolution & Maintenance
|
||||||
if (current_loss_val > 0.0f) {
|
if (current_loss_val > 0.0f) {
|
||||||
evolution_manager_->update_population_dynamics(
|
evolution_manager_->update_population_dynamics(
|
||||||
loss_velocity,
|
loss_velocity, ema_loss_, step_counter_, config_.total_steps);
|
||||||
ema_loss_,
|
|
||||||
step_counter_,
|
|
||||||
config_.total_steps
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step_counter_ % 50 == 0) {
|
if (step_counter_ % 50 == 0) {
|
||||||
@@ -220,9 +223,13 @@ torch::Tensor FCESOptimizer::step(LossClosure closure) {
|
|||||||
void FCESOptimizer::update_fitness(float loss) {
|
void FCESOptimizer::update_fitness(float loss) {
|
||||||
// 1. Divergence Safety
|
// 1. Divergence Safety
|
||||||
bool is_nan = std::isnan(loss) || !std::isfinite(loss);
|
bool is_nan = std::isnan(loss) || !std::isfinite(loss);
|
||||||
bool is_spike = (step_counter_ > 1) && (ema_loss_ > 0.0f) && (loss > config_.rollback_threshold * ema_loss_) && (ema_loss_ > 0.1f);
|
bool is_spike = (step_counter_ > 1) && (ema_loss_ > 0.0f) &&
|
||||||
|
(loss > config_.rollback_threshold * ema_loss_) &&
|
||||||
|
(ema_loss_ > 0.1f);
|
||||||
if (is_nan || is_spike) {
|
if (is_nan || is_spike) {
|
||||||
Telemetry::get().warning("divergence_detected", "loss=" + std::to_string(loss) + " ema=" + std::to_string(ema_loss_));
|
Telemetry::get().warning("divergence_detected",
|
||||||
|
"loss=" + std::to_string(loss) +
|
||||||
|
" ema=" + std::to_string(ema_loss_));
|
||||||
handle_rollback();
|
handle_rollback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -245,14 +252,18 @@ void FCESOptimizer::update_fitness(float loss) {
|
|||||||
float grad_mean = grad_norm_tracker_.get_mean();
|
float grad_mean = grad_norm_tracker_.get_mean();
|
||||||
float grad_cv = grad_std / (grad_mean + 1e-8f);
|
float grad_cv = grad_std / (grad_mean + 1e-8f);
|
||||||
|
|
||||||
float raw_rank = (spectral_sensor_) ? spectral_sensor_->get_global_rank() : 0.0f;
|
float raw_rank =
|
||||||
|
(spectral_sensor_) ? spectral_sensor_->get_global_rank() : 0.0f;
|
||||||
float csr_factor = 1.0f;
|
float csr_factor = 1.0f;
|
||||||
if (config_.csr_enabled) {
|
if (config_.csr_enabled) {
|
||||||
if (step_counter_ < config_.csr_warmup_steps) {
|
if (step_counter_ < config_.csr_warmup_steps) {
|
||||||
csr_factor = 0.0f;
|
csr_factor = 0.0f;
|
||||||
} else {
|
} else {
|
||||||
float steps_since_warmup = static_cast<float>(step_counter_ - config_.csr_warmup_steps);
|
float steps_since_warmup =
|
||||||
csr_factor = std::min(1.0f, steps_since_warmup / std::max(1.0f, static_cast<float>(config_.csr_ramp_steps)));
|
static_cast<float>(step_counter_ - config_.csr_warmup_steps);
|
||||||
|
csr_factor = std::min(
|
||||||
|
1.0f, steps_since_warmup /
|
||||||
|
std::max(1.0f, static_cast<float>(config_.csr_ramp_steps)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
float effective_rank = config_.csr_enabled ? raw_rank * csr_factor : raw_rank;
|
float effective_rank = config_.csr_enabled ? raw_rank * csr_factor : raw_rank;
|
||||||
@@ -339,7 +350,8 @@ void FCESOptimizer::gather_stats() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto grad = p.grad();
|
auto grad = p.grad();
|
||||||
if (torch::isnan(grad).any().item<bool>() || torch::isinf(grad).any().item<bool>()) {
|
if (torch::isnan(grad).any().item<bool>() ||
|
||||||
|
torch::isinf(grad).any().item<bool>()) {
|
||||||
has_nan_or_inf = true;
|
has_nan_or_inf = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,11 +367,14 @@ void FCESOptimizer::gather_stats() {
|
|||||||
|
|
||||||
int64_t total_elements = grad.numel();
|
int64_t total_elements = grad.numel();
|
||||||
int64_t zeros = (grad.abs() < 1e-5f).sum().item<int64_t>();
|
int64_t zeros = (grad.abs() < 1e-5f).sum().item<int64_t>();
|
||||||
float sparsity = (total_elements > 0) ? static_cast<float>(zeros) / total_elements : 0.0f;
|
float sparsity = (total_elements > 0)
|
||||||
|
? static_cast<float>(zeros) / total_elements
|
||||||
|
: 0.0f;
|
||||||
|
|
||||||
int layer_type = classify_layer_by_shape(p);
|
int layer_type = classify_layer_by_shape(p);
|
||||||
int group_idx = static_cast<int>(layer_stats_.size());
|
int group_idx = static_cast<int>(layer_stats_.size());
|
||||||
layer_stats_.push_back({grad_norm, sparsity, static_cast<float>(layer_type)});
|
layer_stats_.push_back(
|
||||||
|
{grad_norm, sparsity, static_cast<float>(layer_type)});
|
||||||
param_group_mapping_.push_back(group_idx);
|
param_group_mapping_.push_back(group_idx);
|
||||||
|
|
||||||
if (spectral_sensor_ && p.dim() >= 2) {
|
if (spectral_sensor_ && p.dim() >= 2) {
|
||||||
@@ -373,7 +388,8 @@ void FCESOptimizer::gather_stats() {
|
|||||||
|
|
||||||
if (has_nan_or_inf) {
|
if (has_nan_or_inf) {
|
||||||
Telemetry::get().error("poisoned_gradients_detected",
|
Telemetry::get().error("poisoned_gradients_detected",
|
||||||
"NaN/Inf detected in gradients during step " + std::to_string(step_counter_));
|
"NaN/Inf detected in gradients during step " +
|
||||||
|
std::to_string(step_counter_));
|
||||||
handle_rollback();
|
handle_rollback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -382,8 +398,10 @@ void FCESOptimizer::gather_stats() {
|
|||||||
float safe_lr = 0.01f / (max_grad_norm + 1e-8f);
|
float safe_lr = 0.01f / (max_grad_norm + 1e-8f);
|
||||||
for (auto &group : param_groups()) {
|
for (auto &group : param_groups()) {
|
||||||
if (group.options().get_lr() > safe_lr) {
|
if (group.options().get_lr() > safe_lr) {
|
||||||
Telemetry::get().info("auto_calibration_throttled_lr",
|
Telemetry::get().info(
|
||||||
"old=" + std::to_string(group.options().get_lr()) + " new=" + std::to_string(safe_lr));
|
"auto_calibration_throttled_lr",
|
||||||
|
"old=" + std::to_string(group.options().get_lr()) +
|
||||||
|
" new=" + std::to_string(safe_lr));
|
||||||
group.options().set_lr(safe_lr);
|
group.options().set_lr(safe_lr);
|
||||||
config_.lr = safe_lr;
|
config_.lr = safe_lr;
|
||||||
}
|
}
|
||||||
@@ -421,7 +439,8 @@ void FCESOptimizer::apply_parameter_updates(const torch::Tensor& actions) {
|
|||||||
|
|
||||||
float mult = actions[g_idx][0].item<float>();
|
float mult = actions[g_idx][0].item<float>();
|
||||||
float sign_gate = actions[g_idx][1].item<float>();
|
float sign_gate = actions[g_idx][1].item<float>();
|
||||||
float wd_mult = (actions.size(1) > 2) ? actions[g_idx][2].item<float>() : 1.0f;
|
float wd_mult =
|
||||||
|
(actions.size(1) > 2) ? actions[g_idx][2].item<float>() : 1.0f;
|
||||||
|
|
||||||
bool use_sign = sign_gate > 0.0f;
|
bool use_sign = sign_gate > 0.0f;
|
||||||
if (config_.ablation_mode == "force_sign") {
|
if (config_.ablation_mode == "force_sign") {
|
||||||
@@ -445,7 +464,8 @@ void FCESOptimizer::apply_parameter_updates(const torch::Tensor& actions) {
|
|||||||
p.data().add_(update);
|
p.data().add_(update);
|
||||||
|
|
||||||
if (config_.parasitic_mode) {
|
if (config_.parasitic_mode) {
|
||||||
parasitic_accum += calculate_parasitic_reward(p, mult, grad_norm_tracker_);
|
parasitic_accum +=
|
||||||
|
calculate_parasitic_reward(p, mult, grad_norm_tracker_);
|
||||||
}
|
}
|
||||||
|
|
||||||
param_idx++;
|
param_idx++;
|
||||||
@@ -455,7 +475,8 @@ void FCESOptimizer::apply_parameter_updates(const torch::Tensor& actions) {
|
|||||||
|
|
||||||
if (config_.parasitic_mode && count_updated > 0) {
|
if (config_.parasitic_mode && count_updated > 0) {
|
||||||
float reward = parasitic_accum / static_cast<float>(count_updated);
|
float reward = parasitic_accum / static_cast<float>(count_updated);
|
||||||
population_.update_controller_fitness(active_controller, reward * 10.0f, false);
|
population_.update_controller_fitness(active_controller, reward * 10.0f,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include "fces/oscillation.hpp"
|
#include "fces/oscillation.hpp"
|
||||||
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
@@ -17,7 +17,8 @@ bool OscillationDetector::detect() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float OscillationDetector::get_score() const {
|
float OscillationDetector::get_score() const {
|
||||||
if (static_cast<int>(loss_history_.size()) < WINDOW_SIZE) return 0.0f;
|
if (static_cast<int>(loss_history_.size()) < WINDOW_SIZE)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
auto detrended = detrend(loss_history_);
|
auto detrended = detrend(loss_history_);
|
||||||
auto power = compute_power_spectrum(detrended);
|
auto power = compute_power_spectrum(detrended);
|
||||||
@@ -34,12 +35,14 @@ float OscillationDetector::get_score() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (total_power < 1e-8f) return 0.0f;
|
if (total_power < 1e-8f)
|
||||||
|
return 0.0f;
|
||||||
return osc_power / total_power;
|
return osc_power / total_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
float OscillationDetector::get_variance_50() const {
|
float OscillationDetector::get_variance_50() const {
|
||||||
if (loss_history_.size() < 50) return 0.0f;
|
if (loss_history_.size() < 50)
|
||||||
|
return 0.0f;
|
||||||
auto start = loss_history_.end() - 50;
|
auto start = loss_history_.end() - 50;
|
||||||
float mean = std::accumulate(start, loss_history_.end(), 0.0f) / 50.0f;
|
float mean = std::accumulate(start, loss_history_.end(), 0.0f) / 50.0f;
|
||||||
float var = 0.0f;
|
float var = 0.0f;
|
||||||
@@ -50,13 +53,13 @@ float OscillationDetector::get_variance_50() const {
|
|||||||
return var / 50.0f;
|
return var / 50.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OscillationDetector::reset() {
|
void OscillationDetector::reset() { loss_history_.clear(); }
|
||||||
loss_history_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<float> OscillationDetector::detrend(const std::vector<float>& signal) {
|
std::vector<float>
|
||||||
|
OscillationDetector::detrend(const std::vector<float> &signal) {
|
||||||
int n = static_cast<int>(signal.size());
|
int n = static_cast<int>(signal.size());
|
||||||
if (n < 2) return signal;
|
if (n < 2)
|
||||||
|
return signal;
|
||||||
|
|
||||||
// Remove linear trend via least squares
|
// Remove linear trend via least squares
|
||||||
float sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
|
float sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
|
||||||
@@ -66,7 +69,8 @@ std::vector<float> OscillationDetector::detrend(const std::vector<float>& signal
|
|||||||
sum_xy += i * signal[i];
|
sum_xy += i * signal[i];
|
||||||
sum_xx += i * i;
|
sum_xx += i * i;
|
||||||
}
|
}
|
||||||
float slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x + 1e-8f);
|
float slope =
|
||||||
|
(n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x + 1e-8f);
|
||||||
float intercept = (sum_y - slope * sum_x) / n;
|
float intercept = (sum_y - slope * sum_x) / n;
|
||||||
|
|
||||||
std::vector<float> result(n);
|
std::vector<float> result(n);
|
||||||
@@ -76,8 +80,10 @@ std::vector<float> OscillationDetector::detrend(const std::vector<float>& signal
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> OscillationDetector::compute_power_spectrum(const std::vector<float>& signal) {
|
std::vector<float>
|
||||||
// Simple DFT (for WINDOW_SIZE=64, this is fast enough; upgrade to FFT if needed)
|
OscillationDetector::compute_power_spectrum(const std::vector<float> &signal) {
|
||||||
|
// Simple DFT (for WINDOW_SIZE=64, this is fast enough; upgrade to FFT if
|
||||||
|
// needed)
|
||||||
int n = static_cast<int>(signal.size());
|
int n = static_cast<int>(signal.size());
|
||||||
int half = n / 2;
|
int half = n / 2;
|
||||||
std::vector<float> power(half);
|
std::vector<float> power(half);
|
||||||
|
|||||||
@@ -4,22 +4,20 @@
|
|||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
Population::Population(
|
Population::Population(int active_size, int repo_size,
|
||||||
int active_size, int repo_size, EliteStrategy elite_strategy,
|
EliteStrategy elite_strategy, bool link_mutation,
|
||||||
bool link_mutation, bool link_elite, bool link_violator,
|
bool link_elite, bool link_violator,
|
||||||
bool use_fuzzy_pacer, bool use_fuzzy_importance,
|
bool use_fuzzy_pacer, bool use_fuzzy_importance,
|
||||||
bool direct_construction, bool use_banach_fission
|
bool direct_construction, bool use_banach_fission)
|
||||||
)
|
: elite_strategy_(elite_strategy), link_mutation_(link_mutation),
|
||||||
: elite_strategy_(elite_strategy),
|
link_elite_(link_elite), link_violator_(link_violator),
|
||||||
link_mutation_(link_mutation),
|
|
||||||
link_elite_(link_elite),
|
|
||||||
link_violator_(link_violator),
|
|
||||||
use_fuzzy_pacer_(use_fuzzy_pacer),
|
use_fuzzy_pacer_(use_fuzzy_pacer),
|
||||||
use_fuzzy_importance_(use_fuzzy_importance),
|
use_fuzzy_importance_(use_fuzzy_importance),
|
||||||
direct_construction_(direct_construction),
|
direct_construction_(direct_construction),
|
||||||
use_banach_fission_(use_banach_fission) {
|
use_banach_fission_(use_banach_fission) {
|
||||||
|
|
||||||
if (direct_construction) active_size = 1;
|
if (direct_construction)
|
||||||
|
active_size = 1;
|
||||||
|
|
||||||
gladiators_.reserve(active_size);
|
gladiators_.reserve(active_size);
|
||||||
for (int i = 0; i < active_size; ++i) {
|
for (int i = 0; i < active_size; ++i) {
|
||||||
@@ -48,12 +46,14 @@ FuzzyController& Population::select_weighted() {
|
|||||||
sum_fit += std::max(0.0f, g.fitness);
|
sum_fit += std::max(0.0f, g.fitness);
|
||||||
}
|
}
|
||||||
if (sum_fit == 0.0f) {
|
if (sum_fit == 0.0f) {
|
||||||
std::uniform_int_distribution<int> dist(0, static_cast<int>(gladiators_.size()) - 1);
|
std::uniform_int_distribution<int> dist(
|
||||||
|
0, static_cast<int>(gladiators_.size()) - 1);
|
||||||
return gladiators_[dist(rng)];
|
return gladiators_[dist(rng)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select 3 random candidates for tournament
|
// Select 3 random candidates for tournament
|
||||||
std::uniform_int_distribution<int> dist(0, static_cast<int>(gladiators_.size()) - 1);
|
std::uniform_int_distribution<int> dist(
|
||||||
|
0, static_cast<int>(gladiators_.size()) - 1);
|
||||||
int idx1 = dist(rng);
|
int idx1 = dist(rng);
|
||||||
int idx2 = dist(rng);
|
int idx2 = dist(rng);
|
||||||
int idx3 = dist(rng);
|
int idx3 = dist(rng);
|
||||||
@@ -64,7 +64,10 @@ FuzzyController& Population::select_weighted() {
|
|||||||
if (behavioral_archive_.size() >= 5) {
|
if (behavioral_archive_.size() >= 5) {
|
||||||
float novelty = 0.0f;
|
float novelty = 0.0f;
|
||||||
// Get behavioral vector: first 20 weights
|
// Get behavioral vector: first 20 weights
|
||||||
std::vector<float> behavior(c.genome.weights.begin(), c.genome.weights.begin() + std::min(20, static_cast<int>(c.genome.weights.size())));
|
std::vector<float> behavior(
|
||||||
|
c.genome.weights.begin(),
|
||||||
|
c.genome.weights.begin() +
|
||||||
|
std::min(20, static_cast<int>(c.genome.weights.size())));
|
||||||
std::vector<float> distances;
|
std::vector<float> distances;
|
||||||
distances.reserve(behavioral_archive_.size());
|
distances.reserve(behavioral_archive_.size());
|
||||||
for (const auto &archived : behavioral_archive_) {
|
for (const auto &archived : behavioral_archive_) {
|
||||||
@@ -81,7 +84,8 @@ FuzzyController& Population::select_weighted() {
|
|||||||
for (int i = 0; i < k; ++i) {
|
for (int i = 0; i < k; ++i) {
|
||||||
avg_dist += distances[i];
|
avg_dist += distances[i];
|
||||||
}
|
}
|
||||||
if (k > 0) avg_dist /= static_cast<float>(k);
|
if (k > 0)
|
||||||
|
avg_dist /= static_cast<float>(k);
|
||||||
base_score += NOVELTY_WEIGHT * avg_dist;
|
base_score += NOVELTY_WEIGHT * avg_dist;
|
||||||
}
|
}
|
||||||
return base_score;
|
return base_score;
|
||||||
@@ -108,7 +112,8 @@ FuzzyController& Population::select_weighted() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FuzzyController &Population::get_best_active() {
|
FuzzyController &Population::get_best_active() {
|
||||||
return *std::max_element(gladiators_.begin(), gladiators_.end(),
|
return *std::max_element(
|
||||||
|
gladiators_.begin(), gladiators_.end(),
|
||||||
[](const FuzzyController &a, const FuzzyController &b) {
|
[](const FuzzyController &a, const FuzzyController &b) {
|
||||||
return a.fitness < b.fitness;
|
return a.fitness < b.fitness;
|
||||||
});
|
});
|
||||||
@@ -131,13 +136,17 @@ FuzzyController& Population::get_worst_active() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (non_elites.empty()) {
|
if (non_elites.empty()) {
|
||||||
return *std::min_element(gladiators_.begin(), gladiators_.end(),
|
return *std::min_element(
|
||||||
|
gladiators_.begin(), gladiators_.end(),
|
||||||
[](const FuzzyController &a, const FuzzyController &b) {
|
[](const FuzzyController &a, const FuzzyController &b) {
|
||||||
return a.fitness < b.fitness;
|
return a.fitness < b.fitness;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return **std::min_element(non_elites.begin(), non_elites.end(),
|
// cppcheck-suppress returnReference; False Positive: elements of non_elites
|
||||||
|
// point to members of gladiators_
|
||||||
|
return **std::min_element(
|
||||||
|
non_elites.begin(), non_elites.end(),
|
||||||
[](const FuzzyController *a, const FuzzyController *b) {
|
[](const FuzzyController *a, const FuzzyController *b) {
|
||||||
return a->fitness < b->fitness;
|
return a->fitness < b->fitness;
|
||||||
});
|
});
|
||||||
@@ -151,7 +160,8 @@ void Population::kill(FuzzyController& controller) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = std::find_if(gladiators_.begin(), gladiators_.end(),
|
auto it = std::find_if(
|
||||||
|
gladiators_.begin(), gladiators_.end(),
|
||||||
[&](const FuzzyController &c) { return c.id == controller.id; });
|
[&](const FuzzyController &c) { return c.id == controller.id; });
|
||||||
if (it != gladiators_.end()) {
|
if (it != gladiators_.end()) {
|
||||||
gladiators_.erase(it);
|
gladiators_.erase(it);
|
||||||
@@ -161,7 +171,8 @@ void Population::kill(FuzzyController& controller) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Population::update_controller_fitness(FuzzyController& controller, float reward, bool increment_eval) {
|
void Population::update_controller_fitness(FuzzyController &controller,
|
||||||
|
float reward, bool increment_eval) {
|
||||||
if (increment_eval) {
|
if (increment_eval) {
|
||||||
controller.age++;
|
controller.age++;
|
||||||
controller.evaluation_count++;
|
controller.evaluation_count++;
|
||||||
@@ -177,7 +188,8 @@ void Population::update_controller_fitness(FuzzyController& controller, float re
|
|||||||
|
|
||||||
if (elite_strategy_ == EliteStrategy::EMA) {
|
if (elite_strategy_ == EliteStrategy::EMA) {
|
||||||
constexpr float EMA_ALPHA = 0.1f;
|
constexpr float EMA_ALPHA = 0.1f;
|
||||||
controller.ema_fitness = (1.0f - EMA_ALPHA) * controller.ema_fitness + EMA_ALPHA * reward;
|
controller.ema_fitness =
|
||||||
|
(1.0f - EMA_ALPHA) * controller.ema_fitness + EMA_ALPHA * reward;
|
||||||
controller.fitness = reward;
|
controller.fitness = reward;
|
||||||
} else if (elite_strategy_ == EliteStrategy::Rolling) {
|
} else if (elite_strategy_ == EliteStrategy::Rolling) {
|
||||||
controller.fitness = reward;
|
controller.fitness = reward;
|
||||||
@@ -187,35 +199,41 @@ void Population::update_controller_fitness(FuzzyController& controller, float re
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Population::mark_violated(FuzzyController &controller) {
|
void Population::mark_violated(FuzzyController &controller) {
|
||||||
auto it = std::find_if(violated_controllers_.begin(), violated_controllers_.end(),
|
auto it = std::find_if(
|
||||||
|
violated_controllers_.begin(), violated_controllers_.end(),
|
||||||
[&](const FuzzyController &c) { return c.id == controller.id; });
|
[&](const FuzzyController &c) { return c.id == controller.id; });
|
||||||
if (it == violated_controllers_.end()) {
|
if (it == violated_controllers_.end()) {
|
||||||
violated_controllers_.push_back(controller);
|
violated_controllers_.push_back(controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float Population::get_effective_fitness(const FuzzyController& controller, float training_progress) const {
|
float Population::get_effective_fitness(const FuzzyController &controller,
|
||||||
|
float training_progress) const {
|
||||||
float recent_avg = 0.0f;
|
float recent_avg = 0.0f;
|
||||||
if (!controller.fitness_history.empty()) {
|
if (!controller.fitness_history.empty()) {
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
for (float f : controller.fitness_history) sum += f;
|
for (float f : controller.fitness_history)
|
||||||
|
sum += f;
|
||||||
recent_avg = sum / controller.fitness_history.size();
|
recent_avg = sum / controller.fitness_history.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
float lifetime_avg = 0.0f;
|
float lifetime_avg = 0.0f;
|
||||||
if (controller.evaluation_count > 0) {
|
if (controller.evaluation_count > 0) {
|
||||||
lifetime_avg = controller.lifetime_fitness / static_cast<float>(controller.evaluation_count);
|
lifetime_avg = controller.lifetime_fitness /
|
||||||
|
static_cast<float>(controller.evaluation_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
float alpha = 0.2f + 0.6f * training_progress;
|
float alpha = 0.2f + 0.6f * training_progress;
|
||||||
return alpha * recent_avg + (1.0f - alpha) * lifetime_avg;
|
return alpha * recent_avg + (1.0f - alpha) * lifetime_avg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Population::evolve(float current_loss, float velocity, float training_progress) {
|
void Population::evolve(float current_loss, float velocity,
|
||||||
|
float training_progress) {
|
||||||
static thread_local std::mt19937 rng{std::random_device{}()};
|
static thread_local std::mt19937 rng{std::random_device{}()};
|
||||||
std::uniform_real_distribution<float> coin(0.0f, 1.0f);
|
std::uniform_real_distribution<float> coin(0.0f, 1.0f);
|
||||||
|
|
||||||
if (gladiators_.empty()) return;
|
if (gladiators_.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
FuzzyController &worst = get_worst_active();
|
FuzzyController &worst = get_worst_active();
|
||||||
FuzzyController &best_active = get_best_active();
|
FuzzyController &best_active = get_best_active();
|
||||||
@@ -223,7 +241,10 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
|
|
||||||
// Update behavioral archive for novelty search
|
// Update behavioral archive for novelty search
|
||||||
if (best_active.fitness > -999.0f) {
|
if (best_active.fitness > -999.0f) {
|
||||||
std::vector<float> behavior(best_active.genome.weights.begin(), best_active.genome.weights.begin() + std::min(20, static_cast<int>(best_active.genome.weights.size())));
|
std::vector<float> behavior(
|
||||||
|
best_active.genome.weights.begin(),
|
||||||
|
best_active.genome.weights.begin() +
|
||||||
|
std::min(20, static_cast<int>(best_active.genome.weights.size())));
|
||||||
behavioral_archive_.push_back(behavior);
|
behavioral_archive_.push_back(behavior);
|
||||||
if (behavioral_archive_.size() > BEHAVIORAL_ARCHIVE_SIZE) {
|
if (behavioral_archive_.size() > BEHAVIORAL_ARCHIVE_SIZE) {
|
||||||
behavioral_archive_.erase(behavioral_archive_.begin());
|
behavioral_archive_.erase(behavioral_archive_.begin());
|
||||||
@@ -256,7 +277,8 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
}
|
}
|
||||||
float violator_prob = 0.1f;
|
float violator_prob = 0.1f;
|
||||||
if (link_violator_) {
|
if (link_violator_) {
|
||||||
violator_prob = std::max(0.0f, std::min(0.5f, (current_loss - 1.0f) / 4.0f));
|
violator_prob =
|
||||||
|
std::max(0.0f, std::min(0.5f, (current_loss - 1.0f) / 4.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select parent
|
// Select parent
|
||||||
@@ -265,10 +287,12 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
|
|
||||||
float roll = coin(rng);
|
float roll = coin(rng);
|
||||||
if (roll < elite_prob && !elites.empty()) {
|
if (roll < elite_prob && !elites.empty()) {
|
||||||
std::uniform_int_distribution<int> elite_dist(0, static_cast<int>(elites.size()) - 1);
|
std::uniform_int_distribution<int> elite_dist(
|
||||||
|
0, static_cast<int>(elites.size()) - 1);
|
||||||
parent = elites[elite_dist(rng)];
|
parent = elites[elite_dist(rng)];
|
||||||
partner_pool = elites;
|
partner_pool = elites;
|
||||||
} else if (roll < elite_prob + violator_prob && !violated_controllers_.empty()) {
|
} else if (roll < elite_prob + violator_prob &&
|
||||||
|
!violated_controllers_.empty()) {
|
||||||
parent = &best_active;
|
parent = &best_active;
|
||||||
// Filter living violators
|
// Filter living violators
|
||||||
for (auto &v : violated_controllers_) {
|
for (auto &v : violated_controllers_) {
|
||||||
@@ -281,13 +305,15 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
}
|
}
|
||||||
if (partner_pool.empty()) {
|
if (partner_pool.empty()) {
|
||||||
// Fallback
|
// Fallback
|
||||||
for (size_t i = 0; i < std::min(static_cast<size_t>(10), gladiators_.size()); ++i) {
|
for (size_t i = 0;
|
||||||
|
i < std::min(static_cast<size_t>(10), gladiators_.size()); ++i) {
|
||||||
partner_pool.push_back(&gladiators_[i]);
|
partner_pool.push_back(&gladiators_[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
parent = &best_active;
|
parent = &best_active;
|
||||||
for (size_t i = 0; i < std::min(static_cast<size_t>(10), gladiators_.size()); ++i) {
|
for (size_t i = 0;
|
||||||
|
i < std::min(static_cast<size_t>(10), gladiators_.size()); ++i) {
|
||||||
partner_pool.push_back(&gladiators_[i]);
|
partner_pool.push_back(&gladiators_[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -295,7 +321,8 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
// Crossover or mutation
|
// Crossover or mutation
|
||||||
FuzzyController child;
|
FuzzyController child;
|
||||||
if (coin(rng) < 0.7f && partner_pool.size() > 1) {
|
if (coin(rng) < 0.7f && partner_pool.size() > 1) {
|
||||||
std::uniform_int_distribution<int> pool_dist(0, static_cast<int>(partner_pool.size()) - 1);
|
std::uniform_int_distribution<int> pool_dist(
|
||||||
|
0, static_cast<int>(partner_pool.size()) - 1);
|
||||||
FuzzyController *partner = partner_pool[pool_dist(rng)];
|
FuzzyController *partner = partner_pool[pool_dist(rng)];
|
||||||
if (partner->id == parent->id) {
|
if (partner->id == parent->id) {
|
||||||
// Pick another if possible
|
// Pick another if possible
|
||||||
@@ -346,7 +373,8 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
// Banach-Tarski Fission
|
// Banach-Tarski Fission
|
||||||
if (use_banach_fission_ && coin(rng) < 0.2f && !elites.empty()) {
|
if (use_banach_fission_ && coin(rng) < 0.2f && !elites.empty()) {
|
||||||
auto *prime_elite = elites[0];
|
auto *prime_elite = elites[0];
|
||||||
auto fission_pair = prime_elite->banach_tarski_fission(phase_phoenix_intensity);
|
auto fission_pair =
|
||||||
|
prime_elite->banach_tarski_fission(phase_phoenix_intensity);
|
||||||
|
|
||||||
// Find second worst
|
// Find second worst
|
||||||
FuzzyController *second_worst = nullptr;
|
FuzzyController *second_worst = nullptr;
|
||||||
@@ -361,7 +389,9 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
// Replace worst and second_worst with plus and minus child
|
// Replace worst and second_worst with plus and minus child
|
||||||
if (second_worst) {
|
if (second_worst) {
|
||||||
uint64_t sw_id = second_worst->id;
|
uint64_t sw_id = second_worst->id;
|
||||||
auto it = std::find_if(gladiators_.begin(), gladiators_.end(), [&](const FuzzyController& c) { return c.id == sw_id; });
|
auto it =
|
||||||
|
std::find_if(gladiators_.begin(), gladiators_.end(),
|
||||||
|
[&](const FuzzyController &c) { return c.id == sw_id; });
|
||||||
if (it != gladiators_.end()) {
|
if (it != gladiators_.end()) {
|
||||||
gladiators_.erase(it);
|
gladiators_.erase(it);
|
||||||
}
|
}
|
||||||
@@ -369,7 +399,9 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint64_t w_id = worst.id;
|
uint64_t w_id = worst.id;
|
||||||
auto it = std::find_if(gladiators_.begin(), gladiators_.end(), [&](const FuzzyController& c) { return c.id == w_id; });
|
auto it =
|
||||||
|
std::find_if(gladiators_.begin(), gladiators_.end(),
|
||||||
|
[&](const FuzzyController &c) { return c.id == w_id; });
|
||||||
if (it != gladiators_.end()) {
|
if (it != gladiators_.end()) {
|
||||||
gladiators_.erase(it);
|
gladiators_.erase(it);
|
||||||
}
|
}
|
||||||
@@ -377,14 +409,17 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
} else {
|
} else {
|
||||||
// Phoenix Rebirth or Standard replacement
|
// Phoenix Rebirth or Standard replacement
|
||||||
uint64_t w_id = worst.id;
|
uint64_t w_id = worst.id;
|
||||||
auto it = std::find_if(gladiators_.begin(), gladiators_.end(), [&](const FuzzyController& c) { return c.id == w_id; });
|
auto it =
|
||||||
|
std::find_if(gladiators_.begin(), gladiators_.end(),
|
||||||
|
[&](const FuzzyController &c) { return c.id == w_id; });
|
||||||
if (it != gladiators_.end()) {
|
if (it != gladiators_.end()) {
|
||||||
gladiators_.erase(it);
|
gladiators_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (coin(rng) < 0.1f && !elites.empty()) {
|
if (coin(rng) < 0.1f && !elites.empty()) {
|
||||||
auto *prime_elite = elites[0];
|
auto *prime_elite = elites[0];
|
||||||
gladiators_.push_back(prime_elite->create_orthogonal_child(phase_phoenix_intensity));
|
gladiators_.push_back(
|
||||||
|
prime_elite->create_orthogonal_child(phase_phoenix_intensity));
|
||||||
} else {
|
} else {
|
||||||
gladiators_.push_back(child);
|
gladiators_.push_back(child);
|
||||||
}
|
}
|
||||||
@@ -411,7 +446,8 @@ void Population::evolve(float current_loss, float velocity, float training_progr
|
|||||||
|
|
||||||
void Population::resize(int target_size, float training_progress) {
|
void Population::resize(int target_size, float training_progress) {
|
||||||
int current_size = static_cast<int>(gladiators_.size());
|
int current_size = static_cast<int>(gladiators_.size());
|
||||||
if (current_size == target_size) return;
|
if (current_size == target_size)
|
||||||
|
return;
|
||||||
|
|
||||||
static thread_local std::mt19937 rng{std::random_device{}()};
|
static thread_local std::mt19937 rng{std::random_device{}()};
|
||||||
|
|
||||||
@@ -430,7 +466,8 @@ void Population::resize(int target_size, float training_progress) {
|
|||||||
candidates.push_back({get_effective_fitness(g, training_progress), &g});
|
candidates.push_back({get_effective_fitness(g, training_progress), &g});
|
||||||
}
|
}
|
||||||
std::sort(candidates.begin(), candidates.end(),
|
std::sort(candidates.begin(), candidates.end(),
|
||||||
[](const std::pair<float, FuzzyController*>& a, const std::pair<float, FuzzyController*>& b) {
|
[](const std::pair<float, FuzzyController *> &a,
|
||||||
|
const std::pair<float, FuzzyController *> &b) {
|
||||||
return a.first > b.first;
|
return a.first > b.first;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -465,17 +502,21 @@ void Population::resize(int target_size, float training_progress) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::sort(evaluated.begin(), evaluated.end(),
|
std::sort(evaluated.begin(), evaluated.end(),
|
||||||
[this, training_progress](const FuzzyController* a, const FuzzyController* b) {
|
[this, training_progress](const FuzzyController *a,
|
||||||
return get_effective_fitness(*a, training_progress) > get_effective_fitness(*b, training_progress);
|
const FuzzyController *b) {
|
||||||
|
return get_effective_fitness(*a, training_progress) >
|
||||||
|
get_effective_fitness(*b, training_progress);
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<FuzzyController> new_pop;
|
std::vector<FuzzyController> new_pop;
|
||||||
new_pop.reserve(target_size);
|
new_pop.reserve(target_size);
|
||||||
for (int i = 0; i < std::min(target_size, static_cast<int>(evaluated.size())); ++i) {
|
for (int i = 0;
|
||||||
|
i < std::min(target_size, static_cast<int>(evaluated.size())); ++i) {
|
||||||
new_pop.push_back(*evaluated[i]);
|
new_pop.push_back(*evaluated[i]);
|
||||||
}
|
}
|
||||||
int remaining = target_size - static_cast<int>(new_pop.size());
|
int remaining = target_size - static_cast<int>(new_pop.size());
|
||||||
for (int i = 0; i < std::min(remaining, static_cast<int>(unevaluated.size())); ++i) {
|
for (int i = 0;
|
||||||
|
i < std::min(remaining, static_cast<int>(unevaluated.size())); ++i) {
|
||||||
new_pop.push_back(*unevaluated[i]);
|
new_pop.push_back(*unevaluated[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,14 +530,16 @@ void Population::calm_down() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
float Population::get_diversity_index() const {
|
float Population::get_diversity_index() const {
|
||||||
if (gladiators_.size() < 2) return 0.0f;
|
if (gladiators_.size() < 2)
|
||||||
|
return 0.0f;
|
||||||
float sum_dist = 0.0f;
|
float sum_dist = 0.0f;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (size_t i = 0; i < gladiators_.size(); ++i) {
|
for (size_t i = 0; i < gladiators_.size(); ++i) {
|
||||||
for (size_t j = i + 1; j < gladiators_.size(); ++j) {
|
for (size_t j = i + 1; j < gladiators_.size(); ++j) {
|
||||||
float dist_sq = 0.0f;
|
float dist_sq = 0.0f;
|
||||||
for (size_t w = 0; w < GENOME_SIZE; ++w) {
|
for (size_t w = 0; w < GENOME_SIZE; ++w) {
|
||||||
float diff = gladiators_[i].genome.weights[w] - gladiators_[j].genome.weights[w];
|
float diff =
|
||||||
|
gladiators_[i].genome.weights[w] - gladiators_[j].genome.weights[w];
|
||||||
dist_sq += diff * diff;
|
dist_sq += diff * diff;
|
||||||
}
|
}
|
||||||
sum_dist += std::sqrt(dist_sq);
|
sum_dist += std::sqrt(dist_sq);
|
||||||
@@ -521,13 +564,15 @@ std::vector<FuzzyController*> Population::get_elites() {
|
|||||||
for (auto &g : gladiators_) {
|
for (auto &g : gladiators_) {
|
||||||
float effective_fitness = 0.0f;
|
float effective_fitness = 0.0f;
|
||||||
if (elite_strategy_ == EliteStrategy::AgePenalty) {
|
if (elite_strategy_ == EliteStrategy::AgePenalty) {
|
||||||
effective_fitness = g.fitness / std::log(static_cast<float>(g.age) + 2.0f);
|
effective_fitness =
|
||||||
|
g.fitness / std::log(static_cast<float>(g.age) + 2.0f);
|
||||||
} else if (elite_strategy_ == EliteStrategy::EMA) {
|
} else if (elite_strategy_ == EliteStrategy::EMA) {
|
||||||
effective_fitness = g.ema_fitness;
|
effective_fitness = g.ema_fitness;
|
||||||
} else if (elite_strategy_ == EliteStrategy::Rolling) {
|
} else if (elite_strategy_ == EliteStrategy::Rolling) {
|
||||||
if (!g.fitness_history.empty()) {
|
if (!g.fitness_history.empty()) {
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
for (float f : g.fitness_history) sum += f;
|
for (float f : g.fitness_history)
|
||||||
|
sum += f;
|
||||||
effective_fitness = sum / g.fitness_history.size();
|
effective_fitness = sum / g.fitness_history.size();
|
||||||
} else {
|
} else {
|
||||||
effective_fitness = g.fitness;
|
effective_fitness = g.fitness;
|
||||||
@@ -539,7 +584,8 @@ std::vector<FuzzyController*> Population::get_elites() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::sort(candidates.begin(), candidates.end(),
|
std::sort(candidates.begin(), candidates.end(),
|
||||||
[](const std::pair<float, FuzzyController*>& a, const std::pair<float, FuzzyController*>& b) {
|
[](const std::pair<float, FuzzyController *> &a,
|
||||||
|
const std::pair<float, FuzzyController *> &b) {
|
||||||
return a.first > b.first;
|
return a.first > b.first;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -552,7 +598,8 @@ std::vector<FuzzyController*> Population::get_elites() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Population::add_to_repository(const FuzzyController &controller) {
|
void Population::add_to_repository(const FuzzyController &controller) {
|
||||||
auto it = std::lower_bound(repository_.begin(), repository_.end(), controller,
|
auto it =
|
||||||
|
std::lower_bound(repository_.begin(), repository_.end(), controller,
|
||||||
[](const FuzzyController &a, const FuzzyController &b) {
|
[](const FuzzyController &a, const FuzzyController &b) {
|
||||||
return a.fitness > b.fitness;
|
return a.fitness > b.fitness;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,14 +5,16 @@ namespace fces {
|
|||||||
|
|
||||||
SpectralSensor::SpectralSensor(torch::nn::Module & /*model*/) {}
|
SpectralSensor::SpectralSensor(torch::nn::Module & /*model*/) {}
|
||||||
|
|
||||||
void SpectralSensor::track_layer(const std::string& name, const torch::Tensor& weight) {
|
void SpectralSensor::track_layer(const std::string &name,
|
||||||
|
const torch::Tensor &weight) {
|
||||||
if (weight.dim() >= 2) {
|
if (weight.dim() >= 2) {
|
||||||
layer_ranks_[name] = compute_effective_rank(weight);
|
layer_ranks_[name] = compute_effective_rank(weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float SpectralSensor::get_global_rank() const {
|
float SpectralSensor::get_global_rank() const {
|
||||||
if (layer_ranks_.empty()) return 0.0f;
|
if (layer_ranks_.empty())
|
||||||
|
return 0.0f;
|
||||||
float sum = 0.0f;
|
float sum = 0.0f;
|
||||||
for (const auto &[_, rank] : layer_ranks_) {
|
for (const auto &[_, rank] : layer_ranks_) {
|
||||||
sum += rank;
|
sum += rank;
|
||||||
@@ -20,9 +22,7 @@ float SpectralSensor::get_global_rank() const {
|
|||||||
return sum / static_cast<float>(layer_ranks_.size());
|
return sum / static_cast<float>(layer_ranks_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpectralSensor::reset() {
|
void SpectralSensor::reset() { layer_ranks_.clear(); }
|
||||||
layer_ranks_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
float SpectralSensor::compute_effective_rank(const torch::Tensor &weight) {
|
float SpectralSensor::compute_effective_rank(const torch::Tensor &weight) {
|
||||||
// SVD-based effective rank (Shannon entropy of normalized singular values)
|
// SVD-based effective rank (Shannon entropy of normalized singular values)
|
||||||
@@ -34,7 +34,8 @@ float SpectralSensor::compute_effective_rank(const torch::Tensor& weight) {
|
|||||||
return std::exp(entropy);
|
return std::exp(entropy);
|
||||||
}
|
}
|
||||||
|
|
||||||
float SpectralController::compute_alpha(float global_rank, float grokking_coefficient) const {
|
float SpectralController::compute_alpha(float global_rank,
|
||||||
|
float grokking_coefficient) const {
|
||||||
return global_rank * grokking_coefficient;
|
return global_rank * grokking_coefficient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#include "fces/telemetry.hpp"
|
#include "fces/telemetry.hpp"
|
||||||
#include <iostream>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
namespace fces {
|
namespace fces {
|
||||||
|
|
||||||
@@ -11,19 +11,22 @@ Telemetry& Telemetry::get() {
|
|||||||
|
|
||||||
void Telemetry::info(const std::string &event, const std::string &detail) {
|
void Telemetry::info(const std::string &event, const std::string &detail) {
|
||||||
std::cout << "[INFO] " << event;
|
std::cout << "[INFO] " << event;
|
||||||
if (!detail.empty()) std::cout << " | " << detail;
|
if (!detail.empty())
|
||||||
|
std::cout << " | " << detail;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Telemetry::warning(const std::string &event, const std::string &detail) {
|
void Telemetry::warning(const std::string &event, const std::string &detail) {
|
||||||
std::cerr << "[WARN] " << event;
|
std::cerr << "[WARN] " << event;
|
||||||
if (!detail.empty()) std::cerr << " | " << detail;
|
if (!detail.empty())
|
||||||
|
std::cerr << " | " << detail;
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Telemetry::error(const std::string &event, const std::string &detail) {
|
void Telemetry::error(const std::string &event, const std::string &detail) {
|
||||||
std::cerr << "[ERROR] " << event;
|
std::cerr << "[ERROR] " << event;
|
||||||
if (!detail.empty()) std::cerr << " | " << detail;
|
if (!detail.empty())
|
||||||
|
std::cerr << " | " << detail;
|
||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "fces/controller.hpp"
|
#include "fces/controller.hpp"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
@@ -40,7 +40,8 @@ TEST(ControllerTest, Crossover) {
|
|||||||
TEST(ControllerTest, DecideUpdate) {
|
TEST(ControllerTest, DecideUpdate) {
|
||||||
FuzzyController ctrl;
|
FuzzyController ctrl;
|
||||||
std::vector<std::vector<float>> stats = {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f}};
|
std::vector<std::vector<float>> stats = {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f}};
|
||||||
auto actions = ctrl.decide_update(stats, 0.0f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f);
|
auto actions =
|
||||||
|
ctrl.decide_update(stats, 0.0f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f);
|
||||||
EXPECT_EQ(actions.size(0), 1);
|
EXPECT_EQ(actions.size(0), 1);
|
||||||
EXPECT_EQ(actions.size(1), GENOME_OUTPUT_DIM);
|
EXPECT_EQ(actions.size(1), GENOME_OUTPUT_DIM);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "fces/fitness.hpp"
|
#include "fces/fitness.hpp"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
@@ -14,7 +14,8 @@ TEST(RunningStatsTest, BasicUpdate) {
|
|||||||
|
|
||||||
TEST(RunningStatsTest, ZScore) {
|
TEST(RunningStatsTest, ZScore) {
|
||||||
RunningStats stats;
|
RunningStats stats;
|
||||||
for (int i = 0; i < 100; ++i) stats.update(static_cast<float>(i));
|
for (int i = 0; i < 100; ++i)
|
||||||
|
stats.update(static_cast<float>(i));
|
||||||
float z = stats.z_score(50.0f);
|
float z = stats.z_score(50.0f);
|
||||||
EXPECT_NEAR(z, 0.0f, 0.1f);
|
EXPECT_NEAR(z, 0.0f, 0.1f);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
|
#include "fces/optimizer.hpp"
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <torch/torch.h>
|
#include <torch/torch.h>
|
||||||
#include "fces/optimizer.hpp"
|
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
TEST(OptimizerTest, Construction) {
|
TEST(OptimizerTest, Construction) {
|
||||||
auto model = torch::nn::Linear(10, 5);
|
auto model = torch::nn::Linear(10, 5);
|
||||||
std::vector<torch::Tensor> params;
|
std::vector<torch::Tensor> params;
|
||||||
for (auto& p : model->parameters()) params.push_back(p);
|
for (auto &p : model->parameters())
|
||||||
|
params.push_back(p);
|
||||||
|
|
||||||
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
||||||
EXPECT_EQ(opt.step_count(), 0);
|
EXPECT_EQ(opt.step_count(), 0);
|
||||||
@@ -16,7 +17,8 @@ TEST(OptimizerTest, Construction) {
|
|||||||
TEST(OptimizerTest, StepUpdatesCounter) {
|
TEST(OptimizerTest, StepUpdatesCounter) {
|
||||||
auto model = torch::nn::Linear(10, 5);
|
auto model = torch::nn::Linear(10, 5);
|
||||||
std::vector<torch::Tensor> params;
|
std::vector<torch::Tensor> params;
|
||||||
for (auto& p : model->parameters()) params.push_back(p);
|
for (auto &p : model->parameters())
|
||||||
|
params.push_back(p);
|
||||||
|
|
||||||
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
||||||
|
|
||||||
@@ -33,7 +35,8 @@ TEST(OptimizerTest, StepUpdatesCounter) {
|
|||||||
TEST(OptimizerTest, UpdateFitness) {
|
TEST(OptimizerTest, UpdateFitness) {
|
||||||
auto model = torch::nn::Linear(10, 5);
|
auto model = torch::nn::Linear(10, 5);
|
||||||
std::vector<torch::Tensor> params;
|
std::vector<torch::Tensor> params;
|
||||||
for (auto& p : model->parameters()) params.push_back(p);
|
for (auto &p : model->parameters())
|
||||||
|
params.push_back(p);
|
||||||
|
|
||||||
FCESOptimizer opt(params);
|
FCESOptimizer opt(params);
|
||||||
opt.update_fitness(3.0f);
|
opt.update_fitness(3.0f);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#include <gtest/gtest.h>
|
|
||||||
#include "fces/population.hpp"
|
#include "fces/population.hpp"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
using namespace fces;
|
using namespace fces;
|
||||||
|
|
||||||
@@ -9,8 +9,8 @@ TEST(PopulationTest, Construction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(PopulationTest, DirectConstruction) {
|
TEST(PopulationTest, DirectConstruction) {
|
||||||
Population pop(200, 10000, EliteStrategy::Cumulative,
|
Population pop(200, 10000, EliteStrategy::Cumulative, false, false, false,
|
||||||
false, false, false, false, false, true);
|
false, false, true);
|
||||||
EXPECT_EQ(pop.size(), 1);
|
EXPECT_EQ(pop.size(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user