From 19504dd938cff1f09136e51905e8f44d38343869 Mon Sep 17 00:00:00 2001 From: Brett Date: Mon, 28 Apr 2025 15:11:38 -0400 Subject: [PATCH] nonsense --- .idea/editor.xml | 236 ---------------------------------- CMakeLists.txt | 2 +- include/blt/gp/program.h | 83 ++++++++---- include/blt/gp/transformers.h | 18 ++- include/blt/gp/tree.h | 6 +- lib/blt | 2 +- src/program.cpp | 10 -- src/transformers.cpp | 35 +++++ tests/serialization_test.cpp | 74 +---------- 9 files changed, 123 insertions(+), 343 deletions(-) diff --git a/.idea/editor.xml b/.idea/editor.xml index 521c365..a8c6caa 100644 --- a/.idea/editor.xml +++ b/.idea/editor.xml @@ -1,248 +1,12 @@ - diff --git a/CMakeLists.txt b/CMakeLists.txt index 548a31f..5f3631b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,7 @@ macro(compile_options target_name) sanitizers(${target_name}) endmacro() -project(blt-gp VERSION 0.5.17) +project(blt-gp VERSION 0.5.18) include(CTest) diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 85927ee..b71bff6 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -53,6 +53,7 @@ #include #include #include "blt/format/format.h" +#include "blt/std/variant.h" namespace blt::gp { @@ -108,85 +109,122 @@ namespace blt::gp namespace errors::serialization { - struct invalid_read_t + struct error_to_string_t + { + virtual ~error_to_string_t() = default; + [[nodiscard]] virtual std::string to_string() const = 0; + }; + + struct invalid_read_t final : error_to_string_t { i64 read; i64 expected; - [[nodiscard]] std::string to_string() const + invalid_read_t(const i64 read, const i64 expected): read(read), expected(expected) + { + } + + [[nodiscard]] std::string to_string() const override { return "Invalid read; unable to read sufficient bytes to populate the object. Expected " + std::to_string(expected) + " but read " + std::to_string(read); } }; - struct unexpected_size_t + struct unexpected_size_t final : error_to_string_t { size_t read_size; size_t expected_size; - [[nodiscard]] std::string to_string() const + unexpected_size_t(const size_t read_size, const size_t expected_size): read_size(read_size), expected_size(expected_size) + { + } + + [[nodiscard]] std::string to_string() const override { return "Invalid read of a size type. Expected to find " + std::to_string(expected_size) + " found " + std::to_string(read_size); } }; - struct invalid_operator_id_t + struct invalid_operator_id_t final : error_to_string_t { operator_id read; operator_id expected; - [[nodiscard]] std::string to_string() const + invalid_operator_id_t(const operator_id read, const operator_id expected): read(read), expected(expected) + { + } + + [[nodiscard]] std::string to_string() const override { return "Loaded invalid operator ID. Expected " + std::to_string(expected) + " but found " + std::to_string(read); } }; - struct invalid_name_t + struct invalid_name_t final : error_to_string_t { operator_id id; std::string found; std::string expected; - [[nodiscard]] std::string to_string() const + invalid_name_t(const operator_id id, std::string found, const std::string& expected): id(id), found(std::move(found)), expected(expected) + { + } + + [[nodiscard]] std::string to_string() const override { return "Operator ID " + std::to_string(id) + " expected to have name '" + expected + "' but found '" + found + "'"; } }; - struct mismatched_bytes_t + struct mismatched_bytes_t final : error_to_string_t { operator_id id; size_t read_size; size_t expected_size; - [[nodiscard]] std::string to_string() const + mismatched_bytes_t(const operator_id id, const size_t read_size, const size_t expected_size): id(id), read_size(read_size), + expected_size(expected_size) + { + } + + [[nodiscard]] std::string to_string() const override { return "Operator ID " + std::to_string(id) + " expected bytes " + std::to_string(expected_size) + " but found " + std::to_string(read_size); } }; - struct mismatched_argc_t + struct mismatched_argc_t final : error_to_string_t { operator_id id; size_t read_argc; size_t expected_argc; - [[nodiscard]] std::string to_string() const + mismatched_argc_t(const operator_id id, const size_t read_argc, const size_t expected_argc): id(id), read_argc(read_argc), + expected_argc(expected_argc) + { + } + + [[nodiscard]] std::string to_string() const override { return "Operator ID " + std::to_string(id) + " expected argc " + std::to_string(expected_argc) + " but found " + std::to_string(read_argc); } }; - struct mismatched_return_type_t + struct mismatched_return_type_t final : error_to_string_t { operator_id id; type_id read_type; type_id expected_type; - [[nodiscard]] std::string to_string() const + mismatched_return_type_t(const operator_id id, const type_id read_type, const type_id expected_type): id(id), read_type(read_type), + expected_type(expected_type) + { + } + + [[nodiscard]] std::string to_string() const override { return "Operator ID " + std::to_string(id) + " expected return type " + std::to_string(expected_type) + @@ -194,14 +232,19 @@ namespace blt::gp } }; - struct mismatched_arg_type_t + struct mismatched_arg_type_t final : error_to_string_t { operator_id id; size_t arg_index; type_id read_type; type_id expected_type; - [[nodiscard]] std::string to_string() const + mismatched_arg_type_t(const operator_id id, const size_t arg_index, const type_id read_type, const type_id expected_type): id(id), + arg_index(arg_index), read_type(read_type), expected_type(expected_type) + { + } + + [[nodiscard]] std::string to_string() const override { return "Operator ID " + std::to_string(id) + " expected argument " + std::to_string(arg_index) + @@ -210,12 +253,8 @@ namespace blt::gp } }; - using serializer_error_t = std::variant; - - std::string to_string(const serializer_error_t& error); + using serializer_error_t = variant_t; } diff --git a/include/blt/gp/transformers.h b/include/blt/gp/transformers.h index 94fbaf1..59537c1 100644 --- a/include/blt/gp/transformers.h +++ b/include/blt/gp/transformers.h @@ -143,7 +143,7 @@ namespace blt::gp * @param c2 reference to output child 2 * @return true if function succeeded, otherwise false */ - virtual bool apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2); // NOLINT + virtual bool apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) override; // NOLINT ~subtree_crossover_t() override = default; @@ -151,8 +151,24 @@ namespace blt::gp [[nodiscard]] std::optional get_point_traverse_retry(const tree_t& t, std::optional type) const; }; + class one_point_crossover_t : public crossover_t + { + one_point_crossover_t(): crossover_t(config_t{}) + { + } + + explicit one_point_crossover_t(const config_t& config): crossover_t(config) + { + } + + bool apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) override; + }; + class advanced_crossover_t : public crossover_t { + advanced_crossover_t(): crossover_t(config_t{}) + { + } public: bool apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) override; }; diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index 263e0af..4bdab6e 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -200,6 +200,8 @@ namespace blt::gp ptrdiff_t pos; type_id type; + subtree_point_t() = default; + explicit subtree_point_t(const ptrdiff_t pos): pos(pos), type(0) { } @@ -245,6 +247,7 @@ namespace blt::gp bytes = 0; } } + private: tree_t& tree; u8* data; @@ -585,7 +588,8 @@ namespace blt::gp template static auto make_execution_lambda(size_t call_reserve_size, Operators&... operators) { - return [call_reserve_size, &operators...](const tree_t& tree, void* context) -> evaluation_context& { + return [call_reserve_size, &operators...](const tree_t& tree, void* context) -> evaluation_context& + { const auto& ops = tree.operations; const auto& vals = tree.values; diff --git a/lib/blt b/lib/blt index e5a3c9d..f0fe0c1 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit e5a3c9d669900ea3976fc575840e499d1ecdac27 +Subproject commit f0fe0c1ceed644513eb8fa787aac3001a906d209 diff --git a/src/program.cpp b/src/program.cpp index 95ca853..ad946b5 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -27,16 +27,6 @@ namespace blt::gp { - std::string errors::serialization::to_string(const serializer_error_t& error) - { - return std::visit(lambda_visitor{ - [](const auto& val) - { - return val.to_string(); - } - }, error); - } - // default static references for mutation, crossover, and initializer // this is largely to not break the tests :3 // it's also to allow for quick setup of a gp program if you don't care how crossover or mutation is handled diff --git a/src/transformers.cpp b/src/transformers.cpp index d713478..7d20710 100644 --- a/src/transformers.cpp +++ b/src/transformers.cpp @@ -121,6 +121,41 @@ namespace blt::gp return t.select_subtree_traverse(config.terminal_chance, config.depth_multiplier); } + bool one_point_crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) + { + if (p1.size() < config.min_tree_size || p2.size() < config.min_tree_size) + return false; + + tree_t::subtree_point_t point1, point2; + if (config.traverse) + { + point1 = p1.select_subtree_traverse(config.terminal_chance, config.depth_multiplier); + if (const auto val = p2.select_subtree_traverse(point1.type, config.max_crossover_tries, config.terminal_chance, config.depth_multiplier)) + point2 = *val; + else + return false; + } else + { + point1 = p1.select_subtree(config.terminal_chance); + if (const auto val = p2.select_subtree(point1.type, config.max_crossover_tries, config.terminal_chance)) + point2 = *val; + else + return false; + } + + const auto& p1_operator = p1.get_operator(point1.pos); + const auto& p2_operator = p2.get_operator(point2.pos); + + const auto& p1_info = program.get_operator_info(p1_operator.id()); + const auto& p2_info = program.get_operator_info(p2_operator.id()); + + for (size_t i = 0; i < std::min(p1_info.argument_types.size(), p2_info.argument_types.size()); i++) + { + if (p1_info.argument_types[i] != p2_info.argument_types[i]) + return false; + } + } + bool advanced_crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) { if (p1.size() < config.min_tree_size || p2.size() < config.min_tree_size) diff --git a/tests/serialization_test.cpp b/tests/serialization_test.cpp index ac78936..ed70b30 100644 --- a/tests/serialization_test.cpp +++ b/tests/serialization_test.cpp @@ -15,7 +15,6 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include #include #include "../examples/symbolic_regression.h" @@ -26,71 +25,6 @@ #include #include -struct default_type -{ - virtual std::string to_string() // NOLINT - { - return "Unimplemented"; - } -}; - -struct type1 : default_type -{ - virtual std::string to_string() final // NOLINT - { - return "type1"; - } -}; - -struct type2 : default_type -{ - virtual std::string to_string() final // NOLINT - { - return "type2"; - } -}; - -struct type3 : default_type -{ - virtual std::string to_string() final // NOLINT - { - return "type3"; - } -}; - -template -void print() -{ - BLT_TRACE("{}", blt::type_string()); -} - -void test() -{ - // auto ptr = &default_type::to_string; - // auto ptr2 = reinterpret_cast(ptr); - - - // blt::black_box(hi.to_string()); - // default_type* t = blt::black_box_ret(&hi); - // blt::black_box(t->to_string()); - - // BLT_TRACE("Validate:"); - - // BLT_TRACE("TYPE1: {}", type1{}.to_string()); - // BLT_TRACE("TYPE2: {}", type2{}.to_string()); - // BLT_TRACE("TYPE3: {}\n\n", type3{}.to_string()); - - // BLT_TRACE("Output:"); - - blt::variant_t some_type1{type1{}}; - blt::variant_t some_type2{type2{}}; - blt::variant_t some_type3{type3{}}; - - BLT_TRACE("TYPE1: {}", some_type1.call_member_args(&default_type::to_string)); - BLT_TRACE("TYPE2: {}", some_type2.call_member_args(&default_type::to_string)); - BLT_TRACE("TYPE3: {}", some_type3.call_member_args(&default_type::to_string)); -} - using namespace blt::gp; struct context @@ -155,8 +89,6 @@ bool fitness_function(const tree_t& current_tree, fitness_t& fitness, size_t) int main() { - test(); - return 0; operator_builder builder{}; const auto& operators = builder.build(addf, subf, mulf, pro_divf, op_sinf, op_cosf, op_expf, op_logf, litf, op_xf); regression.get_program().set_operations(operators); @@ -213,9 +145,9 @@ int main() { std::ifstream stream{"serialization_test2.data", std::ios::binary}; blt::fs::fstream_reader_t reader{stream}; - if (auto err = test_program.load_state(reader)) + if (auto error = test_program.load_state(reader)) { - BLT_ERROR("Error: {}", blt::gp::errors::serialization::to_string(*err)); + BLT_ERROR("Error: {}", error->call_member(&errors::serialization::error_to_string_t::to_string)); BLT_ABORT("Expected program to succeeded without returning an error state!"); } @@ -231,7 +163,7 @@ int main() { std::ifstream stream{"serialization_test2.data", std::ios::binary}; blt::fs::fstream_reader_t reader{stream}; - if (!bad_program.load_state(reader).has_value()) + if (!bad_program.load_state(reader)) { BLT_ABORT("Expected program to throw an exception when parsing state data into an incompatible program!"); }