From 52732bc1a15ebcd8612dae8088050fd86083ef8d Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Mon, 19 Aug 2024 22:05:42 -0400 Subject: [PATCH 1/7] fix printing issue --- CMakeLists.txt | 2 +- include/blt/gp/stack.h | 16 ++++++++-------- src/tree.cpp | 4 +++- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 876201a..ba93029 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.12) +project(blt-gp VERSION 0.1.13) include(CTest) diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index bb0bffa..a356ad9 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -130,7 +130,7 @@ namespace blt::gp if (stack.empty()) return; if (size_ < stack.bytes_stored + bytes_stored) - expand(stack.bytes_stored + bytes_stored); + expand(stack.bytes_stored + size_); std::memcpy(data_ + bytes_stored, stack.data_, stack.bytes_stored); bytes_stored += stack.bytes_stored; } @@ -140,7 +140,7 @@ namespace blt::gp if (bytes == 0) return; if (size_ < bytes + bytes_stored) - expand(bytes + bytes_stored); + expand(bytes + size_); std::memcpy(data_ + bytes_stored, stack.data_ + (stack.bytes_stored - bytes), bytes); bytes_stored += bytes; } @@ -150,7 +150,7 @@ namespace blt::gp if (bytes == 0 || data == nullptr) return; if (size_ < bytes + bytes_stored) - expand(bytes + bytes_stored); + expand(bytes + size_); std::memcpy(data_ + bytes_stored, data, bytes); bytes_stored += bytes; } @@ -196,7 +196,7 @@ namespace blt::gp BLT_ABORT(("Not enough bytes in stack to reference " + std::to_string(size) + " bytes requested but " + std::to_string(bytes) + " bytes stored!").c_str()); #endif - return *reinterpret_cast(data_ + bytes_stored - size); + return *reinterpret_cast(data_ + (bytes_stored - size)); } void pop_bytes(blt::size_t bytes) @@ -298,15 +298,15 @@ namespace blt::gp void* allocate_bytes_for_size(blt::size_t bytes) { - auto aligned_ptr = get_aligned_pointer(bytes); + auto used_bytes = aligned_size(bytes); + auto aligned_ptr = get_aligned_pointer(used_bytes); if (aligned_ptr == nullptr) { - expand(size_ + bytes); - aligned_ptr = get_aligned_pointer(bytes); + expand(size_ + used_bytes); + aligned_ptr = get_aligned_pointer(used_bytes); } if (aligned_ptr == nullptr) throw std::bad_alloc(); - auto used_bytes = aligned_size(bytes); bytes_stored += used_bytes; return aligned_ptr; } diff --git a/src/tree.cpp b/src/tree.cpp index 46cd827..96198c0 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -135,8 +135,10 @@ namespace blt::gp { create_indent(out, indent, pretty_print); if (program.is_static(v.id)) + { program.get_print_func(v.id)(out, reversed); - else + reversed.pop_bytes(stack_allocator::aligned_size(v.type_size)); + } else out << name; out << return_type << end_indent(pretty_print); } else From 82b8c8276803eec3fa5d3e53b531dafa0dfb36d9 Mon Sep 17 00:00:00 2001 From: Brett Date: Tue, 20 Aug 2024 13:07:33 -0400 Subject: [PATCH 2/7] need to add leaf nodes back --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 30 ++--- include/blt/gp/fwdecl.h | 3 +- include/blt/gp/operations.h | 71 ++++++------ include/blt/gp/program.h | 191 +++++++++++++++++++++---------- include/blt/gp/tree.h | 18 ++- lib/blt | 2 +- src/generators.cpp | 3 +- src/transformers.cpp | 92 +++++++-------- src/tree.cpp | 79 ++++++------- 10 files changed, 281 insertions(+), 210 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ba93029..2b8b85e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.13) +project(blt-gp VERSION 0.1.14) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index f61ce8a..3227c6a 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -54,9 +54,9 @@ blt::gp::operation_t op_cos([](float a) { return std::cos(a); }, "cos"); blt::gp::operation_t op_exp([](float a) { return std::exp(a); }, "exp"); blt::gp::operation_t op_log([](float a) { return a == 0.0f ? 0.0f : std::log(a); }, "log"); -blt::gp::operation_t lit([]() { +auto lit = blt::gp::operation_t([]() { return program.get_random().get_float(-320.0f, 320.0f); -}, "lit"); +}, "lit").set_ephemeral(); blt::gp::operation_t op_x([](const context& context) { return context.x; }, "x"); @@ -65,7 +65,7 @@ constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fit constexpr double value_cutoff = 1.e15; for (auto& fitness_case : fitness_cases) { - auto diff = std::abs(fitness_case.y - current_tree.get_evaluation_value(&fitness_case)); + auto diff = std::abs(fitness_case.y - current_tree.get_evaluation_value(&fitness_case, program.get_eval_func())); if (diff < value_cutoff) { fitness.raw_fitness += diff; @@ -102,19 +102,19 @@ int main() type_system.register_type(); blt::gp::operator_builder 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(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); - builder.add_operator(lit, true); - builder.add_operator(op_x); - - program.set_operations(builder.build()); + program.set_operations(builder.build(add, sub, mul, pro_div, op_sin, op_cos, op_exp, op_log, lit, op_x)); BLT_DEBUG("Generate Initial Population"); auto sel = blt::gp::select_fitness_proportionate_t{}; diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index c335344..97b1761 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -57,7 +57,8 @@ namespace blt::gp class operator_storage_test; // context*, read stack, write stack - using callable_t = std::function; + //using callable_t = std::function; + using eval_func_t = std::function; // debug function, using print_func_t = std::function; diff --git a/include/blt/gp/operations.h b/include/blt/gp/operations.h index 126f625..0678634 100644 --- a/include/blt/gp/operations.h +++ b/include/blt/gp/operations.h @@ -144,11 +144,12 @@ namespace blt::gp template class operation_t; - template - class operation_t + template + class operation_t { public: - using function_t = ArgType; + using function_t = RawFunction; + using First_Arg = typename blt::meta::arg_helper::First; constexpr operation_t(const operation_t& copy) = default; @@ -186,21 +187,21 @@ namespace blt::gp } } - template - [[nodiscard]] detail::callable_t make_callable() const - { - return [this](void* context, stack_allocator& read_allocator, stack_allocator& write_allocator, detail::bitmask_t* mask) { - if constexpr (detail::is_same_v::type>>) - { - // first arg is context - write_allocator.push(this->operator()(context, read_allocator, mask)); - } else - { - // first arg isn't context - write_allocator.push(this->operator()(read_allocator, mask)); - } - }; - } +// template +// [[nodiscard]] detail::callable_t make_callable() const +// { +// return [this](void* context, stack_allocator& read_allocator, stack_allocator& write_allocator, detail::bitmask_t* mask) { +// if constexpr (detail::is_same_v::type>>) +// { +// // first arg is context +// write_allocator.push(this->operator()(context, read_allocator, mask)); +// } else +// { +// // first arg isn't context +// write_allocator.push(this->operator()(read_allocator, mask)); +// } +// }; +// } [[nodiscard]] inline constexpr std::optional get_name() const { @@ -212,38 +213,42 @@ namespace blt::gp return func; } + inline auto set_ephemeral() + { + is_ephemeral_ = true; + return *this; + } + + inline bool is_ephemeral() + { + return is_ephemeral_; + } + operator_id id = -1; private: function_t func; std::optional name; + bool is_ephemeral_ = false; }; - template - class operation_t : public operation_t + template + class operation_t : public operation_t { public: - using operation_t::operation_t; + using operation_t::operation_t; }; template - operation_t(Lambda) - -> - operation_t; + operation_t(Lambda) -> operation_t; template - operation_t(Return(*) - (Args...)) -> - operation_t; + operation_t(Return(*)(Args...)) -> operation_t; template - operation_t(Lambda, std::optional - ) -> - operation_t; + operation_t(Lambda, std::optional) -> operation_t; template - operation_t(Return(*) - (Args...), std::optional) -> - operation_t; + operation_t(Return(*)(Args...), std::optional) -> operation_t; } #endif //BLT_GP_OPERATIONS_H diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 3a09687..fdee5cd 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -75,10 +75,6 @@ namespace blt::gp type_id return_type; // number of arguments for this operator argc_t argc; - // function to call this operator - detail::callable_t function; - // function used to transfer values between stacks - //detail::transfer_t transfer; }; struct operator_storage @@ -93,6 +89,8 @@ namespace blt::gp std::vector print_funcs; std::vector destroy_funcs; std::vector> names; + + detail::eval_func_t eval_func; }; template @@ -106,65 +104,41 @@ namespace blt::gp explicit operator_builder(type_provider& system): system(system) {} - template - operator_builder& add_operator(operation_t& op, bool is_static = false) + template + operator_storage& build(Operators& ... operators) { - auto return_type_id = system.get_type().id(); - auto operator_id = blt::gp::operator_id(storage.operators.size()); - op.id = operator_id; + std::vector sizes; + (sizes.push_back(add_operator(operators)), ...); + blt::size_t largest = 0; + for (auto v : sizes) + largest = std::max(v, largest); - operator_info info; - - if constexpr (sizeof...(Args) > 0) - { - (add_non_context_argument>(info.argument_types), ...); - } - - info.argc.argc_context = info.argc.argc = sizeof...(Args); - info.return_type = system.get_type().id(); - - ((std::is_same_v, Context> ? info.argc.argc -= 1 : (blt::size_t) nullptr), ...); - - auto& operator_list = info.argc.argc == 0 ? storage.terminals : storage.non_terminals; - operator_list[return_type_id].push_back(operator_id); - - BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!"); - - info.function = op.template make_callable(); - - storage.operators.push_back(info); - storage.print_funcs.push_back([&op](std::ostream& out, stack_allocator& stack) { - if constexpr (blt::meta::is_streamable_v) + storage.eval_func = [&operators..., largest](const tree_t& tree, void* context) { + const auto& ops = tree.get_operations(); + const auto& vals = tree.get_values(); + + evaluation_context results{}; + + auto value_stack = vals; + auto& values_process = results.values; + static thread_local detail::bitmask_t bitfield; + bitfield.clear(); + + for (const auto& operation : blt::reverse_iterate(ops.begin(), ops.end())) { - out << stack.from(0); - (void) (op); // remove warning - } else - { - out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]"; + if (operation.is_value) + { + value_stack.transfer_bytes(values_process, operation.type_size); + bitfield.push_back(false); + continue; + } + call_jmp_table(operation.id, context, values_process, values_process, &bitfield, operators...); + bitfield.push_back(true); } - }); - storage.destroy_funcs.push_back([](detail::destroy_t type, detail::bitmask_t* mask, stack_allocator& alloc) { - switch (type) - { - case detail::destroy_t::ARGS: - alloc.call_destructors(mask); - break; - case detail::destroy_t::RETURN: - if constexpr (detail::has_func_drop_v>) - { - alloc.from>(0).drop(); - } - break; - } - }); - storage.names.push_back(op.get_name()); - if (is_static) - storage.static_types.insert(operator_id); - return *this; - } - - operator_storage& build() - { + + return results; + }; + blt::hashset_t has_terminals; for (const auto& v : blt::enumerate(storage.terminals)) @@ -232,6 +206,64 @@ namespace blt::gp } private: + template + auto add_operator(operation_t& op) + { + auto total_size_required = stack_allocator::aligned_size(sizeof(Return)); + ((total_size_required += stack_allocator::aligned_size(sizeof(Args))) , ...); + + auto return_type_id = system.get_type().id(); + auto operator_id = blt::gp::operator_id(storage.operators.size()); + op.id = operator_id; + + operator_info info; + + if constexpr (sizeof...(Args) > 0) + { + (add_non_context_argument>(info.argument_types), ...); + } + + info.argc.argc_context = info.argc.argc = sizeof...(Args); + info.return_type = return_type_id; + + ((std::is_same_v, Context> ? info.argc.argc -= 1 : (blt::size_t) nullptr), ...); + + auto& operator_list = info.argc.argc == 0 ? storage.terminals : storage.non_terminals; + operator_list[return_type_id].push_back(operator_id); + + BLT_ASSERT(info.argc.argc_context - info.argc.argc <= 1 && "Cannot pass multiple context as arguments!"); + + storage.operators.push_back(info); + storage.print_funcs.push_back([&op](std::ostream& out, stack_allocator& stack) { + if constexpr (blt::meta::is_streamable_v) + { + out << stack.from(0); + (void) (op); // remove warning + } else + { + out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]"; + } + }); + storage.destroy_funcs.push_back([](detail::destroy_t type, detail::bitmask_t* mask, stack_allocator& alloc) { + switch (type) + { + case detail::destroy_t::ARGS: + alloc.call_destructors(mask); + break; + case detail::destroy_t::RETURN: + if constexpr (detail::has_func_drop_v>) + { + alloc.from>(0).drop(); + } + break; + } + }); + storage.names.push_back(op.get_name()); + if (op.is_ephemeral()) + storage.static_types.insert(operator_id); + return total_size_required; + } + template void add_non_context_argument(decltype(operator_info::argument_types)& types) { @@ -241,6 +273,42 @@ namespace blt::gp } } + template + static inline bool execute(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, + Lambda lambda) + { + if (op == id) + { + if constexpr (HasContext) + { + write_stack.push(lambda(context, read_stack, mask)); + } else + { + write_stack.push(lambda(read_stack, mask)); + } + return false; + } + return true; + } + + template + static inline void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, + detail::bitmask_t* mask, std::integer_sequence, Lambdas... lambdas) + { + if (op > sizeof...(operator_ids)) + BLT_UNREACHABLE; + (execute, operator_ids>( + op, context, write_stack, read_stack, mask, lambdas) && ...); + } + + template + static inline void call_jmp_table(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, + detail::bitmask_t* mask, Lambdas... lambdas) + { + call_jmp_table_internal(op, context, write_stack, read_stack, mask, std::index_sequence_for(), + lambdas...); + } + type_provider& system; operator_storage storage; }; @@ -603,6 +671,11 @@ namespace blt::gp storage = std::move(op); } + inline detail::eval_func_t& get_eval_func() + { + return storage.eval_func; + } + [[nodiscard]] inline auto get_current_generation() const { return current_generation.load(); diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index 97eca1d..1e69dc5 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -34,11 +34,10 @@ namespace blt::gp struct op_container_t { - op_container_t(detail::callable_t& func, blt::size_t type_size, operator_id id, bool is_value): - func(func), type_size(type_size), id(id), is_value(is_value) + op_container_t(blt::size_t type_size, operator_id id, bool is_value): + type_size(type_size), id(id), is_value(is_value) {} - std::reference_wrapper func; blt::size_t type_size; operator_id id; bool is_value; @@ -46,11 +45,8 @@ namespace blt::gp class evaluation_context { - friend class tree_t; - - private: - explicit evaluation_context() - {} + public: + explicit evaluation_context() = default; blt::gp::stack_allocator values; }; @@ -86,7 +82,7 @@ namespace blt::gp return values; } - evaluation_context evaluate(void* context) const; + evaluation_context evaluate(void* context, detail::eval_func_t& func) const; blt::size_t get_depth(gp_program& program); @@ -112,9 +108,9 @@ namespace blt::gp * Helper template for returning the result of evaluation (this calls it) */ template - T get_evaluation_value(void* context) + T get_evaluation_value(void* context, detail::eval_func_t& func) { - auto results = evaluate(context); + auto results = evaluate(context, func); return results.values.pop(); } diff --git a/lib/blt b/lib/blt index 78710a1..9ce6c89 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit 78710a12cca9ecf7f92394ddf66ed5e2c0301484 +Subproject commit 9ce6c89ce0145902d31515194a707a9aca948121 diff --git a/src/generators.cpp b/src/generators.cpp index 1443f07..301a22b 100644 --- a/src/generators.cpp +++ b/src/generators.cpp @@ -63,7 +63,6 @@ namespace blt::gp auto& info = args.program.get_operator_info(top.id); tree.get_operations().emplace_back( - info.function, args.program.get_typesystem().get_type(info.return_type).size(), top.id, args.program.is_static(top.id)); @@ -71,7 +70,7 @@ namespace blt::gp if (args.program.is_static(top.id)) { - info.function(nullptr, tree.get_values(), tree.get_values(), nullptr); + //info.function(nullptr, tree.get_values(), tree.get_values(), nullptr); continue; } diff --git a/src/transformers.cpp b/src/transformers.cpp index 5b255a0..a64faa5 100644 --- a/src/transformers.cpp +++ b/src/transformers.cpp @@ -93,8 +93,8 @@ namespace blt::gp blt::size_t c1_stack_after_bytes = accumulate_type_sizes(crossover_point_end_itr, c1_ops.end()); blt::size_t c1_stack_for_bytes = accumulate_type_sizes(crossover_point_begin_itr, crossover_point_end_itr); - blt::size_t c2_stack_after_bytes = accumulate_type_sizes(found_point_end_itr, c2_ops.end()); - blt::size_t c2_stack_for_bytes = accumulate_type_sizes(found_point_begin_itr, found_point_end_itr); + blt::size_t c2_stack_after_bytes = accumulate_type_sizes(found_point_end_itr, c2_ops.end()); + blt::size_t c2_stack_for_bytes = accumulate_type_sizes(found_point_begin_itr, found_point_end_itr); auto c1_total = static_cast(c1_stack_after_bytes + c1_stack_for_bytes); auto c2_total = static_cast(c2_stack_after_bytes + c2_stack_for_bytes); auto copy_ptr_c1 = get_thread_pointer_for_size(c1_total); @@ -111,7 +111,7 @@ namespace blt::gp c1_stack.copy_from(copy_ptr_c2, c2_stack_for_bytes); c1_stack.copy_from(copy_ptr_c1 + c1_stack_for_bytes, c1_stack_after_bytes); - + // now swap the operators auto insert_point_c1 = crossover_point_begin_itr - 1; auto insert_point_c2 = found_point_begin_itr - 1; @@ -252,46 +252,46 @@ namespace blt::gp // this will check to make sure that the tree is in a correct and executable state. it requires that the evaluation is context free! #if BLT_DEBUG_LEVEL >= 2 -// BLT_ASSERT(new_vals_r.empty()); - //BLT_ASSERT(stack_after.empty()); - blt::size_t bytes_expected = 0; - auto bytes_size = vals_r.size().total_used_bytes; - - for (const auto& op : c.get_operations()) - { - if (op.is_value) - bytes_expected += stack_allocator::aligned_size(op.type_size); - } - - if (bytes_expected != bytes_size) - { - BLT_WARN_STREAM << "Stack state: " << vals_r.size() << "\n"; - BLT_WARN("Child tree bytes %ld vs expected %ld, difference: %ld", bytes_size, bytes_expected, - static_cast(bytes_expected) - static_cast(bytes_size)); - BLT_TRACE("Total bytes after: %ld", total_bytes_after); - BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); - } - auto copy = c; - try - { - auto result = copy.evaluate(nullptr); - blt::black_box(result); - } catch (...) - { - std::cout << "This occurred at point " << begin_point << " ending at (old) " << end_point << "\n"; - std::cout << "our root type is " << ops_r[begin_point].id << " with size " << stack_allocator::aligned_size(ops_r[begin_point].type_size) - << "\n"; - std::cout << "now Named: " << (program.get_name(ops_r[begin_point].id) ? *program.get_name(ops_r[begin_point].id) : "Unnamed") << "\n"; - std::cout << "Was named: " << (program.get_name(begin_operator_id) ? *program.get_name(begin_operator_id) : "Unnamed") << "\n"; - //std::cout << "Parent:" << std::endl; - //p.print(program, std::cout, false, true); - std::cout << "Child:" << std::endl; - c.print(program, std::cout, false, true); - std::cout << std::endl; - c.print(program, std::cout, true, true); - std::cout << std::endl; - throw std::exception(); - } + // BLT_ASSERT(new_vals_r.empty()); + //BLT_ASSERT(stack_after.empty()); + blt::size_t bytes_expected = 0; + auto bytes_size = vals_r.size().total_used_bytes; + + for (const auto& op : c.get_operations()) + { + if (op.is_value) + bytes_expected += stack_allocator::aligned_size(op.type_size); + } + + if (bytes_expected != bytes_size) + { + BLT_WARN_STREAM << "Stack state: " << vals_r.size() << "\n"; + BLT_WARN("Child tree bytes %ld vs expected %ld, difference: %ld", bytes_size, bytes_expected, + static_cast(bytes_expected) - static_cast(bytes_size)); + BLT_TRACE("Total bytes after: %ld", total_bytes_after); + BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); + } + auto copy = c; + try + { + auto result = copy.evaluate(nullptr); + blt::black_box(result); + } catch (...) + { + std::cout << "This occurred at point " << begin_point << " ending at (old) " << end_point << "\n"; + std::cout << "our root type is " << ops_r[begin_point].id << " with size " << stack_allocator::aligned_size(ops_r[begin_point].type_size) + << "\n"; + std::cout << "now Named: " << (program.get_name(ops_r[begin_point].id) ? *program.get_name(ops_r[begin_point].id) : "Unnamed") << "\n"; + std::cout << "Was named: " << (program.get_name(begin_operator_id) ? *program.get_name(begin_operator_id) : "Unnamed") << "\n"; + //std::cout << "Parent:" << std::endl; + //p.print(program, std::cout, false, true); + std::cout << "Child:" << std::endl; + c.print(program, std::cout, false, true); + std::cout << std::endl; + c.print(program, std::cout, true, true); + std::cout << std::endl; + throw std::exception(); + } #endif return begin_point + new_ops_r.size(); } @@ -457,8 +457,8 @@ namespace blt::gp vals.copy_from(data, total_bytes_after); } // now finally update the type. - ops[c_node] = {replacement_func_info.function, program.get_typesystem().get_type(replacement_func_info.return_type).size(), - random_replacement, program.is_static(random_replacement)}; + ops[c_node] = {program.get_typesystem().get_type(replacement_func_info.return_type).size(), random_replacement, + program.is_static(random_replacement)}; } #if BLT_DEBUG_LEVEL >= 2 if (!c.check(program, nullptr)) @@ -543,7 +543,7 @@ namespace blt::gp vals.copy_from(combined_ptr + for_bytes, after_bytes); ops.insert(ops.begin() + static_cast(c_node), - {replacement_func_info.function, program.get_typesystem().get_type(replacement_func_info.return_type).size(), + {program.get_typesystem().get_type(replacement_func_info.return_type).size(), random_replacement, program.is_static(random_replacement)}); #if BLT_DEBUG_LEVEL >= 2 diff --git a/src/tree.cpp b/src/tree.cpp index 96198c0..73acafa 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -37,10 +37,7 @@ namespace blt::gp return buffer; } - inline auto empty_callable = detail::callable_t( - [](void*, stack_allocator&, stack_allocator&, detail::bitmask_t*) { BLT_ABORT("This should never be called!"); }); - - evaluation_context tree_t::evaluate(void* context) const + evaluation_context tree_t::evaluate(void* context, detail::eval_func_t& func) const { #if BLT_DEBUG_LEVEL >= 2 blt::size_t expected_bytes = 0; @@ -56,27 +53,27 @@ namespace blt::gp BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); } #endif - // copy the initial values - evaluation_context results{}; +// // copy the initial values +// evaluation_context results{}; +// +// auto value_stack = values; +// auto& values_process = results.values; +// static thread_local detail::bitmask_t bitfield; +// bitfield.clear(); +// +// for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) +// { +// if (operation.is_value) +// { +// value_stack.transfer_bytes(values_process, operation.type_size); +// bitfield.push_back(false); +// continue; +// } +// operation.func(context, values_process, values_process, &bitfield); +// bitfield.push_back(true); +// } - auto value_stack = values; - auto& values_process = results.values; - static thread_local detail::bitmask_t bitfield; - bitfield.clear(); - - for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) - { - if (operation.is_value) - { - value_stack.transfer_bytes(values_process, operation.type_size); - bitfield.push_back(false); - continue; - } - operation.func(context, values_process, values_process, &bitfield); - bitfield.push_back(true); - } - - return results; + return func(*this, context); } std::ostream& create_indent(std::ostream& out, blt::size_t amount, bool pretty_print) @@ -216,7 +213,7 @@ namespace blt::gp values_process.pop_back(); } value_stack.push_back(local_depth + 1); - operations_stack.emplace_back(empty_callable, operation.type_size, operation.id, true); + operations_stack.emplace_back(operation.type_size, operation.id, true); } return depth; @@ -291,22 +288,22 @@ namespace blt::gp blt::size_t total_produced = 0; blt::size_t total_consumed = 0; - for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) - { - if (operation.is_value) - { - value_stack.transfer_bytes(values_process, operation.type_size); - total_produced += stack_allocator::aligned_size(operation.type_size); - bitfield.push_back(false); - continue; - } - auto& info = program.get_operator_info(operation.id); - for (auto& arg : info.argument_types) - total_consumed += stack_allocator::aligned_size(program.get_typesystem().get_type(arg).size()); - operation.func(context, values_process, values_process, &bitfield); - bitfield.push_back(true); - total_produced += stack_allocator::aligned_size(program.get_typesystem().get_type(info.return_type).size()); - } +// for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) +// { +// if (operation.is_value) +// { +// value_stack.transfer_bytes(values_process, operation.type_size); +// total_produced += stack_allocator::aligned_size(operation.type_size); +// bitfield.push_back(false); +// continue; +// } +// auto& info = program.get_operator_info(operation.id); +// for (auto& arg : info.argument_types) +// total_consumed += stack_allocator::aligned_size(program.get_typesystem().get_type(arg).size()); +// operation.func(context, values_process, values_process, &bitfield); +// bitfield.push_back(true); +// total_produced += stack_allocator::aligned_size(program.get_typesystem().get_type(info.return_type).size()); +// } auto v1 = results.values.bytes_in_head(); auto v2 = static_cast(stack_allocator::aligned_size(operations.front().type_size)); From 17a2805ef108a4d496f7197988b0f45aefa73614 Mon Sep 17 00:00:00 2001 From: Brett Date: Tue, 20 Aug 2024 13:52:06 -0400 Subject: [PATCH 3/7] silly --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 12 ------------ include/blt/gp/fwdecl.h | 2 +- include/blt/gp/operations.h | 30 +++++++++++++++--------------- include/blt/gp/program.h | 3 +++ src/generators.cpp | 2 +- 6 files changed, 21 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2b8b85e..019bcd6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.14) +project(blt-gp VERSION 0.1.15) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index 3227c6a..53024da 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -102,18 +102,6 @@ int main() type_system.register_type(); blt::gp::operator_builder 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(add, sub, mul, pro_div, op_sin, op_cos, op_exp, op_log, lit, op_x)); BLT_DEBUG("Generate Initial Population"); diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index 97b1761..bc45258 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -57,7 +57,7 @@ namespace blt::gp class operator_storage_test; // context*, read stack, write stack - //using callable_t = std::function; + using operator_func_t = std::function; using eval_func_t = std::function; // debug function, using print_func_t = std::function; diff --git a/include/blt/gp/operations.h b/include/blt/gp/operations.h index 0678634..57f8ffd 100644 --- a/include/blt/gp/operations.h +++ b/include/blt/gp/operations.h @@ -187,21 +187,21 @@ namespace blt::gp } } -// template -// [[nodiscard]] detail::callable_t make_callable() const -// { -// return [this](void* context, stack_allocator& read_allocator, stack_allocator& write_allocator, detail::bitmask_t* mask) { -// if constexpr (detail::is_same_v::type>>) -// { -// // first arg is context -// write_allocator.push(this->operator()(context, read_allocator, mask)); -// } else -// { -// // first arg isn't context -// write_allocator.push(this->operator()(read_allocator, mask)); -// } -// }; -// } + template + [[nodiscard]] detail::operator_func_t make_callable() const + { + return [this](void* context, stack_allocator& read_allocator, stack_allocator& write_allocator) { + if constexpr (detail::is_same_v::type>>) + { + // first arg is context + write_allocator.push(this->operator()(context, read_allocator, nullptr)); + } else + { + // first arg isn't context + write_allocator.push(this->operator()(read_allocator, nullptr)); + } + }; + } [[nodiscard]] inline constexpr std::optional get_name() const { diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index fdee5cd..51fbefb 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -75,6 +75,8 @@ namespace blt::gp type_id return_type; // number of arguments for this operator argc_t argc; + // per operator function callable (slow) + detail::operator_func_t func; }; struct operator_storage @@ -225,6 +227,7 @@ namespace blt::gp info.argc.argc_context = info.argc.argc = sizeof...(Args); info.return_type = return_type_id; + info.func = op.template make_callable(); ((std::is_same_v, Context> ? info.argc.argc -= 1 : (blt::size_t) nullptr), ...); diff --git a/src/generators.cpp b/src/generators.cpp index 301a22b..9c5b4eb 100644 --- a/src/generators.cpp +++ b/src/generators.cpp @@ -70,7 +70,7 @@ namespace blt::gp if (args.program.is_static(top.id)) { - //info.function(nullptr, tree.get_values(), tree.get_values(), nullptr); + info.func(nullptr, tree.get_values(), tree.get_values()); continue; } From 24f702b35e7d12b2de3d393dcf4d6147d24ade96 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Tue, 20 Aug 2024 21:58:29 -0400 Subject: [PATCH 4/7] silly tables --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 2 +- include/blt/gp/program.h | 53 +++++++++++++++++++------------- include/blt/gp/stack.h | 25 ++++++++++----- 4 files changed, 52 insertions(+), 30 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 019bcd6..ba2e0f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.15) +project(blt-gp VERSION 0.1.16) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index 53024da..7e4869d 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -39,7 +39,7 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t() .set_mutation_chance(0.1) .set_reproduction_chance(0) .set_max_generations(50) - .set_pop_size(500) + .set_pop_size(5000) .set_thread_count(0); blt::gp::type_provider type_system; diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 51fbefb..5c03aad 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -120,21 +120,22 @@ namespace blt::gp const auto& vals = tree.get_values(); evaluation_context results{}; + results.values.reserve(largest); - auto value_stack = vals; - auto& values_process = results.values; static thread_local detail::bitmask_t bitfield; bitfield.clear(); + blt::size_t total_so_far = 0; for (const auto& operation : blt::reverse_iterate(ops.begin(), ops.end())) { if (operation.is_value) { - value_stack.transfer_bytes(values_process, operation.type_size); + total_so_far += stack_allocator::aligned_size(operation.type_size); + results.values.copy_from(vals.from(total_so_far), stack_allocator::aligned_size(operation.type_size)); bitfield.push_back(false); continue; } - call_jmp_table(operation.id, context, values_process, values_process, &bitfield, operators...); + call_jmp_table(operation.id, context, results.values, results.values, &bitfield, operators...); bitfield.push_back(true); } @@ -212,7 +213,7 @@ namespace blt::gp auto add_operator(operation_t& op) { auto total_size_required = stack_allocator::aligned_size(sizeof(Return)); - ((total_size_required += stack_allocator::aligned_size(sizeof(Args))) , ...); + ((total_size_required += stack_allocator::aligned_size(sizeof(Args))), ...); auto return_type_id = system.get_type().id(); auto operator_id = blt::gp::operator_id(storage.operators.size()); @@ -276,19 +277,26 @@ namespace blt::gp } } - template - static inline bool execute(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, - Lambda lambda) + template + static inline void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, + Lambda& lambda) { - if (op == id) + if constexpr (std::is_same_v, Context>) { - if constexpr (HasContext) - { - write_stack.push(lambda(context, read_stack, mask)); - } else - { - write_stack.push(lambda(read_stack, mask)); - } + write_stack.push(lambda(context, read_stack, mask)); + } else + { + write_stack.push(lambda(read_stack, mask)); + } + } + + template + static inline bool call(blt::size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, + Lambda& lambda) + { + if (id == op) + { + execute(context, write_stack, read_stack, mask, lambda); return false; } return true; @@ -296,17 +304,20 @@ namespace blt::gp template static inline void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, - detail::bitmask_t* mask, std::integer_sequence, Lambdas... lambdas) + detail::bitmask_t* mask, std::integer_sequence, Lambdas& ... lambdas) { - if (op > sizeof...(operator_ids)) + if (op >= sizeof...(operator_ids)) + { BLT_UNREACHABLE; - (execute, operator_ids>( - op, context, write_stack, read_stack, mask, lambdas) && ...); + } + (call(op, context, write_stack, read_stack, mask, lambdas) && ...); +// std::initializer_list{((op == operator_ids) ? (execute(context, write_stack, read_stack, mask, lambdas), 0) : 0)...}; + } template static inline void call_jmp_table(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, - detail::bitmask_t* mask, Lambdas... lambdas) + detail::bitmask_t* mask, Lambdas& ... lambdas) { call_jmp_table_internal(op, context, write_stack, read_stack, mask, std::index_sequence_for(), lambdas...); diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index a356ad9..59971b5 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -66,6 +66,7 @@ namespace blt::gp using Allocator = aligned_allocator; public: static Allocator& get_allocator(); + struct size_data_t { blt::size_t total_size_bytes = 0; @@ -185,18 +186,22 @@ namespace blt::gp return *reinterpret_cast(data_ + bytes_stored); } + [[nodiscard]] blt::u8* from(blt::size_t bytes) const + { +#if BLT_DEBUG_LEVEL > 0 + if (bytes_stored < bytes) + BLT_ABORT(("Not enough bytes in stack to reference " + std::to_string(bytes) + " bytes requested but " + std::to_string(bytes) + + " bytes stored!").c_str()); +#endif + return data_ + (bytes_stored - bytes); + } + template> T& from(blt::size_t bytes) { static_assert(std::is_trivially_copyable_v && "Type must be bitwise copyable!"); static_assert(alignof(NO_REF) <= MAX_ALIGNMENT && "Type alignment must not be greater than the max alignment!"); - auto size = aligned_size(sizeof(NO_REF)) + bytes; -#if BLT_DEBUG_LEVEL > 0 - if (bytes_stored < size) - BLT_ABORT(("Not enough bytes in stack to reference " + std::to_string(size) + " bytes requested but " + std::to_string(bytes) + - " bytes stored!").c_str()); -#endif - return *reinterpret_cast(data_ + (bytes_stored - size)); + return *reinterpret_cast(from(aligned_size(sizeof(NO_REF)) + bytes)); } void pop_bytes(blt::size_t bytes) @@ -266,6 +271,12 @@ namespace blt::gp return data; } + + void reserve(blt::size_t bytes) + { + if (bytes > size_) + expand(bytes); + } private: void expand(blt::size_t bytes) From 3d82f693700cab5d9fc7a9d485b07f27d0e6b795 Mon Sep 17 00:00:00 2001 From: Brett Date: Wed, 21 Aug 2024 00:54:39 -0400 Subject: [PATCH 5/7] i think this works now --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 3 ++- test_perf.sh | 2 +- test_perf_clang.sh | 2 +- test_perf_minsize_clang.sh | 1 + 5 files changed, 6 insertions(+), 4 deletions(-) create mode 100755 test_perf_minsize_clang.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index ba2e0f6..b2240b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.16) +project(blt-gp VERSION 0.1.17) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index 7e4869d..bdf65f5 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -39,7 +39,7 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t() .set_mutation_chance(0.1) .set_reproduction_chance(0) .set_max_generations(50) - .set_pop_size(5000) + .set_pop_size(50000) .set_thread_count(0); blt::gp::type_provider type_system; @@ -57,6 +57,7 @@ blt::gp::operation_t op_log([](float a) { return a == 0.0f ? 0.0f : std::log(a); auto lit = blt::gp::operation_t([]() { return program.get_random().get_float(-320.0f, 320.0f); }, "lit").set_ephemeral(); + blt::gp::operation_t op_x([](const context& context) { return context.x; }, "x"); diff --git a/test_perf.sh b/test_perf.sh index ae120c8..a3527af 100755 --- a/test_perf.sh +++ b/test_perf.sh @@ -1 +1 @@ -perf stat -d -d -d -r 30 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch,page-faults,page-faults:u,page-faults:k ./cmake-build-release/blt-symbolic-regression-example +perf stat -d -d -d -r 50 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch,page-faults,page-faults:u,page-faults:k ./cmake-build-release/blt-symbolic-regression-example diff --git a/test_perf_clang.sh b/test_perf_clang.sh index 6cf0e9e..949d6ba 100755 --- a/test_perf_clang.sh +++ b/test_perf_clang.sh @@ -1 +1 @@ -perf stat -d -d -d -r 30 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch,page-faults,page-faults:u,page-faults:k ./cmake-build-release-clang/blt-SR-playground-example +perf stat -d -d -d -r 50 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch,page-faults,page-faults:u,page-faults:k ./cmake-build-release-clang/blt-symbolic-regression-example diff --git a/test_perf_minsize_clang.sh b/test_perf_minsize_clang.sh new file mode 100755 index 0000000..27205b8 --- /dev/null +++ b/test_perf_minsize_clang.sh @@ -0,0 +1 @@ +perf stat -d -d -d -r 50 -e branches,branch-misses,cache-misses,cache-references,cycles,instructions,alignment-faults,cgroup-switches,faults,duration_time,user_time,system_time,L1-dcache-loads,L1-dcache-load-misses,L1-dcache-prefetches,L1-icache-loads,L1-icache-load-misses,dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses,l2_request_g1.all_no_prefetch,page-faults,page-faults:u,page-faults:k ./cmake-build-minsizerel-clang/blt-symbolic-regression-example From 46ceaf49dd48f98a289d22f039d933d3138d3130 Mon Sep 17 00:00:00 2001 From: Brett Date: Wed, 21 Aug 2024 01:40:21 -0400 Subject: [PATCH 6/7] meow --- CMakeLists.txt | 2 +- tests/gp_test_1.cpp | 15 ++++++--------- tests/gp_test_2.cpp | 22 ++++++++++------------ tests/order_tests.cpp | 16 ++++++---------- tests/stack_tests.cpp | 24 ++++++++++++------------ 5 files changed, 35 insertions(+), 44 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2240b9..c7bdaad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.17) +project(blt-gp VERSION 0.1.18) include(CTest) diff --git a/tests/gp_test_1.cpp b/tests/gp_test_1.cpp index e1fe9be..bf0b295 100644 --- a/tests/gp_test_1.cpp +++ b/tests/gp_test_1.cpp @@ -319,9 +319,9 @@ namespace blt::gp::detail explicit operator_storage_test(blt::gp::operator_builder& ops): ops(ops) {} - inline blt::gp::detail::callable_t& operator[](blt::size_t index) + inline blt::gp::detail::operator_func_t& operator[](blt::size_t index) { - return ops.storage.operators[index].function; + return ops.storage.operators[index].func; } private: @@ -447,24 +447,21 @@ int main() //BLT_TRACE(blt::type_string>()); //BLT_TRACE("Same types? %s", (std::is_same_v>) ? "true" : "false"); - ops.add_operator(silly_op_3); - ops.add_operator(silly_op_4); - ops.add_operator(silly_op_2); - + ops.build(silly_op_3, silly_op_4, silly_op_2); blt::gp::detail::operator_storage_test de(ops); context hello{5, 10}; alloc.push(1.153f); - de[0](static_cast(&hello), alloc, alloc, nullptr); + de[0](static_cast(&hello), alloc, alloc); BLT_TRACE("first value: %f", alloc.pop()); - de[1](static_cast(&hello), alloc, alloc, nullptr); + de[1](static_cast(&hello), alloc, alloc); BLT_TRACE("second value: %f", alloc.pop()); alloc.push(1.0f); alloc.push(52.213f); - de[2](static_cast(&hello), alloc, alloc, nullptr); + de[2](static_cast(&hello), alloc, alloc); BLT_TRACE("third value: %f", alloc.pop()); //auto* pointer = static_cast(head->metadata.offset); diff --git a/tests/gp_test_2.cpp b/tests/gp_test_2.cpp index e2c641f..50a68dc 100644 --- a/tests/gp_test_2.cpp +++ b/tests/gp_test_2.cpp @@ -32,18 +32,21 @@ blt::gp::operation_t add([](float a, float b) { }); blt::gp::operation_t sub([](float a, float b) { BLT_TRACE("a: %f - b: %f = %f", a, b, a - b); - return a - b; }); + return a - b; +}); blt::gp::operation_t mul([](float a, float b) { BLT_TRACE("a: %f * b: %f = %f", a, b, a * b); - return a * b; }); + return a * b; +}); blt::gp::operation_t pro_div([](float a, float b) { BLT_TRACE("a: %f / b: %f = %f", a, b, (b == 0 ? 0.0f : a / b)); - return b == 0 ? 0.0f : a / b; }); -blt::gp::operation_t lit([]() { + return b == 0 ? 0.0f : a / b; +}); +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); return program.get_random().get_float(0.0f, 10.0f); -}); +}).set_ephemeral(); /** * This is a test using a type with blt::gp @@ -53,18 +56,13 @@ int main() type_system.register_type(); blt::gp::operator_builder silly{type_system}; - silly.add_operator(add); - silly.add_operator(sub); - silly.add_operator(mul); - silly.add_operator(pro_div); - silly.add_operator(lit, true); - program.set_operations(silly.build()); + program.set_operations(silly.build(add, sub, mul, pro_div, lit)); blt::gp::grow_generator_t grow; auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7}); - auto value = tree.get_evaluation_value(nullptr); + auto value = tree.get_evaluation_value(nullptr, program.get_eval_func()); BLT_TRACE(value); diff --git a/tests/order_tests.cpp b/tests/order_tests.cpp index 1eb05c6..d59ea4e 100644 --- a/tests/order_tests.cpp +++ b/tests/order_tests.cpp @@ -72,13 +72,13 @@ blt::gp::operation_t basic_sub([](float a, float b, bool choice) { } }, "sub"); -blt::gp::operation_t basic_lit_f([]() { +auto basic_lit_f= blt::gp::operation_t([]() { return b_rand.choice() ? 5.0f : 10.0f; -}); +}).set_ephemeral(); -blt::gp::operation_t basic_lit_b([]() { +auto basic_lit_b = blt::gp::operation_t([]() { return false; -}); +}).set_ephemeral(); void basic_test() { @@ -86,18 +86,14 @@ void basic_test() blt::gp::operator_builder builder{type_system}; - builder.add_operator(basic_sub); - builder.add_operator(basic_lit_f, true); - builder.add_operator(basic_lit_b, true); - - program.set_operations(builder.build()); + program.set_operations(builder.build(basic_sub, basic_lit_f, basic_lit_b)); blt::gp::grow_generator_t gen; blt::gp::generator_arguments args{program, type_system.get_type().id(), 1, 1}; auto tree = gen.generate(args); context ctx{&program}; - auto result = tree.get_evaluation_value(&ctx); + auto result = tree.get_evaluation_value(&ctx, program.get_eval_func()); BLT_TRACE(result); BLT_ASSERT(result == -5.0f || result == 5.0f || result == 0.0f); tree.print(program, std::cout, true, true); diff --git a/tests/stack_tests.cpp b/tests/stack_tests.cpp index bb66af6..c9a34c7 100644 --- a/tests/stack_tests.cpp +++ b/tests/stack_tests.cpp @@ -302,7 +302,7 @@ void test_basic() stack.push(50.0f); stack.push(10.0f); BLT_TRACE_STREAM << stack.size() << "\n"; - basic_2.make_callable()(nullptr, stack, stack, nullptr); + basic_2.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(val != 60.000000f, stack, "Basic 2 Test Passed", "Basic 2 Test Failed. Unexpected value produced '%lf'", val); @@ -318,7 +318,7 @@ void test_basic() auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; //BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); - basic_2.make_callable()(nullptr, stack, stack, nullptr); + basic_2.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); stack.pop>(); @@ -339,7 +339,7 @@ void test_mixed() stack.push(false); BLT_TRACE_STREAM << stack.size() << "\n"; - basic_mixed_4.make_callable()(nullptr, stack, stack, nullptr); + basic_mixed_4.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(val != 50.000000f, stack, "Mixed 4 Test Passed", "Mixed 4 Test Failed. Unexpected value produced '%lf'", val); @@ -357,7 +357,7 @@ void test_mixed() auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; // BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); - basic_mixed_4.make_callable()(nullptr, stack, stack, nullptr); + basic_mixed_4.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); stack.pop>(); @@ -377,7 +377,7 @@ void test_large_256() stack.push(69.420f); BLT_TRACE_STREAM << stack.size() << "\n"; - large_256_basic_3.make_callable()(nullptr, stack, stack, nullptr); + large_256_basic_3.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(!compare(val, base_256), stack, "Large 256 3 Test Passed", "Large 256 3 Test Failed. Unexpected value produced '%lf'", val); @@ -394,7 +394,7 @@ void test_large_256() auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; // BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); - large_256_basic_3.make_callable()(nullptr, stack, stack, nullptr); + large_256_basic_3.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); stack.pop>(); @@ -413,7 +413,7 @@ void test_large_4096() stack.push(33.0f); stack.push(true); BLT_TRACE_STREAM << stack.size() << "\n"; - large_4096_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_4096_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(!compare(val, base_4096), stack, "Large 4096 3 Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val); @@ -429,7 +429,7 @@ void test_large_4096() auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; // BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); - large_4096_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_4096_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(!compare(val, base_4096), stack, "Large 4096 3 Boundary Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val); @@ -447,7 +447,7 @@ void test_large_18290() stack.push(-2543.0f); stack.push(true); BLT_TRACE_STREAM << stack.size() << "\n"; - large_18290_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_18290_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(!compare(val, base_18290), stack, "Large 18290 3 Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val); @@ -464,7 +464,7 @@ void test_large_18290() auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; // BLT_ASSERT(size.blocks > 1 && "Stack doesn't have more than one block!"); - large_18290_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_18290_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); stack.pop>(); @@ -480,12 +480,12 @@ void test_large_18290() stack.push(true); auto size = stack.size(); BLT_TRACE_STREAM << size << "\n"; - large_18290_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_18290_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; stack.push(-2543.0f); stack.push(true); BLT_TRACE_STREAM << stack.size() << "\n"; - large_18290_basic_3b.make_callable()(nullptr, stack, stack, nullptr); + large_18290_basic_3b.make_callable()(nullptr, stack, stack); BLT_TRACE_STREAM << stack.size() << "\n"; auto val = stack.pop(); RUN_TEST(!compare(val, base_18290), stack, "Large 18290 3 Boundary Test Passed", "Large 4096 3 Test Failed. Unexpected value produced '%lf'", val); From 7aaad7013299f50ee91d4f5015c9ad48b80e23b6 Mon Sep 17 00:00:00 2001 From: Brett Laptop Date: Wed, 21 Aug 2024 20:40:42 -0400 Subject: [PATCH 7/7] remove bitmask, fix the other tests --- CMakeLists.txt | 2 +- examples/symbolic_regression.cpp | 4 +- include/blt/gp/fwdecl.h | 5 +- include/blt/gp/operations.h | 22 ++++----- include/blt/gp/program.h | 47 +++++++----------- include/blt/gp/stack.h | 23 ++------- include/blt/gp/tree.h | 19 +++++--- src/generators.cpp | 2 +- src/tree.cpp | 82 ++------------------------------ tests/evaluation_tests.cpp | 20 ++------ tests/gp_test_1.cpp | 4 +- tests/gp_test_2.cpp | 2 +- tests/gp_test_3.cpp | 25 ++-------- tests/gp_test_4.cpp | 23 ++------- tests/gp_test_5.cpp | 25 ++-------- tests/gp_test_6.cpp | 23 ++------- tests/gp_test_7.cpp | 23 ++------- tests/order_tests.cpp | 2 +- 18 files changed, 77 insertions(+), 276 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7bdaad..00f2f30 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.18) +project(blt-gp VERSION 0.1.19) include(CTest) diff --git a/examples/symbolic_regression.cpp b/examples/symbolic_regression.cpp index bdf65f5..d9c0b05 100644 --- a/examples/symbolic_regression.cpp +++ b/examples/symbolic_regression.cpp @@ -39,7 +39,7 @@ blt::gp::prog_config_t config = blt::gp::prog_config_t() .set_mutation_chance(0.1) .set_reproduction_chance(0) .set_max_generations(50) - .set_pop_size(50000) + .set_pop_size(5000) .set_thread_count(0); blt::gp::type_provider type_system; @@ -66,7 +66,7 @@ constexpr auto fitness_function = [](blt::gp::tree_t& current_tree, blt::gp::fit constexpr double value_cutoff = 1.e15; for (auto& fitness_case : fitness_cases) { - auto diff = std::abs(fitness_case.y - current_tree.get_evaluation_value(&fitness_case, program.get_eval_func())); + auto diff = std::abs(fitness_case.y - current_tree.get_evaluation_value(&fitness_case)); if (diff < value_cutoff) { fitness.raw_fitness += diff; diff --git a/include/blt/gp/fwdecl.h b/include/blt/gp/fwdecl.h index bc45258..c058d5a 100644 --- a/include/blt/gp/fwdecl.h +++ b/include/blt/gp/fwdecl.h @@ -52,9 +52,6 @@ namespace blt::gp namespace detail { - // requires operator[](bit_index), push_back, clear - using bitmask_t = std::vector; - class operator_storage_test; // context*, read stack, write stack using operator_func_t = std::function; @@ -68,7 +65,7 @@ namespace blt::gp RETURN }; - using destroy_func_t = std::function; + using destroy_func_t = std::function; } } diff --git a/include/blt/gp/operations.h b/include/blt/gp/operations.h index 57f8ffd..9662d6a 100644 --- a/include/blt/gp/operations.h +++ b/include/blt/gp/operations.h @@ -102,16 +102,16 @@ namespace blt::gp } template - void call_destructors_without_first(stack_allocator& read_allocator, detail::bitmask_t* mask) + void call_destructors_without_first(stack_allocator& read_allocator) { if constexpr (sizeof...(NoCtxArgs) > 0) { - read_allocator.call_destructors...>(mask); + read_allocator.call_destructors...>(); } } template - Return operator()(bool has_context, detail::bitmask_t* mask, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args) + Return operator()(bool has_context, Func&& func, stack_allocator& read_allocator, ExtraArgs&& ... args) { constexpr auto seq = std::make_integer_sequence(); #if BLT_DEBUG_LEVEL > 0 @@ -120,9 +120,9 @@ namespace blt::gp #endif Return ret = exec_sequence_to_indices(std::forward(func), read_allocator, seq, std::forward(args)...); if (has_context) - call_destructors_without_first(read_allocator, mask); + call_destructors_without_first(read_allocator); else - read_allocator.call_destructors...>(mask); + read_allocator.call_destructors...>(); read_allocator.pop_bytes((stack_allocator::aligned_size>() + ...)); return ret; #if BLT_DEBUG_LEVEL > 0 @@ -159,18 +159,18 @@ namespace blt::gp constexpr explicit operation_t(const Functor& functor, std::optional name = {}): func(functor), name(name) {} - [[nodiscard]] constexpr inline Return operator()(stack_allocator& read_allocator, detail::bitmask_t* mask) const + [[nodiscard]] constexpr inline Return operator()(stack_allocator& read_allocator) const { if constexpr (sizeof...(Args) == 0) { return func(); } else { - return call_with()(false, mask, func, read_allocator); + return call_with()(false, func, read_allocator); } } - [[nodiscard]] constexpr inline Return operator()(void* context, stack_allocator& read_allocator, detail::bitmask_t* mask) const + [[nodiscard]] constexpr inline Return operator()(void* context, stack_allocator& read_allocator) const { // should be an impossible state if constexpr (sizeof...(Args) == 0) @@ -183,7 +183,7 @@ namespace blt::gp return func(ctx_ref); } else { - return call_without_first()(true, mask, func, read_allocator, ctx_ref); + return call_without_first()(true, func, read_allocator, ctx_ref); } } @@ -194,11 +194,11 @@ namespace blt::gp if constexpr (detail::is_same_v::type>>) { // first arg is context - write_allocator.push(this->operator()(context, read_allocator, nullptr)); + write_allocator.push(this->operator()(context, read_allocator)); } else { // first arg isn't context - write_allocator.push(this->operator()(read_allocator, nullptr)); + write_allocator.push(this->operator()(read_allocator)); } }; } diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 5c03aad..8a87553 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -122,8 +122,6 @@ namespace blt::gp evaluation_context results{}; results.values.reserve(largest); - static thread_local detail::bitmask_t bitfield; - bitfield.clear(); blt::size_t total_so_far = 0; for (const auto& operation : blt::reverse_iterate(ops.begin(), ops.end())) @@ -132,11 +130,9 @@ namespace blt::gp { total_so_far += stack_allocator::aligned_size(operation.type_size); results.values.copy_from(vals.from(total_so_far), stack_allocator::aligned_size(operation.type_size)); - bitfield.push_back(false); continue; } - call_jmp_table(operation.id, context, results.values, results.values, &bitfield, operators...); - bitfield.push_back(true); + call_jmp_table(operation.id, context, results.values, results.values, operators...); } return results; @@ -248,11 +244,11 @@ namespace blt::gp out << "[Printing Value on '" << (op.get_name() ? *op.get_name() : "") << "' Not Supported!]"; } }); - storage.destroy_funcs.push_back([](detail::destroy_t type, detail::bitmask_t* mask, stack_allocator& alloc) { + storage.destroy_funcs.push_back([](detail::destroy_t type, stack_allocator& alloc) { switch (type) { case detail::destroy_t::ARGS: - alloc.call_destructors(mask); + alloc.call_destructors(); break; case detail::destroy_t::RETURN: if constexpr (detail::has_func_drop_v>) @@ -277,50 +273,45 @@ namespace blt::gp } } - template - static inline void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, - Lambda& lambda) + template + static inline void execute(void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation) { - if constexpr (std::is_same_v, Context>) + if constexpr (std::is_same_v, Context>) { - write_stack.push(lambda(context, read_stack, mask)); + write_stack.push(operation(context, read_stack)); } else { - write_stack.push(lambda(read_stack, mask)); + write_stack.push(operation(read_stack)); } } - template - static inline bool call(blt::size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, detail::bitmask_t* mask, - Lambda& lambda) + template + static inline bool call(blt::size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, Operator& operation) { if (id == op) { - execute(context, write_stack, read_stack, mask, lambda); + execute(context, write_stack, read_stack, operation); return false; } return true; } - template + template static inline void call_jmp_table_internal(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, - detail::bitmask_t* mask, std::integer_sequence, Lambdas& ... lambdas) + std::integer_sequence, Operators&... operators) { if (op >= sizeof...(operator_ids)) { BLT_UNREACHABLE; } - (call(op, context, write_stack, read_stack, mask, lambdas) && ...); -// std::initializer_list{((op == operator_ids) ? (execute(context, write_stack, read_stack, mask, lambdas), 0) : 0)...}; - + (call(op, context, write_stack, read_stack, operators) && ...); } - template + template static inline void call_jmp_table(size_t op, void* context, stack_allocator& write_stack, stack_allocator& read_stack, - detail::bitmask_t* mask, Lambdas& ... lambdas) + Operators& ... operators) { - call_jmp_table_internal(op, context, write_stack, read_stack, mask, std::index_sequence_for(), - lambdas...); + call_jmp_table_internal(op, context, write_stack, read_stack, std::index_sequence_for(), operators...); } type_provider& system; @@ -542,8 +533,6 @@ namespace blt::gp void reset_program(type_id root_type, bool eval_fitness_now = true) { current_generation = 0; - for (auto& pop : current_pop) - pop.tree.drop(*this); current_pop = config.pop_initializer.get().generate( {*this, root_type, config.population_size, config.initial_min_tree_size, config.initial_max_tree_size}); if (eval_fitness_now) @@ -552,7 +541,6 @@ namespace blt::gp void next_generation() { - current_pop.drop(*this); current_pop = std::move(next_pop); current_generation++; } @@ -702,7 +690,6 @@ namespace blt::gp ~gp_program() { - current_pop.drop(*this); thread_helper.lifetime_over = true; thread_helper.barrier.notify_all(); thread_helper.thread_function_condition.notify_all(); diff --git a/include/blt/gp/stack.h b/include/blt/gp/stack.h index 59971b5..21668eb 100644 --- a/include/blt/gp/stack.h +++ b/include/blt/gp/stack.h @@ -227,22 +227,13 @@ namespace blt::gp } template - void call_destructors(detail::bitmask_t* mask) + void call_destructors() { if constexpr (sizeof...(Args) > 0) { blt::size_t offset = (stack_allocator::aligned_size(sizeof(NO_REF_T)) + ...) - stack_allocator::aligned_size(sizeof(NO_REF_T::First>)); - blt::size_t index = 0; - if (mask != nullptr) - index = mask->size() - sizeof...(Args); - ((call_drop(offset, index, mask), offset -= stack_allocator::aligned_size(sizeof(NO_REF_T)), ++index), ...); - if (mask != nullptr) - { - auto& mask_r = *mask; - for (blt::size_t i = 0; i < sizeof...(Args); i++) - mask_r.pop_back(); - } + ((call_drop(offset), offset -= stack_allocator::aligned_size(sizeof(NO_REF_T))), ...); } } @@ -282,11 +273,9 @@ namespace blt::gp void expand(blt::size_t bytes) { bytes = to_nearest_page_size(bytes); -// auto new_data = static_cast(std::malloc(bytes)); auto new_data = static_cast(get_allocator().allocate(bytes)); if (bytes_stored > 0) std::memcpy(new_data, data_, bytes_stored); -// std::free(data_); get_allocator().deallocate(data_, size_); data_ = new_data; size_ = bytes; @@ -323,16 +312,10 @@ namespace blt::gp } template - inline void call_drop(blt::size_t offset, blt::size_t index, detail::bitmask_t* mask) + inline void call_drop(blt::size_t offset) { if constexpr (detail::has_func_drop_v) { - if (mask != nullptr) - { - auto& mask_r = *mask; - if (!mask_r[index]) - return; - } from>(offset).drop(); } } diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index 1e69dc5..96dedfa 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -55,6 +55,8 @@ namespace blt::gp { using iter_type = std::vector::const_iterator; public: + explicit tree_t(gp_program& program); + struct child_t { blt::ptrdiff_t start; @@ -82,7 +84,10 @@ namespace blt::gp return values; } - evaluation_context evaluate(void* context, detail::eval_func_t& func) const; + evaluation_context evaluate(void* context) const + { + return (*func)(*this, context); + } blt::size_t get_depth(gp_program& program); @@ -108,9 +113,9 @@ namespace blt::gp * Helper template for returning the result of evaluation (this calls it) */ template - T get_evaluation_value(void* context, detail::eval_func_t& func) + T get_evaluation_value(void* context) { - auto results = evaluate(context, func); + auto results = evaluate(context); return results.values.pop(); } @@ -120,7 +125,9 @@ namespace blt::gp bool check(gp_program& program, void* context) const; void find_child_extends(gp_program& program, std::vector& vec, blt::size_t parent_node, blt::size_t argc) const; + blt::ptrdiff_t find_endpoint(blt::gp::gp_program& program, blt::ptrdiff_t start) const; + blt::ptrdiff_t find_parent(blt::gp::gp_program& program, blt::ptrdiff_t start) const; // valid for [begin, end) @@ -150,12 +157,11 @@ namespace blt::gp { return total_value_bytes(operations.begin(), operations.end()); } - - void drop(gp_program& program); + private: std::vector operations; blt::gp::stack_allocator values; - std::atomic_int64_t* reference_counter; + detail::eval_func_t* func; }; struct fitness_t @@ -306,7 +312,6 @@ namespace blt::gp population_t& operator=(population_t&&) = default; - void drop(gp_program& program); private: std::vector individuals; }; diff --git a/src/generators.cpp b/src/generators.cpp index 9c5b4eb..1ca796e 100644 --- a/src/generators.cpp +++ b/src/generators.cpp @@ -53,7 +53,7 @@ namespace blt::gp { std::stack tree_generator = get_initial_stack(args.program, args.root_type); blt::size_t max_depth = 0; - tree_t tree; + tree_t tree{args.program}; while (!tree_generator.empty()) { diff --git a/src/tree.cpp b/src/tree.cpp index 73acafa..5d6ac32 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -37,45 +37,6 @@ namespace blt::gp return buffer; } - evaluation_context tree_t::evaluate(void* context, detail::eval_func_t& func) const - { -#if BLT_DEBUG_LEVEL >= 2 - blt::size_t expected_bytes = 0; - blt::size_t found_bytes = values.size().total_used_bytes; - for (const auto& op : operations) - { - if (op.is_value) - expected_bytes += stack_allocator::aligned_size(op.type_size); - } - if (expected_bytes != found_bytes) - { - BLT_WARN("Bytes found %ld vs bytes expected %ld", found_bytes, expected_bytes); - BLT_ABORT("Amount of bytes in stack doesn't match the number of bytes expected for the operations"); - } -#endif -// // copy the initial values -// evaluation_context results{}; -// -// auto value_stack = values; -// auto& values_process = results.values; -// static thread_local detail::bitmask_t bitfield; -// bitfield.clear(); -// -// for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) -// { -// if (operation.is_value) -// { -// value_stack.transfer_bytes(values_process, operation.type_size); -// bitfield.push_back(false); -// continue; -// } -// operation.func(context, values_process, values_process, &bitfield); -// bitfield.push_back(true); -// } - - return func(*this, context); - } - std::ostream& create_indent(std::ostream& out, blt::size_t amount, bool pretty_print) { if (!pretty_print) @@ -259,8 +220,6 @@ namespace blt::gp bool tree_t::check(gp_program& program, void* context) const { - static thread_local detail::bitmask_t bitfield; - bitfield.clear(); blt::size_t bytes_expected = 0; auto bytes_size = values.size().total_used_bytes; @@ -287,7 +246,7 @@ namespace blt::gp blt::size_t total_produced = 0; blt::size_t total_consumed = 0; - + // for (const auto& operation : blt::reverse_iterate(operations.begin(), operations.end())) // { // if (operation.is_value) @@ -318,40 +277,6 @@ namespace blt::gp return true; } - void tree_t::drop(gp_program& program) - { - return; - if (values.empty()) - return; - //std::cout << "---- NEW TREE ---- References " << *reference_counter << " ----" << std::endl; - if (reference_counter->load() > 1) - return; - static blt::hashset_t sets; - while (!operations.empty()) - { - auto operation = operations.back(); - if (operation.is_value) - { - struct hello - { - float* f; - blt::size_t i; - }; - //auto h = values.from(0); - /*if (sets.find(h.i) != sets.end()) - std::cout << "HEY ASSHOLE Duplicate Value " << h.i << std::endl; - else - { - std::cout << "Destroying Value " << h.i << std::endl; - sets.insert(h.i); - }*/ - program.get_destroy_func(operation.id)(detail::destroy_t::RETURN, nullptr, values); - values.pop_bytes(static_cast(stack_allocator::aligned_size(operation.type_size))); - } - operations.pop_back(); - } - } - void tree_t::find_child_extends(gp_program& program, std::vector& vec, blt::size_t parent_node, blt::size_t argc) const { while (vec.size() < argc) @@ -372,9 +297,8 @@ namespace blt::gp } } - void population_t::drop(gp_program& program) + tree_t::tree_t(gp_program& program): func(&program.get_eval_func()) { - for (auto& pop : get_individuals()) - pop.tree.drop(program); + } } \ No newline at end of file diff --git a/tests/evaluation_tests.cpp b/tests/evaluation_tests.cpp index 25b8feb..fb6c524 100644 --- a/tests/evaluation_tests.cpp +++ b/tests/evaluation_tests.cpp @@ -58,13 +58,12 @@ blt::gp::gp_program program{type_system, SEED}; blt::gp::op_container_t make_container(blt::gp::operator_id id) { auto& info = program.get_operator_info(id); - return {info.function, type_system.get_type(info.return_type).size(), id, false}; + return {type_system.get_type(info.return_type).size(), id, false}; } blt::gp::op_container_t make_value(const blt::gp::type& id) { - static blt::gp::detail::callable_t empty([](void*, blt::gp::stack_allocator&, blt::gp::stack_allocator&, blt::gp::detail::bitmask_t*) {}); - return {empty, id.size(), 0, true}; + return {id.size(), 0, true}; } blt::gp::operation_t add([](float a, float b) { @@ -105,7 +104,7 @@ blt::gp::operation_t large_literal([]() { void basic_tree() { BLT_INFO("Testing if we can get a basic tree going."); - blt::gp::tree_t tree; + blt::gp::tree_t tree{program}; tree.get_operations().push_back(make_container(sub.id)); tree.get_operations().push_back(make_value(type_system.get_type())); @@ -120,7 +119,7 @@ void basic_tree() void large_cross_type_tree() { - blt::gp::tree_t tree; + blt::gp::tree_t tree{program}; auto& ops = tree.get_operations(); auto& vals = tree.get_values(); @@ -149,16 +148,7 @@ int main() type_system.register_type(); blt::gp::operator_builder builder{type_system}; - - builder.add_operator(f_literal); // 0 - builder.add_operator(b_literal); // 1 - builder.add_operator(add); // 2 - builder.add_operator(basic_2t); // 3 - builder.add_operator(sub); // 4 - builder.add_operator(large_literal); // 5 - builder.add_operator(cross_large_type); // 6 - - program.set_operations(builder.build()); + program.set_operations(builder.build(f_literal, b_literal, add, basic_2t, sub, large_literal, cross_large_type)); basic_tree(); large_cross_type_tree(); diff --git a/tests/gp_test_1.cpp b/tests/gp_test_1.cpp index bf0b295..6d2c7cb 100644 --- a/tests/gp_test_1.cpp +++ b/tests/gp_test_1.cpp @@ -424,7 +424,7 @@ int main() return f + g; }); - std::cout << silly_op(alloc, nullptr) << std::endl; + std::cout << silly_op(alloc) << std::endl; std::cout << "Is empty? " << alloc.empty() << std::endl; @@ -479,7 +479,7 @@ int main() //blt::span spv{arr}; - std::cout << silly_op.operator()(alloc, nullptr) << std::endl; + std::cout << silly_op.operator()(alloc) << std::endl; std::cout << "Hello World!" << std::endl; diff --git a/tests/gp_test_2.cpp b/tests/gp_test_2.cpp index 50a68dc..960d414 100644 --- a/tests/gp_test_2.cpp +++ b/tests/gp_test_2.cpp @@ -62,7 +62,7 @@ int main() blt::gp::grow_generator_t grow; auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7}); - auto value = tree.get_evaluation_value(nullptr, program.get_eval_func()); + auto value = tree.get_evaluation_value(nullptr); BLT_TRACE(value); diff --git a/tests/gp_test_3.cpp b/tests/gp_test_3.cpp index 6f026bd..d961b3d 100644 --- a/tests/gp_test_3.cpp +++ b/tests/gp_test_3.cpp @@ -40,11 +40,11 @@ blt::gp::operation_t op_or([](bool a, bool b) {return a || b; }); blt::gp::operation_t op_xor([](bool a, bool b) {return static_cast(a ^ b); }); blt::gp::operation_t op_not([](bool b) {return !b; }); -blt::gp::operation_t lit([]() { +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); - return program.get_random().get_float(0.0f, 10.f); -}); + return program.get_random().get_float(0.0f, 10.0f); +}).set_ephemeral(); /** * This is a test using multiple types with blt::gp @@ -55,24 +55,7 @@ int main() type_system.register_type(); blt::gp::operator_builder silly{type_system}; - silly.add_operator(add); - silly.add_operator(sub); - silly.add_operator(mul); - silly.add_operator(pro_div); - - silly.add_operator(op_if); - silly.add_operator(eq_f); - silly.add_operator(eq_b); - silly.add_operator(lt); - silly.add_operator(gt); - silly.add_operator(op_and); - silly.add_operator(op_or); - silly.add_operator(op_xor); - silly.add_operator(op_not); - - silly.add_operator(lit, true); - - program.set_operations(silly.build()); + program.set_operations(silly.build(add, sub, mul, pro_div, op_if, eq_f, eq_b, lt, gt, op_and, op_or, op_xor, op_not, lit)); blt::gp::grow_generator_t grow; auto tree = grow.generate(blt::gp::generator_arguments{program, type_system.get_type().id(), 3, 7}); diff --git a/tests/gp_test_4.cpp b/tests/gp_test_4.cpp index 16a966d..585585d 100644 --- a/tests/gp_test_4.cpp +++ b/tests/gp_test_4.cpp @@ -40,11 +40,11 @@ blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }); blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }); blt::gp::operation_t op_not([](bool b) { return !b; }); -blt::gp::operation_t lit([]() { +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); return program.get_random().get_float(0.0f, 10.0f); -}); +}).set_ephemeral(); /** * This is a test using multiple types with blt::gp @@ -55,24 +55,7 @@ int main() type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(add); - builder.add_operator(sub); - builder.add_operator(mul); - builder.add_operator(pro_div); - - builder.add_operator(op_if); - builder.add_operator(eq_f); - builder.add_operator(eq_b); - builder.add_operator(lt); - builder.add_operator(gt); - builder.add_operator(op_and); - builder.add_operator(op_or); - builder.add_operator(op_xor); - builder.add_operator(op_not); - - builder.add_operator(lit, true); - - program.set_operations(builder.build()); + program.set_operations(builder.build(add, sub, mul, pro_div, op_if, eq_f, eq_b, lt, gt, op_and, op_or, op_xor, op_not, lit)); blt::gp::ramped_half_initializer_t pop_init; diff --git a/tests/gp_test_5.cpp b/tests/gp_test_5.cpp index bf9e783..7ef9e7a 100644 --- a/tests/gp_test_5.cpp +++ b/tests/gp_test_5.cpp @@ -61,11 +61,11 @@ blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }, "or"); // 10 blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }, "xor"); // 11 blt::gp::operation_t op_not([](bool b) { return !b; }, "not"); // 12 -blt::gp::operation_t lit([]() { // 13 +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); - return program.get_random().get_float(0.0f, 10.f); -}, "lit"); + return program.get_random().get_float(0.0f, 10.0f); +}).set_ephemeral(); /** * This is a test using multiple types with blt::gp @@ -76,24 +76,7 @@ int main() type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(add); - builder.add_operator(sub); - builder.add_operator(mul); - builder.add_operator(pro_div); - - builder.add_operator(op_if); - builder.add_operator(eq_f); - builder.add_operator(eq_b); - builder.add_operator(lt); - builder.add_operator(gt); - builder.add_operator(op_and); - builder.add_operator(op_or); - builder.add_operator(op_xor); - builder.add_operator(op_not); - - builder.add_operator(lit, true); - - program.set_operations(builder.build()); + program.set_operations(builder.build(add, sub, mul, pro_div, op_if, eq_f, eq_b, lt, gt, op_and, op_or, op_xor, op_not, lit)); blt::gp::ramped_half_initializer_t pop_init; diff --git a/tests/gp_test_6.cpp b/tests/gp_test_6.cpp index 1a1c36a..a3955e6 100644 --- a/tests/gp_test_6.cpp +++ b/tests/gp_test_6.cpp @@ -59,11 +59,11 @@ blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }, "or"); // 10 blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }, "xor"); // 11 blt::gp::operation_t op_not([](bool b) { return !b; }, "not"); // 12 -blt::gp::operation_t lit([]() { // 13 +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); return program.get_random().get_float(0.0f, 10.0f); -}, "lit"); +}).set_ephemeral(); /** * This is a test using multiple types with blt::gp @@ -74,24 +74,7 @@ int main() type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(add); - builder.add_operator(sub); - builder.add_operator(mul); - builder.add_operator(pro_div); - - builder.add_operator(op_if); - builder.add_operator(eq_f); - builder.add_operator(eq_b); - builder.add_operator(lt); - builder.add_operator(gt); - builder.add_operator(op_and); - builder.add_operator(op_or); - builder.add_operator(op_xor); - builder.add_operator(op_not); - - builder.add_operator(lit, true); - - program.set_operations(builder.build()); + program.set_operations(builder.build(add, sub, mul, pro_div, op_if, eq_f, eq_b, lt, gt, op_and, op_or, op_xor, op_not, lit)); blt::gp::ramped_half_initializer_t pop_init; diff --git a/tests/gp_test_7.cpp b/tests/gp_test_7.cpp index 4a71b89..25e9ad1 100644 --- a/tests/gp_test_7.cpp +++ b/tests/gp_test_7.cpp @@ -42,11 +42,11 @@ blt::gp::operation_t op_or([](bool a, bool b) { return a || b; }, "or"); // 10 blt::gp::operation_t op_xor([](bool a, bool b) { return static_cast(a ^ b); }, "xor"); // 11 blt::gp::operation_t op_not([](bool b) { return !b; }, "not"); // 12 -blt::gp::operation_t lit([]() { // 13 +auto lit = blt::gp::operation_t([]() { //static std::uniform_real_distribution dist(-32000, 32000); // static std::uniform_real_distribution dist(0.0f, 10.0f); return program.get_random().get_float(0.0f, 10.0f); -}, "lit"); +}).set_ephemeral(); void print_best() { @@ -90,24 +90,7 @@ int main() type_system.register_type(); blt::gp::operator_builder builder{type_system}; - builder.add_operator(add); - builder.add_operator(sub); - builder.add_operator(mul); - builder.add_operator(pro_div); - - builder.add_operator(op_if); - builder.add_operator(eq_f); - builder.add_operator(eq_b); - builder.add_operator(lt); - builder.add_operator(gt); - builder.add_operator(op_and); - builder.add_operator(op_or); - builder.add_operator(op_xor); - builder.add_operator(op_not); - - builder.add_operator(lit, true); - - program.set_operations(builder.build()); + program.set_operations(builder.build(add, sub, mul, pro_div, op_if, eq_f, eq_b, lt, gt, op_and, op_or, op_xor, op_not, lit)); auto sel = blt::gp::select_tournament_t{}; program.generate_population(type_system.get_type().id(), fitness_function, sel, sel, sel); diff --git a/tests/order_tests.cpp b/tests/order_tests.cpp index d59ea4e..9db441b 100644 --- a/tests/order_tests.cpp +++ b/tests/order_tests.cpp @@ -93,7 +93,7 @@ void basic_test() auto tree = gen.generate(args); context ctx{&program}; - auto result = tree.get_evaluation_value(&ctx, program.get_eval_func()); + auto result = tree.get_evaluation_value(&ctx); BLT_TRACE(result); BLT_ASSERT(result == -5.0f || result == 5.0f || result == 0.0f); tree.print(program, std::cout, true, true);