cancerious copy consturctors and fun little tests

main
Brett 2024-01-30 13:57:27 -05:00
parent 68dad0f963
commit dae1d8cf6a
7 changed files with 179 additions and 102 deletions

View File

@ -21,12 +21,13 @@
#include <blt/std/types.h> #include <blt/std/types.h>
inline constexpr blt::i32 MIN_DEPTH = 3;
inline constexpr blt::i32 MAX_DEPTH = 12; inline constexpr blt::i32 MAX_DEPTH = 12;
inline constexpr blt::i32 width = 256, height = 256; inline constexpr blt::i32 width = 256, height = 256;
inline constexpr blt::i32 POPULATION_SIZE = 20; inline constexpr blt::i32 POPULATION_SIZE = 20;
inline constexpr blt::i32 GEN_COUNT = 20; inline constexpr blt::i32 GEN_COUNT = 20;
inline constexpr blt::i32 TOURNAMENT_SIZE = 3; inline constexpr blt::i32 TOURNAMENT_SIZE = 3;
inline constexpr float CROSSOVER_RATE = 0.9; inline constexpr float CROSSOVER_RATE = 0.9;
inline constexpr float MUTATION_RATE = 0.9; inline constexpr float MUTATION_RATE = 0.1;
#endif //GP_IMAGE_TEST_CONFIG_H #endif //GP_IMAGE_TEST_CONFIG_H

View File

@ -244,8 +244,7 @@ inline static allowed_funcs<function_t> intersection_comp(const allowed_funcs<fu
// distribution from normality (DFN) // distribution from normality (DFN)
float eval_DNF_SW(const image& img); float eval_DNF_SW(const image& img);
float eval_DNF_SW_1(const image& img);
float eval_DNF_KS(const image& img);
//template<typename F> //template<typename F>
//bool isNan(F f) //bool isNan(F f)

View File

@ -65,6 +65,8 @@ struct node
} }
} }
node(const node& copy);
static node* construct_random_tree(blt::size_t max_depth = MAX_DEPTH); static node* construct_random_tree(blt::size_t max_depth = MAX_DEPTH);
void evaluate(); void evaluate();

View File

@ -10,44 +10,47 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
const std::vector<double> large_c { const std::vector<double> large_c{
0.139E100, 0.157E100, 0.175E100, 0.256E100, 0.344E100, 0.413E100, 0.503E100, 0.577E100, 0.139E100, 0.157E100, 0.175E100, 0.256E100, 0.344E100, 0.413E100, 0.503E100, 0.577E100,
0.614E100, 0.655E100, 0.954E100, 1.392E100, 1.557E100, 1.648E100, 1.690E100, 1.994E100, 0.614E100, 0.655E100, 0.954E100, 1.392E100, 1.557E100, 1.648E100, 1.690E100, 1.994E100,
2.174E100, 2.206E100, 3.245E100, 3.510E100, 3.571E100, 4.354E100, 4.980E100, 6.084E100, 2.174E100, 2.206E100, 3.245E100, 3.510E100, 3.571E100, 4.354E100, 4.980E100, 6.084E100,
8.351E100}; 8.351E100};
const std::vector<double> normally_c {-0.4417998157703872, const std::vector<double> normally_c{-0.4417998157703872,
-0.310841224215176, -0.310841224215176,
-0.2544758389229413, -0.2544758389229413,
-0.21509882047762266, -0.21509882047762266,
-0.18254731741828356, -0.18254731741828356,
-0.1541570107663562, -0.1541570107663562,
-0.12852819470327187, -0.12852819470327187,
-0.1048199468783084, -0.1048199468783084,
-0.08247628697708857, -0.08247628697708857,
-0.061100278634889656, -0.061100278634889656,
-0.040388574421146996, -0.040388574421146996,
-0.020093702456713224, -0.020093702456713224,
0.0, 0.0,
0.020093702456713224, 0.020093702456713224,
0.040388574421146996, 0.040388574421146996,
0.061100278634889656, 0.061100278634889656,
0.08247628697708857, 0.08247628697708857,
0.1048199468783084, 0.1048199468783084,
0.12852819470327187, 0.12852819470327187,
0.1541570107663562, 0.1541570107663562,
0.18254731741828356, 0.18254731741828356,
0.21509882047762266, 0.21509882047762266,
0.2544758389229413, 0.2544758389229413,
0.310841224215176, 0.310841224215176,
0.4417998157703872}; 0.4417998157703872};
const std::vector<double> nearly_c { const std::vector<double> nearly_c{
-0.44, -0.31, -0.25, -0.21, -0.18, -0.15, -0.12, -0.10, -0.08, -0.06, -0.04, -0.02, -0.44, -0.31, -0.25, -0.21, -0.18, -0.15, -0.12, -0.10, -0.08, -0.06, -0.04, -0.02,
0.0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.15, 0.18, 0.21, 0.25, 0.31, 0.44}; 0.0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.15, 0.18, 0.21, 0.25, 0.31, 0.44};
const auto runs = 500000;
#undef BLT_DEBUG #undef BLT_DEBUG
#define BLT_DEBUG(...) #define BLT_DEBUG(...)
void shapiro_test_local() void shapiro_test_local()
{ {
auto normally = normally_c; auto normally = normally_c;
@ -57,21 +60,26 @@ void shapiro_test_local()
std::sort(normally.begin(), normally.end()); std::sort(normally.begin(), normally.end());
std::sort(nearly.begin(), nearly.end()); std::sort(nearly.begin(), nearly.end());
std::sort(large.begin(), large.end()); std::sort(large.begin(), large.end());
willbruh w1(normally);
BLT_ASSERT(w1->estimate == 0.9999999999999999);
BLT_ASSERT(w1->p_value == 1.0);
BLT_DEBUG("%f // %f", w1->estimate, w1->p_value);
willbruh w2(nearly); BLT_START_INTERVAL("shapiro", "local_sorted");
BLT_ASSERT(w2->estimate == 0.9997987717271388); for (size_t i = 0; i < runs; i++)
BLT_ASSERT(w2->p_value == 1.0); {
BLT_DEBUG("%f // %f", w2->estimate, w2->p_value); willbruh w1(normally);
BLT_ASSERT(w1->estimate == 0.9999999999999999);
willbruh w3(large); BLT_ASSERT(w1->p_value == 1.0);
BLT_ASSERT(w3->estimate == 0.8346662753181684); BLT_DEBUG("%f // %f", w1->estimate, w1->p_value);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value); willbruh w2(nearly);
BLT_ASSERT(w2->estimate == 0.9997987717271388);
BLT_ASSERT(w2->p_value == 1.0);
BLT_DEBUG("%f // %f", w2->estimate, w2->p_value);
willbruh w3(large);
BLT_ASSERT(w3->estimate == 0.8346662753181684);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value);
}
BLT_END_INTERVAL("shapiro", "local_sorted");
} }
void shapiro_test_unsorted() void shapiro_test_unsorted()
@ -80,20 +88,25 @@ void shapiro_test_unsorted()
auto nearly = nearly_c; auto nearly = nearly_c;
auto large = large_c; auto large = large_c;
willbruh w1(willbert_unsorted(normally.data(), normally.size())); BLT_START_INTERVAL("shapiro", "unsorted_mut");
BLT_ASSERT(w1->estimate == 0.9999999999999999); for (int i = 0; i < runs; i++)
BLT_ASSERT(w1->p_value == 1.0); {
BLT_DEBUG("%f // %f", w1->estimate, w1->p_value); willbruh w1(willbert_unsorted(normally.data(), normally.size()));
BLT_ASSERT(w1->estimate == 0.9999999999999999);
willbruh w2(willbert_unsorted(nearly.data(), nearly.size())); BLT_ASSERT(w1->p_value == 1.0);
BLT_ASSERT(w2->estimate == 0.9997987717271388); BLT_DEBUG("%f // %f", w1->estimate, w1->p_value);
BLT_ASSERT(w2->p_value == 1.0);
BLT_DEBUG("%f // %f", w2->estimate, w2->p_value); willbruh w2(willbert_unsorted(nearly.data(), nearly.size()));
BLT_ASSERT(w2->estimate == 0.9997987717271388);
willbruh w3(willbert_unsorted(large.data(), large.size())); BLT_ASSERT(w2->p_value == 1.0);
BLT_ASSERT(w3->estimate == 0.8346662753181684); BLT_DEBUG("%f // %f", w2->estimate, w2->p_value);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value); willbruh w3(willbert_unsorted(large.data(), large.size()));
BLT_ASSERT(w3->estimate == 0.8346662753181684);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value);
}
BLT_END_INTERVAL("shapiro", "unsorted_mut");
} }
void shapiro_test_copy() void shapiro_test_copy()
@ -102,36 +115,32 @@ void shapiro_test_copy()
auto nearly = nearly_c; auto nearly = nearly_c;
auto large = large_c; auto large = large_c;
willbruh w1(willbert_unsorted_copy(normally.data(), normally.size())); BLT_START_INTERVAL("shapiro", "copy");
BLT_ASSERT(w1->estimate == 0.9999999999999999); for (int i = 0; i < runs; i++)
BLT_ASSERT(w1->p_value == 1.0); {
BLT_DEBUG("%f // %f", w1->estimate, w1->p_value); willbruh w1(willbert_unsorted_copy(normally.data(), normally.size()));
BLT_ASSERT(w1->estimate == 0.9999999999999999);
willbruh w2(willbert_unsorted_copy(nearly.data(), nearly.size())); BLT_ASSERT(w1->p_value == 1.0);
BLT_ASSERT(w2->estimate == 0.9997987717271388); BLT_DEBUG("%f // %f", w1->estimate, w1->p_value);
BLT_ASSERT(w2->p_value == 1.0);
BLT_DEBUG("%f // %f", w2->estimate, w2->p_value); willbruh w2(willbert_unsorted_copy(nearly.data(), nearly.size()));
BLT_ASSERT(w2->estimate == 0.9997987717271388);
willbruh w3(willbert_unsorted_copy(large.data(), large.size())); BLT_ASSERT(w2->p_value == 1.0);
BLT_ASSERT(w3->estimate == 0.8346662753181684); BLT_DEBUG("%f // %f", w2->estimate, w2->p_value);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value); willbruh w3(willbert_unsorted_copy(large.data(), large.size()));
BLT_ASSERT(w3->estimate == 0.8346662753181684);
BLT_ASSERT(w3->p_value == 0.0009134904817755807);
BLT_DEBUG("%f // %f", w3->estimate, w3->p_value);
}
BLT_END_INTERVAL("shapiro", "copy");
} }
void shapiro_test_run() void shapiro_test_run()
{ {
const auto runs = 500000;
BLT_START_INTERVAL("shapiro", "copy"); shapiro_test_copy();
for (size_t i = 0; i < runs; i++) shapiro_test_unsorted();
shapiro_test_copy(); shapiro_test_local();
BLT_END_INTERVAL("shapiro", "copy");
BLT_START_INTERVAL("shapiro", "unsorted_mut");
for (size_t i = 0; i < runs; i++)
shapiro_test_unsorted();
BLT_END_INTERVAL("shapiro", "unsorted_mut");
BLT_START_INTERVAL("shapiro", "local_sorted");
for (size_t i = 0; i < runs; i++)
shapiro_test_local();
BLT_END_INTERVAL("shapiro", "local_sorted");
BLT_PRINT_PROFILE("shapiro"); BLT_PRINT_PROFILE("shapiro");
} }

View File

@ -281,8 +281,30 @@ float eval_DNF_SW(const image& img)
return static_cast<float>(total); return static_cast<float>(total);
} }
float eval_DNF_KS(const image& img) float eval_DNF_SW_1(const image& img)
{ {
return 0; std::vector<double> order(width * height);
for (const auto& v : img.getData())
order.push_back(v.magnitude());
std::sort(order.begin(), order.end());
blt::size_t len = width / 4;
blt::size_t current_pos = 0;
double total = 0;
while (true)
{
if (order.size() - current_pos < len)
{
len = order.size() - current_pos;
if (len <= 0)
break;
}
total += on_data(order.data() + current_pos, len);
current_pos += len;
}
return static_cast<float>(total);
} }

View File

@ -148,7 +148,7 @@ node* node::construct_random_tree(blt::size_t max_depth)
if (front.second != current_depth) if (front.second != current_depth)
current_depth++; current_depth++;
if (choice(engine)) if (choice(engine) && current_depth >= MIN_DEPTH)
front.first->grow(front.second >= max_depth); front.first->grow(front.second >= max_depth);
else else
front.first->full(front.second >= max_depth); front.first->full(front.second >= max_depth);
@ -192,3 +192,17 @@ void node::evaluate()
} }
#undef FUNC_DEFINE #undef FUNC_DEFINE
} }
node::node(const node& copy)
{
argc = copy.argc;
type = copy.type;
static_assert(sizeof(data_t) == sizeof(float) * 3 && "Uhhh something is wrong here!");
std::memcpy(data.data(), copy.data.data(), sizeof(data_t));
for (blt::size_t i = 0; i < argc; i++)
{
sub_nodes[i] = node_allocator.allocate(1);
// tee hee
::new(&sub_nodes[i]) node(*copy.sub_nodes[i]);
}
}

View File

@ -109,6 +109,7 @@ class tree
auto top = stack.top(); auto top = stack.top();
auto* node = top.second; auto* node = top.second;
auto depth = top.first; auto depth = top.first;
stack.pop();
max_depth = std::max(max_depth, depth); max_depth = std::max(max_depth, depth);
for (blt::size_t i = 0; i < node->argc; i++) for (blt::size_t i = 0; i < node->argc; i++)
{ {
@ -117,7 +118,6 @@ class tree
stack.emplace(depth + 1, node->sub_nodes[i]); stack.emplace(depth + 1, node->sub_nodes[i]);
} }
} }
stack.pop();
} }
return max_depth; return max_depth;
@ -125,9 +125,14 @@ class tree
static bool crossover(tree* p1, tree* p2) static bool crossover(tree* p1, tree* p2)
{ {
if (p1 == nullptr || p2 == nullptr)
return false;
auto n1 = p1->select_random_child(); auto n1 = p1->select_random_child();
auto n2 = p2->select_random_child(); auto n2 = p2->select_random_child();
if (n1.parent == nullptr || n2.parent == nullptr)
return false;
const auto& p1_allowed = function_arg_allowed_set_map[to_underlying(n1.parent->type)][n1.index]; const auto& p1_allowed = function_arg_allowed_set_map[to_underlying(n1.parent->type)][n1.index];
const auto& p2_allowed = function_arg_allowed_set_map[to_underlying(n2.parent->type)][n2.index]; const auto& p2_allowed = function_arg_allowed_set_map[to_underlying(n2.parent->type)][n2.index];
@ -142,7 +147,7 @@ class tree
return true; return true;
} }
static void mutate(tree* p) static bool mutate(tree* p)
{ {
static std::random_device dev; static std::random_device dev;
static std::mt19937_64 engine{dev()}; static std::mt19937_64 engine{dev()};
@ -150,11 +155,15 @@ class tree
auto n = p->select_random_child(); auto n = p->select_random_child();
if (n.parent == nullptr)
return false;
auto d = depth(n.child); auto d = depth(n.child);
node* new_subtree = node::construct_random_tree(d + 1); node* new_subtree = node::construct_random_tree(d + 1);
n.parent->sub_nodes[n.index] = new_subtree; n.parent->sub_nodes[n.index] = new_subtree;
destroyNode(n.child); destroyNode(n.child);
return true;
} }
void evaluate() void evaluate()
@ -180,7 +189,8 @@ class tree
float fitness() float fitness()
{ {
return eval_DNF_SW(root->getImage()); auto& img = root->getImage();
return eval_DNF_SW(img) * eval_DNF_SW_1(img);
} }
void printTree() void printTree()
@ -197,6 +207,7 @@ class gp_population
std::unique_ptr<tree> t = nullptr; std::unique_ptr<tree> t = nullptr;
float fitness = 0; float fitness = 0;
}; };
blt::size_t best = -1;
private: private:
std::array<gp_i, POPULATION_SIZE> pop; std::array<gp_i, POPULATION_SIZE> pop;
public: public:
@ -218,17 +229,20 @@ class gp_population
evaluate_population(); evaluate_population();
} }
tree* select() tree* select(blt::size_t* out = nullptr)
{ {
tree* n = nullptr; tree* n = nullptr;
float fitness = 0; float fitness = 0;
for (int i = 0; i < TOURNAMENT_SIZE; i++) for (int i = 0; i < TOURNAMENT_SIZE; i++)
{ {
auto& v = pop[choice()]; auto index = choice();
auto& v = pop[index];
if (n != v.t.get() && v.fitness > fitness) if (n != v.t.get() && v.fitness > fitness)
{ {
n = v.t.get(); n = v.t.get();
fitness = v.fitness; fitness = v.fitness;
if (out != nullptr)
*out = index;
} }
} }
return n; return n;
@ -240,35 +254,53 @@ class gp_population
static std::mt19937_64 engine{dev()}; static std::mt19937_64 engine{dev()};
static std::uniform_real_distribution rand(0.0, 1.0); static std::uniform_real_distribution rand(0.0, 1.0);
blt::size_t crossover_count = 0;
blt::size_t mutation_count = 0;
BLT_TRACE("Running Crossover");
for (blt::size_t i = 0; i < POPULATION_SIZE; i++) for (blt::size_t i = 0; i < POPULATION_SIZE; i++)
{ {
if (rand(engine) < CROSSOVER_RATE) if (rand(engine) < CROSSOVER_RATE)
{ {
auto* p1 = select(); blt::size_t i1 = -1, i2 = -1;
auto* p2 = select(); auto* p1 = select(&i1);
auto* p2 = select(&i2);
tree::crossover(p1, p2); // do not crossover the elite
if (i1 == best || i2 == best)
continue;
if (tree::crossover(p1, p2))
crossover_count++;
} }
} }
BLT_TRACE("Running Mutation");
for (blt::size_t i = 0; i < POPULATION_SIZE; i++) for (blt::size_t i = 0; i < POPULATION_SIZE; i++)
{ {
if (rand(engine) < MUTATION_RATE) if (rand(engine) < MUTATION_RATE)
{ {
auto* p1 = select(); blt::size_t i1 = 0;
auto* p1 = select(&i1);
tree::mutate(p1); if (i1 == best)
continue;
if(tree::mutate(p1))
mutation_count++;
} }
} }
BLT_TRACE("ran %d crossovers and %d mutations", crossover_count, mutation_count);
} }
void evaluate_population() void evaluate_population()
{ {
BLT_TRACE("Running Eval");
for (auto& v : pop) for (auto& v : pop)
{ {
v.t->evaluate(); v.t->evaluate();
v.fitness = v.t->fitness(); v.fitness = v.t->fitness();
} }
BLT_TRACE("Complete");
} }
image& display(blt::size_t i) image& display(blt::size_t i)
@ -288,6 +320,7 @@ class gp_population
fitness = pop[j].fitness; fitness = pop[j].fitness;
} }
} }
best = i;
return {i, fitness}; return {i, fitness};
} }
@ -341,6 +374,7 @@ void update(std::int32_t w, std::int32_t h)
if (ImGui::Button("Regenerate")) if (ImGui::Button("Regenerate"))
{ {
BLT_INFO("Regen tree"); BLT_INFO("Regen tree");
pop = {};
pop.init(); pop.init();
best = pop.best_fitness(); best = pop.best_fitness();
} }
@ -358,10 +392,6 @@ void update(std::int32_t w, std::int32_t h)
{ {
BLT_INFO("Uploading"); BLT_INFO("Uploading");
texture->upload((void*) pop.display_best().getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT); texture->upload((void*) pop.display_best().getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT);
;
// if (test_tree->hasTree())
// test_tree->printTree();
} }
ImGui::Text("Best Fitness: %f", best); ImGui::Text("Best Fitness: %f", best);