begin program

thread
Brett 2024-06-19 14:12:04 -04:00
parent b8268467da
commit ac36a63c5b
6 changed files with 322 additions and 279 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
project(blt-gp VERSION 0.0.20)
project(blt-gp VERSION 0.0.21)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)

View File

@ -24,252 +24,252 @@
#include <random>
//// small scale
//enum class op
//{
// ADD,
// SUB,
// MUL,
// DIV,
// LIT
//};
//
//std::string to_string(op o)
//{
// switch (o)
// {
// case op::ADD:
// return "ADD";
// case op::SUB:
// return "SUB";
// case op::MUL:
// return "MUL";
// case op::DIV:
// return "DIV";
// case op::LIT:
// return "LIT";
// }
// return "";
//}
//
//constexpr static long SEED = 41912;
//
//op generate_op()
//{
// static std::mt19937_64 engine(SEED);
// static std::uniform_int_distribution dist(0, static_cast<int>(op::LIT) - 1);
// return static_cast<op>(dist(engine));
//}
//
//bool choice()
//{
// static std::mt19937_64 engine(SEED);
// static std::uniform_int_distribution dist(0, 1);
// return dist(engine);
//}
//
//float random_value()
//{
// static std::mt19937_64 engine(SEED);
// static std::uniform_real_distribution dist(0.0f, 10.0f);
// return dist(engine);
//}
//
//void test()
//{
// std::vector<op> operations;
// std::vector<float> values;
//
// std::stack<op> tree_generator;
// tree_generator.push(generate_op());
//
// while (!tree_generator.empty())
// {
// auto opn = tree_generator.top();
// tree_generator.pop();
//
// operations.push_back(opn);
// if (opn == op::LIT)
// {
// values.push_back(random_value());
// continue;
// }
//
// // child 1
// if (choice())
// tree_generator.push(generate_op());
// else
// tree_generator.push(op::LIT);
//
// // child 2
// if (choice())
// tree_generator.push(generate_op());
// else
// tree_generator.push(op::LIT);
// }
//
// for (const auto& v : operations)
// std::cout << to_string(v) << " ";
// std::cout << std::endl;
//
// {
// std::stack<blt::size_t> process;
// for (const auto& v : operations)
// {
// switch (v)
// {
// case op::ADD:
// case op::SUB:
// case op::MUL:
// case op::DIV:
// process.emplace(2);
// std::cout << "(";
// break;
// case op::LIT:
// break;
// }
// std::cout << to_string(v);
// while (!process.empty())
// {
// auto top = process.top();
// process.pop();
// if (top == 0)
// {
// std::cout << ")";
// continue;
// } else
// {
// std::cout << " ";
// process.push(top - 1);
// break;
// }
// }
// }
// while (!process.empty())
// {
// auto top = process.top();
// process.pop();
// if (top == 0)
// {
// std::cout << ") ";
// continue;
// } else
// {
// std::cerr << "FUCK YOU\n";
// break;
// }
// }
// std::cout << std::endl;
// }
//
// for (const auto& v : values)
// std::cout << v << " ";
// std::cout << std::endl;
//
// {
// std::stack<blt::size_t> process;
// blt::size_t index = 0;
// for (const auto& v : operations)
// {
// switch (v)
// {
// case op::ADD:
// case op::SUB:
// case op::MUL:
// case op::DIV:
// process.emplace(2);
// std::cout << "(";
// std::cout << to_string(v);
// break;
// case op::LIT:
// std::cout << values[index++];
// break;
// }
//
// while (!process.empty())
// {
// auto top = process.top();
// process.pop();
// if (top == 0)
// {
// std::cout << ")";
// continue;
// } else
// {
// std::cout << " ";
// process.push(top - 1);
// break;
// }
// }
// }
// while (!process.empty())
// {
// auto top = process.top();
// process.pop();
// if (top == 0)
// {
// std::cout << ") ";
// continue;
// } else
// {
// std::cerr << "FUCK YOU\n";
// break;
// }
// }
// std::cout << std::endl;
// }
//
// std::stack<float> process;
// std::stack<op> operators;
//
// for (const auto& v : operations)
// operators.push(v);
//
// while (!operators.empty())
// {
// auto oper = operators.top();
// operators.pop();
// if (oper == op::LIT)
// {
// process.push(values.back());
// values.pop_back();
// } else
// {
// auto v1 = process.top();
// process.pop();
// auto v2 = process.top();
// process.pop();
// std::cout << "processing oper " << to_string(oper) << " with values " << v1 << " " << v2 << std::endl;
// switch (oper)
// {
// case op::ADD:
// values.push_back(v1 + v2);
// operators.push(op::LIT);
// break;
// case op::SUB:
// values.push_back(v1 - v2);
// operators.push(op::LIT);
// break;
// case op::MUL:
// values.push_back(v1 * v2);
// operators.push(op::LIT);
// break;
// case op::DIV:
// if (v2 == 0)
// v2 = 1;
// values.push_back(v1 / v2);
// operators.push(op::LIT);
// break;
// case op::LIT:
// break;
// }
// std::cout << "\tresult: " << values.back() << std::endl;
// }
// }
//
// std::cout << process.size() << std::endl;
// std::cout << process.top() << std::endl;
//
//}
enum class op
{
ADD,
SUB,
MUL,
DIV,
LIT
};
std::string to_string(op o)
{
switch (o)
{
case op::ADD:
return "ADD";
case op::SUB:
return "SUB";
case op::MUL:
return "MUL";
case op::DIV:
return "DIV";
case op::LIT:
return "LIT";
}
return "";
}
constexpr static long SEED = 41912;
op generate_op()
{
static std::mt19937_64 engine(SEED);
static std::uniform_int_distribution dist(0, static_cast<int>(op::LIT) - 1);
return static_cast<op>(dist(engine));
}
bool choice()
{
static std::mt19937_64 engine(SEED);
static std::uniform_int_distribution dist(0, 1);
return dist(engine);
}
float random_value()
{
static std::mt19937_64 engine(SEED);
static std::uniform_real_distribution dist(0.0f, 10.0f);
return dist(engine);
}
void test()
{
std::vector<op> operations;
std::vector<float> values;
std::stack<op> tree_generator;
tree_generator.push(generate_op());
while (!tree_generator.empty())
{
auto opn = tree_generator.top();
tree_generator.pop();
operations.push_back(opn);
if (opn == op::LIT)
{
values.push_back(random_value());
continue;
}
// child 1
if (choice())
tree_generator.push(generate_op());
else
tree_generator.push(op::LIT);
// child 2
if (choice())
tree_generator.push(generate_op());
else
tree_generator.push(op::LIT);
}
for (const auto& v : operations)
std::cout << to_string(v) << " ";
std::cout << std::endl;
{
std::stack<blt::size_t> process;
for (const auto& v : operations)
{
switch (v)
{
case op::ADD:
case op::SUB:
case op::MUL:
case op::DIV:
process.emplace(2);
std::cout << "(";
break;
case op::LIT:
break;
}
std::cout << to_string(v);
while (!process.empty())
{
auto top = process.top();
process.pop();
if (top == 0)
{
std::cout << ")";
continue;
} else
{
std::cout << " ";
process.push(top - 1);
break;
}
}
}
while (!process.empty())
{
auto top = process.top();
process.pop();
if (top == 0)
{
std::cout << ") ";
continue;
} else
{
std::cerr << "FUCK YOU\n";
break;
}
}
std::cout << std::endl;
}
for (const auto& v : values)
std::cout << v << " ";
std::cout << std::endl;
{
std::stack<blt::size_t> process;
blt::size_t index = 0;
for (const auto& v : operations)
{
switch (v)
{
case op::ADD:
case op::SUB:
case op::MUL:
case op::DIV:
process.emplace(2);
std::cout << "(";
std::cout << to_string(v);
break;
case op::LIT:
std::cout << values[index++];
break;
}
while (!process.empty())
{
auto top = process.top();
process.pop();
if (top == 0)
{
std::cout << ")";
continue;
} else
{
std::cout << " ";
process.push(top - 1);
break;
}
}
}
while (!process.empty())
{
auto top = process.top();
process.pop();
if (top == 0)
{
std::cout << ") ";
continue;
} else
{
std::cerr << "FUCK YOU\n";
break;
}
}
std::cout << std::endl;
}
std::stack<float> process;
std::stack<op> operators;
for (const auto& v : operations)
operators.push(v);
while (!operators.empty())
{
auto oper = operators.top();
operators.pop();
if (oper == op::LIT)
{
process.push(values.back());
values.pop_back();
} else
{
auto v1 = process.top();
process.pop();
auto v2 = process.top();
process.pop();
std::cout << "processing oper " << to_string(oper) << " with values " << v1 << " " << v2 << std::endl;
switch (oper)
{
case op::ADD:
values.push_back(v1 + v2);
operators.push(op::LIT);
break;
case op::SUB:
values.push_back(v1 - v2);
operators.push(op::LIT);
break;
case op::MUL:
values.push_back(v1 * v2);
operators.push(op::LIT);
break;
case op::DIV:
if (v2 == 0)
v2 = 1;
values.push_back(v1 / v2);
operators.push(op::LIT);
break;
case op::LIT:
break;
}
std::cout << "\tresult: " << values.back() << std::endl;
}
}
std::cout << process.size() << std::endl;
std::cout << process.top() << std::endl;
}
//
//struct silly
//{
@ -368,12 +368,12 @@ int main()
alloc.push(120);
alloc.push(true);
blt::gp::operation<float(float, int, bool)> silly_op(nyah);
blt::gp::operation<float(float,float)> silly_op_2([](float f, float g) {
blt::gp::operation_t<float(float, int, bool)> silly_op(nyah);
blt::gp::operation_t<float(float, float)> silly_op_2([](float f, float g) {
return f + g;
});
std::cout << silly_op_2(alloc) << std::endl;
std::cout << silly_op(alloc) << std::endl;
std::cout << "Is empty? " << alloc.empty() << std::endl;

View File

@ -21,7 +21,7 @@
namespace blt::gp
{
class identifier;
}
#endif //BLT_GP_FWDECL_H

View File

@ -24,6 +24,7 @@
#include <blt/gp/fwdecl.h>
#include <functional>
#include <blt/std/ranges.h>
#include <blt/std/hashmap.h>
#include <blt/std/types.h>
#include <blt/std/utility.h>
#include <type_traits>
@ -34,9 +35,6 @@
namespace blt::gp
{
class identifier
{
};
class type
{
@ -79,33 +77,39 @@ namespace blt::gp
template<typename T>
inline type register_type()
{
types.push_back(type::make_type<T>(types.size()));
return types.back();
types[blt::type_string_raw<T>()](type::make_type<T>(types.size()));
return types[blt::type_string_raw<T>()];
}
template<typename T>
inline type get_type()
{
return types[blt::type_string_raw<T>()];
}
private:
std::vector<type> types;
blt::hashmap_t<std::string, type> types;
};
template<typename Signature>
class operation;
class operation_t;
template<typename Return, typename... Args>
class operation<Return(Args...)>
class operation_t<Return(Args...)>
{
public:
using function_t = std::function<Return(Args...)>;
constexpr operation(const operation& copy) = default;
constexpr operation_t(const operation_t& copy) = default;
constexpr operation(operation&& move) = default;
constexpr operation_t(operation_t&& move) = default;
template<typename Functor>
constexpr explicit operation(const Functor& functor): func(functor)
constexpr explicit operation_t(const Functor& functor): func(functor)
{}
template<blt::u64 index>
[[nodiscard]] inline constexpr blt::size_t getByteOffset() const
[[nodiscard]] inline constexpr static blt::size_t getByteOffset()
{
blt::size_t offset = 0;
blt::size_t current_index = 0;
@ -114,7 +118,7 @@ namespace blt::gp
}
template<blt::u64... indices>
inline constexpr Return sequence_to_indices(stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>) const
inline constexpr Return exec_sequence_to_indices(stack_allocator& allocator, std::integer_sequence<blt::u64, indices...>) const
{
// expands Args and indices, providing each argument with its index calculating the current argument byte offset
return func(allocator.from<Args>(getByteOffset<indices>())...);
@ -123,29 +127,30 @@ namespace blt::gp
[[nodiscard]] constexpr inline Return operator()(stack_allocator& allocator) const
{
constexpr auto seq = std::make_integer_sequence<blt::u64, sizeof...(Args)>();
Return ret = sequence_to_indices(allocator, seq);
Return ret = exec_sequence_to_indices(allocator, seq);
allocator.call_destructors<Args...>();
allocator.pop_bytes((stack_allocator::aligned_size<Args>() + ...));
return ret;
}
private:
// template<typename T, blt::size_t index>
// static inline T& access_pack_index(blt::span<void*> args)
// {
// return *reinterpret_cast<T*>(args[index]);
// }
//
// template<typename T, T... indexes>
// Return function_evaluator(blt::span<void*> args, std::integer_sequence<T, indexes...>)
// {
// return func(access_pack_index<Args, indexes>(args)...);
// }
[[nodiscard]] std::function<void(stack_allocator&)> make_callable() const
{
return [this](stack_allocator& values) {
values.push(this->operator()(values));
};
}
[[nodiscard]] blt::size_t get_argc() const
{
return sizeof...(Args);
}
private:
function_t func;
};
template<typename Return, typename... Args>
operation(Return (*)(Args...)) -> operation<Return(Args...)>;
operation_t(Return (*)(Args...)) -> operation_t<Return(Args...)>;
//
// template<typename Sig>
// operation(std::function<Sig>) -> operation<Sig>;
@ -153,6 +158,37 @@ namespace blt::gp
// template<typename Return, typename... Args>
// operation(std::function<Return(Args...)>) -> operation<Return(Args...)>;
class gp_program
{
public:
explicit gp_program(type_system system): system(std::move(system))
{}
template<typename Return, typename... Args>
void add_operator(const operation_t<Return(Args...)>& op)
{
if (op.get_argc() == 0)
terminals.push_back(operators.size());
else
non_terminals.push_back(operators.size());
operators.push_back(op.make_callable());
std::vector<type> types;
(types.push_back(system.get_type<Args>()), ...);
arg_types.push_back(std::move(types));
return_types.push_back(system.get_type<Return>());
}
private:
type_system system;
std::vector<std::function<void(stack_allocator&)>> operators;
std::vector<blt::size_t> terminals;
std::vector<blt::size_t> non_terminals;
std::vector<type> return_types;
std::vector<std::vector<type>> arg_types;
};
}

View File

@ -112,6 +112,13 @@ namespace blt::gp
}
}
template<typename... Args>
void call_destructors()
{
blt::size_t offset = 0;
((from<Args>(offset).~Args(), offset += stack_allocator::aligned_size<Args>()), ...);
}
[[nodiscard]] bool empty() const
{
if (head == nullptr)

@ -1 +1 @@
Subproject commit 8d3bfbcdc36fb769257ae58c0374ef44253e0a34
Subproject commit 2266d64f042bc97b54e7e50dcaac730bcc3ab4c3