Compare commits
No commits in common. "e9954f5065d703295f5a627ed25fda1540007a45" and "ff5a30c7782dc10c8871f4d7623c69d187380e62" have entirely different histories.
e9954f5065
...
ff5a30c778
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.135)
|
project(blt-gp VERSION 0.0.133)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
@ -97,7 +97,6 @@ if (${BUILD_GP_TESTS})
|
||||||
blt_add_project(blt-stack tests/stack_tests.cpp test)
|
blt_add_project(blt-stack tests/stack_tests.cpp test)
|
||||||
blt_add_project(blt-eval tests/evaluation_tests.cpp test)
|
blt_add_project(blt-eval tests/evaluation_tests.cpp test)
|
||||||
blt_add_project(blt-order tests/order_tests.cpp test)
|
blt_add_project(blt-order tests/order_tests.cpp test)
|
||||||
blt_add_project(blt-destructor tests/destructor_test.cpp test)
|
|
||||||
blt_add_project(blt-gp1 tests/gp_test_1.cpp test)
|
blt_add_project(blt-gp1 tests/gp_test_1.cpp test)
|
||||||
blt_add_project(blt-gp2 tests/gp_test_2.cpp test)
|
blt_add_project(blt-gp2 tests/gp_test_2.cpp test)
|
||||||
blt_add_project(blt-gp3 tests/gp_test_3.cpp test)
|
blt_add_project(blt-gp3 tests/gp_test_3.cpp test)
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <blt/gp/tree.h>
|
#include <blt/gp/tree.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
//static constexpr long SEED = 41912;
|
//static constexpr long SEED = 41912;
|
||||||
static const unsigned long SEED = std::random_device()();
|
static const unsigned long SEED = std::random_device()();
|
||||||
|
@ -76,7 +77,7 @@ constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fit
|
||||||
}
|
}
|
||||||
fitness.standardized_fitness = fitness.raw_fitness;
|
fitness.standardized_fitness = fitness.raw_fitness;
|
||||||
fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness));
|
fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness));
|
||||||
return static_cast<blt::size_t>(fitness.hits) == fitness_cases.size();
|
return fitness.hits == fitness_cases.size();
|
||||||
};
|
};
|
||||||
|
|
||||||
float example_function(float x)
|
float example_function(float x)
|
||||||
|
|
|
@ -181,11 +181,11 @@ namespace blt::gp
|
||||||
if constexpr (detail::is_same_v<Context, detail::remove_cv_ref<typename detail::first_arg<Args...>::type>>)
|
if constexpr (detail::is_same_v<Context, detail::remove_cv_ref<typename detail::first_arg<Args...>::type>>)
|
||||||
{
|
{
|
||||||
// first arg is context
|
// first arg is context
|
||||||
write_allocator.push(this->operator()(context, read_allocator));
|
write_allocator.push(std::move(this->operator()(context, read_allocator)));
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
// first arg isn't context
|
// first arg isn't context
|
||||||
write_allocator.push(this->operator()(read_allocator));
|
write_allocator.push(std::move(this->operator()(read_allocator)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include <blt/std/assert.h>
|
#include <blt/std/assert.h>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <blt/std/allocator.h>
|
#include <blt/std/allocator.h>
|
||||||
#include <blt/std/meta.h>
|
|
||||||
#include <blt/gp/fwdecl.h>
|
#include <blt/gp/fwdecl.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -36,11 +35,6 @@
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
BLT_META_MAKE_FUNCTION_CHECK(drop);
|
|
||||||
}
|
|
||||||
|
|
||||||
class stack_allocator
|
class stack_allocator
|
||||||
{
|
{
|
||||||
constexpr static blt::size_t PAGE_SIZE = 0x1000;
|
constexpr static blt::size_t PAGE_SIZE = 0x1000;
|
||||||
|
@ -232,8 +226,7 @@ namespace blt::gp
|
||||||
// make copy
|
// make copy
|
||||||
NO_REF_T t = *reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE);
|
NO_REF_T t = *reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE);
|
||||||
// call destructor
|
// call destructor
|
||||||
if constexpr (detail::has_func_drop_v<T>)
|
reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE)->~NO_REF_T();
|
||||||
reinterpret_cast<NO_REF_T*>(head->metadata.offset - TYPE_SIZE)->~NO_REF_T();
|
|
||||||
// move offset back
|
// move offset back
|
||||||
head->metadata.offset -= TYPE_SIZE;
|
head->metadata.offset -= TYPE_SIZE;
|
||||||
// moving back allows us to allocate with other data, if there is room.
|
// moving back allows us to allocate with other data, if there is room.
|
||||||
|
@ -320,7 +313,7 @@ namespace blt::gp
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Warning this function should be used to transfer types, not arrays of types! It will produce an error if you attempt to pass more
|
* Warning this function should be used to transfer types, not arrays of types! It will produce an error if you attempt to pass more
|
||||||
* than one type # of bytes at a time!
|
* than one type # of bytes at a time~!
|
||||||
* @param to stack to push to
|
* @param to stack to push to
|
||||||
* @param bytes number of bytes to transfer out.
|
* @param bytes number of bytes to transfer out.
|
||||||
*/
|
*/
|
||||||
|
@ -350,7 +343,8 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
blt::size_t offset = 0;
|
blt::size_t offset = 0;
|
||||||
|
|
||||||
((call_drop<Args>(offset), offset += stack_allocator::aligned_size<NO_REF_T<Args>>()), ...);
|
((from<NO_REF_T<Args >>(offset).~NO_REF_T<Args>(), offset += stack_allocator::aligned_size<NO_REF_T<Args>>
|
||||||
|
()), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool empty() const noexcept
|
[[nodiscard]] bool empty() const noexcept
|
||||||
|
@ -550,15 +544,6 @@ namespace blt::gp
|
||||||
blt::u8* start_point;
|
blt::u8* start_point;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void call_drop(blt::size_t offset)
|
|
||||||
{
|
|
||||||
if constexpr (detail::has_func_drop_v<T>)
|
|
||||||
{
|
|
||||||
from<NO_REF_T<T>>(offset).drop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void* allocate_bytes()
|
void* allocate_bytes()
|
||||||
{
|
{
|
||||||
|
|
2
lib/blt
2
lib/blt
|
@ -1 +1 @@
|
||||||
Subproject commit 4327b34c841fd6d8fb6509757d5cab2717d35457
|
Subproject commit 99e735b7601716caf9e5b6dbac0ae22b2ab99b3d
|
|
@ -1,230 +0,0 @@
|
||||||
/*
|
|
||||||
* <Short Description>
|
|
||||||
* Copyright (C) 2024 Brett Terpstra
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* <Short Description>
|
|
||||||
* Copyright (C) 2024 Brett Terpstra
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include <blt/gp/program.h>
|
|
||||||
#include <blt/profiling/profiler_v2.h>
|
|
||||||
#include <blt/gp/tree.h>
|
|
||||||
#include <blt/std/logging.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <atomic>
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
//static constexpr long SEED = 41912;
|
|
||||||
static const unsigned long SEED = std::random_device()();
|
|
||||||
|
|
||||||
inline std::atomic_uint64_t constructions = 0;
|
|
||||||
inline std::atomic_uint64_t destructions = 0;
|
|
||||||
|
|
||||||
class move_float
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
move_float(): f(new float())
|
|
||||||
{ constructions++; }
|
|
||||||
|
|
||||||
explicit move_float(float f): f(new float(f))
|
|
||||||
{
|
|
||||||
constructions++;
|
|
||||||
// BLT_TRACE("Value Constructed");
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator float() const
|
|
||||||
{
|
|
||||||
return *f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float get() const
|
|
||||||
{
|
|
||||||
return *f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float operator*() const
|
|
||||||
{
|
|
||||||
return *f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drop() // NOLINT
|
|
||||||
{
|
|
||||||
//BLT_TRACE("Drop Called");
|
|
||||||
delete f;
|
|
||||||
f = nullptr;
|
|
||||||
destructions++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float* f = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(std::is_trivially_copyable_v<move_float>);
|
|
||||||
//static_assert(std::is_standard_layout_v<move_float>);
|
|
||||||
|
|
||||||
struct context
|
|
||||||
{
|
|
||||||
move_float x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<context, 200> fitness_cases;
|
|
||||||
|
|
||||||
blt::gp::prog_config_t config = blt::gp::prog_config_t()
|
|
||||||
.set_initial_min_tree_size(2)
|
|
||||||
.set_initial_max_tree_size(6)
|
|
||||||
.set_elite_count(2)
|
|
||||||
.set_crossover_chance(0.9)
|
|
||||||
.set_mutation_chance(0.1)
|
|
||||||
.set_reproduction_chance(0)
|
|
||||||
.set_max_generations(1)
|
|
||||||
.set_pop_size(1)
|
|
||||||
.set_thread_count(0);
|
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
|
||||||
blt::gp::gp_program program{type_system, SEED, config};
|
|
||||||
|
|
||||||
blt::gp::operation_t add([](const move_float& a, const move_float& b) { return move_float(*a + *b); }, "add");
|
|
||||||
blt::gp::operation_t sub([](const move_float& a, const move_float& b) { return move_float(*a - *b); }, "sub");
|
|
||||||
blt::gp::operation_t mul([](const move_float& a, const move_float& b) { return move_float(*a * *b); }, "mul");
|
|
||||||
blt::gp::operation_t pro_div([](const move_float& a, const move_float& b) { return move_float(*b == 0.0f ? 1.0f : *a / *b); }, "div");
|
|
||||||
blt::gp::operation_t op_sin([](const move_float& a) { return move_float(std::sin(*a)); }, "sin");
|
|
||||||
blt::gp::operation_t op_cos([](const move_float& a) { return move_float(std::cos(*a)); }, "cos");
|
|
||||||
blt::gp::operation_t op_exp([](const move_float& a) { return move_float(std::exp(*a)); }, "exp");
|
|
||||||
blt::gp::operation_t op_log([](const move_float& a) { return move_float(*a == 0.0f ? 0.0f : std::log(*a)); }, "log");
|
|
||||||
|
|
||||||
blt::gp::operation_t lit([]() {
|
|
||||||
return move_float(program.get_random().get_float(-320.0f, 320.0f));
|
|
||||||
}, "lit");
|
|
||||||
blt::gp::operation_t op_x([](const context& context) {
|
|
||||||
return context.x;
|
|
||||||
}, "x");
|
|
||||||
|
|
||||||
constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fitness_t& fitness, blt::size_t) {
|
|
||||||
constexpr double value_cutoff = 1.e15;
|
|
||||||
for (auto& fitness_case : fitness_cases)
|
|
||||||
{
|
|
||||||
auto diff = std::abs(*fitness_case.y - *current_tree.get_evaluation_value<move_float>(&fitness_case));
|
|
||||||
if (diff < value_cutoff)
|
|
||||||
{
|
|
||||||
fitness.raw_fitness += diff;
|
|
||||||
if (diff < 0.01)
|
|
||||||
fitness.hits++;
|
|
||||||
} else
|
|
||||||
fitness.raw_fitness += value_cutoff;
|
|
||||||
}
|
|
||||||
fitness.standardized_fitness = fitness.raw_fitness;
|
|
||||||
fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness));
|
|
||||||
return static_cast<blt::size_t>(fitness.hits) == fitness_cases.size();
|
|
||||||
};
|
|
||||||
|
|
||||||
float example_function(float x)
|
|
||||||
{
|
|
||||||
return x * x * x * x + x * x * x + x * x + x;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
BLT_INFO("Starting BLT-GP Symbolic Regression Example");
|
|
||||||
BLT_START_INTERVAL("Symbolic Regression", "Main");
|
|
||||||
BLT_DEBUG("Setup Fitness cases");
|
|
||||||
for (auto& fitness_case : fitness_cases)
|
|
||||||
{
|
|
||||||
constexpr float range = 10;
|
|
||||||
constexpr float half_range = range / 2.0;
|
|
||||||
auto x = program.get_random().get_float(-half_range, half_range);
|
|
||||||
auto y = example_function(x);
|
|
||||||
fitness_case = {move_float(x), move_float(y)};
|
|
||||||
}
|
|
||||||
|
|
||||||
BLT_DEBUG("Setup Types and Operators");
|
|
||||||
type_system.register_type<move_float>();
|
|
||||||
|
|
||||||
blt::gp::operator_builder<context> builder{type_system};
|
|
||||||
builder.add_operator(add);
|
|
||||||
builder.add_operator(sub);
|
|
||||||
builder.add_operator(mul);
|
|
||||||
builder.add_operator(pro_div);
|
|
||||||
builder.add_operator(op_sin);
|
|
||||||
builder.add_operator(op_cos);
|
|
||||||
builder.add_operator(op_exp);
|
|
||||||
builder.add_operator(op_log);
|
|
||||||
|
|
||||||
builder.add_operator(lit, true);
|
|
||||||
builder.add_operator(op_x);
|
|
||||||
|
|
||||||
program.set_operations(builder.build());
|
|
||||||
|
|
||||||
BLT_DEBUG("Generate Initial Population");
|
|
||||||
program.generate_population(type_system.get_type<float>().id(), fitness_function);
|
|
||||||
|
|
||||||
BLT_DEBUG("Begin Generation Loop");
|
|
||||||
while (!program.should_terminate())
|
|
||||||
{
|
|
||||||
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
|
|
||||||
BLT_START_INTERVAL("Symbolic Regression", "Gen");
|
|
||||||
auto sel = blt::gp::select_fitness_proportionate_t{};
|
|
||||||
program.create_next_generation(sel, sel, sel);
|
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Gen");
|
|
||||||
BLT_TRACE("Move to next generation");
|
|
||||||
BLT_START_INTERVAL("Symbolic Regression", "Fitness");
|
|
||||||
program.next_generation();
|
|
||||||
BLT_TRACE("Evaluate Fitness");
|
|
||||||
program.evaluate_fitness();
|
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Fitness");
|
|
||||||
BLT_TRACE("----------------------------------------------");
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLT_END_INTERVAL("Symbolic Regression", "Main");
|
|
||||||
|
|
||||||
auto best = program.get_best_individuals<3>();
|
|
||||||
|
|
||||||
BLT_INFO("Best approximations:");
|
|
||||||
for (auto& i_ref : best)
|
|
||||||
{
|
|
||||||
auto& i = i_ref.get();
|
|
||||||
BLT_DEBUG("Fitness: %lf, stand: %lf, raw: %lf", i.fitness.adjusted_fitness, i.fitness.standardized_fitness, i.fitness.raw_fitness);
|
|
||||||
i.tree.print(program, std::cout);
|
|
||||||
std::cout << "\n";
|
|
||||||
}
|
|
||||||
auto& stats = program.get_population_stats();
|
|
||||||
BLT_INFO("Stats:");
|
|
||||||
BLT_INFO("Average fitness: %lf", stats.average_fitness.load());
|
|
||||||
BLT_INFO("Best fitness: %lf", stats.best_fitness.load());
|
|
||||||
BLT_INFO("Worst fitness: %lf", stats.worst_fitness.load());
|
|
||||||
BLT_INFO("Overall fitness: %lf", stats.overall_fitness.load());
|
|
||||||
// TODO: make stats helper
|
|
||||||
|
|
||||||
BLT_PRINT_PROFILE("Symbolic Regression", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL);
|
|
||||||
|
|
||||||
BLT_TRACE("Constructions %ld Destructions %ld Difference %ld", constructions.load(), destructions.load(),
|
|
||||||
std::abs(static_cast<blt::ptrdiff_t>(constructions) - static_cast<blt::ptrdiff_t>(destructions)));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
Loading…
Reference in New Issue