事案
- 遺伝的プログラミングを実装したい
- 条件をクラスで定義し、それに基づいて構文木を出力する
- ノードは条件、行動の2つからできているが、後々拡張する可能性がある
想定する実装
template <typename T>
class GPCase {
};
template <typename T>
class GPNode {
T* left;
T* right;
};
template <typename T>
class GP {
GPNode<T>* nodes[N];
};
class TestNode : GPNode<TestNode> {
enum class Type {
Action, Condition
};
enum class Action {
A, B, C
};
enum class Condition {
X, Y, Z
};
void action(State& state) {
switch() {
case Action::A:
actionA(state);
break;
case Action::B:
actionB(state);
break;
case Action::C:
actionC(state);
break;
}
}
void actionA(State& state);
void actionB(State& state);
void actionC(State& state);
Type type;
};
class TestCase : public GPCase<TestNode> {
TestCase(パラメーター) {
this.パラメータ = パラメータ;
}
int execute(State& state) {
TestNode* current = root;
while(current != nullptr) {
switch(current.type) {
case Type::Action:
action(state);
return;
break;
case Type::Condition:
if(condition(state)) {
current = current.left;
}
else {
current = current.right;
}
break;
}
}
}
void show();
};
int main() {
GP<TestCase> gp(パラメータ);
gp.generate();
gp.show();
}
#include <iostream>
#include <memory>
#include <cstdlib>
#include <ctime>
#include <string>
class Node {
public:
struct TAG_Action {};
struct TAG_Condition {};
enum class NODE_TYPE {
CONDITION, ACTION
};
enum class VALUE_ACTION {
ACTION_A, ACTION_B, ACTION_C, ACTION_D
};
static const int ACTION_SIZE = 4;
enum class VALUE_CONDITION {
CONDITION_A, CONDITION_B, CONDITION_C, CONDITION_D
};
const std::string CONDITION_NAME[4];
static const int CONDITION_SIZE = 4;
Node(NODE_TYPE type, int value) : type(type), value(value) {}
std::unique_ptr<Node> left;
std::unique_ptr<Node> right;
void execute(int x, TAG_Action) {
switch((VALUE_ACTION)value) {
case VALUE_ACTION::ACTION_A:
std::cout << "行動A" << std::endl;
break;
case VALUE_ACTION::ACTION_B:
std::cout << "行動B" << std::endl;
break;
case VALUE_ACTION::ACTION_C:
std::cout << "行動C" << std::endl;
break;
case VALUE_ACTION::ACTION_D:
std::cout << "行動D" << std::endl;
break;
}
}
void execute(bool& flag, int x, TAG_Condition) {
switch((VALUE_CONDITION)value) {
case VALUE_CONDITION::CONDITION_A:
flag = x > 0;
break;
case VALUE_CONDITION::CONDITION_B:
flag = x % 2 == 0;
break;
case VALUE_CONDITION::CONDITION_C:
flag = x * x < 30;
break;
case VALUE_CONDITION::CONDITION_D:
flag = x < 0;
break;
}
}
private:
NODE_TYPE type;
int value;
};
template <typename T>
class Tree {
public:
Tree() { }
void createAtRandom(int m, int n) {
int length = std::rand() % (n - m + 1) + m;
int condition = std::rand() % CONDITION_SIZE;
root = std::make_unique<T>(NODE_TYPE::CONDITION, condition);
createAtRandomRecursive(*root.get(), length);
}
void show() {
showRecursive(*root.get());
}
protected:
virtual showRecursive(T& current) = 0;
void createAtRandomRecursive(T& node, int size) {
if(size <= 0) {
int action = std::rand() % ACTION_SIZE;
node.value = action;
node.type = NODE_TYPE::ACTION;
return;
}
int length = std::rand() % size;
int condition = std::rand() % CONDITION_SIZE;
node.left = std::make_unique<T>(NODE_TYPE::CONDITION, condition);
condition = std::rand() % CONDITION_SIZE;
node.right = std::make_unique<T>(NODE_TYPE::CONDITION, condition);
createAtRandomRecursive(*node.left.get(), length);
createAtRandomRecursive(*node.right.get(), size - length - 1);
}
Node& select() {
}
std::unique_ptr<Node> root;
};
class Ant : public Tree<Node> {
public:
int execute() {
Node* current = root.get();
while(current != nullptr) {
switch(current->type) {
case NODE_TYPE::ACTION:
goto exit;
break;
case NODE_TYPE::CONDITION:
break;
}
}
exit:
;
}
void showRecursive(T& current, int level = 0) {
std::string tab = "";
for(int i = 0; i < level; ++i) {
tab += "\t";
}
switch(current.type) {
case NODE_TYPE::CONDITION:
std::cout << tab << "if(" << CONDITION_NAME[current.value] << ") {" << std::endl;
showRecursive(*current.left.get(), level + 1);
std::cout << tab << "} else { " << std::endl;
showRecursive(*current.right.get(), level + 1);
std::cout << tab << "}" << std::endl;
break;
case NODE_TYPE::ACTION:
std::cout << tab << ACTION_NAME[current.value] << "を実行" << std::endl;
break;
}
}
};
int main() {
Tree tree;
std::srand((unsigned int)std::time(NULL));
tree.createAtRandom(2, 10);
tree.show();
std::cin.get();
}