2023-07-18 21:59:41 -04:00
|
|
|
//
|
|
|
|
// Created by brett on 7/18/23.
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef PARKSNREC_PROGRAM_V3_H
|
|
|
|
#define PARKSNREC_PROGRAM_V3_H
|
|
|
|
|
|
|
|
#include <genetic/v3/functions_v3.h>
|
2023-07-19 19:38:52 -04:00
|
|
|
#include "ImNodesEz.h"
|
2023-07-18 21:59:41 -04:00
|
|
|
|
|
|
|
namespace parks::genetic {
|
|
|
|
|
|
|
|
struct GeneticNode {
|
|
|
|
FunctionID op;
|
|
|
|
unsigned int pos{};
|
|
|
|
ParameterSet set;
|
|
|
|
|
2023-07-19 19:38:52 -04:00
|
|
|
GeneticNode(FunctionID op, unsigned int pos, ParameterSet set);
|
2023-07-18 21:59:41 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
class GeneticTree {
|
|
|
|
private:
|
|
|
|
GeneticNode** nodes;
|
|
|
|
int size = 1;
|
2023-07-19 22:06:04 -04:00
|
|
|
int max_height;
|
2023-07-18 21:59:41 -04:00
|
|
|
|
2023-07-23 21:54:56 -04:00
|
|
|
static size_t getPixelPosition(unsigned int x, unsigned int y){
|
|
|
|
return x * CHANNELS + y * WIDTH * CHANNELS;
|
|
|
|
}
|
|
|
|
static double similarity(const unsigned char* pixels, unsigned int x, unsigned int y, int size);
|
|
|
|
static double aroundSimilarity(const unsigned char* pixels, unsigned int x, unsigned int y, int size);
|
|
|
|
|
2023-07-19 22:06:04 -04:00
|
|
|
void generateRandomTree(int n);
|
2023-07-18 21:59:41 -04:00
|
|
|
|
|
|
|
Color execute_internal(double x, double y, int node);
|
|
|
|
public:
|
2023-07-19 22:06:04 -04:00
|
|
|
explicit GeneticTree(int max_height): max_height(max_height) {
|
2023-07-18 21:59:41 -04:00
|
|
|
for (int i = 0; i < max_height; i++)
|
|
|
|
size *= 2;
|
2023-07-23 21:54:56 -04:00
|
|
|
size += 1;
|
2023-07-18 21:59:41 -04:00
|
|
|
nodes = new GeneticNode*[size];
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
nodes[i] = nullptr;
|
|
|
|
|
2023-07-19 21:21:16 -04:00
|
|
|
//nodes[0] = new GeneticNode(FunctionID::ADD, 0, functions[FunctionID::ADD].generateRandomParameters());
|
|
|
|
|
2023-07-19 22:06:04 -04:00
|
|
|
generateRandomTree(0);
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
Color execute(double x, double y);
|
|
|
|
|
|
|
|
static inline int left(int pos){
|
2023-07-19 21:21:16 -04:00
|
|
|
return 2 * (pos + 1);
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
2023-07-19 19:38:52 -04:00
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
static inline int right(int pos){
|
2023-07-19 21:21:16 -04:00
|
|
|
return 2 * (pos + 1) + 1;
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
2023-07-19 19:38:52 -04:00
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
static inline int parent(int pos){
|
|
|
|
if (pos <= 0)
|
2023-07-19 19:38:52 -04:00
|
|
|
return -1;
|
|
|
|
//if (pos % 2 == 0)
|
|
|
|
return pos / 2;
|
|
|
|
//return (pos + 1) / 2;
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
2023-07-19 19:38:52 -04:00
|
|
|
|
|
|
|
inline GeneticNode* node(int pos){
|
2023-07-18 21:59:41 -04:00
|
|
|
if (pos < 0 || pos >= size)
|
|
|
|
return nullptr;
|
2023-07-19 19:38:52 -04:00
|
|
|
return nodes[pos];
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
2023-07-19 19:38:52 -04:00
|
|
|
|
|
|
|
inline GeneticNode* leftNode(int pos){
|
|
|
|
return node(left(pos));
|
|
|
|
}
|
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
inline GeneticNode* rightNode(int pos){
|
|
|
|
if (pos < 0 || pos >= size)
|
|
|
|
return nullptr;
|
2023-07-19 19:38:52 -04:00
|
|
|
return node(right(pos));
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int height(int node);
|
2023-07-23 21:54:56 -04:00
|
|
|
[[nodiscard]] int subtreeSize(int n) const;
|
2023-07-19 22:06:04 -04:00
|
|
|
|
|
|
|
void deleteSubtree(int n);
|
2023-07-23 21:54:56 -04:00
|
|
|
std::pair<GeneticNode**, size_t> moveSubtree(int n);
|
|
|
|
void insertSubtree(int n, GeneticNode** tree, size_t size);
|
|
|
|
void processImage(unsigned char* pixels);
|
|
|
|
static double evaluate(const unsigned char* pixels);
|
|
|
|
double evaluate();
|
2023-07-18 21:59:41 -04:00
|
|
|
|
|
|
|
void deleteTree(){
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
delete nodes[i];
|
|
|
|
nodes[i] = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-19 19:38:52 -04:00
|
|
|
[[nodiscard]] inline int getSize() const {
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2023-07-19 22:06:04 -04:00
|
|
|
void mutate();
|
|
|
|
|
2023-07-23 21:54:56 -04:00
|
|
|
void crossover(GeneticTree* other);
|
|
|
|
|
|
|
|
static GeneticTree* breed(GeneticTree* parent1, GeneticTree* parent2);
|
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
~GeneticTree(){
|
|
|
|
deleteTree();
|
|
|
|
delete[] nodes;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Program {
|
|
|
|
private:
|
2023-07-19 19:38:52 -04:00
|
|
|
struct ImNode_t
|
|
|
|
{
|
|
|
|
int height{};
|
|
|
|
int index{};
|
|
|
|
FunctionID id;
|
|
|
|
ImVec2 pos{};
|
|
|
|
bool selected{};
|
|
|
|
ImNodes::Ez::SlotInfo inputs[1]{};
|
|
|
|
ImNodes::Ez::SlotInfo outputs[2]{};
|
|
|
|
};
|
|
|
|
std::vector<ImNode_t> treeNodes;
|
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
unsigned char pixels[WIDTH * HEIGHT * CHANNELS];
|
2023-07-19 19:38:52 -04:00
|
|
|
GeneticTree* tree;
|
2023-07-23 21:54:56 -04:00
|
|
|
GeneticTree* last_tree = nullptr;
|
|
|
|
GeneticTree* saved_tree = nullptr;
|
2023-07-18 21:59:41 -04:00
|
|
|
|
2023-07-19 19:38:52 -04:00
|
|
|
void regenTreeDisplay();
|
|
|
|
|
2023-07-23 21:54:56 -04:00
|
|
|
float renderProgress = 0;
|
2023-07-18 21:59:41 -04:00
|
|
|
public:
|
2023-07-19 19:38:52 -04:00
|
|
|
Program() = default;
|
|
|
|
|
2023-07-18 21:59:41 -04:00
|
|
|
void run();
|
2023-07-19 19:38:52 -04:00
|
|
|
void draw();
|
2023-07-18 21:59:41 -04:00
|
|
|
|
2023-07-19 19:38:52 -04:00
|
|
|
[[nodiscard]] float getRenderProgress() const{
|
|
|
|
return renderProgress;
|
2023-07-18 21:59:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
inline unsigned char* getPixels(){
|
|
|
|
return pixels;
|
|
|
|
}
|
2023-07-19 19:38:52 -04:00
|
|
|
|
|
|
|
~Program(){
|
|
|
|
delete tree;
|
|
|
|
}
|
2023-07-18 21:59:41 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //PARKSNREC_PROGRAM_V3_H
|