diff --git a/CMakeLists.txt b/CMakeLists.txt index 48fa62f..749752e 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.3.26) +project(blt-gp VERSION 0.3.27) include(CTest) diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index b82c786..9922f86 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -290,17 +290,17 @@ namespace blt::gp { if (copy_it == copy.operations.end()) break; + if (copy_it->is_value()) + { + copy.handle_refcount_increment(copy_it, total_copy_bytes); + total_copy_bytes += copy_it->type_size(); + } if (op_it->is_value()) { handle_refcount_decrement(op_it, total_op_bytes); total_op_bytes += op_it->type_size(); } *op_it = *copy_it; - if (copy_it->is_value()) - { - copy.handle_refcount_increment(copy_it, total_copy_bytes); - total_copy_bytes += copy_it->type_size(); - } ++copy_it; } const auto op_it_cpy = op_it; diff --git a/src/tree.cpp b/src/tree.cpp index be8ea89..128f718 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -273,7 +273,7 @@ namespace blt::gp operators.reserve(operators.size() + ops); // TODO something better! for (size_t i = 0; i < ops; ++i) - operators.emplace_back(0,0,false, operator_special_flags{}); + operators.emplace_back(0, 0, false, operator_special_flags{}); size_t for_bytes = 0; size_t pos = 0; for (auto& it : iterate(point_begin_itr, point_end_itr).rev()) @@ -576,7 +576,9 @@ namespace blt::gp const auto v1 = results.values.bytes_in_head(); const auto v2 = static_cast(operations.front().type_size()); - m_program->get_destroy_func(operations.front().id())(detail::destroy_t::RETURN, results.values.from(operations.front().type_size())); + // ephemeral don't need to be dropped as there are no copies which matter when checking the tree + if (!operations.front().get_flags().is_ephemeral()) + m_program->get_destroy_func(operations.front().id())(detail::destroy_t::RETURN, results.values.from(operations.front().type_size())); if (v1 != v2) { const auto vd = std::abs(v1 - v2); diff --git a/tests/drop_test.cpp b/tests/drop_test.cpp index 7d8fccb..9d4d064 100644 --- a/tests/drop_test.cpp +++ b/tests/drop_test.cpp @@ -28,25 +28,30 @@ std::atomic_uint64_t ephemeral_drop = 0; struct drop_type { - float value; + float* m_value; bool ephemeral = false; - drop_type() : value(0) + drop_type() : m_value(new float(0)) { ++normal_construct; } - explicit drop_type(const float silly) : value(silly) + explicit drop_type(const float silly) : m_value(new float(silly)) { ++normal_construct; } - explicit drop_type(const float silly, bool) : value(silly), ephemeral(true) + explicit drop_type(const float silly, bool) : m_value(new float(silly)), ephemeral(true) { // BLT_TRACE("Constructor with value %f", silly); ++ephemeral_construct; } + [[nodiscard]] float value() const + { + return *m_value; + } + void drop() const { if (ephemeral) @@ -55,11 +60,12 @@ struct drop_type ++ephemeral_drop; }else ++normal_drop; + delete m_value; } friend std::ostream& operator<<(std::ostream& os, const drop_type& dt) { - os << dt.value; + os << dt.m_value; return os; } }; @@ -83,14 +89,14 @@ prog_config_t config = prog_config_t() example::symbolic_regression_t regression{691ul, config}; -operation_t add{[](const drop_type a, const drop_type b) { return drop_type{a.value + b.value}; }, "add"}; -operation_t sub([](const drop_type a, const drop_type b) { return drop_type{a.value - b.value}; }, "sub"); -operation_t mul([](const drop_type a, const drop_type b) { return drop_type{a.value * b.value}; }, "mul"); -operation_t pro_div([](const drop_type a, const drop_type b) { return drop_type{b.value == 0.0f ? 0.0f : a.value / b.value}; }, "div"); -operation_t op_sin([](const drop_type a) { return drop_type{std::sin(a.value)}; }, "sin"); -operation_t op_cos([](const drop_type a) { return drop_type{std::cos(a.value)}; }, "cos"); -operation_t op_exp([](const drop_type a) { return drop_type{std::exp(a.value)}; }, "exp"); -operation_t op_log([](const drop_type a) { return drop_type{a.value <= 0.0f ? 0.0f : std::log(a.value)}; }, "log"); +operation_t add{[](const drop_type a, const drop_type b) { return drop_type{a.value() + b.value()}; }, "add"}; +operation_t sub([](const drop_type a, const drop_type b) { return drop_type{a.value() - b.value()}; }, "sub"); +operation_t mul([](const drop_type a, const drop_type b) { return drop_type{a.value() * b.value()}; }, "mul"); +operation_t pro_div([](const drop_type a, const drop_type b) { return drop_type{b.value() == 0.0f ? 0.0f : a.value() / b.value()}; }, "div"); +operation_t op_sin([](const drop_type a) { return drop_type{std::sin(a.value())}; }, "sin"); +operation_t op_cos([](const drop_type a) { return drop_type{std::cos(a.value())}; }, "cos"); +operation_t op_exp([](const drop_type a) { return drop_type{std::exp(a.value())}; }, "exp"); +operation_t op_log([](const drop_type a) { return drop_type{a.value() <= 0.0f ? 0.0f : std::log(a.value())}; }, "log"); auto lit = operation_t([]() { return drop_type{regression.get_program().get_random().get_float(-1.0f, 1.0f), true}; @@ -108,7 +114,7 @@ bool fitness_function(const tree_t& current_tree, fitness_t& fitness, size_t) { BLT_GP_UPDATE_CONTEXT(fitness_case); auto val = current_tree.get_evaluation_ref(fitness_case); - const auto diff = std::abs(fitness_case.y - val.get().value); + const auto diff = std::abs(fitness_case.y - val.get().value()); if (diff < value_cutoff) { fitness.raw_fitness += diff;