style: run clang-format and configure pre-commit hooks

This commit is contained in:
AI-anonymous
2026-05-20 00:18:23 +02:00
parent 041eab7155
commit 3b15770437
28 changed files with 2226 additions and 2061 deletions

51
.pre-commit-config.yaml Normal file
View 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" ]

View File

@@ -1,45 +1,47 @@
#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,
benchmark::DoNotOptimize(actions); 1.0f, 0.0f);
} benchmark::DoNotOptimize(actions);
}
} }
BENCHMARK(BM_ControllerDecideUpdate)->Arg(10)->Arg(50)->Arg(200); BENCHMARK(BM_ControllerDecideUpdate)->Arg(10)->Arg(50)->Arg(200);
static void BM_Evolve(benchmark::State& state) { static void BM_Evolve(benchmark::State &state) {
Population pop(state.range(0)); Population pop(state.range(0));
for (auto _ : state) { for (auto _ : state) {
pop.evolve(2.0f, -0.01f, 0.5f); pop.evolve(2.0f, -0.01f, 0.5f);
} }
} }
BENCHMARK(BM_Evolve)->Arg(50)->Arg(100)->Arg(200); BENCHMARK(BM_Evolve)->Arg(50)->Arg(100)->Arg(200);
static void BM_Mutation(benchmark::State& state) { static void BM_Mutation(benchmark::State &state) {
FuzzyController ctrl; FuzzyController ctrl;
for (auto _ : state) { for (auto _ : state) {
auto child = ctrl.mutate(2.0f, 1.0f); auto child = ctrl.mutate(2.0f, 1.0f);
benchmark::DoNotOptimize(child); benchmark::DoNotOptimize(child);
} }
} }
BENCHMARK(BM_Mutation); BENCHMARK(BM_Mutation);
static void BM_Crossover(benchmark::State& state) { static void BM_Crossover(benchmark::State &state) {
FuzzyController a, b; FuzzyController a, b;
for (auto _ : state) { for (auto _ : state) {
auto child = a.crossover(b); auto child = a.crossover(b);
benchmark::DoNotOptimize(child); benchmark::DoNotOptimize(child);
} }
} }
BENCHMARK(BM_Crossover); BENCHMARK(BM_Crossover);

View File

@@ -1,25 +1,26 @@
#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));
auto x = torch::randn({8, state.range(0)}); auto x = torch::randn({8, state.range(0)});
for (auto _ : state) { for (auto _ : state) {
auto y = model->forward(x); auto y = model->forward(x);
auto loss = y.sum(); auto loss = y.sum();
loss.backward(); loss.backward();
opt.step(); opt.step();
opt.zero_grad(); opt.zero_grad();
benchmark::DoNotOptimize(loss); benchmark::DoNotOptimize(loss);
} }
} }
BENCHMARK(BM_OptimizerStep)->Arg(64)->Arg(256)->Arg(1024); BENCHMARK(BM_OptimizerStep)->Arg(64)->Arg(256)->Arg(1024);

View File

@@ -3,59 +3,57 @@
* @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};
TinyNet() { TinyNet() {
fc1 = register_module("fc1", torch::nn::Linear(10, 32)); fc1 = register_module("fc1", torch::nn::Linear(10, 32));
fc2 = register_module("fc2", torch::nn::Linear(32, 1)); fc2 = register_module("fc2", torch::nn::Linear(32, 1));
} }
torch::Tensor forward(torch::Tensor x) { torch::Tensor forward(torch::Tensor x) {
x = torch::relu(fc1->forward(x)); x = torch::relu(fc1->forward(x));
return fc2->forward(x); return fc2->forward(x);
} }
}; };
int main() { 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, .set_lr(1.6e-3f)
fces::FCESConfig{} .set_population_size(200)
.set_lr(1.6e-3f) .set_total_steps(1000));
.set_population_size(200)
.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});
auto y_train = torch::sin(x_train.sum(1, true)); auto y_train = torch::sin(x_train.sum(1, true));
for (int epoch = 0; epoch < 100; ++epoch) { for (int epoch = 0; epoch < 100; ++epoch) {
optimizer.zero_grad(); optimizer.zero_grad();
auto pred = model->forward(x_train); auto pred = model->forward(x_train);
auto loss = torch::mse_loss(pred, y_train); auto loss = torch::mse_loss(pred, y_train);
loss.backward(); loss.backward();
optimizer.step(); optimizer.step();
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;
}
} }
}
std::cout << "\nTraining complete. Final loss: " std::cout << "\nTraining complete. Final loss: "
<< torch::mse_loss(model->forward(x_train), y_train).item<float>() << torch::mse_loss(model->forward(x_train), y_train).item<float>()
<< std::endl; << std::endl;
return 0; return 0;
} }

View File

@@ -3,34 +3,33 @@
* @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
auto target = torch::tensor({1.0f, 2.0f, 3.0f, 4.0f, 5.0f}); auto target = torch::tensor({1.0f, 2.0f, 3.0f, 4.0f, 5.0f});
auto x = torch::randn({5}, torch::requires_grad()); auto x = torch::randn({5}, torch::requires_grad());
std::vector<torch::Tensor> params = {x}; std::vector<torch::Tensor> params = {x};
fces::FCESOptimizer optimizer(params, fces::FCESConfig{}.set_lr(1e-2f)); fces::FCESOptimizer optimizer(params, fces::FCESConfig{}.set_lr(1e-2f));
for (int step = 0; step < 500; ++step) { for (int step = 0; step < 500; ++step) {
optimizer.zero_grad(); optimizer.zero_grad();
auto loss = (x - target).pow(2).sum(); auto loss = (x - target).pow(2).sum();
loss.backward(); loss.backward();
optimizer.step(); optimizer.step();
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;
}
} }
}
std::cout << "\nFinal x: " << x << std::endl; std::cout << "\nFinal x: " << x << std::endl;
std::cout << "Target: " << target << std::endl; std::cout << "Target: " << target << std::endl;
return 0; return 0;
} }

View File

@@ -3,112 +3,124 @@
* @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 {
torch::nn::Linear fc1{nullptr}, fc2{nullptr}; torch::nn::Linear fc1{nullptr}, fc2{nullptr};
RegressionNet() { RegressionNet() {
fc1 = register_module("fc1", torch::nn::Linear(1, 16)); fc1 = register_module("fc1", torch::nn::Linear(1, 16));
fc2 = register_module("fc2", torch::nn::Linear(16, 1)); fc2 = register_module("fc2", torch::nn::Linear(16, 1));
} }
torch::Tensor forward(torch::Tensor x) { torch::Tensor forward(torch::Tensor x) {
x = torch::tanh(fc1->forward(x)); x = torch::tanh(fc1->forward(x));
return fc2->forward(x); return fc2->forward(x);
} }
}; };
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>();
// Generate training data: x in [-2, 2], y = x^2 + noise
auto x_train = torch::linspace(-2.0, 2.0, 100).unsqueeze(1);
auto y_train = x_train.pow(2) + 0.1 * torch::randn({100, 1});
// 2. Configure Optimizer // Generate training data: x in [-2, 2], y = x^2 + noise
std::vector<torch::Tensor> params; auto x_train = torch::linspace(-2.0, 2.0, 100).unsqueeze(1);
for (auto& p : model->parameters()) { auto y_train = x_train.pow(2) + 0.1 * torch::randn({100, 1});
params.push_back(p);
// 2. Configure Optimizer
std::vector<torch::Tensor> params;
for (auto &p : model->parameters()) {
params.push_back(p);
}
fces::FCESOptimizer optimizer(
params,
fces::FCESConfig{}.set_lr(2e-3f).set_population_size(150).set_total_steps(
100));
fces::Telemetry::get().info("training_start",
"Beginning neural net optimization with FCES.");
auto start_train = std::chrono::high_resolution_clock::now();
// 3. Optimization Loop
for (int epoch = 0; epoch <= 100; ++epoch) {
optimizer.zero_grad();
auto pred = model->forward(x_train);
auto loss = torch::mse_loss(pred, y_train);
loss.backward();
optimizer.step();
optimizer.update_fitness(loss.item<float>());
if (epoch % 20 == 0) {
fces::Telemetry::get().info(
"epoch_checkpoint", "Epoch " + std::to_string(epoch) + " | Loss: " +
std::to_string(loss.item<float>()));
} }
}
fces::FCESOptimizer optimizer( auto end_train = std::chrono::high_resolution_clock::now();
params, double train_duration =
fces::FCESConfig{} std::chrono::duration<double, std::milli>(end_train - start_train)
.set_lr(2e-3f) .count();
.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_complete",
"Duration: " + std::to_string(train_duration) +
" ms");
auto start_train = std::chrono::high_resolution_clock::now(); // 4. Inference Phase
fces::Telemetry::get().info("inference_phase_start",
"Evaluating model on new test inputs.");
// 3. Optimization Loop // Generate test inputs
for (int epoch = 0; epoch <= 100; ++epoch) { auto x_test = torch::tensor({-1.5f, -0.5f, 0.0f, 0.5f, 1.5f}).unsqueeze(1);
optimizer.zero_grad(); auto y_expected = x_test.pow(2);
auto pred = model->forward(x_train);
auto loss = torch::mse_loss(pred, y_train);
loss.backward();
optimizer.step();
optimizer.update_fitness(loss.item<float>());
if (epoch % 20 == 0) { // Switch model to evaluation mode
fces::Telemetry::get().info("epoch_checkpoint", model->eval();
"Epoch " + std::to_string(epoch) + " | Loss: " + std::to_string(loss.item<float>()));
}
}
auto end_train = std::chrono::high_resolution_clock::now(); // Run inference and measure latency
double train_duration = std::chrono::duration<double, std::milli>(end_train - start_train).count(); auto start_inf = std::chrono::high_resolution_clock::now();
torch::Tensor y_pred;
{
torch::NoGradGuard no_grad;
y_pred = model->forward(x_test);
}
auto end_inf = std::chrono::high_resolution_clock::now();
double inf_duration =
std::chrono::duration<double, std::milli>(end_inf - start_inf).count();
fces::Telemetry::get().info("training_complete", // Log telemetry for inference performance
"Duration: " + std::to_string(train_duration) + " ms"); fces::Telemetry::get().info(
"inference_perf", "Inputs: " + std::to_string(x_test.size(0)) +
" | Latency: " + std::to_string(inf_duration) +
" ms");
// 4. Inference Phase // Print predictions and expected values side-by-side
fces::Telemetry::get().info("inference_phase_start", "Evaluating model on new test inputs."); std::cout << "\n================ INFERENCE RESULTS ================"
<< 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) {
float x_val = x_test[i][0].item<float>();
float pred_val = y_pred[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::cout << "====================================================\n"
<< std::endl;
// Generate test inputs fces::Telemetry::get().info("app_finish", "Exiting demo successfully.");
auto x_test = torch::tensor({-1.5f, -0.5f, 0.0f, 0.5f, 1.5f}).unsqueeze(1); return 0;
auto y_expected = x_test.pow(2);
// Switch model to evaluation mode
model->eval();
// Run inference and measure latency
auto start_inf = std::chrono::high_resolution_clock::now();
torch::Tensor y_pred;
{
torch::NoGradGuard no_grad;
y_pred = model->forward(x_test);
}
auto end_inf = std::chrono::high_resolution_clock::now();
double inf_duration = std::chrono::duration<double, std::milli>(end_inf - start_inf).count();
// Log telemetry for inference performance
fces::Telemetry::get().info("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
std::cout << "\n================ INFERENCE RESULTS ================" << 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) {
float x_val = x_test[i][0].item<float>();
float pred_val = y_pred[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::cout << "====================================================\n" << std::endl;
fces::Telemetry::get().info("app_finish", "Exiting demo successfully.");
return 0;
} }

View File

@@ -18,65 +18,80 @@ namespace fces {
* All fields have sensible defaults matching the Python V49.0 implementation. * All fields have sensible defaults matching the Python V49.0 implementation.
*/ */
struct FCESConfig { struct FCESConfig {
// Learning rate (V49 optimal default) // Learning rate (V49 optimal default)
float lr = 1.6e-3f; float lr = 1.6e-3f;
// Weight decay coefficient // Weight decay coefficient
float weight_decay = 0.0f; float weight_decay = 0.0f;
// Population size for evolutionary search // Population size for evolutionary search
int population_size = 200; int population_size = 200;
// Total training steps (for progress-aware scheduling) // Total training steps (for progress-aware scheduling)
int total_steps = 5000; int total_steps = 5000;
// Signal mode for loss velocity calculation // Signal mode for loss velocity calculation
std::string signal_mode = "relative"; std::string signal_mode = "relative";
// Grokking awareness coefficient (0.0 = disabled) // Grokking awareness coefficient (0.0 = disabled)
float grokking_coefficient = 0.1f; float grokking_coefficient = 0.1f;
// Spectral sensing frequency (every N steps) // Spectral sensing frequency (every N steps)
int spectral_frequency = 10; int spectral_frequency = 10;
// Curriculum Spectral Regularization // Curriculum Spectral Regularization
bool csr_enabled = false; bool csr_enabled = false;
int csr_warmup_steps = 500; int csr_warmup_steps = 500;
int csr_ramp_steps = 1000; int csr_ramp_steps = 1000;
// Trust region clipping // Trust region clipping
float trust_region_clip = 0.01f; float trust_region_clip = 0.01f;
// Rollback threshold // Rollback threshold
float rollback_threshold = 1.5f; float rollback_threshold = 1.5f;
// Adaptive weight decay // Adaptive weight decay
bool adaptive_wd = false; bool adaptive_wd = false;
// Parasitic mode (gradient alignment reward) // Parasitic mode (gradient alignment reward)
bool parasitic_mode = false; bool parasitic_mode = false;
// Ablation mode: "", "force_sign", "force_grad" // Ablation mode: "", "force_sign", "force_grad"
std::string ablation_mode = ""; std::string ablation_mode = "";
// Fractional factorial scoring (CRO trick) // Fractional factorial scoring (CRO trick)
bool use_fractional_scoring = false; bool use_fractional_scoring = false;
// Direct construction mode (pop_size=1) // Direct construction mode (pop_size=1)
bool direct_construction = false; bool direct_construction = false;
// Banach-Tarski fission // Banach-Tarski fission
bool use_banach_fission = false; bool use_banach_fission = false;
// Auto-population (stabilize on divergence) // Auto-population (stabilize on divergence)
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

View File

@@ -27,28 +27,29 @@ 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
(GENOME_HIDDEN_DIM * GENOME_OUTPUT_DIM) + // hidden -> output weights (GENOME_HIDDEN_DIM * GENOME_OUTPUT_DIM) + // hidden -> output weights
GENOME_OUTPUT_DIM; // output biases GENOME_OUTPUT_DIM; // output biases
/** /**
* Genome — the "DNA" of a fuzzy controller. * Genome — the "DNA" of a fuzzy controller.
* A flat array of floats encoding a micro-MLP. * A flat array of floats encoding a micro-MLP.
*/ */
struct Genome { struct Genome {
std::array<float, GENOME_SIZE> weights{}; std::array<float, GENOME_SIZE> weights{};
std::array<float, GENOME_SIZE> gene_success{}; std::array<float, GENOME_SIZE> gene_success{};
float sigma_gene = 0.1f; float sigma_gene = 0.1f;
float plasticity = 1.0f; float plasticity = 1.0f;
/// Initialize with random weights from a normal distribution /// Initialize with random weights from a normal distribution
void randomize(std::mt19937& rng); void randomize(std::mt19937 &rng);
/// Deep copy /// Deep copy
Genome clone() const; Genome clone() const;
}; };
/** /**
@@ -62,84 +63,81 @@ struct Genome {
*/ */
class FuzzyController { class FuzzyController {
public: public:
/// Unique identifier /// Unique identifier
uint64_t id; uint64_t id;
/// The neural genome /// The neural genome
Genome genome; Genome genome;
/// Fitness scores /// Fitness scores
float fitness = 0.0f; float fitness = 0.0f;
float lifetime_fitness = 0.0f; float lifetime_fitness = 0.0f;
float ema_fitness = 0.0f; float ema_fitness = 0.0f;
int evaluation_count = 0; int evaluation_count = 0;
int age = 0; int age = 0;
/// Origin tracking /// Origin tracking
std::string origin = "random"; std::string origin = "random";
/// Trust region violation counter /// Trust region violation counter
int trust_violations = 0; int trust_violations = 0;
/// Rolling fitness history (for Phase 23 strategies) /// Rolling fitness history (for Phase 23 strategies)
std::vector<float> fitness_history; std::vector<float> fitness_history;
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Construction // Construction
// --------------------------------------------------------------- // ---------------------------------------------------------------
FuzzyController(); FuzzyController();
explicit FuzzyController(Genome genome); explicit FuzzyController(Genome genome);
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Core Operations // Core Operations
// --------------------------------------------------------------- // ---------------------------------------------------------------
/** /**
* Forward pass through the micro-MLP to produce update decisions. * Forward pass through the micro-MLP to produce update decisions.
* *
* @param layer_stats Vector of per-layer feature maps * @param layer_stats Vector of per-layer feature maps
* @param loss_trend Current loss velocity * @param loss_trend Current loss velocity
* @param step_pct Training progress [0, 1] * @param step_pct Training progress [0, 1]
* @param rollback_rate Rolling average rollback frequency * @param rollback_rate Rolling average rollback frequency
* @param grad_stability Gradient coefficient of variation * @param grad_stability Gradient coefficient of variation
* @param spectral_alpha Log spectral rank * @param spectral_alpha Log spectral rank
* @param stagnation_intensity Stagnation counter / 500 * @param stagnation_intensity Stagnation counter / 500
* @param kzm_damping Kibble-Zurek damping factor * @param kzm_damping Kibble-Zurek damping factor
* @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
// --------------------------------------------------------------- // ---------------------------------------------------------------
/// Create a mutated child /// Create a mutated child
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_;
static thread_local std::mt19937 rng_; static thread_local std::mt19937 rng_;
}; };
} // namespace fces } // namespace fces

View File

@@ -21,34 +21,27 @@ namespace fces {
*/ */
class EvolutionManager { class EvolutionManager {
public: public:
explicit EvolutionManager( explicit EvolutionManager(Population &population, int selection_interval = 50,
Population& population, bool auto_population = false,
int selection_interval = 50, bool direct_construction = false);
bool auto_population = 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;
/// Selection interval (how long a controller stays active) /// Selection interval (how long a controller stays active)
int selection_interval; int selection_interval;
private: private:
Population& population_; Population &population_;
bool auto_population_; bool auto_population_;
bool direct_construction_; bool direct_construction_;
}; };
} // namespace fces } // namespace fces

View File

@@ -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 {
@@ -19,18 +20,18 @@ namespace fces {
*/ */
class RunningStats { class RunningStats {
public: public:
void update(float value); void update(float value);
float z_score(float value) const; float z_score(float value) const;
float get_mean() const { return mean_; } float get_mean() const { return mean_; }
float get_std() const; float get_std() const;
int get_count() const { return count_; } int get_count() const { return count_; }
void reset(); void reset();
private: private:
int count_ = 0; int count_ = 0;
float mean_ = 0.0f; float mean_ = 0.0f;
float m2_ = 0.0f; float m2_ = 0.0f;
}; };
/** /**
@@ -38,26 +39,27 @@ private:
*/ */
class FitnessEngine { class FitnessEngine {
public: public:
explicit FitnessEngine(float grokking_coefficient = 0.1f); explicit FitnessEngine(float grokking_coefficient = 0.1f);
/** /**
* Calculate loss velocity signal. * Calculate loss velocity signal.
* *
* @param current_loss Current step loss * @param current_loss Current step loss
* @param ema_loss Exponential moving average loss * @param ema_loss Exponential moving average loss
* @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.
* Prevents topological defects during phase transitions. * Prevents topological defects during phase transitions.
*/ */
float compute_kzm_damping(float spectral_alpha) const; float compute_kzm_damping(float spectral_alpha) const;
private: private:
float grokking_coefficient_; float grokking_coefficient_;
}; };
/** /**
@@ -65,75 +67,76 @@ private:
*/ */
class FuzzySet { class FuzzySet {
public: public:
FuzzySet(std::string name, float a, float b, float c, float d) noexcept FuzzySet(std::string name, float a, float b, float c, float d) noexcept
: name_(std::move(name)), a_(a), b_(b), c_(c), d_(d) {} : name_(std::move(name)), a_(a), b_(b), c_(c), d_(d) {}
float membership(float x) const noexcept { float membership(float x) const noexcept {
if (!std::isfinite(x)) { if (!std::isfinite(x)) {
return 0.0f; return 0.0f;
}
if (x <= a_ || x >= d_) {
return 0.0f;
}
if (x >= b_ && x <= c_) {
return 1.0f;
}
if (x > a_ && x < b_) {
float range = b_ - a_;
return (x - a_) / (range > 0.0f ? range : 1e-9f);
}
if (x > c_ && x < d_) {
float range = d_ - c_;
return (d_ - x) / (range > 0.0f ? range : 1e-9f);
}
return 0.0f;
} }
if (x <= a_ || x >= d_) {
return 0.0f;
}
if (x >= b_ && x <= c_) {
return 1.0f;
}
if (x > a_ && x < b_) {
float range = b_ - a_;
return (x - a_) / (range > 0.0f ? range : 1e-9f);
}
if (x > c_ && x < d_) {
float range = d_ - c_;
return (d_ - x) / (range > 0.0f ? range : 1e-9f);
}
return 0.0f;
}
const std::string& name() const noexcept { return name_; } const std::string &name() const noexcept { return name_; }
private: private:
std::string name_; std::string name_;
float a_; float a_;
float b_; float b_;
float c_; float c_;
float d_; float d_;
}; };
/** /**
* Fitness metrics for multi-objective evaluation. * Fitness metrics for multi-objective evaluation.
*/ */
struct FitnessMetrics { struct FitnessMetrics {
float training_advantage = 0.0f; float training_advantage = 0.0f;
float validation_advantage = 0.0f; float validation_advantage = 0.0f;
float grad_cv = 0.0f; float grad_cv = 0.0f;
float sparsity_delta = 0.0f; float sparsity_delta = 0.0f;
float consistency_gap = 0.0f; float consistency_gap = 0.0f;
float stable_rank = 0.0f; float stable_rank = 0.0f;
}; };
/** /**
* FuzzyFitnessEvaluator — multi-objective fitness evaluation with fuzzy weighting. * FuzzyFitnessEvaluator — multi-objective fitness evaluation with fuzzy
* weighting.
*/ */
class FuzzyFitnessEvaluator { class FuzzyFitnessEvaluator {
public: public:
FuzzyFitnessEvaluator() noexcept; FuzzyFitnessEvaluator() noexcept;
float evaluate(const FitnessMetrics& metrics) const noexcept; float evaluate(const FitnessMetrics &metrics) const noexcept;
private: private:
FuzzySet stability_set_; FuzzySet stability_set_;
FuzzySet train_set_; FuzzySet train_set_;
FuzzySet val_set_; FuzzySet val_set_;
FuzzySet sparsity_set_; FuzzySet sparsity_set_;
FuzzySet consistency_set_; FuzzySet consistency_set_;
FuzzySet rank_set_; FuzzySet rank_set_;
float w_stability_ = 0.2f; float w_stability_ = 0.2f;
float w_train_ = 0.2f; float w_train_ = 0.2f;
float w_val_ = 0.3f; float w_val_ = 0.3f;
float w_sparsity_ = 0.1f; float w_sparsity_ = 0.1f;
float w_consistency_ = 0.2f; float w_consistency_ = 0.2f;
float w_rank_ = 0.1f; float w_rank_ = 0.1f;
}; };
} // namespace fces } // namespace fces

View File

@@ -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,73 +33,72 @@ 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
explicit FCESOptimizerOptions(double lr = 0.01) : lr_(lr) {} : public torch::optim::OptimizerCloneableOptions<FCESOptimizerOptions> {
explicit FCESOptimizerOptions(double lr = 0.01) : lr_(lr) {}
double get_lr() const override { return lr_; } double get_lr() const override { return lr_; }
void set_lr(const double lr) override { lr_ = lr; } void set_lr(const double lr) override { lr_ = lr; }
double lr_; double lr_;
}; };
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;
/// Update evolutionary fitness with current loss /// Update evolutionary fitness with current loss
void update_fitness(float loss); void update_fitness(float loss);
/// Backup model weights to CPU RAM /// Backup model weights to CPU RAM
void backup_to_ram(); void backup_to_ram();
/// Restore model weights from CPU RAM backup /// Restore model weights from CPU RAM backup
void restore_from_ram(); void restore_from_ram();
/// Get current step count /// Get current step count
int step_count() const { return step_counter_; } int step_count() const { return step_counter_; }
/// Calculate model sparsity /// Calculate model sparsity
float calculate_sparsity() const; float calculate_sparsity() const;
private: private:
FCESConfig config_; FCESConfig config_;
Population population_; Population population_;
FitnessEngine fitness_engine_; FitnessEngine fitness_engine_;
FuzzyFitnessEvaluator fitness_evaluator_; FuzzyFitnessEvaluator fitness_evaluator_;
std::unique_ptr<EvolutionManager> evolution_manager_; std::unique_ptr<EvolutionManager> evolution_manager_;
OscillationDetector oscillation_detector_; OscillationDetector oscillation_detector_;
RunningStats grad_norm_tracker_; RunningStats grad_norm_tracker_;
// State // State
int step_counter_ = 0; int step_counter_ = 0;
float ema_loss_ = 0.0f; float ema_loss_ = 0.0f;
float last_step_loss_ = 0.0f; float last_step_loss_ = 0.0f;
float best_loss_window_ = std::numeric_limits<float>::infinity(); float best_loss_window_ = std::numeric_limits<float>::infinity();
float rollback_ema_ = 0.0f; float rollback_ema_ = 0.0f;
int stagnation_counter_ = 0; int stagnation_counter_ = 0;
float last_loss_velocity_ = 0.0f; float last_loss_velocity_ = 0.0f;
float last_sparsity_ = 0.0f; float last_sparsity_ = 0.0f;
// RAM backup // RAM backup
std::vector<torch::Tensor> ram_backup_; std::vector<torch::Tensor> ram_backup_;
// Layer stats and group mappings // Layer stats and group mappings
std::vector<std::vector<float>> layer_stats_; std::vector<std::vector<float>> layer_stats_;
std::vector<int> param_group_mapping_; std::vector<int> param_group_mapping_;
std::unique_ptr<SpectralSensor> spectral_sensor_; std::unique_ptr<SpectralSensor> spectral_sensor_;
SpectralController spectral_controller_; SpectralController spectral_controller_;
float last_spectral_rank_ = 0.0f; float last_spectral_rank_ = 0.0f;
// Internal methods // Internal methods
void gather_stats(); void gather_stats();
void apply_parameter_updates(const torch::Tensor& actions); void apply_parameter_updates(const torch::Tensor &actions);
void handle_rollback(); void handle_rollback();
}; };
} // namespace fces } // namespace fces

View File

@@ -11,21 +11,22 @@ namespace fces {
class OscillationDetector { class OscillationDetector {
public: public:
static constexpr int WINDOW_SIZE = 64; static constexpr int WINDOW_SIZE = 64;
static constexpr float POWER_THRESHOLD = 0.5f; static constexpr float POWER_THRESHOLD = 0.5f;
static constexpr int MIN_PERIOD = 4; static constexpr int MIN_PERIOD = 4;
static constexpr int MAX_PERIOD = 16; static constexpr int MAX_PERIOD = 16;
void update(float loss); void update(float loss);
bool detect() const; bool detect() const;
float get_score() const; float get_score() const;
float get_variance_50() const; float get_variance_50() const;
void reset(); void reset();
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

View File

@@ -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"
@@ -28,11 +28,11 @@ namespace fces {
* Elite selection strategy for stale elite mitigation (Phase 23). * Elite selection strategy for stale elite mitigation (Phase 23).
*/ */
enum class EliteStrategy { enum class EliteStrategy {
Cumulative, // Raw cumulative fitness Cumulative, // Raw cumulative fitness
EMA, // Exponential moving average EMA, // Exponential moving average
Rolling, // Rolling window average Rolling, // Rolling window average
Reset, // Periodic reset every 500 steps Reset, // Periodic reset every 500 steps
AgePenalty // fitness / log(age + 2) AgePenalty // fitness / log(age + 2)
}; };
/** /**
@@ -40,126 +40,124 @@ enum class EliteStrategy {
*/ */
class Population { class Population {
public: public:
// Configuration constants // Configuration constants
static constexpr int ELITE_COUNT = 2; static constexpr int ELITE_COUNT = 2;
static constexpr float NOVELTY_WEIGHT = 0.1f; static constexpr float NOVELTY_WEIGHT = 0.1f;
static constexpr float ISLAND_MIGRATION_RATE = 0.05f; static constexpr float ISLAND_MIGRATION_RATE = 0.05f;
static constexpr int BEHAVIORAL_ARCHIVE_SIZE = 100; static constexpr int BEHAVIORAL_ARCHIVE_SIZE = 100;
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Construction // Construction
// --------------------------------------------------------------- // ---------------------------------------------------------------
explicit Population( explicit Population(int active_size = 75, int repo_size = 10000,
int active_size = 75, EliteStrategy elite_strategy = EliteStrategy::Cumulative,
int repo_size = 10000, bool link_mutation = false, bool link_elite = false,
EliteStrategy elite_strategy = EliteStrategy::Cumulative, bool link_violator = false, bool use_fuzzy_pacer = false,
bool link_mutation = false, bool use_fuzzy_importance = false,
bool link_elite = false, bool direct_construction = false,
bool link_violator = false, bool use_banach_fission = false);
bool use_fuzzy_pacer = false,
bool use_fuzzy_importance = false,
bool direct_construction = false,
bool use_banach_fission = false
);
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Core API // Core API
// --------------------------------------------------------------- // ---------------------------------------------------------------
/// Get the currently active controller (sticky selection) /// Get the currently active controller (sticky selection)
FuzzyController& get_active_controller(); FuzzyController &get_active_controller();
/// Select a controller via fitness-weighted tournament /// Select a controller via fitness-weighted tournament
FuzzyController& select_weighted(); FuzzyController &select_weighted();
/// Get the best controller in the active population /// Get the best controller in the active population
FuzzyController& get_best_active(); FuzzyController &get_best_active();
/// Get the worst non-elite controller /// Get the worst non-elite controller
FuzzyController& get_worst_active(); FuzzyController &get_worst_active();
/// Remove a specific controller (unless elite) /// Remove a specific controller (unless elite)
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
// --------------------------------------------------------------- // ---------------------------------------------------------------
/** /**
* Evolve the population: select parents, crossover/mutate, replace worst. * Evolve the population: select parents, crossover/mutate, replace worst.
* *
* @param current_loss Current training loss * @param current_loss Current training loss
* @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);
/// Reduce mutation variance after rollback /// Reduce mutation variance after rollback
void calm_down(); void calm_down();
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Accessors // Accessors
// --------------------------------------------------------------- // ---------------------------------------------------------------
int size() const { return static_cast<int>(gladiators_.size()); } int size() const { return static_cast<int>(gladiators_.size()); }
float global_sigma_modifier() const { return global_sigma_modifier_; } float global_sigma_modifier() const { return global_sigma_modifier_; }
/// Compute diversity index (behavioral spread) /// Compute diversity index (behavioral spread)
float get_diversity_index() const; float get_diversity_index() const;
/// Serialization /// Serialization
// TODO: state_dict / load_state_dict // TODO: state_dict / load_state_dict
private: private:
std::vector<FuzzyController> gladiators_; std::vector<FuzzyController> gladiators_;
std::vector<FuzzyController> repository_; std::vector<FuzzyController> repository_;
std::vector<FuzzyController> violated_controllers_; std::vector<FuzzyController> violated_controllers_;
float global_sigma_modifier_ = 1.0f; float global_sigma_modifier_ = 1.0f;
// Sticky controller selection // Sticky controller selection
FuzzyController* active_controller_ = nullptr; FuzzyController *active_controller_ = nullptr;
int steps_active_ = 0; int steps_active_ = 0;
int selection_interval_ = 20; int selection_interval_ = 20;
// Configuration // Configuration
EliteStrategy elite_strategy_; EliteStrategy elite_strategy_;
bool link_mutation_; bool link_mutation_;
bool link_elite_; bool link_elite_;
bool link_violator_; bool link_violator_;
bool use_fuzzy_pacer_; bool use_fuzzy_pacer_;
bool use_fuzzy_importance_; bool use_fuzzy_importance_;
bool direct_construction_; bool direct_construction_;
bool use_banach_fission_; bool use_banach_fission_;
// Novelty search // Novelty search
std::vector<std::vector<float>> behavioral_archive_; std::vector<std::vector<float>> behavioral_archive_;
// Fitness history for fuzzy pacer // Fitness history for fuzzy pacer
std::vector<float> fitness_history_; std::vector<float> fitness_history_;
// Phase 23: periodic reset counter // Phase 23: periodic reset counter
int reset_step_counter_ = 0; int reset_step_counter_ = 0;
// --------------------------------------------------------------- // ---------------------------------------------------------------
// Internal // Internal
// --------------------------------------------------------------- // ---------------------------------------------------------------
std::vector<FuzzyController*> get_elites(); std::vector<FuzzyController *> get_elites();
void add_to_repository(const FuzzyController& controller); void add_to_repository(const FuzzyController &controller);
}; };
} // namespace fces } // namespace fces

View File

@@ -23,23 +23,23 @@ namespace fces {
*/ */
class SpectralSensor { class SpectralSensor {
public: public:
SpectralSensor() = default; SpectralSensor() = default;
explicit SpectralSensor(torch::nn::Module& model); explicit SpectralSensor(torch::nn::Module &model);
/// Track a layer's weight tensor /// Track a layer's weight tensor
void track_layer(const std::string& name, const torch::Tensor& weight); void track_layer(const std::string &name, const torch::Tensor &weight);
/// Get the global (average) effective rank /// Get the global (average) effective rank
float get_global_rank() const; float get_global_rank() const;
/// Reset all tracked layers /// Reset all tracked layers
void reset(); void reset();
private: private:
std::unordered_map<std::string, float> layer_ranks_; std::unordered_map<std::string, float> layer_ranks_;
/// Compute effective rank via SVD /// Compute effective rank via SVD
static float compute_effective_rank(const torch::Tensor& weight); static float compute_effective_rank(const torch::Tensor &weight);
}; };
/** /**
@@ -47,8 +47,8 @@ private:
*/ */
class SpectralController { class SpectralController {
public: public:
/// Compute the spectral alpha (gating factor for rank-aware updates) /// Compute the spectral alpha (gating factor for rank-aware updates)
float compute_alpha(float global_rank, float grokking_coefficient) const; float compute_alpha(float global_rank, float grokking_coefficient) const;
}; };
} // namespace fces } // namespace fces

View File

@@ -11,16 +11,16 @@ namespace fces {
class Telemetry { class Telemetry {
public: public:
static Telemetry& get(); static Telemetry &get();
void info(const std::string& event, const std::string& detail = ""); void info(const std::string &event, const std::string &detail = "");
void warning(const std::string& event, const std::string& detail = ""); void warning(const std::string &event, const std::string &detail = "");
void error(const std::string& event, const std::string& detail = ""); void error(const std::string &event, const std::string &detail = "");
void push_to_remote(); void push_to_remote();
private: private:
Telemetry() = default; Telemetry() = default;
}; };
} // namespace fces } // namespace fces

View File

@@ -13,39 +13,40 @@
#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;
PYBIND11_MODULE(fces_native, m) { PYBIND11_MODULE(fces_native, m) {
m.doc() = "FCES-native: High-performance C++ FCES optimizer"; m.doc() = "FCES-native: High-performance C++ FCES optimizer";
py::class_<fces::FCESConfig>(m, "FCESConfig") py::class_<fces::FCESConfig>(m, "FCESConfig")
.def(py::init<>()) .def(py::init<>())
.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) .def("restore_from_ram", &fces::FCESOptimizer::restore_from_ram)
.def("restore_from_ram", &fces::FCESOptimizer::restore_from_ram) .def("step_count", &fces::FCESOptimizer::step_count)
.def("step_count", &fces::FCESOptimizer::step_count) .def("calculate_sparsity", &fces::FCESOptimizer::calculate_sparsity)
.def("calculate_sparsity", &fces::FCESOptimizer::calculate_sparsity) .def("zero_grad", [](fces::FCESOptimizer &self) {
.def("zero_grad", [](fces::FCESOptimizer& self) { for (auto &group : self.param_groups()) {
for (auto& group : self.param_groups()) { for (auto &p : group.params()) {
for (auto& p : group.params()) { if (p.grad().defined()) {
if (p.grad().defined()) { p.grad().zero_();
p.grad().zero_();
}
}
} }
}); }
}
});
} }

View File

@@ -13,341 +13,354 @@ thread_local std::mt19937 FuzzyController::rng_{std::random_device{}()};
// Genome // Genome
// --------------------------------------------------------------- // ---------------------------------------------------------------
void Genome::randomize(std::mt19937& rng) { void Genome::randomize(std::mt19937 &rng) {
std::normal_distribution<float> dist(0.0f, 0.5f); std::normal_distribution<float> dist(0.0f, 0.5f);
for (auto& w : weights) { for (auto &w : weights) {
w = dist(rng); w = dist(rng);
} }
gene_success.fill(0.0f); gene_success.fill(0.0f);
} }
Genome Genome::clone() const { Genome Genome::clone() const {
return *this; // Copy all fields return *this; // Copy all fields
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
// 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
// Set output biases (last GENOME_OUTPUT_DIM elements) to +2.0, -1.0, 0.0 with noise // 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_);
genome.weights[bias_start + 1] = -1.0f + bias_noise(rng_); genome.weights[bias_start + 1] = -1.0f + bias_noise(rng_);
genome.weights[bias_start + 2] = 0.0f + bias_noise(rng_); genome.weights[bias_start + 2] = 0.0f + bias_noise(rng_);
// Initialize plasticity with variance to seed evolution // Initialize plasticity with variance to seed evolution
std::normal_distribution<float> plast_noise(0.0f, 0.05f); std::normal_distribution<float> plast_noise(0.0f, 0.05f);
genome.plasticity = std::max(0.01f, 0.1f + plast_noise(rng_)); genome.plasticity = std::max(0.01f, 0.1f + plast_noise(rng_));
genome.sigma_gene = 0.1f; genome.sigma_gene = 0.1f;
genome.gene_success.fill(1.0f); genome.gene_success.fill(1.0f);
} }
FuzzyController::FuzzyController(Genome genome) 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, const int num_groups = static_cast<int>(layer_stats.size());
float spectral_alpha, auto actions = torch::zeros({num_groups, GENOME_OUTPUT_DIM});
float stagnation_intensity,
float kzm_damping,
float projected_drift
) {
const int num_groups = static_cast<int>(layer_stats.size());
auto actions = torch::zeros({num_groups, GENOME_OUTPUT_DIM});
// Extract weight views for the micro-MLP // Extract weight views for the micro-MLP
const float* w = genome.weights.data(); const float *w = genome.weights.data();
// 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 =
int type_idx = std::min(5, static_cast<int>(layer_type_val)); (layer_stats[g].size() >= 3) ? layer_stats[g][2] : 5.0f;
std::array<float, 5> type_onehot{0.0f, 0.0f, 0.0f, 0.0f, 0.0f}; int type_idx = std::min(5, static_cast<int>(layer_type_val));
if (type_idx >= 0 && type_idx < 5) { std::array<float, 5> type_onehot{0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
type_onehot[type_idx] = 1.0f; if (type_idx >= 0 && type_idx < 5) {
} type_onehot[type_idx] = 1.0f;
// Build input vector
std::array<float, GENOME_INPUT_DIM> input{};
float gn = (layer_stats[g].size() >= 1) ? layer_stats[g][0] : 0.0f;
float sp = (layer_stats[g].size() >= 2) ? layer_stats[g][1] : 0.0f;
// Sanitization matching nan_to_num
if (!std::isfinite(gn) || std::isnan(gn)) 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 (sp > 1.0f) sp = 1.0f;
if (sp < 0.0f) sp = 0.0f;
input[0] = gn;
input[1] = sp;
input[2] = loss_trend;
input[3] = step_pct;
input[4] = (num_groups > 1) ? static_cast<float>(g) / (num_groups - 1.0f) : 0.0f;
input[5] = rollback_rate;
input[6] = grad_stability;
input[7] = spectral_alpha;
input[8] = type_onehot[0];
input[9] = type_onehot[1];
input[10] = type_onehot[2];
input[11] = type_onehot[3];
input[12] = type_onehot[4];
input[13] = projected_drift;
// Forward pass: hidden = tanh(W1 * [input, 1])
std::array<float, GENOME_HIDDEN_DIM> hidden{};
for (int h = 0; h < GENOME_HIDDEN_DIM; ++h) {
float sum = W1[GENOME_INPUT_DIM * GENOME_HIDDEN_DIM + h]; // Bias weight
for (int i = 0; i < GENOME_INPUT_DIM; ++i) {
sum += input[i] * W1[i * GENOME_HIDDEN_DIM + h];
}
hidden[h] = std::tanh(sum);
}
// Output = W2 * [hidden, 1]
std::array<float, GENOME_OUTPUT_DIM> out_layer{};
for (int o = 0; o < GENOME_OUTPUT_DIM; ++o) {
float sum = W2[GENOME_HIDDEN_DIM * GENOME_OUTPUT_DIM + o]; // Bias weight
for (int h = 0; h < GENOME_HIDDEN_DIM; ++h) {
sum += hidden[h] * W2[h * GENOME_OUTPUT_DIM + o];
}
out_layer[o] = sum;
}
// Parse Output
float log_mult_raw = out_layer[0];
float log_wd_raw = out_layer[2];
float sign_logit = out_layer[1];
if (!std::isfinite(sign_logit) || std::isnan(sign_logit)) {
sign_logit = 0.0f;
}
float noise_std = 0.0f;
if (genome.plasticity > 0.01f) {
noise_std += genome.plasticity;
}
if (stagnation_intensity > 0.0f) {
noise_std += stagnation_intensity * 0.5f;
}
if (kzm_damping > 0.0f) {
noise_std *= (1.0f - kzm_damping);
log_mult_raw *= (1.0f - kzm_damping);
}
if (noise_std > 0.0f) {
std::normal_distribution<float> noise_dist(0.0f, noise_std);
log_mult_raw += noise_dist(rng_);
log_wd_raw += noise_dist(rng_);
}
if (!std::isfinite(log_mult_raw) || std::isnan(log_mult_raw)) {
log_mult_raw = 0.0f;
}
log_mult_raw = std::max(-6.0f, std::min(6.0f, log_mult_raw));
float mult = std::pow(2.0f, log_mult_raw);
if (!std::isfinite(log_wd_raw) || std::isnan(log_wd_raw)) {
log_wd_raw = 0.0f;
}
log_wd_raw = std::max(-6.0f, std::min(6.0f, log_wd_raw));
float wd_mult = std::pow(2.0f, log_wd_raw);
actions[g][0] = mult;
actions[g][1] = sign_logit;
actions[g][2] = wd_mult;
} }
return actions; // Build input vector
std::array<float, GENOME_INPUT_DIM> input{};
float gn = (layer_stats[g].size() >= 1) ? layer_stats[g][0] : 0.0f;
float sp = (layer_stats[g].size() >= 2) ? layer_stats[g][1] : 0.0f;
// Sanitization matching nan_to_num
if (!std::isfinite(gn) || std::isnan(gn))
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 (sp > 1.0f)
sp = 1.0f;
if (sp < 0.0f)
sp = 0.0f;
input[0] = gn;
input[1] = sp;
input[2] = loss_trend;
input[3] = step_pct;
input[4] =
(num_groups > 1) ? static_cast<float>(g) / (num_groups - 1.0f) : 0.0f;
input[5] = rollback_rate;
input[6] = grad_stability;
input[7] = spectral_alpha;
input[8] = type_onehot[0];
input[9] = type_onehot[1];
input[10] = type_onehot[2];
input[11] = type_onehot[3];
input[12] = type_onehot[4];
input[13] = projected_drift;
// Forward pass: hidden = tanh(W1 * [input, 1])
std::array<float, GENOME_HIDDEN_DIM> hidden{};
for (int h = 0; h < GENOME_HIDDEN_DIM; ++h) {
float sum = W1[GENOME_INPUT_DIM * GENOME_HIDDEN_DIM + h]; // Bias weight
for (int i = 0; i < GENOME_INPUT_DIM; ++i) {
sum += input[i] * W1[i * GENOME_HIDDEN_DIM + h];
}
hidden[h] = std::tanh(sum);
}
// Output = W2 * [hidden, 1]
std::array<float, GENOME_OUTPUT_DIM> out_layer{};
for (int o = 0; o < GENOME_OUTPUT_DIM; ++o) {
float sum = W2[GENOME_HIDDEN_DIM * GENOME_OUTPUT_DIM + o]; // Bias weight
for (int h = 0; h < GENOME_HIDDEN_DIM; ++h) {
sum += hidden[h] * W2[h * GENOME_OUTPUT_DIM + o];
}
out_layer[o] = sum;
}
// Parse Output
float log_mult_raw = out_layer[0];
float log_wd_raw = out_layer[2];
float sign_logit = out_layer[1];
if (!std::isfinite(sign_logit) || std::isnan(sign_logit)) {
sign_logit = 0.0f;
}
float noise_std = 0.0f;
if (genome.plasticity > 0.01f) {
noise_std += genome.plasticity;
}
if (stagnation_intensity > 0.0f) {
noise_std += stagnation_intensity * 0.5f;
}
if (kzm_damping > 0.0f) {
noise_std *= (1.0f - kzm_damping);
log_mult_raw *= (1.0f - kzm_damping);
}
if (noise_std > 0.0f) {
std::normal_distribution<float> noise_dist(0.0f, noise_std);
log_mult_raw += noise_dist(rng_);
log_wd_raw += noise_dist(rng_);
}
if (!std::isfinite(log_mult_raw) || std::isnan(log_mult_raw)) {
log_mult_raw = 0.0f;
}
log_mult_raw = std::max(-6.0f, std::min(6.0f, log_mult_raw));
float mult = std::pow(2.0f, log_mult_raw);
if (!std::isfinite(log_wd_raw) || std::isnan(log_wd_raw)) {
log_wd_raw = 0.0f;
}
log_wd_raw = std::max(-6.0f, std::min(6.0f, log_wd_raw));
float wd_mult = std::pow(2.0f, log_wd_raw);
actions[g][0] = mult;
actions[g][1] = sign_logit;
actions[g][2] = wd_mult;
}
return actions;
} }
FuzzyController FuzzyController::mutate(float current_loss, float sigma_scale) const { FuzzyController FuzzyController::mutate(float current_loss,
Genome child_genome = genome.clone(); float sigma_scale) const {
std::normal_distribution<float> std_normal(0.0f, 1.0f); Genome child_genome = genome.clone();
std::normal_distribution<float> std_normal(0.0f, 1.0f);
float tau = 0.2f; float tau = 0.2f;
float new_sigma = genome.sigma_gene * std::exp(tau * std_normal(rng_)); float new_sigma = genome.sigma_gene * std::exp(tau * std_normal(rng_));
new_sigma = std::max(0.001f, std::min(0.8f, new_sigma)); new_sigma = std::max(0.001f, std::min(0.8f, new_sigma));
float new_plast = genome.plasticity * std::exp(tau * std_normal(rng_)); float new_plast = genome.plasticity * std::exp(tau * std_normal(rng_));
new_plast = std::max(0.0f, std::min(0.5f, new_plast)); new_plast = std::max(0.0f, std::min(0.5f, new_plast));
float loss_val = std::max(0.0f, current_loss); float loss_val = std::max(0.0f, current_loss);
float annealing_factor = std::sqrt(loss_val + 0.1f); float annealing_factor = std::sqrt(loss_val + 0.1f);
float effective_sigma = new_sigma * sigma_scale * annealing_factor; float effective_sigma = new_sigma * sigma_scale * annealing_factor;
std::normal_distribution<float> noise(0.0f, effective_sigma); std::normal_distribution<float> noise(0.0f, effective_sigma);
for (size_t i = 0; i < child_genome.weights.size(); ++i) { for (size_t i = 0; i < child_genome.weights.size(); ++i) {
child_genome.weights[i] += noise(rng_); child_genome.weights[i] += noise(rng_);
child_genome.gene_success[i] = genome.gene_success[i] * 0.95f; child_genome.gene_success[i] = genome.gene_success[i] * 0.95f;
} }
child_genome.sigma_gene = new_sigma; child_genome.sigma_gene = new_sigma;
child_genome.plasticity = new_plast; child_genome.plasticity = new_plast;
FuzzyController child(child_genome); FuzzyController child(child_genome);
child.origin = "mutation"; child.origin = "mutation";
return child; return child;
} }
FuzzyController FuzzyController::crossover(const FuzzyController& partner, bool /*use_alignment*/) const { FuzzyController FuzzyController::crossover(const FuzzyController &partner,
Genome child_genome; bool /*use_alignment*/) const {
std::uniform_real_distribution<float> u_dist(0.0f, 1.0f); Genome child_genome;
std::uniform_real_distribution<float> u_dist(0.0f, 1.0f);
for (size_t i = 0; i < child_genome.weights.size(); ++i) { for (size_t i = 0; i < child_genome.weights.size(); ++i) {
float success_self = genome.gene_success[i]; float success_self = genome.gene_success[i];
float success_partner = partner.genome.gene_success[i]; float success_partner = partner.genome.gene_success[i];
float prob_a = success_self / (success_self + success_partner + 1e-9f); float prob_a = success_self / (success_self + success_partner + 1e-9f);
bool choose_self = false; bool choose_self = false;
if (u_dist(rng_) < 0.1f) { if (u_dist(rng_) < 0.1f) {
// 10% Random injection // 10% Random injection
choose_self = (u_dist(rng_) < 0.5f); choose_self = (u_dist(rng_) < 0.5f);
} else { } else {
// 90% Meritocratic // 90% Meritocratic
choose_self = (u_dist(rng_) < prob_a); choose_self = (u_dist(rng_) < prob_a);
}
if (choose_self) {
child_genome.weights[i] = genome.weights[i];
child_genome.gene_success[i] = success_self;
} else {
child_genome.weights[i] = partner.genome.weights[i];
child_genome.gene_success[i] = success_partner;
}
} }
child_genome.sigma_gene = (genome.sigma_gene + partner.genome.sigma_gene) * 0.5f; if (choose_self) {
child_genome.plasticity = (genome.plasticity + partner.genome.plasticity) * 0.5f; child_genome.weights[i] = genome.weights[i];
child_genome.gene_success[i] = success_self;
} else {
child_genome.weights[i] = partner.genome.weights[i];
child_genome.gene_success[i] = success_partner;
}
}
FuzzyController child(child_genome); child_genome.sigma_gene =
child.origin = "crossover"; (genome.sigma_gene + partner.genome.sigma_gene) * 0.5f;
return child; child_genome.plasticity =
(genome.plasticity + partner.genome.plasticity) * 0.5f;
FuzzyController child(child_genome);
child.origin = "crossover";
return child;
} }
FuzzyController FuzzyController::create_orthogonal_child(float intensity) const { FuzzyController
Genome child_genome; FuzzyController::create_orthogonal_child(float intensity) const {
std::normal_distribution<float> norm_dist(0.0f, 1.0f); Genome child_genome;
std::normal_distribution<float> norm_dist(0.0f, 1.0f);
float norm_elite = 0.0f; float norm_elite = 0.0f;
for (float w : genome.weights) { for (float w : genome.weights) {
norm_elite += w * w; norm_elite += w * w;
} }
norm_elite = std::sqrt(norm_elite) + 1e-9f; norm_elite = std::sqrt(norm_elite) + 1e-9f;
std::array<float, GENOME_SIZE> random_vec{}; std::array<float, GENOME_SIZE> random_vec{};
float dot_product = 0.0f; float dot_product = 0.0f;
for (size_t i = 0; i < GENOME_SIZE; ++i) {
random_vec[i] = norm_dist(rng_);
dot_product += random_vec[i] * genome.weights[i];
}
std::array<float, GENOME_SIZE> orthogonal_vec{};
float norm_ortho = 0.0f;
for (size_t i = 0; i < GENOME_SIZE; ++i) {
float projection =
(dot_product / (norm_elite * norm_elite)) * genome.weights[i];
orthogonal_vec[i] = random_vec[i] - projection;
norm_ortho += orthogonal_vec[i] * orthogonal_vec[i];
}
norm_ortho = std::sqrt(norm_ortho) + 1e-9f;
std::array<float, GENOME_SIZE> scaled_vec{};
float final_norm = 0.0f;
for (size_t i = 0; i < GENOME_SIZE; ++i) {
scaled_vec[i] = orthogonal_vec[i] * (norm_elite / norm_ortho) * intensity;
final_norm += scaled_vec[i] * scaled_vec[i];
}
final_norm = std::sqrt(final_norm);
float max_allowed = std::max(norm_elite, 10.0f);
if (final_norm > max_allowed) {
float scale = max_allowed / (final_norm + 1e-9f);
for (size_t i = 0; i < GENOME_SIZE; ++i) { for (size_t i = 0; i < GENOME_SIZE; ++i) {
random_vec[i] = norm_dist(rng_); scaled_vec[i] *= scale;
dot_product += random_vec[i] * genome.weights[i];
} }
}
std::array<float, GENOME_SIZE> orthogonal_vec{}; child_genome.weights = scaled_vec;
float norm_ortho = 0.0f; child_genome.gene_success.fill(1.0f);
for (size_t i = 0; i < GENOME_SIZE; ++i) { child_genome.sigma_gene = 0.2f;
float projection = (dot_product / (norm_elite * norm_elite)) * genome.weights[i]; child_genome.plasticity = 0.2f;
orthogonal_vec[i] = random_vec[i] - projection;
norm_ortho += orthogonal_vec[i] * orthogonal_vec[i];
}
norm_ortho = std::sqrt(norm_ortho) + 1e-9f;
std::array<float, GENOME_SIZE> scaled_vec{}; FuzzyController child(child_genome);
float final_norm = 0.0f; child.origin = "phoenix_rebirth";
for (size_t i = 0; i < GENOME_SIZE; ++i) { return child;
scaled_vec[i] = orthogonal_vec[i] * (norm_elite / norm_ortho) * intensity;
final_norm += scaled_vec[i] * scaled_vec[i];
}
final_norm = std::sqrt(final_norm);
float max_allowed = std::max(norm_elite, 10.0f);
if (final_norm > max_allowed) {
float scale = max_allowed / (final_norm + 1e-9f);
for (size_t i = 0; i < GENOME_SIZE; ++i) {
scaled_vec[i] *= scale;
}
}
child_genome.weights = scaled_vec;
child_genome.gene_success.fill(1.0f);
child_genome.sigma_gene = 0.2f;
child_genome.plasticity = 0.2f;
FuzzyController child(child_genome);
child.origin = "phoenix_rebirth";
return child;
} }
std::pair<FuzzyController, FuzzyController> FuzzyController::banach_tarski_fission(float intensity) const { std::pair<FuzzyController, FuzzyController>
Genome plus_genome; FuzzyController::banach_tarski_fission(float intensity) const {
Genome minus_genome; Genome plus_genome;
Genome minus_genome;
float norm_parent = 0.0f; float norm_parent = 0.0f;
float max_success = 0.0f; float max_success = 0.0f;
for (size_t i = 0; i < GENOME_SIZE; ++i) { for (size_t i = 0; i < GENOME_SIZE; ++i) {
norm_parent += genome.weights[i] * genome.weights[i]; norm_parent += genome.weights[i] * genome.weights[i];
if (genome.gene_success[i] > max_success) { if (genome.gene_success[i] > max_success) {
max_success = genome.gene_success[i]; max_success = genome.gene_success[i];
}
} }
norm_parent = std::sqrt(norm_parent) + 1e-9f; }
max_success += 1e-9f; norm_parent = std::sqrt(norm_parent) + 1e-9f;
max_success += 1e-9f;
std::normal_distribution<float> norm_dist(0.0f, 1.0f); std::normal_distribution<float> norm_dist(0.0f, 1.0f);
std::array<float, GENOME_SIZE> noise{}; std::array<float, GENOME_SIZE> noise{};
float dot_product = 0.0f; float dot_product = 0.0f;
for (size_t i = 0; i < GENOME_SIZE; ++i) { for (size_t i = 0; i < GENOME_SIZE; ++i) {
float saliency = genome.gene_success[i] / max_success; float saliency = genome.gene_success[i] / max_success;
noise[i] = norm_dist(rng_) * saliency; noise[i] = norm_dist(rng_) * saliency;
dot_product += noise[i] * genome.weights[i]; dot_product += noise[i] * genome.weights[i];
} }
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)) *
norm_fission += fission_vec[i] * fission_vec[i]; genome.weights[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 =
plus_genome.weights[i] = genome.weights[i] + scaled_fission; fission_vec[i] * (norm_parent / norm_fission) * 0.1f * intensity;
minus_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;
plus_genome.gene_success[i] = 1.0f; plus_genome.gene_success[i] = 1.0f;
minus_genome.gene_success[i] = 1.0f; minus_genome.gene_success[i] = 1.0f;
} }
plus_genome.sigma_gene = genome.sigma_gene * 0.9f; plus_genome.sigma_gene = genome.sigma_gene * 0.9f;
minus_genome.sigma_gene = genome.sigma_gene * 0.9f; minus_genome.sigma_gene = genome.sigma_gene * 0.9f;
plus_genome.plasticity = genome.plasticity; plus_genome.plasticity = genome.plasticity;
minus_genome.plasticity = genome.plasticity; minus_genome.plasticity = genome.plasticity;
FuzzyController child_plus(plus_genome); FuzzyController child_plus(plus_genome);
child_plus.origin = "fission_plus"; child_plus.origin = "fission_plus";
FuzzyController child_minus(minus_genome); FuzzyController child_minus(minus_genome);
child_minus.origin = "fission_minus"; child_minus.origin = "fission_minus";
return {child_plus, child_minus}; return {child_plus, child_minus};
} }
} // namespace fces } // namespace fces

View File

@@ -2,51 +2,46 @@
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) {}
FuzzyController& EvolutionManager::get_active_controller() { 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,
float progress = static_cast<float>(step_counter) / std::max(1, total_steps); int 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) {
); return;
}
int current_pop = population_.size();
float adaptive_threshold = 0.05f * (1.0f + ema_loss);
adaptive_threshold = std::min(0.5f, adaptive_threshold);
if (std::abs(loss_velocity) < adaptive_threshold) {
int target_pop = 200;
if (target_pop > current_pop) {
population_.resize(target_pop, progress);
} }
} else {
if (!auto_population_ || step_counter % 50 != 0) { int target_pop = 40;
return; if (target_pop < current_pop) {
} population_.resize(target_pop, progress);
int current_pop = population_.size();
float adaptive_threshold = 0.05f * (1.0f + ema_loss);
adaptive_threshold = std::min(0.5f, adaptive_threshold);
if (std::abs(loss_velocity) < adaptive_threshold) {
int target_pop = 200;
if (target_pop > current_pop) {
population_.resize(target_pop, progress);
}
} else {
int target_pop = 40;
if (target_pop < current_pop) {
population_.resize(target_pop, progress);
}
} }
}
} }
} // namespace fces } // namespace fces

View File

@@ -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 {
@@ -11,28 +11,30 @@ namespace fces {
// --------------------------------------------------------------- // ---------------------------------------------------------------
void RunningStats::update(float value) { void RunningStats::update(float value) {
count_++; count_++;
float delta = value - mean_; float delta = value - mean_;
mean_ += delta / static_cast<float>(count_); mean_ += delta / static_cast<float>(count_);
float delta2 = value - mean_; float delta2 = value - mean_;
m2_ += delta * delta2; m2_ += delta * delta2;
} }
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 (value - mean_) / s; return 0.0f;
return (value - mean_) / s;
} }
float RunningStats::get_std() const { float RunningStats::get_std() const {
if (count_ < 2) return 1.0f; if (count_ < 2)
return std::sqrt(m2_ / static_cast<float>(count_ - 1)); return 1.0f;
return std::sqrt(m2_ / static_cast<float>(count_ - 1));
} }
void RunningStats::reset() { void RunningStats::reset() {
count_ = 0; count_ = 0;
mean_ = 0.0f; mean_ = 0.0f;
m2_ = 0.0f; m2_ = 0.0f;
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -42,18 +44,20 @@ 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);
} }
return current_loss - ema_loss; return current_loss - ema_loss;
} }
float FitnessEngine::compute_kzm_damping(float spectral_alpha) const { float FitnessEngine::compute_kzm_damping(float spectral_alpha) const {
// Kibble-Zurek damping: high spectral rank = more damping // Kibble-Zurek damping: high spectral rank = more damping
return 1.0f / (1.0f + grokking_coefficient_ * spectral_alpha); return 1.0f / (1.0f + grokking_coefficient_ * spectral_alpha);
} }
// --------------------------------------------------------------- // ---------------------------------------------------------------
@@ -68,30 +72,28 @@ 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(
float m_stability = stability_set_.membership(metrics.grad_cv); const FitnessMetrics &metrics) const noexcept {
float m_train = train_set_.membership(metrics.training_advantage); float m_stability = stability_set_.membership(metrics.grad_cv);
float m_val = val_set_.membership(metrics.validation_advantage); float m_train = train_set_.membership(metrics.training_advantage);
float m_sparsity = sparsity_set_.membership(metrics.sparsity_delta); float m_val = val_set_.membership(metrics.validation_advantage);
float m_consistency = consistency_set_.membership(metrics.consistency_gap); float m_sparsity = sparsity_set_.membership(metrics.sparsity_delta);
float m_rank = rank_set_.membership(metrics.stable_rank); float m_consistency = consistency_set_.membership(metrics.consistency_gap);
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 =
if (total_weight > 0.0f) { w_stability_ + w_train_ + w_val_ + w_sparsity_ + w_consistency_ + w_rank_;
weighted_score /= total_weight; if (total_weight > 0.0f) {
} weighted_score /= total_weight;
}
// V153: Generalization-Aware Gate (Non-Linear) // V153: Generalization-Aware Gate (Non-Linear)
float gate_efficiency = 0.5f + 0.5f * m_consistency; float gate_efficiency = 0.5f + 0.5f * m_consistency;
return weighted_score * gate_efficiency; return weighted_score * gate_efficiency;
} }
} // namespace fces } // namespace fces

View File

@@ -1,475 +1,496 @@
#include "fces/optimizer.hpp" #include "fces/optimizer.hpp"
#include <algorithm>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include <algorithm>
namespace fces { namespace fces {
namespace { namespace {
int classify_layer_by_shape(const torch::Tensor& p) { int classify_layer_by_shape(const torch::Tensor &p) {
auto dims = p.sizes(); auto dims = p.sizes();
if (dims.size() == 2) { if (dims.size() == 2) {
int64_t d0 = dims[0]; int64_t d0 = dims[0];
int64_t d1 = dims[1]; int64_t d1 = dims[1];
if (d0 > 10000 || d1 > 10000) { if (d0 > 10000 || d1 > 10000) {
return 0; // Embedding return 0; // Embedding
} else if (d0 * 3 == d1 || d0 == d1 * 3) { } else if (d0 * 3 == d1 || d0 == d1 * 3) {
return 1; // Attention QKV return 1; // Attention QKV
} else if (d0 == d1) { } else if (d0 == d1) {
return 3; // MLP/FFN return 3; // MLP/FFN
} else { } else {
return 2; // Attention Proj return 2; // Attention Proj
}
} else if (dims.size() == 1) {
if (dims[0] < 128) {
return 4; // LayerNorm
} else {
return 5; // Other / bias
}
} }
return 5; // Other } else if (dims.size() == 1) {
if (dims[0] < 128) {
return 4; // LayerNorm
} else {
return 5; // Other / bias
}
}
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) {
return torch::zeros_like(update); if (torch::isnan(update).any().item<bool>() ||
torch::isinf(update).any().item<bool>()) {
return torch::zeros_like(update);
}
float p_norm = p.norm().item<float>();
if (p_norm > 1e-6f) {
float update_mag = update.norm().item<float>();
if (!std::isfinite(update_mag)) {
return torch::zeros_like(update);
} }
float p_norm = p.norm().item<float>(); float max_update = trust_region_clip * p_norm;
if (p_norm > 1e-6f) { if (update_mag > max_update) {
float update_mag = update.norm().item<float>(); float correction = max_update / (update_mag + 1e-8f);
if (!std::isfinite(update_mag)) { update.mul_(correction);
return torch::zeros_like(update);
}
float max_update = trust_region_clip * p_norm;
if (update_mag > max_update) {
float correction = max_update / (update_mag + 1e-8f);
update.mul_(correction);
}
} }
}
if (torch::isnan(update).any().item<bool>() || torch::isinf(update).any().item<bool>()) { if (torch::isnan(update).any().item<bool>() ||
return torch::zeros_like(update); torch::isinf(update).any().item<bool>()) {
} 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,
if (!p.grad().defined()) { const RunningStats &grad_norm_tracker) {
return 0.0f; if (!p.grad().defined()) {
} return 0.0f;
float g_norm = p.grad().abs().mean().item<float>(); }
float z_g = grad_norm_tracker.z_score(g_norm); float g_norm = p.grad().abs().mean().item<float>();
return z_g * (mult - 1.0f); float z_g = grad_norm_tracker.z_score(g_norm);
return z_g * (mult - 1.0f);
} }
std::unique_ptr<torch::optim::OptimizerOptions> make_optimizer_options(double lr) { std::unique_ptr<torch::optim::OptimizerOptions>
return std::make_unique<FCESOptimizerOptions>(lr); make_optimizer_options(double 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>();
// Initial RAM backup // Initial RAM backup
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) {
torch::NoGradGuard no_grad; torch::NoGradGuard no_grad;
step_counter_++; step_counter_++;
torch::Tensor loss = {}; torch::Tensor loss = {};
if (closure) { if (closure) {
torch::AutoGradMode grad_mode(true); torch::AutoGradMode grad_mode(true);
loss = closure(); loss = closure();
} }
// 1. Gather Statistics // 1. Gather Statistics
gather_stats(); gather_stats();
// 2. Strategy: Population Selection & Dynamics // 2. Strategy: Population Selection & Dynamics
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
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_));
handle_rollback();
return loss;
}
float loss_velocity = fitness_engine_.calculate_loss_signal(current_loss_val, ema_loss_, config_.signal_mode);
last_loss_velocity_ = loss_velocity;
float progress = std::min(1.0f, static_cast<float>(step_counter_) / 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;
if (config_.csr_enabled) {
if (step_counter_ < config_.csr_warmup_steps) {
csr_factor = 0.0f;
} else {
float steps_since_warmup = 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
float spectral_alpha = 0.0f;
if (config_.grokking_coefficient > 0.0f && spectral_sensor_) {
if (step_counter_ % config_.spectral_frequency == 0 || last_spectral_rank_ == 0.0f) {
int param_idx = 0;
for (auto& group : param_groups()) {
for (auto& p : group.params()) {
if (p.dim() >= 2) {
std::string name = "layer_" + std::to_string(param_idx);
spectral_sensor_->track_layer(name, p);
}
param_idx++;
}
}
last_spectral_rank_ = spectral_sensor_->get_global_rank();
}
spectral_alpha = last_spectral_rank_;
}
float effective_alpha = spectral_alpha * csr_factor;
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 log_spectral_alpha = std::log(effective_alpha + 1e-6f);
// Call decide_update
auto actions = active_controller.decide_update(
layer_stats_,
loss_velocity,
progress,
rollback_ema_,
grad_cv,
log_spectral_alpha,
stagnation_intensity,
kzm_damping,
loss_velocity
);
// Bandit-style Early Stopping
if (step_counter_ % 5 == 0 && loss_velocity > 0.05f) {
Telemetry::get().warning("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;
}
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));
population_.kill(active_controller);
auto& new_controller = evolution_manager_->get_active_controller();
actions = torch::zeros_like(actions);
for (int i = 0; i < actions.size(0); ++i) {
actions[i][0] = 0.5f; // log_mult default
}
}
// 4. Action: Apply Updates
apply_parameter_updates(actions);
// 5. Evolution & Maintenance
if (current_loss_val > 0.0f) {
evolution_manager_->update_population_dynamics(
loss_velocity,
ema_loss_,
step_counter_,
config_.total_steps
);
}
if (step_counter_ % 50 == 0) {
backup_to_ram();
}
// Emergency Brake - NaN/Inf Detection
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_));
handle_rollback();
return loss; return loss;
}
float loss_velocity = fitness_engine_.calculate_loss_signal(
current_loss_val, ema_loss_, config_.signal_mode);
last_loss_velocity_ = loss_velocity;
float progress = std::min(1.0f, static_cast<float>(step_counter_) /
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;
if (config_.csr_enabled) {
if (step_counter_ < config_.csr_warmup_steps) {
csr_factor = 0.0f;
} else {
float steps_since_warmup =
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
float spectral_alpha = 0.0f;
if (config_.grokking_coefficient > 0.0f && spectral_sensor_) {
if (step_counter_ % config_.spectral_frequency == 0 ||
last_spectral_rank_ == 0.0f) {
int param_idx = 0;
for (auto &group : param_groups()) {
for (auto &p : group.params()) {
if (p.dim() >= 2) {
std::string name = "layer_" + std::to_string(param_idx);
spectral_sensor_->track_layer(name, p);
}
param_idx++;
}
}
last_spectral_rank_ = spectral_sensor_->get_global_rank();
}
spectral_alpha = last_spectral_rank_;
}
float effective_alpha = spectral_alpha * csr_factor;
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 log_spectral_alpha = std::log(effective_alpha + 1e-6f);
// Call decide_update
auto actions = active_controller.decide_update(
layer_stats_, loss_velocity, progress, rollback_ema_, grad_cv,
log_spectral_alpha, stagnation_intensity, kzm_damping, loss_velocity);
// Bandit-style Early Stopping
if (step_counter_ % 5 == 0 && loss_velocity > 0.05f) {
Telemetry::get().warning(
"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;
}
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));
population_.kill(active_controller);
auto &new_controller = evolution_manager_->get_active_controller();
actions = torch::zeros_like(actions);
for (int i = 0; i < actions.size(0); ++i) {
actions[i][0] = 0.5f; // log_mult default
}
}
// 4. Action: Apply Updates
apply_parameter_updates(actions);
// 5. Evolution & Maintenance
if (current_loss_val > 0.0f) {
evolution_manager_->update_population_dynamics(
loss_velocity, ema_loss_, step_counter_, config_.total_steps);
}
if (step_counter_ % 50 == 0) {
backup_to_ram();
}
return loss;
} }
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) &&
if (is_nan || is_spike) { (loss > config_.rollback_threshold * ema_loss_) &&
Telemetry::get().warning("divergence_detected", "loss=" + std::to_string(loss) + " ema=" + std::to_string(ema_loss_)); (ema_loss_ > 0.1f);
handle_rollback(); if (is_nan || is_spike) {
return; Telemetry::get().warning("divergence_detected",
} "loss=" + std::to_string(loss) +
" ema=" + std::to_string(ema_loss_));
handle_rollback();
return;
}
if (step_counter_ == 1 || ema_loss_ == 0.0f) { if (step_counter_ == 1 || ema_loss_ == 0.0f) {
ema_loss_ = loss; ema_loss_ = loss;
last_step_loss_ = loss;
last_sparsity_ = calculate_sparsity();
return;
}
// 2. Metric Calculation
float train_adv = ema_loss_ - loss;
float val_adv = 0.0f;
float current_sparsity = calculate_sparsity();
float sparsity_delta = current_sparsity - last_sparsity_;
float consistency_gap = std::max(0.0f, train_adv - val_adv);
float grad_std = grad_norm_tracker_.get_std();
float grad_mean = grad_norm_tracker_.get_mean();
float grad_cv = grad_std / (grad_mean + 1e-8f);
float raw_rank = (spectral_sensor_) ? spectral_sensor_->get_global_rank() : 0.0f;
float csr_factor = 1.0f;
if (config_.csr_enabled) {
if (step_counter_ < config_.csr_warmup_steps) {
csr_factor = 0.0f;
} else {
float steps_since_warmup = 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;
FitnessMetrics metrics;
metrics.training_advantage = train_adv;
metrics.validation_advantage = val_adv;
metrics.grad_cv = grad_cv;
metrics.sparsity_delta = sparsity_delta;
metrics.consistency_gap = consistency_gap;
metrics.stable_rank = effective_rank;
// 3. Fuzzy Evaluation
float final_fitness = fitness_evaluator_.evaluate(metrics);
// 4. State Update
ema_loss_ = 0.95f * ema_loss_ + 0.05f * loss;
last_step_loss_ = loss; last_step_loss_ = loss;
last_sparsity_ = current_sparsity; last_sparsity_ = calculate_sparsity();
return;
}
// Stagnation logic // 2. Metric Calculation
if (loss < best_loss_window_ * 0.995f) { float train_adv = ema_loss_ - loss;
best_loss_window_ = loss; float val_adv = 0.0f;
stagnation_counter_ = 0; float current_sparsity = calculate_sparsity();
float sparsity_delta = current_sparsity - last_sparsity_;
float consistency_gap = std::max(0.0f, train_adv - val_adv);
float grad_std = grad_norm_tracker_.get_std();
float grad_mean = grad_norm_tracker_.get_mean();
float grad_cv = grad_std / (grad_mean + 1e-8f);
float raw_rank =
(spectral_sensor_) ? spectral_sensor_->get_global_rank() : 0.0f;
float csr_factor = 1.0f;
if (config_.csr_enabled) {
if (step_counter_ < config_.csr_warmup_steps) {
csr_factor = 0.0f;
} else { } else {
stagnation_counter_++; float steps_since_warmup =
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;
// 5. Apply to Population FitnessMetrics metrics;
auto& active_controller = evolution_manager_->get_active_controller(); metrics.training_advantage = train_adv;
population_.update_controller_fitness(active_controller, final_fitness); metrics.validation_advantage = val_adv;
metrics.grad_cv = grad_cv;
metrics.sparsity_delta = sparsity_delta;
metrics.consistency_gap = consistency_gap;
metrics.stable_rank = effective_rank;
Telemetry::get().info("fitness_calculated", // 3. Fuzzy Evaluation
"loss=" + std::to_string(loss) + float final_fitness = fitness_evaluator_.evaluate(metrics);
" ema_loss=" + std::to_string(ema_loss_) +
" fitness=" + std::to_string(final_fitness)); // 4. State Update
ema_loss_ = 0.95f * ema_loss_ + 0.05f * loss;
last_step_loss_ = loss;
last_sparsity_ = current_sparsity;
// Stagnation logic
if (loss < best_loss_window_ * 0.995f) {
best_loss_window_ = loss;
stagnation_counter_ = 0;
} else {
stagnation_counter_++;
}
// 5. Apply to Population
auto &active_controller = evolution_manager_->get_active_controller();
population_.update_controller_fitness(active_controller, final_fitness);
Telemetry::get().info("fitness_calculated",
"loss=" + std::to_string(loss) +
" ema_loss=" + std::to_string(ema_loss_) +
" fitness=" + std::to_string(final_fitness));
} }
void FCESOptimizer::backup_to_ram() { void FCESOptimizer::backup_to_ram() {
ram_backup_.clear(); ram_backup_.clear();
for (auto& group : param_groups()) { for (auto &group : param_groups()) {
for (auto& p : group.params()) { for (auto &p : group.params()) {
ram_backup_.push_back(p.data().clone().cpu()); ram_backup_.push_back(p.data().clone().cpu());
}
} }
}
} }
void FCESOptimizer::restore_from_ram() { void FCESOptimizer::restore_from_ram() {
int idx = 0; int idx = 0;
for (auto& group : param_groups()) { for (auto &group : param_groups()) {
for (auto& p : group.params()) { for (auto &p : group.params()) {
if (idx < static_cast<int>(ram_backup_.size())) { if (idx < static_cast<int>(ram_backup_.size())) {
p.data().copy_(ram_backup_[idx].to(p.device())); p.data().copy_(ram_backup_[idx].to(p.device()));
idx++; idx++;
} }
}
} }
}
} }
float FCESOptimizer::calculate_sparsity() const { float FCESOptimizer::calculate_sparsity() const {
int64_t total = 0, zeros = 0; int64_t total = 0, zeros = 0;
for (const auto& group : param_groups()) { for (const auto &group : param_groups()) {
for (const auto& p : group.params()) { for (const auto &p : group.params()) {
total += p.numel(); total += p.numel();
zeros += (p.data().abs() < 1e-5f).sum().item<int64_t>(); zeros += (p.data().abs() < 1e-5f).sum().item<int64_t>();
}
} }
return (total > 0) ? static_cast<float>(zeros) / total : 0.0f; }
return (total > 0) ? static_cast<float>(zeros) / total : 0.0f;
} }
void FCESOptimizer::gather_stats() { void FCESOptimizer::gather_stats() {
layer_stats_.clear(); layer_stats_.clear();
param_group_mapping_.clear(); param_group_mapping_.clear();
int param_idx = 0; int param_idx = 0;
bool has_nan_or_inf = false; bool has_nan_or_inf = false;
float max_grad_norm = 0.0f; float max_grad_norm = 0.0f;
for (auto& group : param_groups()) { for (auto &group : param_groups()) {
for (auto& p : group.params()) { for (auto &p : group.params()) {
if (!p.grad().defined()) { if (!p.grad().defined()) {
param_group_mapping_.push_back(-1); param_group_mapping_.push_back(-1);
continue; continue;
} }
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>() ||
has_nan_or_inf = true; torch::isinf(grad).any().item<bool>()) {
} has_nan_or_inf = true;
}
float grad_norm = grad.norm().item<float>(); float grad_norm = grad.norm().item<float>();
if (std::isnan(grad_norm) || !std::isfinite(grad_norm)) { if (std::isnan(grad_norm) || !std::isfinite(grad_norm)) {
has_nan_or_inf = true; has_nan_or_inf = true;
grad_norm = 0.0f; grad_norm = 0.0f;
} }
if (grad_norm > max_grad_norm) { if (grad_norm > max_grad_norm) {
max_grad_norm = grad_norm; max_grad_norm = grad_norm;
} }
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(
param_group_mapping_.push_back(group_idx); {grad_norm, sparsity, static_cast<float>(layer_type)});
param_group_mapping_.push_back(group_idx);
if (spectral_sensor_ && p.dim() >= 2) { if (spectral_sensor_ && p.dim() >= 2) {
std::string name = "layer_" + std::to_string(param_idx); std::string name = "layer_" + std::to_string(param_idx);
spectral_sensor_->track_layer(name, p); spectral_sensor_->track_layer(name, p);
} }
param_idx++; param_idx++;
}
} }
}
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 " +
handle_rollback(); std::to_string(step_counter_));
return; handle_rollback();
} return;
}
if (step_counter_ == 1 && max_grad_norm > 1.0f) { if (step_counter_ == 1 && max_grad_norm > 1.0f) {
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",
group.options().set_lr(safe_lr); "old=" + std::to_string(group.options().get_lr()) +
config_.lr = safe_lr; " new=" + std::to_string(safe_lr));
} group.options().set_lr(safe_lr);
} config_.lr = safe_lr;
}
} }
}
if (!layer_stats_.empty()) { if (!layer_stats_.empty()) {
float first_grad_norm = layer_stats_[0][0]; float first_grad_norm = layer_stats_[0][0];
grad_norm_tracker_.update(first_grad_norm); grad_norm_tracker_.update(first_grad_norm);
} }
} }
void FCESOptimizer::apply_parameter_updates(const torch::Tensor& actions) { void FCESOptimizer::apply_parameter_updates(const torch::Tensor &actions) {
int param_idx = 0; int param_idx = 0;
float parasitic_accum = 0.0f; float parasitic_accum = 0.0f;
int count_updated = 0; int count_updated = 0;
auto& active_controller = evolution_manager_->get_active_controller(); auto &active_controller = evolution_manager_->get_active_controller();
for (auto& group : param_groups()) { for (auto &group : param_groups()) {
float lr = static_cast<float>(group.options().get_lr()); float lr = static_cast<float>(group.options().get_lr());
float wd = config_.weight_decay; float wd = config_.weight_decay;
for (auto& p : group.params()) { for (auto &p : group.params()) {
if (!p.grad().defined()) { if (!p.grad().defined()) {
param_idx++; param_idx++;
continue; continue;
} }
int g_idx = param_group_mapping_[param_idx]; int g_idx = param_group_mapping_[param_idx];
if (g_idx < 0 || g_idx >= actions.size(0)) { if (g_idx < 0 || g_idx >= actions.size(0)) {
param_idx++; param_idx++;
continue; continue;
} }
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") {
use_sign = true; use_sign = true;
} else if (config_.ablation_mode == "force_grad") { } else if (config_.ablation_mode == "force_grad") {
use_sign = false; use_sign = false;
} }
if (wd > 0.0f) { if (wd > 0.0f) {
float effective_wd = wd; float effective_wd = wd;
if (config_.adaptive_wd) { if (config_.adaptive_wd) {
effective_wd *= wd_mult; effective_wd *= wd_mult;
}
p.data().mul_(1.0f - lr * effective_wd);
}
torch::Tensor update_vec = use_sign ? torch::sign(p.grad()) : p.grad();
torch::Tensor update = -lr * mult * update_vec;
update = apply_trust_clipping(p, update, config_.trust_region_clip);
p.data().add_(update);
if (config_.parasitic_mode) {
parasitic_accum += calculate_parasitic_reward(p, mult, grad_norm_tracker_);
}
param_idx++;
count_updated++;
} }
} p.data().mul_(1.0f - lr * effective_wd);
}
if (config_.parasitic_mode && count_updated > 0) { torch::Tensor update_vec = use_sign ? torch::sign(p.grad()) : p.grad();
float reward = parasitic_accum / static_cast<float>(count_updated); torch::Tensor update = -lr * mult * update_vec;
population_.update_controller_fitness(active_controller, reward * 10.0f, false);
update = apply_trust_clipping(p, update, config_.trust_region_clip);
p.data().add_(update);
if (config_.parasitic_mode) {
parasitic_accum +=
calculate_parasitic_reward(p, mult, grad_norm_tracker_);
}
param_idx++;
count_updated++;
} }
}
if (config_.parasitic_mode && count_updated > 0) {
float reward = parasitic_accum / static_cast<float>(count_updated);
population_.update_controller_fitness(active_controller, reward * 10.0f,
false);
}
} }
void FCESOptimizer::handle_rollback() { void FCESOptimizer::handle_rollback() {
restore_from_ram(); restore_from_ram();
population_.calm_down(); population_.calm_down();
rollback_ema_ = 0.9f * rollback_ema_ + 0.1f; rollback_ema_ = 0.9f * rollback_ema_ + 0.1f;
ema_loss_ = 0.0f; ema_loss_ = 0.0f;
last_step_loss_ = 0.0f; last_step_loss_ = 0.0f;
grad_norm_tracker_.reset(); grad_norm_tracker_.reset();
zero_grad(); zero_grad();
Telemetry::get().warning("hard_reset_executed", "rollback_sanitization"); Telemetry::get().warning("hard_reset_executed", "rollback_sanitization");
} }
} // namespace fces } // namespace fces

View File

@@ -1,97 +1,103 @@
#include "fces/oscillation.hpp" #include "fces/oscillation.hpp"
#include <algorithm>
#include <cmath> #include <cmath>
#include <numeric> #include <numeric>
#include <algorithm>
namespace fces { namespace fces {
void OscillationDetector::update(float loss) { void OscillationDetector::update(float loss) {
loss_history_.push_back(loss); loss_history_.push_back(loss);
if (static_cast<int>(loss_history_.size()) > WINDOW_SIZE) { if (static_cast<int>(loss_history_.size()) > WINDOW_SIZE) {
loss_history_.erase(loss_history_.begin()); loss_history_.erase(loss_history_.begin());
} }
} }
bool OscillationDetector::detect() const { bool OscillationDetector::detect() const {
return get_score() > POWER_THRESHOLD; return get_score() > POWER_THRESHOLD;
} }
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);
// Sum power in oscillation bands (periods 4-16) // Sum power in oscillation bands (periods 4-16)
float osc_power = 0.0f; float osc_power = 0.0f;
float total_power = 0.0f; float total_power = 0.0f;
int n = static_cast<int>(power.size()); int n = static_cast<int>(power.size());
for (int i = 1; i < n; ++i) { for (int i = 1; i < n; ++i) {
total_power += power[i]; total_power += power[i];
int period = n / i; int period = n / i;
if (period >= MIN_PERIOD && period <= MAX_PERIOD) { if (period >= MIN_PERIOD && period <= MAX_PERIOD) {
osc_power += power[i]; osc_power += power[i];
}
} }
}
if (total_power < 1e-8f) return 0.0f; if (total_power < 1e-8f)
return osc_power / total_power; return 0.0f;
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)
auto start = loss_history_.end() - 50; return 0.0f;
float mean = std::accumulate(start, loss_history_.end(), 0.0f) / 50.0f; auto start = loss_history_.end() - 50;
float var = 0.0f; float mean = std::accumulate(start, loss_history_.end(), 0.0f) / 50.0f;
for (auto it = start; it != loss_history_.end(); ++it) { float var = 0.0f;
float d = *it - mean; for (auto it = start; it != loss_history_.end(); ++it) {
var += d * d; float d = *it - mean;
} var += d * d;
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) {
int n = static_cast<int>(signal.size());
if (n < 2)
return signal;
// Remove linear trend via least squares
float sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0;
for (int i = 0; i < n; ++i) {
sum_x += i;
sum_y += signal[i];
sum_xy += i * signal[i];
sum_xx += i * i;
}
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;
std::vector<float> result(n);
for (int i = 0; i < n; ++i) {
result[i] = signal[i] - (slope * i + intercept);
}
return result;
} }
std::vector<float> OscillationDetector::detrend(const std::vector<float>& signal) { std::vector<float>
int n = static_cast<int>(signal.size()); OscillationDetector::compute_power_spectrum(const std::vector<float> &signal) {
if (n < 2) return signal; // Simple DFT (for WINDOW_SIZE=64, this is fast enough; upgrade to FFT if
// needed)
int n = static_cast<int>(signal.size());
int half = n / 2;
std::vector<float> power(half);
// Remove linear trend via least squares for (int k = 0; k < half; ++k) {
float sum_x = 0, sum_y = 0, sum_xy = 0, sum_xx = 0; float re = 0.0f, im = 0.0f;
for (int i = 0; i < n; ++i) { for (int t = 0; t < n; ++t) {
sum_x += i; float angle = 2.0f * 3.14159265358979f * k * t / n;
sum_y += signal[i]; re += signal[t] * std::cos(angle);
sum_xy += i * signal[i]; im -= signal[t] * std::sin(angle);
sum_xx += i * i;
} }
float slope = (n * sum_xy - sum_x * sum_y) / (n * sum_xx - sum_x * sum_x + 1e-8f); power[k] = re * re + im * im;
float intercept = (sum_y - slope * sum_x) / n; }
return power;
std::vector<float> result(n);
for (int i = 0; i < n; ++i) {
result[i] = signal[i] - (slope * i + intercept);
}
return result;
} }
std::vector<float> OscillationDetector::compute_power_spectrum(const std::vector<float>& signal) { } // namespace fces
// Simple DFT (for WINDOW_SIZE=64, this is fast enough; upgrade to FFT if needed)
int n = static_cast<int>(signal.size());
int half = n / 2;
std::vector<float> power(half);
for (int k = 0; k < half; ++k) {
float re = 0.0f, im = 0.0f;
for (int t = 0; t < n; ++t) {
float angle = 2.0f * 3.14159265358979f * k * t / n;
re += signal[t] * std::cos(angle);
im -= signal[t] * std::sin(angle);
}
power[k] = re * re + im * im;
}
return power;
}
} // namespace fces

File diff suppressed because it is too large Load Diff

View File

@@ -3,39 +3,40 @@
namespace fces { 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,
if (weight.dim() >= 2) { const torch::Tensor &weight) {
layer_ranks_[name] = compute_effective_rank(weight); if (weight.dim() >= 2) {
} 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())
float sum = 0.0f; return 0.0f;
for (const auto& [_, rank] : layer_ranks_) { float sum = 0.0f;
sum += rank; for (const auto &[_, rank] : layer_ranks_) {
} sum += rank;
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) {
// SVD-based effective rank (Shannon entropy of normalized singular values)
auto svd_result = torch::svd(weight.to(torch::kFloat32));
auto svd = std::get<1>(svd_result);
auto s = svd / svd.sum();
auto log_s = (s + 1e-10f).log();
float entropy = -s.mul(log_s).sum().item<float>();
return std::exp(entropy);
} }
float SpectralSensor::compute_effective_rank(const torch::Tensor& weight) { float SpectralController::compute_alpha(float global_rank,
// SVD-based effective rank (Shannon entropy of normalized singular values) float grokking_coefficient) const {
auto svd_result = torch::svd(weight.to(torch::kFloat32)); return global_rank * grokking_coefficient;
auto svd = std::get<1>(svd_result);
auto s = svd / svd.sum();
auto log_s = (s + 1e-10f).log();
float entropy = -s.mul(log_s).sum().item<float>();
return std::exp(entropy);
} }
float SpectralController::compute_alpha(float global_rank, float grokking_coefficient) const { } // namespace fces
return global_rank * grokking_coefficient;
}
} // namespace fces

View File

@@ -1,34 +1,37 @@
#include "fces/telemetry.hpp" #include "fces/telemetry.hpp"
#include <iostream>
#include <chrono> #include <chrono>
#include <iostream>
namespace fces { namespace fces {
Telemetry& Telemetry::get() { Telemetry &Telemetry::get() {
static Telemetry instance; static Telemetry instance;
return instance; return instance;
} }
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 << std::endl; std::cout << " | " << detail;
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 << std::endl; std::cerr << " | " << detail;
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 << std::endl; std::cerr << " | " << detail;
std::cerr << std::endl;
} }
void Telemetry::push_to_remote() { void Telemetry::push_to_remote() {
// TODO: Implement telemetry push (Git sync, file export, etc.) // TODO: Implement telemetry push (Git sync, file export, etc.)
} }
} // namespace fces } // namespace fces

View File

@@ -1,58 +1,59 @@
#include <gtest/gtest.h>
#include "fces/controller.hpp" #include "fces/controller.hpp"
#include <gtest/gtest.h>
using namespace fces; using namespace fces;
TEST(ControllerTest, Construction) { TEST(ControllerTest, Construction) {
FuzzyController ctrl; FuzzyController ctrl;
EXPECT_GT(ctrl.id, 0u); EXPECT_GT(ctrl.id, 0u);
EXPECT_EQ(ctrl.fitness, 0.0f); EXPECT_EQ(ctrl.fitness, 0.0f);
EXPECT_EQ(ctrl.origin, "random"); EXPECT_EQ(ctrl.origin, "random");
} }
TEST(ControllerTest, GenomeSize) { TEST(ControllerTest, GenomeSize) {
FuzzyController ctrl; FuzzyController ctrl;
EXPECT_EQ(ctrl.genome.weights.size(), static_cast<size_t>(GENOME_SIZE)); EXPECT_EQ(ctrl.genome.weights.size(), static_cast<size_t>(GENOME_SIZE));
} }
TEST(ControllerTest, Mutation) { TEST(ControllerTest, Mutation) {
FuzzyController parent; FuzzyController parent;
auto child = parent.mutate(1.0f); auto child = parent.mutate(1.0f);
EXPECT_NE(child.id, parent.id); EXPECT_NE(child.id, parent.id);
EXPECT_EQ(child.origin, "mutation"); EXPECT_EQ(child.origin, "mutation");
// Child should differ from parent // Child should differ from parent
bool differs = false; bool differs = false;
for (size_t i = 0; i < parent.genome.weights.size(); ++i) { for (size_t i = 0; i < parent.genome.weights.size(); ++i) {
if (parent.genome.weights[i] != child.genome.weights[i]) { if (parent.genome.weights[i] != child.genome.weights[i]) {
differs = true; differs = true;
break; break;
}
} }
EXPECT_TRUE(differs); }
EXPECT_TRUE(differs);
} }
TEST(ControllerTest, Crossover) { TEST(ControllerTest, Crossover) {
FuzzyController a, b; FuzzyController a, b;
auto child = a.crossover(b); auto child = a.crossover(b);
EXPECT_EQ(child.origin, "crossover"); EXPECT_EQ(child.origin, "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 =
EXPECT_EQ(actions.size(0), 1); ctrl.decide_update(stats, 0.0f, 0.5f, 0.0f, 0.1f, 0.0f, 0.0f, 1.0f, 0.0f);
EXPECT_EQ(actions.size(1), GENOME_OUTPUT_DIM); EXPECT_EQ(actions.size(0), 1);
EXPECT_EQ(actions.size(1), GENOME_OUTPUT_DIM);
} }
TEST(ControllerTest, OrthogonalChild) { TEST(ControllerTest, OrthogonalChild) {
FuzzyController parent; FuzzyController parent;
auto child = parent.create_orthogonal_child(1.0f); auto child = parent.create_orthogonal_child(1.0f);
EXPECT_EQ(child.origin, "phoenix_rebirth"); EXPECT_EQ(child.origin, "phoenix_rebirth");
} }
TEST(ControllerTest, BanachFission) { TEST(ControllerTest, BanachFission) {
FuzzyController parent; FuzzyController parent;
auto [plus, minus] = parent.banach_tarski_fission(1.0f); auto [plus, minus] = parent.banach_tarski_fission(1.0f);
EXPECT_NE(plus.id, minus.id); EXPECT_NE(plus.id, minus.id);
} }

View File

@@ -1,33 +1,34 @@
#include <gtest/gtest.h>
#include "fces/fitness.hpp" #include "fces/fitness.hpp"
#include <gtest/gtest.h>
using namespace fces; using namespace fces;
TEST(RunningStatsTest, BasicUpdate) { TEST(RunningStatsTest, BasicUpdate) {
RunningStats stats; RunningStats stats;
stats.update(1.0f); stats.update(1.0f);
stats.update(2.0f); stats.update(2.0f);
stats.update(3.0f); stats.update(3.0f);
EXPECT_NEAR(stats.get_mean(), 2.0f, 1e-5f); EXPECT_NEAR(stats.get_mean(), 2.0f, 1e-5f);
EXPECT_GT(stats.get_std(), 0.0f); EXPECT_GT(stats.get_std(), 0.0f);
} }
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)
float z = stats.z_score(50.0f); stats.update(static_cast<float>(i));
EXPECT_NEAR(z, 0.0f, 0.1f); float z = stats.z_score(50.0f);
EXPECT_NEAR(z, 0.0f, 0.1f);
} }
TEST(FitnessEngineTest, LossSignal) { TEST(FitnessEngineTest, LossSignal) {
FitnessEngine engine; FitnessEngine engine;
float sig = engine.calculate_loss_signal(1.0f, 2.0f, "relative"); float sig = engine.calculate_loss_signal(1.0f, 2.0f, "relative");
EXPECT_LT(sig, 0.0f); // Improving EXPECT_LT(sig, 0.0f); // Improving
} }
TEST(FitnessEngineTest, KZMDamping) { TEST(FitnessEngineTest, KZMDamping) {
FitnessEngine engine(0.1f); FitnessEngine engine(0.1f);
float d = engine.compute_kzm_damping(5.0f); float d = engine.compute_kzm_damping(5.0f);
EXPECT_GT(d, 0.0f); EXPECT_GT(d, 0.0f);
EXPECT_LT(d, 1.0f); EXPECT_LT(d, 1.0f);
} }

View File

@@ -1,42 +1,45 @@
#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);
} }
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));
// Simulate a training step // Simulate a training step
auto x = torch::randn({2, 10}); auto x = torch::randn({2, 10});
auto y = model->forward(x); auto y = model->forward(x);
auto loss = y.sum(); auto loss = y.sum();
loss.backward(); loss.backward();
opt.step(); opt.step();
EXPECT_EQ(opt.step_count(), 1); EXPECT_EQ(opt.step_count(), 1);
} }
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);
opt.update_fitness(2.5f); opt.update_fitness(2.5f);
// Should not crash // Should not crash
} }

View File

@@ -1,28 +1,28 @@
#include <gtest/gtest.h>
#include "fces/population.hpp" #include "fces/population.hpp"
#include <gtest/gtest.h>
using namespace fces; using namespace fces;
TEST(PopulationTest, Construction) { TEST(PopulationTest, Construction) {
Population pop(50); Population pop(50);
EXPECT_EQ(pop.size(), 50); EXPECT_EQ(pop.size(), 50);
} }
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);
} }
TEST(PopulationTest, GetBestActive) { TEST(PopulationTest, GetBestActive) {
Population pop(10); Population pop(10);
auto& best = pop.get_best_active(); auto &best = pop.get_best_active();
// Should not crash // Should not crash
EXPECT_GE(best.id, 0u); EXPECT_GE(best.id, 0u);
} }
TEST(PopulationTest, CalmDown) { TEST(PopulationTest, CalmDown) {
Population pop(10); Population pop(10);
pop.calm_down(); pop.calm_down();
EXPECT_LT(pop.global_sigma_modifier(), 1.0f); EXPECT_LT(pop.global_sigma_modifier(), 1.0f);
} }