diff --git a/.idea/editor.xml b/.idea/editor.xml
index a164eb6..521c365 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -1,488 +1,249 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 8bf9b9f..38dc036 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -1,6 +1,8 @@
+
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc58c56..bc1212e 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.13)
+project(blt-gp VERSION 0.5.14)
include(CTest)
diff --git a/include/blt/gp/transformers.h b/include/blt/gp/transformers.h
index e7970f4..36109df 100644
--- a/include/blt/gp/transformers.h
+++ b/include/blt/gp/transformers.h
@@ -55,9 +55,6 @@ namespace blt::gp
}
}
- /**
- * Base class for crossover which performs basic subtree crossover on two random nodes in the parent tree
- */
class crossover_t
{
public:
@@ -67,12 +64,6 @@ namespace blt::gp
operator_info_t& type_operator_info;
};
- struct crossover_point_t
- {
- tree_t::subtree_point_t p1_crossover_point;
- tree_t::subtree_point_t p2_crossover_point;
- };
-
struct config_t
{
// number of times crossover will try to pick a valid point in the tree. this is purely based on the return type of the operators
@@ -93,8 +84,6 @@ namespace blt::gp
bool traverse = false;
};
- crossover_t() = default;
-
explicit crossover_t(const config_t& config): config(config)
{
}
@@ -104,9 +93,36 @@ namespace blt::gp
return config;
}
- std::optional get_crossover_point(const tree_t& c1, const tree_t& c2) const;
+ virtual ~crossover_t() = default;
- std::optional get_crossover_point_traverse(const tree_t& c1, const tree_t& c2) const;
+ protected:
+ config_t config;
+ };
+
+ /**
+ * Base class for crossover which performs basic subtree crossover on two random nodes in the parent tree
+ */
+ class subtree_crossover_t : public crossover_t
+ {
+ public:
+ struct crossover_point_t
+ {
+ tree_t::subtree_point_t p1_crossover_point;
+ tree_t::subtree_point_t p2_crossover_point;
+ };
+
+
+ subtree_crossover_t(): crossover_t(config_t{})
+ {
+ }
+
+ explicit subtree_crossover_t(const config_t& config): crossover_t(config)
+ {
+ }
+
+ [[nodiscard]] std::optional get_crossover_point(const tree_t& c1, const tree_t& c2) const;
+
+ [[nodiscard]] std::optional get_crossover_point_traverse(const tree_t& c1, const tree_t& c2) const;
/**
* child1 and child2 are copies of the parents, the result of selecting a crossover point and performing standard subtree crossover.
@@ -114,20 +130,21 @@ namespace blt::gp
* @param program reference to the global program container responsible for managing these trees
* @param p1 reference to the first parent
* @param p2 reference to the second parent
- * @return expected pair of child otherwise returns error enum
+ * @param c1 reference to output child 1
+ * @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 ~crossover_t() = default;
+ ~subtree_crossover_t() override = default;
protected:
[[nodiscard]] std::optional get_point_traverse_retry(const tree_t& t, std::optional type) const;
-
- config_t config;
};
class advanced_crossover_t : public crossover_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/src/transformers.cpp b/src/transformers.cpp
index b6f6b3b..98c5a1e 100644
--- a/src/transformers.cpp
+++ b/src/transformers.cpp
@@ -65,7 +65,7 @@ namespace blt::gp
{
}
- bool crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) // NOLINT
+ bool subtree_crossover_t::apply(gp_program& program, const tree_t& p1, const tree_t& p2, tree_t& c1, tree_t& c2) // NOLINT
{
if (p1.size() < config.min_tree_size || p2.size() < config.min_tree_size)
return false;
@@ -90,7 +90,7 @@ namespace blt::gp
return true;
}
- std::optional crossover_t::get_crossover_point(const tree_t& c1,
+ std::optional subtree_crossover_t::get_crossover_point(const tree_t& c1,
const tree_t& c2) const
{
const auto first = c1.select_subtree(config.terminal_chance);
@@ -102,7 +102,7 @@ namespace blt::gp
return {{first, *second}};
}
- std::optional crossover_t::get_crossover_point_traverse(const tree_t& c1,
+ std::optional subtree_crossover_t::get_crossover_point_traverse(const tree_t& c1,
const tree_t& c2) const
{
auto c1_point_o = get_point_traverse_retry(c1, {});
@@ -114,7 +114,7 @@ namespace blt::gp
return {{*c1_point_o, *c2_point_o}};
}
- std::optional crossover_t::get_point_traverse_retry(const tree_t& t, const std::optional type) const
+ std::optional subtree_crossover_t::get_point_traverse_retry(const tree_t& t, const std::optional type) const
{
if (type)
return t.select_subtree_traverse(*type, config.max_crossover_tries, config.terminal_chance, config.depth_multiplier);
@@ -131,24 +131,13 @@ namespace blt::gp
{
// single point crossover (only if operators at this point are "compatible")
case 0:
- case0:
{
- std::optional point;
-
- if (config.traverse)
- point = get_crossover_point_traverse(p1, p2);
- else
- point = get_crossover_point(p1, p2);
-
- if (!point)
- return false;
// check if can work
// otherwise goto case2
}
// Mating crossover analogs to same species breeding. Only works if tree is mostly similar
case 1:
- case1:
{
// if fails got to case0
if (false)
@@ -156,8 +145,7 @@ namespace blt::gp
}
// Subtree crossover, select random points inside trees and swap their subtrees
case 2:
- case2:
- return crossover_t::apply(program, p1, p2, c1, c2);
+ return subtree_crossover_t{}.apply(program, p1, p2, c1, c2);
default:
#if BLT_DEBUG_LEVEL > 0
BLT_ABORT("This place should be unreachable!");
diff --git a/tests/serialization_test.cpp b/tests/serialization_test.cpp
index 9965f25..a531730 100644
--- a/tests/serialization_test.cpp
+++ b/tests/serialization_test.cpp
@@ -145,7 +145,11 @@ int main()
{
std::ifstream stream{"serialization_test2.data", std::ios::binary};
blt::fs::fstream_reader_t reader{stream};
- test_program.load_state(reader);
+ if (auto err = test_program.load_state(reader))
+ {
+ BLT_ERROR("Error: {}", blt::gp::errors::serialization::to_string(*err));
+ BLT_ABORT("Expected program to succeeded without returning an error state!");
+ }
for (const auto [saved, loaded] : blt::zip(program.get_stats_histories(), test_program.get_stats_histories()))
{
@@ -156,11 +160,12 @@ int main()
}
}
}
- std::ifstream stream{"serialization_test2.data", std::ios::binary};
- blt::fs::fstream_reader_t reader{stream};
- if (auto err = bad_program.load_state(reader))
{
- BLT_ERROR(blt::gp::errors::serialization::to_string(*err));
- BLT_ASSERT(false && "Expected program to throw an exception when parsing state data into an incompatible program!");
+ std::ifstream stream{"serialization_test2.data", std::ios::binary};
+ blt::fs::fstream_reader_t reader{stream};
+ if (!bad_program.load_state(reader).has_value())
+ {
+ BLT_ABORT("Expected program to throw an exception when parsing state data into an incompatible program!");
+ }
}
}