きままにブログ

プログラミングを主とした私のメモ帳です。寂しいのでコメントください笑

設計が悪い、やり直し

事案

  • 遺伝的プログラミングを実装したい
  • 条件をクラスで定義し、それに基づいて構文木を出力する
  • ノードは条件、行動の2つからできているが、後々拡張する可能性がある

想定する実装

template <typename T>
class GPCase {
	// ランダム生成
	// 交叉 crossover
	// 逆位 inverse
	// 突然変異 mutate
	// 評価 evaluate
	// パラメータ
};

template <typename T>
class GPNode {
	T* left;
	T* right;
};

template <typename T>
class GP {
	GPNode<T>* nodes[N];
	// 個体生成 randomGenerate
	// 実行・評価evaluate
	// 選択・交叉・逆位・突然変異select
	// 最終生成 generate
	// 生成物の表示 show
};

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);
	
	// Conditionも同様
	
	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();
}