Compare commits
No commits in common. "1fa12da4772a1f4a0fd527474dfcae0b35e58254" and "bf4394cb0d78e2cf6016b512ed79608d5233ce4e" have entirely different histories.
1fa12da477
...
bf4394cb0d
|
@ -4,4 +4,3 @@ out/
|
||||||
./cmake-build*/
|
./cmake-build*/
|
||||||
./build/
|
./build/
|
||||||
./out/
|
./out/
|
||||||
massif.*
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(blt-gp VERSION 0.0.42)
|
project(blt-gp VERSION 0.0.38)
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
|
|
||||||
|
@ -73,6 +73,5 @@ if (${BUILD_EXAMPLES})
|
||||||
blt_add_example(blt-gp2 examples/gp_test_2.cpp)
|
blt_add_example(blt-gp2 examples/gp_test_2.cpp)
|
||||||
blt_add_example(blt-gp3 examples/gp_test_3.cpp)
|
blt_add_example(blt-gp3 examples/gp_test_3.cpp)
|
||||||
blt_add_example(blt-gp4 examples/gp_test_4.cpp)
|
blt_add_example(blt-gp4 examples/gp_test_4.cpp)
|
||||||
blt_add_example(blt-gp5 examples/gp_test_5.cpp)
|
|
||||||
|
|
||||||
endif ()
|
endif ()
|
|
@ -311,7 +311,7 @@ namespace blt::gp::detail
|
||||||
class operator_storage_test
|
class operator_storage_test
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit operator_storage_test(blt::gp::operator_builder<context>& ops): ops(ops)
|
explicit operator_storage_test(blt::gp::gp_operations<context>& ops): ops(ops)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
inline blt::gp::detail::callable_t& operator[](blt::size_t index)
|
inline blt::gp::detail::callable_t& operator[](blt::size_t index)
|
||||||
|
@ -320,7 +320,7 @@ namespace blt::gp::detail
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
blt::gp::operator_builder<context>& ops;
|
blt::gp::gp_operations<context>& ops;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,9 +413,9 @@ int main()
|
||||||
return ctx.x;
|
return ctx.x;
|
||||||
});
|
});
|
||||||
|
|
||||||
blt::gp::type_provider system;
|
blt::gp::type_system system;
|
||||||
system.register_type<float>();
|
system.register_type<float>();
|
||||||
blt::gp::operator_builder<context> ops{system};
|
blt::gp::gp_operations<context> ops{system};
|
||||||
|
|
||||||
//BLT_TRACE(blt::type_string<decltype(silly_op_3)::first::type>());
|
//BLT_TRACE(blt::type_string<decltype(silly_op_3)::first::type>());
|
||||||
//BLT_TRACE(typeid(decltype(silly_op_3)::first::type).name());
|
//BLT_TRACE(typeid(decltype(silly_op_3)::first::type).name());
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
static constexpr long SEED = 41912;
|
static constexpr long SEED = 41912;
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_system type_system;
|
||||||
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
||||||
|
|
||||||
blt::gp::operation_t add([](float a, float b) {
|
blt::gp::operation_t add([](float a, float b) {
|
||||||
|
@ -52,7 +52,7 @@ int main()
|
||||||
{
|
{
|
||||||
type_system.register_type<float>();
|
type_system.register_type<float>();
|
||||||
|
|
||||||
blt::gp::operator_builder silly{type_system};
|
blt::gp::gp_operations silly{type_system};
|
||||||
silly.add_operator(add);
|
silly.add_operator(add);
|
||||||
silly.add_operator(sub);
|
silly.add_operator(sub);
|
||||||
silly.add_operator(mul);
|
silly.add_operator(mul);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
static constexpr long SEED = 41912;
|
static constexpr long SEED = 41912;
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_system type_system;
|
||||||
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
||||||
|
|
||||||
blt::gp::operation_t add([](float a, float b) { return a + b; });
|
blt::gp::operation_t add([](float a, float b) { return a + b; });
|
||||||
|
@ -54,7 +54,7 @@ int main()
|
||||||
type_system.register_type<float>();
|
type_system.register_type<float>();
|
||||||
type_system.register_type<bool>();
|
type_system.register_type<bool>();
|
||||||
|
|
||||||
blt::gp::operator_builder silly{type_system};
|
blt::gp::gp_operations silly{type_system};
|
||||||
silly.add_operator(add);
|
silly.add_operator(add);
|
||||||
silly.add_operator(sub);
|
silly.add_operator(sub);
|
||||||
silly.add_operator(mul);
|
silly.add_operator(mul);
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
static constexpr long SEED = 41912;
|
static constexpr long SEED = 41912;
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_system type_system;
|
||||||
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
||||||
|
|
||||||
blt::gp::operation_t add([](float a, float b) { return a + b; });
|
blt::gp::operation_t add([](float a, float b) { return a + b; });
|
||||||
|
@ -54,25 +54,25 @@ int main()
|
||||||
type_system.register_type<float>();
|
type_system.register_type<float>();
|
||||||
type_system.register_type<bool>();
|
type_system.register_type<bool>();
|
||||||
|
|
||||||
blt::gp::operator_builder builder{type_system};
|
blt::gp::gp_operations silly{type_system};
|
||||||
builder.add_operator(add);
|
silly.add_operator(add);
|
||||||
builder.add_operator(sub);
|
silly.add_operator(sub);
|
||||||
builder.add_operator(mul);
|
silly.add_operator(mul);
|
||||||
builder.add_operator(pro_div);
|
silly.add_operator(pro_div);
|
||||||
|
|
||||||
builder.add_operator(op_if);
|
silly.add_operator(op_if);
|
||||||
builder.add_operator(eq_f);
|
silly.add_operator(eq_f);
|
||||||
builder.add_operator(eq_b);
|
silly.add_operator(eq_b);
|
||||||
builder.add_operator(lt);
|
silly.add_operator(lt);
|
||||||
builder.add_operator(gt);
|
silly.add_operator(gt);
|
||||||
builder.add_operator(op_and);
|
silly.add_operator(op_and);
|
||||||
builder.add_operator(op_or);
|
silly.add_operator(op_or);
|
||||||
builder.add_operator(op_xor);
|
silly.add_operator(op_xor);
|
||||||
builder.add_operator(op_not);
|
silly.add_operator(op_not);
|
||||||
|
|
||||||
builder.add_operator(lit, true);
|
silly.add_operator(lit, true);
|
||||||
|
|
||||||
program.set_operations(builder.build());
|
program.set_operations(std::move(silly));
|
||||||
|
|
||||||
blt::gp::ramped_half_initializer_t pop_init;
|
blt::gp::ramped_half_initializer_t pop_init;
|
||||||
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
* <Short Description>
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* <Short Description>
|
|
||||||
* 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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
#include <blt/gp/program.h>
|
|
||||||
#include <blt/gp/generators.h>
|
|
||||||
#include <blt/gp/tree.h>
|
|
||||||
#include <blt/std/logging.h>
|
|
||||||
|
|
||||||
static constexpr long SEED = 41912;
|
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
|
||||||
blt::gp::gp_program program(type_system, std::mt19937_64{SEED}); // NOLINT
|
|
||||||
|
|
||||||
blt::gp::operation_t add([](float a, float b) { return a + b; });
|
|
||||||
blt::gp::operation_t sub([](float a, float b) { return a - b; });
|
|
||||||
blt::gp::operation_t mul([](float a, float b) { return a * b; });
|
|
||||||
blt::gp::operation_t pro_div([](float a, float b) { return b == 0 ? 0.0f : a / b; });
|
|
||||||
|
|
||||||
blt::gp::operation_t op_if([](bool b, float a, float c) { return b ? a : c; });
|
|
||||||
blt::gp::operation_t eq_f([](float a, float b) { return a == b; });
|
|
||||||
blt::gp::operation_t eq_b([](bool a, bool b) { return a == b; });
|
|
||||||
blt::gp::operation_t lt([](float a, float b) { return a < b; });
|
|
||||||
blt::gp::operation_t gt([](float a, float b) { return a > b; });
|
|
||||||
blt::gp::operation_t op_and([](bool a, bool b) { return a && b; });
|
|
||||||
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<bool>(a ^ b); });
|
|
||||||
blt::gp::operation_t op_not([](bool b) { return !b; });
|
|
||||||
|
|
||||||
blt::gp::operation_t lit([]() {
|
|
||||||
//static std::uniform_real_distribution<float> dist(-32000, 32000);
|
|
||||||
static std::uniform_real_distribution<float> dist(0.0f, 10.0f);
|
|
||||||
return dist(program.get_random());
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a test using multiple types with blt::gp
|
|
||||||
*/
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
type_system.register_type<float>();
|
|
||||||
type_system.register_type<bool>();
|
|
||||||
|
|
||||||
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());
|
|
||||||
|
|
||||||
blt::gp::ramped_half_initializer_t pop_init;
|
|
||||||
|
|
||||||
auto pop = pop_init.generate(blt::gp::initializer_arguments{program, type_system.get_type<float>().id(), 500, 3, 10});
|
|
||||||
|
|
||||||
for (auto& tree : pop.getIndividuals())
|
|
||||||
{
|
|
||||||
auto value = tree.get_evaluation_value<float>(nullptr);
|
|
||||||
|
|
||||||
BLT_TRACE(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <blt/std/logging.h>
|
#include <blt/std/logging.h>
|
||||||
#include <blt/std/types.h>
|
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
@ -30,7 +29,7 @@ namespace blt::gp
|
||||||
|
|
||||||
class type;
|
class type;
|
||||||
|
|
||||||
class type_provider;
|
class type_system;
|
||||||
|
|
||||||
struct op_container_t;
|
struct op_container_t;
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ namespace blt::gp
|
||||||
// context*, read stack, write stack
|
// context*, read stack, write stack
|
||||||
using callable_t = std::function<void(void*, stack_allocator&, stack_allocator&)>;
|
using callable_t = std::function<void(void*, stack_allocator&, stack_allocator&)>;
|
||||||
// to, from
|
// to, from
|
||||||
using transfer_t = std::function<void(stack_allocator&, stack_allocator&, blt::ptrdiff_t)>;
|
using transfer_t = std::function<void(stack_allocator&, stack_allocator&)>;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include <blt/std/ranges.h>
|
#include <blt/std/ranges.h>
|
||||||
#include <blt/std/hashmap.h>
|
#include <blt/std/hashmap.h>
|
||||||
|
@ -53,38 +52,24 @@ namespace blt::gp
|
||||||
blt::size_t argc_context = 0;
|
blt::size_t argc_context = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct operator_storage
|
|
||||||
{
|
|
||||||
// indexed from return TYPE ID, returns index of operator
|
|
||||||
blt::expanding_buffer<std::vector<operator_id>> terminals;
|
|
||||||
blt::expanding_buffer<std::vector<operator_id>> non_terminals;
|
|
||||||
blt::expanding_buffer<std::vector<std::pair<operator_id, blt::size_t>>> operators_ordered_terminals;
|
|
||||||
// indexed from OPERATOR ID (operator number)
|
|
||||||
blt::expanding_buffer<std::vector<type>> argument_types;
|
|
||||||
blt::expanding_buffer<argc_t> operator_argc;
|
|
||||||
blt::hashset_t<operator_id> static_types;
|
|
||||||
std::vector<detail::callable_t> operators;
|
|
||||||
std::vector<detail::transfer_t> transfer_funcs;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Context = detail::empty_t>
|
template<typename Context = detail::empty_t>
|
||||||
class operator_builder
|
class gp_operations
|
||||||
{
|
{
|
||||||
friend class gp_program;
|
friend class gp_program;
|
||||||
|
|
||||||
friend class blt::gp::detail::operator_storage_test;
|
friend class blt::gp::detail::operator_storage_test;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit operator_builder(type_provider& system): system(system)
|
explicit gp_operations(type_system& system): system(system)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Return, typename... Args>
|
template<typename Return, typename... Args>
|
||||||
operator_builder& add_operator(const operation_t<Return(Args...)>& op, bool is_static = false)
|
gp_operations& add_operator(const operation_t<Return(Args...)>& op, bool is_static = false)
|
||||||
{
|
{
|
||||||
auto return_type_id = system.get_type<Return>().id();
|
auto return_type_id = system.get_type<Return>().id();
|
||||||
auto operator_id = blt::gp::operator_id(storage.operators.size());
|
auto operator_id = blt::gp::operator_id(operators.size());
|
||||||
|
|
||||||
auto& operator_list = op.get_argc() == 0 ? storage.terminals : storage.non_terminals;
|
auto& operator_list = op.get_argc() == 0 ? terminals : non_terminals;
|
||||||
operator_list[return_type_id].push_back(operator_id);
|
operator_list[return_type_id].push_back(operator_id);
|
||||||
|
|
||||||
if constexpr (sizeof...(Args) > 0)
|
if constexpr (sizeof...(Args) > 0)
|
||||||
|
@ -99,95 +84,38 @@ namespace blt::gp
|
||||||
|
|
||||||
BLT_ASSERT(argc.argc_context - argc.argc <= 1 && "Cannot pass multiple context as arguments!");
|
BLT_ASSERT(argc.argc_context - argc.argc <= 1 && "Cannot pass multiple context as arguments!");
|
||||||
|
|
||||||
storage.operator_argc[operator_id] = argc;
|
operator_argc[operator_id] = argc;
|
||||||
|
|
||||||
storage.operators.push_back(op.template make_callable<Context>());
|
operators.push_back(op.template make_callable<Context>());
|
||||||
storage.transfer_funcs.push_back([](stack_allocator& to, stack_allocator& from, blt::ptrdiff_t offset) {
|
transfer_funcs.push_back([](stack_allocator& to, stack_allocator& from) {
|
||||||
if (offset < 0)
|
|
||||||
to.push(from.pop<Return>());
|
to.push(from.pop<Return>());
|
||||||
else
|
|
||||||
to.push(from.from<Return>(offset));
|
|
||||||
});
|
});
|
||||||
if (is_static)
|
if (is_static)
|
||||||
storage.static_types.insert(operator_id);
|
static_types.insert(operator_id);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator_storage&& build()
|
|
||||||
{
|
|
||||||
blt::hashset_t<type_id> has_terminals;
|
|
||||||
|
|
||||||
for (const auto& v : blt::enumerate(storage.terminals))
|
|
||||||
{
|
|
||||||
if (!v.second.empty())
|
|
||||||
has_terminals.insert(v.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& op_r : blt::enumerate(storage.non_terminals))
|
|
||||||
{
|
|
||||||
if (op_r.second.empty())
|
|
||||||
continue;
|
|
||||||
auto return_type = op_r.first;
|
|
||||||
std::vector<std::pair<operator_id, blt::size_t>> ordered_terminals;
|
|
||||||
for (const auto& op : op_r.second)
|
|
||||||
{
|
|
||||||
// count number of terminals
|
|
||||||
blt::size_t terminals = 0;
|
|
||||||
for (const auto& type : storage.argument_types[op])
|
|
||||||
{
|
|
||||||
if (has_terminals.contains(type.id()))
|
|
||||||
terminals++;
|
|
||||||
}
|
|
||||||
ordered_terminals.emplace_back(op, terminals);
|
|
||||||
}
|
|
||||||
bool found_terminal_inputs = false;
|
|
||||||
bool matches_argc = false;
|
|
||||||
for (const auto& terms : ordered_terminals)
|
|
||||||
{
|
|
||||||
if (terms.second == storage.operator_argc[terms.first].argc)
|
|
||||||
matches_argc = true;
|
|
||||||
if (terms.second != 0)
|
|
||||||
found_terminal_inputs = true;
|
|
||||||
if (matches_argc && found_terminal_inputs)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!found_terminal_inputs)
|
|
||||||
BLT_ABORT(("Failed to find function with terminal arguments for return type " + std::to_string(return_type)).c_str());
|
|
||||||
if (!matches_argc)
|
|
||||||
{
|
|
||||||
BLT_ABORT(("Failed to find a function which purely translates types "
|
|
||||||
"(that is all input types are terminals) for return type " + std::to_string(return_type)).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(ordered_terminals.begin(), ordered_terminals.end(), [](const auto& a, const auto& b) {
|
|
||||||
return a.second > b.second;
|
|
||||||
});
|
|
||||||
|
|
||||||
auto first_size = *ordered_terminals.begin();
|
|
||||||
auto iter = ordered_terminals.begin();
|
|
||||||
while (++iter != ordered_terminals.end() && iter->second == first_size.second)
|
|
||||||
{}
|
|
||||||
|
|
||||||
ordered_terminals.erase(iter, ordered_terminals.end());
|
|
||||||
|
|
||||||
storage.operators_ordered_terminals[return_type] = ordered_terminals;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::move(storage);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void add_non_context_argument(blt::gp::operator_id operator_id)
|
void add_non_context_argument(blt::gp::operator_id operator_id)
|
||||||
{
|
{
|
||||||
if constexpr (!std::is_same_v<Context, detail::remove_cv_ref<T>>)
|
if constexpr (!std::is_same_v<Context, detail::remove_cv_ref<T>>)
|
||||||
{
|
{
|
||||||
storage.argument_types[operator_id].push_back(system.get_type<T>());
|
argument_types[operator_id].push_back(system.get_type<T>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type_provider& system;
|
type_system& system;
|
||||||
operator_storage storage;
|
|
||||||
|
// indexed from return TYPE ID, returns index of operator
|
||||||
|
blt::expanding_buffer<std::vector<operator_id>> terminals;
|
||||||
|
blt::expanding_buffer<std::vector<operator_id>> non_terminals;
|
||||||
|
// indexed from OPERATOR ID (operator number)
|
||||||
|
blt::expanding_buffer<std::vector<type>> argument_types;
|
||||||
|
blt::expanding_buffer<argc_t> operator_argc;
|
||||||
|
blt::hashset_t<operator_id> static_types;
|
||||||
|
std::vector<detail::callable_t> operators;
|
||||||
|
std::vector<detail::transfer_t> transfer_funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
class gp_program
|
class gp_program
|
||||||
|
@ -201,7 +129,7 @@ namespace blt::gp
|
||||||
* @param engine random engine to use throughout the program. TODO replace this with something better
|
* @param engine random engine to use throughout the program. TODO replace this with something better
|
||||||
* @param context_size number of arguments which are always present as "context" to the GP system / operators
|
* @param context_size number of arguments which are always present as "context" to the GP system / operators
|
||||||
*/
|
*/
|
||||||
explicit gp_program(type_provider& system, std::mt19937_64 engine):
|
explicit gp_program(type_system& system, std::mt19937_64 engine):
|
||||||
system(system), engine(engine)
|
system(system), engine(engine)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -228,79 +156,98 @@ namespace blt::gp
|
||||||
return dist(engine) < cutoff;
|
return dist(engine) < cutoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline type_provider& get_typesystem()
|
[[nodiscard]] inline type_system& get_typesystem()
|
||||||
{
|
{
|
||||||
return system;
|
return system;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator_id select_terminal(type_id id)
|
inline operator_id select_terminal(type_id id)
|
||||||
{
|
{
|
||||||
// we wanted a terminal, but could not find one, so we will select from a function that has a terminal
|
std::uniform_int_distribution<blt::size_t> dist(0, terminals[id].size() - 1);
|
||||||
if (storage.terminals[id].empty())
|
return terminals[id][dist(engine)];
|
||||||
return select_non_terminal_too_deep(id);
|
|
||||||
std::uniform_int_distribution<blt::size_t> dist(0, storage.terminals[id].size() - 1);
|
|
||||||
return storage.terminals[id][dist(engine)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator_id select_non_terminal(type_id id)
|
inline operator_id select_non_terminal(type_id id)
|
||||||
{
|
{
|
||||||
std::uniform_int_distribution<blt::size_t> dist(0, storage.non_terminals[id].size() - 1);
|
std::uniform_int_distribution<blt::size_t> dist(0, non_terminals[id].size() - 1);
|
||||||
return storage.non_terminals[id][dist(engine)];
|
return non_terminals[id][dist(engine)];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator_id select_non_terminal_too_deep(type_id id)
|
// inline operator_id select_non_terminal_too_deep(type_id id)
|
||||||
{
|
// {
|
||||||
std::uniform_int_distribution<blt::size_t> dist(0, storage.operators_ordered_terminals[id].size() - 1);
|
// std::uniform_int_distribution<blt::size_t> dist(0, non_terminals[id].size() - 1);
|
||||||
return storage.operators_ordered_terminals[id][dist(engine)].first;
|
// operator_id sel;
|
||||||
}
|
// do
|
||||||
|
// {
|
||||||
|
// sel = non_terminals[id][dist(engine)];
|
||||||
|
// } while (std::find_if(argument_types[sel].begin(), argument_types[sel].end(),
|
||||||
|
// [id](const auto& v) {
|
||||||
|
// return v.id() == id;
|
||||||
|
// }) != argument_types[sel].end());
|
||||||
|
// return sel;
|
||||||
|
// }
|
||||||
|
|
||||||
inline std::vector<type>& get_argument_types(operator_id id)
|
inline std::vector<type>& get_argument_types(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.argument_types[id];
|
return argument_types[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector<operator_id>& get_type_terminals(type_id id)
|
inline std::vector<operator_id>& get_type_terminals(type_id id)
|
||||||
{
|
{
|
||||||
return storage.terminals[id];
|
return terminals[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::vector<operator_id>& get_type_non_terminals(type_id id)
|
inline std::vector<operator_id>& get_type_non_terminals(type_id id)
|
||||||
{
|
{
|
||||||
return storage.non_terminals[id];
|
return non_terminals[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline argc_t get_argc(operator_id id)
|
inline argc_t get_argc(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.operator_argc[id];
|
return operator_argc[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline detail::callable_t& get_operation(operator_id id)
|
inline detail::callable_t& get_operation(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.operators[id];
|
return operators[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline detail::transfer_t& get_transfer_func(operator_id id)
|
inline detail::transfer_t& get_transfer_func(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.transfer_funcs[id];
|
return transfer_funcs[id];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_static(operator_id id)
|
inline bool is_static(operator_id id)
|
||||||
{
|
{
|
||||||
return storage.static_types.contains(static_cast<blt::size_t>(id));
|
return static_types.contains(static_cast<blt::size_t>(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_operations(operator_storage&& op)
|
template<typename Context>
|
||||||
|
inline void set_operations(gp_operations<Context>&& op)
|
||||||
{
|
{
|
||||||
storage = std::move(op);
|
terminals = std::move(op.terminals);
|
||||||
|
non_terminals = std::move(op.non_terminals);
|
||||||
|
argument_types = std::move(op.argument_types);
|
||||||
|
static_types = std::move(op.static_types);
|
||||||
|
operator_argc = std::move(op.operator_argc);
|
||||||
|
operators = std::move(op.operators);
|
||||||
|
transfer_funcs = std::move(op.transfer_funcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
type_provider& system;
|
type_system& system;
|
||||||
blt::gp::stack_allocator alloc;
|
blt::gp::stack_allocator alloc;
|
||||||
|
|
||||||
operator_storage storage;
|
|
||||||
|
|
||||||
std::mt19937_64 engine;
|
std::mt19937_64 engine;
|
||||||
|
|
||||||
|
// indexed from return TYPE ID, returns index of operator
|
||||||
|
blt::expanding_buffer<std::vector<operator_id>> terminals;
|
||||||
|
blt::expanding_buffer<std::vector<operator_id>> non_terminals;
|
||||||
|
// indexed from OPERATOR ID (operator number)
|
||||||
|
blt::expanding_buffer<std::vector<type>> argument_types;
|
||||||
|
blt::expanding_buffer<argc_t> operator_argc;
|
||||||
|
blt::hashset_t<operator_id> static_types;
|
||||||
|
std::vector<detail::callable_t> operators;
|
||||||
|
std::vector<detail::transfer_t> transfer_funcs;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,20 +19,9 @@
|
||||||
#ifndef BLT_GP_TRANSFORMERS_H
|
#ifndef BLT_GP_TRANSFORMERS_H
|
||||||
#define BLT_GP_TRANSFORMERS_H
|
#define BLT_GP_TRANSFORMERS_H
|
||||||
|
|
||||||
#include <blt/std/utility.h>
|
|
||||||
#include <blt/gp/fwdecl.h>
|
|
||||||
#include <blt/gp/tree.h>
|
|
||||||
|
|
||||||
namespace blt::gp
|
namespace blt::gp
|
||||||
{
|
{
|
||||||
|
|
||||||
class crossover_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BLT_ATTRIB_CONST virtual std::pair<tree_t, tree_t> apply(gp_program& program, const tree_t& p1, const tree_t& p2);
|
|
||||||
virtual void apply_in_place(gp_program& program, tree_t& p1, tree_t& p2);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //BLT_GP_TRANSFORMERS_H
|
#endif //BLT_GP_TRANSFORMERS_H
|
||||||
|
|
|
@ -80,10 +80,10 @@ namespace blt::gp
|
||||||
* Is a provider for the set of types possible in a GP program
|
* Is a provider for the set of types possible in a GP program
|
||||||
* also provides a set of functions for converting between C++ types and BLT GP types
|
* also provides a set of functions for converting between C++ types and BLT GP types
|
||||||
*/
|
*/
|
||||||
class type_provider
|
class type_system
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
type_provider() = default;
|
type_system() = default;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline type register_type()
|
inline type register_type()
|
||||||
|
@ -98,17 +98,6 @@ namespace blt::gp
|
||||||
return types[blt::type_string_raw<T>()];
|
return types[blt::type_string_raw<T>()];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline type get_type(type_id id)
|
|
||||||
{
|
|
||||||
for (const auto& v : types)
|
|
||||||
{
|
|
||||||
if (v.second.id() == id)
|
|
||||||
return v.second;
|
|
||||||
}
|
|
||||||
BLT_ABORT(("Type " + std::to_string(id) + " does not exist").c_str());
|
|
||||||
std::exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is slow btw
|
* This function is slow btw
|
||||||
* @param engine
|
* @param engine
|
||||||
|
|
|
@ -59,12 +59,12 @@ namespace blt::gp
|
||||||
{
|
{
|
||||||
auto top = tree_generator.top();
|
auto top = tree_generator.top();
|
||||||
tree_generator.pop();
|
tree_generator.pop();
|
||||||
//BLT_INFO("%ld D: %ld (%ld left)", top.id, top.depth, tree_generator.size());
|
|
||||||
|
|
||||||
tree.get_operations().emplace_back(
|
tree.get_operations().emplace_back(
|
||||||
args.program.get_operation(top.id),
|
args.program.get_operation(top.id),
|
||||||
args.program.get_transfer_func(top.id),
|
args.program.get_transfer_func(top.id),
|
||||||
args.program.is_static(top.id));
|
args.program.is_static(top.id)
|
||||||
|
);
|
||||||
max_depth = std::max(max_depth, top.depth);
|
max_depth = std::max(max_depth, top.depth);
|
||||||
|
|
||||||
if (args.program.is_static(top.id))
|
if (args.program.is_static(top.id))
|
||||||
|
@ -90,7 +90,7 @@ namespace blt::gp
|
||||||
if (new_depth >= args.max_depth)
|
if (new_depth >= args.max_depth)
|
||||||
{
|
{
|
||||||
if (program.get_type_terminals(type.id()).empty())
|
if (program.get_type_terminals(type.id()).empty())
|
||||||
tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth});
|
tree_generator.push({program.select_non_terminal(type.id()), new_depth});
|
||||||
else
|
else
|
||||||
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
||||||
return;
|
return;
|
||||||
|
@ -108,7 +108,7 @@ namespace blt::gp
|
||||||
if (new_depth >= args.max_depth)
|
if (new_depth >= args.max_depth)
|
||||||
{
|
{
|
||||||
if (program.get_type_terminals(type.id()).empty())
|
if (program.get_type_terminals(type.id()).empty())
|
||||||
tree_generator.push({program.select_non_terminal_too_deep(type.id()), new_depth});
|
tree_generator.push({program.select_non_terminal(type.id()), new_depth});
|
||||||
else
|
else
|
||||||
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
tree_generator.push({program.select_terminal(type.id()), new_depth});
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -40,7 +40,7 @@ namespace blt::gp
|
||||||
operations_stack.pop_back();
|
operations_stack.pop_back();
|
||||||
if (operation.is_value)
|
if (operation.is_value)
|
||||||
{
|
{
|
||||||
operation.transfer(values_process, value_stack, -1);
|
operation.transfer(values_process, value_stack);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
operation.func(context, values_process, value_stack);
|
operation.func(context, values_process, value_stack);
|
||||||
|
|
Loading…
Reference in New Issue