feat: scaffold FCES-native C++ project with libtorch integration
- CMakeLists.txt with libtorch, GoogleTest, GoogleBenchmark, OpenMP, pybind11 - Header files: config, controller, population, fitness, evolution, spectral, oscillation, telemetry, optimizer - Source implementations: controller (full micro-MLP forward pass, mutation, crossover), fitness (Welford's algorithm), oscillation (DFT), spectral (SVD rank), optimizer (sign-SGD stub) - Tests: controller, population, fitness, optimizer (Google Test) - Benchmarks: evolve throughput, optimizer step (Google Benchmark) - Examples: simple optimization, PyTorch/libtorch integration - Python extension: pybind11 bindings with setup.py - README with architecture diagram and build instructions
This commit is contained in:
58
tests/test_controller.cpp
Normal file
58
tests/test_controller.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "fces/controller.hpp"
|
||||
|
||||
using namespace fces;
|
||||
|
||||
TEST(ControllerTest, Construction) {
|
||||
FuzzyController ctrl;
|
||||
EXPECT_GT(ctrl.id, 0u);
|
||||
EXPECT_EQ(ctrl.fitness, 0.0f);
|
||||
EXPECT_EQ(ctrl.origin, "random");
|
||||
}
|
||||
|
||||
TEST(ControllerTest, GenomeSize) {
|
||||
FuzzyController ctrl;
|
||||
EXPECT_EQ(ctrl.genome.weights.size(), static_cast<size_t>(GENOME_SIZE));
|
||||
}
|
||||
|
||||
TEST(ControllerTest, Mutation) {
|
||||
FuzzyController parent;
|
||||
auto child = parent.mutate(1.0f);
|
||||
EXPECT_NE(child.id, parent.id);
|
||||
EXPECT_EQ(child.origin, "mutation");
|
||||
// Child should differ from parent
|
||||
bool differs = false;
|
||||
for (size_t i = 0; i < parent.genome.weights.size(); ++i) {
|
||||
if (parent.genome.weights[i] != child.genome.weights[i]) {
|
||||
differs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPECT_TRUE(differs);
|
||||
}
|
||||
|
||||
TEST(ControllerTest, Crossover) {
|
||||
FuzzyController a, b;
|
||||
auto child = a.crossover(b);
|
||||
EXPECT_EQ(child.origin, "crossover");
|
||||
}
|
||||
|
||||
TEST(ControllerTest, DecideUpdate) {
|
||||
FuzzyController ctrl;
|
||||
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);
|
||||
EXPECT_EQ(actions.size(0), 1);
|
||||
EXPECT_EQ(actions.size(1), GENOME_OUTPUT_DIM);
|
||||
}
|
||||
|
||||
TEST(ControllerTest, OrthogonalChild) {
|
||||
FuzzyController parent;
|
||||
auto child = parent.create_orthogonal_child(1.0f);
|
||||
EXPECT_EQ(child.origin, "phoenix_rebirth");
|
||||
}
|
||||
|
||||
TEST(ControllerTest, BanachFission) {
|
||||
FuzzyController parent;
|
||||
auto [plus, minus] = parent.banach_tarski_fission(1.0f);
|
||||
EXPECT_NE(plus.id, minus.id);
|
||||
}
|
||||
33
tests/test_fitness.cpp
Normal file
33
tests/test_fitness.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "fces/fitness.hpp"
|
||||
|
||||
using namespace fces;
|
||||
|
||||
TEST(RunningStatsTest, BasicUpdate) {
|
||||
RunningStats stats;
|
||||
stats.update(1.0f);
|
||||
stats.update(2.0f);
|
||||
stats.update(3.0f);
|
||||
EXPECT_NEAR(stats.get_mean(), 2.0f, 1e-5f);
|
||||
EXPECT_GT(stats.get_std(), 0.0f);
|
||||
}
|
||||
|
||||
TEST(RunningStatsTest, ZScore) {
|
||||
RunningStats stats;
|
||||
for (int i = 0; i < 100; ++i) stats.update(static_cast<float>(i));
|
||||
float z = stats.z_score(50.0f);
|
||||
EXPECT_NEAR(z, 0.0f, 0.1f);
|
||||
}
|
||||
|
||||
TEST(FitnessEngineTest, LossSignal) {
|
||||
FitnessEngine engine;
|
||||
float sig = engine.calculate_loss_signal(1.0f, 2.0f, "relative");
|
||||
EXPECT_LT(sig, 0.0f); // Improving
|
||||
}
|
||||
|
||||
TEST(FitnessEngineTest, KZMDamping) {
|
||||
FitnessEngine engine(0.1f);
|
||||
float d = engine.compute_kzm_damping(5.0f);
|
||||
EXPECT_GT(d, 0.0f);
|
||||
EXPECT_LT(d, 1.0f);
|
||||
}
|
||||
42
tests/test_optimizer.cpp
Normal file
42
tests/test_optimizer.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <torch/torch.h>
|
||||
#include "fces/optimizer.hpp"
|
||||
|
||||
using namespace fces;
|
||||
|
||||
TEST(OptimizerTest, Construction) {
|
||||
auto model = torch::nn::Linear(10, 5);
|
||||
std::vector<torch::Tensor> params;
|
||||
for (auto& p : model->parameters()) params.push_back(p);
|
||||
|
||||
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
||||
EXPECT_EQ(opt.step_count(), 0);
|
||||
}
|
||||
|
||||
TEST(OptimizerTest, StepUpdatesCounter) {
|
||||
auto model = torch::nn::Linear(10, 5);
|
||||
std::vector<torch::Tensor> params;
|
||||
for (auto& p : model->parameters()) params.push_back(p);
|
||||
|
||||
FCESOptimizer opt(params, FCESConfig{}.set_lr(1e-3f));
|
||||
|
||||
// Simulate a training step
|
||||
auto x = torch::randn({2, 10});
|
||||
auto y = model->forward(x);
|
||||
auto loss = y.sum();
|
||||
loss.backward();
|
||||
opt.step();
|
||||
|
||||
EXPECT_EQ(opt.step_count(), 1);
|
||||
}
|
||||
|
||||
TEST(OptimizerTest, UpdateFitness) {
|
||||
auto model = torch::nn::Linear(10, 5);
|
||||
std::vector<torch::Tensor> params;
|
||||
for (auto& p : model->parameters()) params.push_back(p);
|
||||
|
||||
FCESOptimizer opt(params);
|
||||
opt.update_fitness(3.0f);
|
||||
opt.update_fitness(2.5f);
|
||||
// Should not crash
|
||||
}
|
||||
28
tests/test_population.cpp
Normal file
28
tests/test_population.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "fces/population.hpp"
|
||||
|
||||
using namespace fces;
|
||||
|
||||
TEST(PopulationTest, Construction) {
|
||||
Population pop(50);
|
||||
EXPECT_EQ(pop.size(), 50);
|
||||
}
|
||||
|
||||
TEST(PopulationTest, DirectConstruction) {
|
||||
Population pop(200, 10000, EliteStrategy::Cumulative,
|
||||
false, false, false, false, false, true);
|
||||
EXPECT_EQ(pop.size(), 1);
|
||||
}
|
||||
|
||||
TEST(PopulationTest, GetBestActive) {
|
||||
Population pop(10);
|
||||
auto& best = pop.get_best_active();
|
||||
// Should not crash
|
||||
EXPECT_GE(best.id, 0u);
|
||||
}
|
||||
|
||||
TEST(PopulationTest, CalmDown) {
|
||||
Population pop(10);
|
||||
pop.calm_down();
|
||||
EXPECT_LT(pop.global_sigma_modifier(), 1.0f);
|
||||
}
|
||||
Reference in New Issue
Block a user