diff --git a/include/blt/gp/program.h b/include/blt/gp/program.h index 4183cc9..bf63684 100644 --- a/include/blt/gp/program.h +++ b/include/blt/gp/program.h @@ -640,7 +640,7 @@ namespace blt::gp return thread_helper.lifetime_over; } - operator_id select_terminal(type_id id) + operator_id select_terminal(const type_id id) { // we wanted a terminal, but could not find one, so we will select from a function that has a terminal if (storage.terminals[id].empty()) @@ -648,7 +648,7 @@ namespace blt::gp return get_random().select(storage.terminals[id]); } - operator_id select_non_terminal(type_id id) + operator_id select_non_terminal(const type_id id) { // non-terminal doesn't exist, return a terminal. This is useful for types that are defined only to have a random value, nothing more. // was considering an std::optional<> but that would complicate the generator code considerably. I'll mark this as a TODO for v2 @@ -657,7 +657,7 @@ namespace blt::gp return get_random().select(storage.non_terminals[id]); } - operator_id select_non_terminal_too_deep(type_id id) + operator_id select_non_terminal_too_deep(const type_id id) { // this should probably be an error. if (storage.operators_ordered_terminals[id].empty()) @@ -688,32 +688,32 @@ namespace blt::gp return storage.system; } - [[nodiscard]] operator_info_t& get_operator_info(operator_id id) + [[nodiscard]] operator_info_t& get_operator_info(const operator_id id) { return storage.operators[id]; } - [[nodiscard]] detail::print_func_t& get_print_func(operator_id id) + [[nodiscard]] detail::print_func_t& get_print_func(const operator_id id) { return storage.print_funcs[id]; } - [[nodiscard]] detail::destroy_func_t& get_destroy_func(operator_id id) + [[nodiscard]] detail::destroy_func_t& get_destroy_func(const operator_id id) { return storage.destroy_funcs[id]; } - [[nodiscard]] std::optional get_name(operator_id id) const + [[nodiscard]] std::optional get_name(const operator_id id) const { return storage.names[id]; } - [[nodiscard]] tracked_vector& get_type_terminals(type_id id) + [[nodiscard]] tracked_vector& get_type_terminals(const type_id id) { return storage.terminals[id]; } - [[nodiscard]] tracked_vector& get_type_non_terminals(type_id id) + [[nodiscard]] tracked_vector& get_type_non_terminals(const type_id id) { return storage.non_terminals[id]; } @@ -753,47 +753,55 @@ namespace blt::gp storage = std::move(op); } - template - std::array get_best_indexes() + template + std::array get_best_indexes() { - std::array arr; + std::array arr; - tracked_vector> values; + tracked_vector> values; values.reserve(current_pop.get_individuals().size()); - for (const auto& [index, value] : blt::enumerate(current_pop.get_individuals())) + for (const auto& [index, value] : enumerate(current_pop.get_individuals())) values.emplace_back(index, value.fitness.adjusted_fitness); std::sort(values.begin(), values.end(), [](const auto& a, const auto& b) { return a.second > b.second; }); - for (blt::size_t i = 0; i < std::min(size, config.population_size); i++) + for (size_t i = 0; i < std::min(size, config.population_size); ++i) arr[i] = values[i].first; - for (blt::size_t i = std::min(size, config.population_size); i < size; i++) + for (size_t i = std::min(size, config.population_size); i < size; ++i) arr[i] = 0; return arr; } - template + template auto get_best_trees() { return convert_array, size>>(get_best_indexes(), - [this](auto&& arr, blt::size_t index) -> tree_t& { + [this](auto&& arr, size_t index) -> tree_t& { return current_pop.get_individuals()[arr[index]].tree; - }, std::make_integer_sequence()); + }, std::make_integer_sequence()); } - template + template auto get_best_individuals() { return convert_array, size>>(get_best_indexes(), - [this](auto&& arr, blt::size_t index) -> individual_t& { + [this](auto&& arr, size_t index) -> individual_t& { return current_pop.get_individuals()[arr[index]]; - }, std::make_integer_sequence()); + }, std::make_integer_sequence()); } + void save_generation(fs::writer_t& writer); + + void save_state(fs::writer_t& writer); + + void load_generation(fs::reader_t& reader); + + void load_state(fs::reader_t& reader); + private: template auto single_threaded_fitness_eval() diff --git a/include/blt/gp/sync.h b/include/blt/gp/sync.h new file mode 100644 index 0000000..cc987ed --- /dev/null +++ b/include/blt/gp/sync.h @@ -0,0 +1,27 @@ +#pragma once +/* + * Copyright (C) 2024 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef BLT_GP_SYNC_H +#define BLT_GP_SYNC_H + +namespace blt::gp +{ + +} + +#endif //BLT_GP_SYNC_H diff --git a/include/blt/gp/tree.h b/include/blt/gp/tree.h index b92f5b0..f9a4be5 100644 --- a/include/blt/gp/tree.h +++ b/include/blt/gp/tree.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -611,11 +612,11 @@ namespace blt::gp void to_byte_array(std::byte* out) const; - void to_file(FILE* file) const; + void to_file(fs::writer_t& file) const; void from_byte_array(const std::byte* in); - void from_file(FILE* file); + void from_file(fs::reader_t& file); ~tree_t() { diff --git a/lib/blt b/lib/blt index 322a533..78c219c 160000 --- a/lib/blt +++ b/lib/blt @@ -1 +1 @@ -Subproject commit 322a533fd9412167e216188a4713a5aa4a99c2cd +Subproject commit 78c219cc67f1fe6b3c7076e2c727f8f4cfffd859 diff --git a/src/program.cpp b/src/program.cpp index 1cee290..2a0d6dd 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -56,6 +56,14 @@ namespace blt::gp return allocator; } + void gp_program::save_state(fs::writer_t& writer) + { + } + + void gp_program::load_state(fs::reader_t& reader) + { + } + void gp_program::create_threads() { #ifdef BLT_TRACK_ALLOCATIONS diff --git a/src/sync.cpp b/src/sync.cpp new file mode 100644 index 0000000..88ab06d --- /dev/null +++ b/src/sync.cpp @@ -0,0 +1,23 @@ +/* + * + * Copyright (C) 2025 Brett Terpstra + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include + +namespace blt::gp +{ + +} \ No newline at end of file diff --git a/src/tree.cpp b/src/tree.cpp index a5ebcfc..5f7a78b 100644 --- a/src/tree.cpp +++ b/src/tree.cpp @@ -692,18 +692,18 @@ namespace blt::gp std::memcpy(out, values.data(), val_size); } - void tree_t::to_file(FILE* file) const + void tree_t::to_file(fs::writer_t& file) const { const auto op_size = operations.size(); - BLT_ASSERT(std::fwrite(&op_size, sizeof(size_t), 1, file) == sizeof(size_t)); + BLT_ASSERT(file.write(&op_size, sizeof(size_t)) == sizeof(size_t)); for (const auto& op : operations) { auto id = op.id(); - std::fwrite(&id, sizeof(operator_id), 1, file); + file.write(&id, sizeof(operator_id)); } const auto val_size = values.bytes_in_head(); - BLT_ASSERT(std::fwrite(&val_size, sizeof(size_t), 1, file) == sizeof(size_t)); - BLT_ASSERT(std::fwrite(values.data(), val_size, 1, file) == val_size); + BLT_ASSERT(file.write(&val_size, sizeof(size_t)) == sizeof(size_t)); + BLT_ASSERT(file.write(values.data(), val_size) == val_size); } void tree_t::from_byte_array(const std::byte* in) @@ -731,15 +731,15 @@ namespace blt::gp values.copy_from(reinterpret_cast(in), val_size); } - void tree_t::from_file(FILE* file) + void tree_t::from_file(fs::reader_t& file) { size_t ops_to_read; - BLT_ASSERT(std::fread(&ops_to_read, sizeof(size_t), 1, file) == sizeof(size_t)); + BLT_ASSERT(file.read(&ops_to_read, sizeof(size_t)) == sizeof(size_t)); operations.reserve(ops_to_read); for (size_t i = 0; i < ops_to_read; i++) { operator_id id; - BLT_ASSERT(std::fread(&id, sizeof(operator_id), 1, file) == sizeof(operator_id)); + BLT_ASSERT(file.read(&id, sizeof(operator_id)) == sizeof(operator_id)); operations.push_back({ m_program->get_typesystem().get_type(m_program->get_operator_info(id).return_type).size(), id, @@ -748,9 +748,9 @@ namespace blt::gp }); } size_t val_size; - BLT_ASSERT(std::fread(&val_size, sizeof(size_t), 1, file) == sizeof(size_t)); + BLT_ASSERT(file.read(&val_size, sizeof(size_t)) == sizeof(size_t)); values.resize(val_size); - BLT_ASSERT(std::fread(values.data(), val_size, 1, file) == val_size); + BLT_ASSERT(file.read(values.data(), val_size) == val_size); } void tree_t::modify_operator(const size_t point, operator_id new_id, std::optional return_type)