diff --git a/CMakeLists.txt b/CMakeLists.txt index ba3639b..dacfcbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.25) -project(blt-gp VERSION 0.1.30) +project(blt-gp VERSION 0.1.31) include(CTest) diff --git a/examples/rice_classification.cpp b/examples/rice_classification.cpp index 47100d8..9a7c48c 100644 --- a/examples/rice_classification.cpp +++ b/examples/rice_classification.cpp @@ -28,7 +28,7 @@ #include "operations_common.h" #include "blt/fs/loader.h" -static const unsigned long SEED = std::random_device()(); +static const auto SEED_FUNC = [] { return std::random_device()(); }; enum class rice_type_t { @@ -59,11 +59,11 @@ 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(500) .set_thread_count(0); blt::gp::type_provider type_system; -blt::gp::gp_program program{type_system, SEED, config}; +blt::gp::gp_program program{type_system, SEED_FUNC, config}; auto lit = blt::gp::operation_t([]() { return program.get_random().get_float(-32000.0f, 32000.0f); @@ -159,6 +159,48 @@ void load_rice_data(std::string_view rice_file_path) BLT_INFO("Created training set of size %ld, testing set is of size %ld", training_size, testing_cases.size()); } +struct test_results_t +{ + blt::size_t cc = 0; + blt::size_t co = 0; + blt::size_t oo = 0; + blt::size_t oc = 0; + blt::size_t hits = 0; + blt::size_t size = 0; + double percent_hit = 0; +}; + +test_results_t test_individual(blt::gp::individual& i) +{ + test_results_t results; + + for (auto& testing_case : testing_cases) + { + auto result = i.tree.get_evaluation_value(&testing_case); + switch (testing_case.type) + { + case rice_type_t::Cammeo: + if (result >= 0) + results.cc++; // cammeo cammeo + else if (result < 0) + results.co++; // cammeo osmancik + break; + case rice_type_t::Osmancik: + if (result < 0) + results.oo++; // osmancik osmancik + else if (result >= 0) + results.oc++; // osmancik cammeo + break; + } + } + + results.hits = results.cc + results.oo; + results.size = testing_cases.size(); + results.percent_hit = static_cast(results.hits) / static_cast(results.size) * 100; + + return results; +} + int main(int argc, const char** argv) { blt::arg_parse parser; diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index b86080f..c15cc64 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -332,11 +332,19 @@ namespace blt::gp * @param context_size number of arguments which are always present as "context" to the GP system / operators */ explicit gp_program(type_provider& system, blt::u64 seed): - system(system), seed(seed) + system(system), seed_func([seed]{return seed;}) { create_threads(); } explicit gp_program(type_provider& system, blt::u64 seed, prog_config_t config): - system(system), seed(seed), config(config) + system(system), seed_func([seed]{return seed;}), config(config) + { create_threads(); } + + explicit gp_program(type_provider& system, std::function seed_func): + system(system), seed_func(std::move(seed_func)) + { create_threads(); } + + explicit gp_program(type_provider& system, std::function seed_func, prog_config_t config): + system(system), seed_func(std::move(seed_func)), config(config) { create_threads(); } void create_next_generation() @@ -719,7 +727,7 @@ namespace blt::gp std::atomic_uint64_t current_generation = 0; std::atomic_bool fitness_should_exit = false; - blt::u64 seed; + std::function seed_func; prog_config_t config{}; struct concurrency_storage diff --git a/include/blt/gp/selection.h b/include/blt/gp/selection.h index baf4842..e23cc6e 100644 --- a/include/blt/gp/selection.h +++ b/include/blt/gp/selection.h @@ -177,7 +177,7 @@ namespace blt::gp public: explicit select_tournament_t(blt::size_t selection_size = 3): selection_size(selection_size) { - if (selection_size < 1) + if (selection_size == 0) BLT_ABORT("Unable to select with this size. Must select at least 1 individual!"); } diff --git a/src/program.cpp b/src/program.cpp index b5e01be..413c932 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -46,7 +46,7 @@ namespace blt::gp random_t& gp_program::get_random() const { - thread_local static blt::gp::random_t random_engine{seed}; + thread_local static blt::gp::random_t random_engine{seed_func()}; return random_engine; } diff --git a/src/selection.cpp b/src/selection.cpp index d54c824..e94a7f2 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -60,22 +60,15 @@ namespace blt::gp tree_t& select_tournament_t::select(gp_program& program, population_t& pop, population_stats&) { - - auto& first = pop.get_individuals()[program.get_random().get_size_t(0ul, pop.get_individuals().size())]; - individual* ind = &first; - double best_guy = first.fitness.adjusted_fitness; - for (blt::size_t i = 0; i < selection_size - 1; i++) + blt::u64 best = program.get_random().get_u64(0, pop.get_individuals().size()); + auto& i_ref = pop.get_individuals(); + for (blt::size_t i = 0; i < selection_size; i++) { - auto& sel = pop.get_individuals()[program.get_random().get_size_t(0ul, pop.get_individuals().size())]; - BLT_TRACE("Selection %ld (of %ld) = %lf, ind %p, first: %p", i, selection_size, sel.fitness.adjusted_fitness, &sel, &first); - if (sel.fitness.adjusted_fitness > best_guy) - { - best_guy = sel.fitness.adjusted_fitness; - ind = &sel; - } + auto sel_point = program.get_random().get_u64(0ul, pop.get_individuals().size()); + if (i_ref[sel_point].fitness.adjusted_fitness > i_ref[best].fitness.adjusted_fitness) + best = sel_point; } - - return ind->tree; + return i_ref[best].tree; } tree_t& select_fitness_proportionate_t::select(gp_program& program, population_t& pop, population_stats& stats)