Commit 8f44bf4a authored by Cancino Waldo's avatar Cancino Waldo
Browse files

Add examples from Ogier, Pierre and Jean-Luc

parent 00c45f4b
/////////////////// BEGIN TREE COMPARE /////////////////////
// Cette fonction n'est pas au point, elle ne traite pas la division.
bool GPNodeCompare(GPNode* root1, GPNode* root2, const unsigned* opArity) {
char code1 = root1->opCode;
char code2 = root2->opCode;
int arity1 = opArity[(int)code1];
int arity2 = opArity[(int)code2];
if (code1 != code2) return false;
// Compare terminal nodes
// They can be equal if they have the same opCode and if they the same value in case of the opCode is OP_ERC
if (!arity1) {
if (code1 == OP_ERC && root1->erc_value != root2->erc_value) return false;
return true;
}
// Compare non-terminal nodes.
// They can be equal if the children of the first node are a permutation of those of second node.
int length = arity2;
int index[length];
// Initialization of the index array.
for (int i = 0; i < length; i++) {
index[i] = i;
}
for (int i = 0; i < arity1; i++) {
int j = 0;
while (!GPNodeCompare(root1->children[i], root2->children[index[j]], opArity)) {
if (++j >= length) return false; // If at the end of the index array we didn't found an equal children, we return false.
}
// The children are equal, so the current index is discarded from the research.
index[j] = index[--length];
}
return true;
}
////////////////// END TREE COMPARE ////////////////////////
\ No newline at end of file
/////////////////////// BEGIN DEPTH OF TREE ///////////////////////
// Returns the depth of a tree
int depthOfTree1(GPNode* root) {
int sonsDepth = 0;
for (int i = 0; i < (int)opArity[(int)root->opCode]; i++) {
int d = depthOfTree1(root->children[i]);
if (d > sonsDepth) sonsDepth = d;
}
return 1+sonsDepth;
}
//////////////////////// END DEPTH OF TREE ////////////////////////
/////////////////////// BEGIN NUMBER OF NODES TREE ////////////////////
int nbOfNodes(GPNode* root) {
int nbNodes = 1;
for (int i = 0; i < (int)opArity[(int)root->opCode]; i++) {
nbNodes += nbOfNodes(root->children[i]);
}
return nbNodes;
}
//////////////////////// END NUMBER OF NODES TREE /////////////////////
///////////////////// BEGIN DEPTH OF NODE IN TREE ///////////////////
int depthOfNodeInTreeR(GPNode* root, GPNode* node, const int currentDepth) {
if (root == node) return currentDepth;
for (int i = 0; i < (int)opArity[(int)root->opCode]; i++) {
int depth = depthOfNodeInTreeR(root->children[i], node, currentDepth+1);
if (depth) return depth;
}
return 0;
}
/* Returns the depth of the node "node" in the tree "root".
Reurns 0 if the node hasn't been found.
*/
int depthOfNodeInTree(GPNode* root, GPNode* node) {
return depthOfNodeInTreeR(root, node, 1);
}
////////////////////// END DEPTH OF NODE IN TREE ////////////////////
/////////////////// BEGIN TREE COMPARE /////////////////////
bool GPNodeCompare(GPNode* root1, GPNode* root2) {
char code1 = root1->opCode;
char code2 = root2->opCode;
int arity1 = opArity[(int)code1];
if (code1 != code2) return false;
// Compare terminal nodes
// They can be equal if they have the same opCode and if they the same value in case of the opCode is OP_ERC
if (!arity1) {
if (code1 == OP_ERC && root1->erc_value != root2->erc_value) return false;
return true;
}
// Compare non-terminal nodes.
// If arity is one, the children must be equals.
if (arity1 == 1 && GPNodeCompare(root1->children[0], root2->children[0]))
return true;
// This arity is an error.
if (arity1 != 2) return false; // Should not happen
// If the opCode is a substraction, the two children must be the same and can't be permuted.
if (code1 == OP_SUB) {
if (GPNodeCompare(root1->children[0], root2->children[0])
&& GPNodeCompare(root1->children[1], root2->children[1]))
return true;
else return false;
}
// They can be equal if the children of the first node are a permutation of those of second node.
if ((GPNodeCompare(root1->children[0], root2->children[0])
&& GPNodeCompare(root1->children[1], root2->children[1]))
|| (GPNodeCompare(root1->children[0], root2->children[1])
&& GPNodeCompare(root1->children[1], root2->children[0])))
return true;
return false;
}
////////////////// END TREE COMPARE ////////////////////////
/////////////////////// BEGIN COLLECT ALL NODES //////////////////////
// Recursively collect all nodes in the tree. Puts collected nodes in
// collection and the number of collected nodes in collected.
void collectAllNodes(GPNode* root, GPNode*** collection, int* collected) {
for (int i = 0; i < (int)opArity[(int)root->opCode]; i++) {
collectAllNodes(root->children[i], collection, collected);
}
(*collection)[(*collected)++] = root;
}
//////////////////////// END COLLECT ALL NODES ///////////////////////
/////////////////////// BEGIN COLLECT NODES HEIGHT ///////////////////
// Recursively collects the nodes which height is "height", puts them
// into "collection" and keep the number of collected nodes in "collected"
void collectNodesHeightR(GPNode* root, const int height, int* currentHeight, GPNode*** collection, int* collected) {
char code = root->opCode;
if (!opArity[(int)code]) {
*currentHeight = 0;
}
else {
int sonsHeight = 0;
for (int i = 0; i < (int)opArity[(int)code]; i++) {
int sh;
collectNodesHeightR(root->children[i], height, &sh, collection, collected);
if (sh > sonsHeight) sonsHeight = sh;
}
*currentHeight = sonsHeight+1;
}
if (*currentHeight == height) (*collection)[(*collected)++] = root;
}
GPNode** collectNodesHeight(GPNode* root, const int height, const int rootDepth, int* nbNodes) {
// It is assumed that the maximum arity is 2, thus the maximum
// number of node is two to the power of DEPTH where DEPTH
// is the maximum depth reachable for nodes with a height of "height".
GPNode** collection = (GPNode**)malloc((1<<(rootDepth-1-height))*sizeof(GPNode*));
int collected = 0;
int currentHeight;
// The nodes at height "height" are put in collection and the total of
// collected nodes is put in "collected".
collectNodesHeightR(root, height, &currentHeight, &collection, &collected);
GPNode** ret = (GPNode**)malloc(collected*sizeof(GPNode*));
for (int i = 0; i < collected; i++) {
ret[i] = collection[i];
}
free(collection);
*nbNodes = collected;
return ret;
}
//////////////////////// END COLLECT NODES HEIGHT ////////////////////
/////////////////////// BEGIN SELECT NODE HEIGHT ///////////////////////
GPNode* selectNode1(GPNode* root) {
int depth = depthOfTree1(root);
// The height of the node is selected first.
int height = globalRandomGenerator->random(0, depth);
GPNode** collectedNodes;
int nbNodes;
// The nodes which height are at the good height are put in collectedNodes.
collectedNodes = collectNodesHeight(root, height, depth, &nbNodes);
// A node is choosen among collected nodes.
int index = globalRandomGenerator->random(0, nbNodes);
GPNode* ret = collectedNodes[index];
free(collectedNodes);
return ret;
}
GPNode* selectNode1(GPNode* root, const int minHeight, const int maxHeight) {
int depth = depthOfTree1(root);
// The height of the node is selected first.
int maxH = max(1, min(depth, maxHeight));
int minH = max(0, min(maxH-1, minHeight));
int height = globalRandomGenerator->random(minH, maxH);
GPNode** collectedNodes;
int nbNodes;
// The nodes which height are at the good height are put in collectedNodes.
collectedNodes = collectNodesHeight(root, height, depth, &nbNodes);
// A node is choosen among collected nodes.
int index = globalRandomGenerator->random(0, nbNodes);
GPNode* ret = collectedNodes[index];
free(collectedNodes);
return ret;
}
/////////////////////// END SELECT NODE HEIGHT ////////////////////////
////////////////////// BEGIN COLLECT ERC NODE //////////////////////
// Recursively collects the ERC nodes into "collection" and keep the
// number of collected nodes in "collected"
void collectERCNodesR(GPNode* root, GPNode*** collection, int* collected) {
char code = root->opCode;
if (code == OP_ERC) {
(*collection)[(*collected)++] = root;
return;
}
for (int i = 0; i < (int)opArity[(int)code]; i++) {
collectERCNodesR(root->children[i], collection, collected);
}
}
GPNode** collectERCNodes(GPNode* root, const int rootDepth, int* nbNodes) {
// It is assumed that the maximum arity is 2, thus the maximum
// number of node is two to the power of DEPTH where DEPTH
// is the depth of the tree.
GPNode** collection = (GPNode**)malloc((1<<(rootDepth-1))*sizeof(GPNode*));
int collected = 0;
// The ERC nodes are put in collection and the total of
// collected nodes is put in "collected".
collectERCNodesR(root, &collection, &collected);
GPNode** ret = (GPNode**)malloc(collected*sizeof(GPNode*));
for (int i = 0; i < collected; i++) {
ret[i] = collection[i];
}
free(collection);
*nbNodes = collected;
return ret;
}
/////////////////////// END COLLECT ERC NODE //////////////////////
/////////////////////// BEGIN SELECT ERC NODE //////////////////////
GPNode* selectERCNode(GPNode* root) {
int depth = depthOfTree1(root);
GPNode** collectedNodes;
int nbNodes;
// The ERC nodes are put in collectedNodes. Their number is put
// nbNodes.
collectedNodes = collectERCNodes(root, depth, &nbNodes);
// Case of a tree with no ERC node.
if (!nbNodes) return NULL;
// A node is choosen among collected nodes.
int index = globalRandomGenerator->random(0, nbNodes);
GPNode* ret = collectedNodes[index];
free(collectedNodes);
return ret;
}
//////////////////////// END SELECT ERC NODE ///////////////////////
/////////////////// BEGIN SNODE ////////////////////////////
typedef struct SNode_r {
int arity;
double erc_value;
char opCode;
SNode_r** children;
} SNode;
/////////////////// END SNODE ///////////////////////////
SNode* createSNode(GPNode* root, const unsigned* opArity);
//////////////////////// BEGIN SORT SNODE //////////////////////
SNode** sortSNode(GPNode** nodes, int arity, const unsigned* opArity) {
SNode** sortedNodes = (SNode**)malloc(arity*sizeof(SNode*));
int index = 0;
for (int i = 0; i < arity; i++) {
if (nodes[i]->opCode == OP_ERC) {
sortedNodes[index++] = createSNode(nodes[i], opArity);
}
}
for (int i = 0; i < arity; i++) {
if (!opArity[(int)nodes[i]->opCode]) {
sortedNodes[index++] = createSNode(nodes[i], opArity);
}
}
for (int i = 0; i < arity; i++) {
if (opArity[(int)nodes[i]->opCode] == 2) {
sortedNodes[index++] = createSNode(nodes[i], opArity);
}
}
for (int i = 0; i < arity; i++) {
if (opArity[(int)nodes[i]->opCode] == 1) {
sortedNodes[index++] = createSNode(nodes[i], opArity);
}
}
printf("%d = %d\n", arity, index);
return sortedNodes;
}
//////////////////////// END SORT SNODE /////////////////////////
///////////////////// BEGIN NUMBER OF LEAVES ////////////////////////
int numberOfLeaves(GPNode* root, const unsigned* opArity) {
char code = root->opCode;
int arity = opArity[(int)code];
bool isLeaf[arity]; // The value at position i is true if children[i] is a leaf for the current node.
if (code == OP_MUL || code == OP_DIV) {
for (int i = 0; i < arity; i++) {
isLeaf[i] = root->children[i]->opCode != OP_MUL && root->children[i]->opCode != OP_DIV;
}
} else if (code == OP_ADD || code == OP_SUB) {
for (int i = 0; i < arity; i++) {
isLeaf[i] = root->children[i]->opCode != OP_ADD && root->children[i]->opCode != OP_SUB;
}
} else return 0; // In all other cases, root can't have leaves.
int leaves = 0; // Number of children which are leaves.
int notLeaves[arity]; // Element of notLeaves are the indexes of the children which are not leaves.
for (int i = 0; i < arity; i++) {
notLeaves[i] = i;
}
for (int i = 0; i < arity; i++) {
// If children[i] is a leaf, it is dicarded from the array by placing the current last index at its place.
// The last element which is not a leaf is at index arity-(leaves+1) in notLeaves.
if (isLeaf[i]) notLeaves[i] = notLeaves[arity - (++leaves)];
}
// totalLeaves, is the sum of the number of children which are leaves and the number of leaves of the other children.
int totalLeaves = leaves;
for (int i = 0; i < arity-leaves; i++) {
totalLeaves += numberOfLeaves(root->children[notLeaves[i]], opArity);
}
return totalLeaves;
}
///////////////////// END NUMBER OF LEAVES /////////////////////////
////////////////////// BEGIN PLACE GPNODE IN SNODE /////////////////////
void placeNodes(GPNode* root, bool leftSide, GPNode*** left, GPNode*** right, int* arity0, int* arity1) {
// This function finds the future leaves of the SNode which will be created from the GPNode root.
// The future SNode consists in a division (respectively a substraction) of two multiplications
// (respectively additions).
// The leaves are sorted so that the children of the left (respectively right) multiplication
// (respectively addition) are in the left (respectively right) array.
// Right and Left must be intialised and large enough to countain all their future leaves.
// arity0 (respectively arity1) is the real number of GPNodes in left (respectively right).
char code = root->opCode;
bool isLeave0;
bool isLeave1;
bool isInvOp;
if (code == OP_MUL || code == OP_DIV) {
isLeave0 = root->children[0]->opCode != OP_MUL && root->children[0]->opCode != OP_DIV;
isLeave1 = root->children[1]->opCode != OP_MUL && root->children[1]->opCode != OP_DIV;
isInvOp = code == OP_DIV;
} else if (code == OP_ADD || code == OP_SUB) {
isLeave0 = root->children[0]->opCode != OP_ADD && root->children[0]->opCode != OP_SUB;
isLeave1 = root->children[1]->opCode != OP_ADD && root->children[1]->opCode != OP_SUB;
isInvOp = code == OP_SUB;
} else return; // Has no effects on GPNodes which can't be transformed.
// Recursively place the leaves in the proper array.
if (isLeave0 && isLeave1) {
if (leftSide) {
(*left)[(*arity0)++] = root->children[0];
if (isInvOp) (*right)[(*arity1)++] = root->children[1];
else (*left)[(*arity0)++] = root->children[1];
} else {
(*right)[(*arity1)++] = root->children[0];
if (isInvOp) (*left)[(*arity0)++] = root->children[1];
else (*right)[(*arity1)++] = root->children[1];
}
return;
}
if (isLeave0) {
if (leftSide) (*left)[(*arity0)++] = root->children[0];
else (*right)[(*arity1)++] = root->children[0];
if (isInvOp) placeNodes(root->children[1], !leftSide, left, right, arity0, arity1);
else placeNodes(root->children[1], leftSide, left, right, arity0, arity1);
return;
}
if (isLeave1) {
placeNodes(root->children[0], leftSide, left, right, arity0, arity1);
if ((leftSide && isInvOp) || (!leftSide && !isInvOp)) (*right)[(*arity1)++] = root->children[1];
else (*left)[(*arity0)++] = root->children[1];
return;
}
placeNodes(root->children[0], leftSide, left, right, arity0, arity1);
if (isInvOp) placeNodes(root->children[1], !leftSide, left, right, arity0, arity1);
else placeNodes(root->children[1], leftSide, left, right, arity0, arity1);
}
////////////////////// END PLACE GPNODE IN SNODE ///////////////////////
///////////////////// BEGIN CREATE SNODE ////////////////////
SNode* createSNode(GPNode* root, const unsigned* opArity) {
// This function transforms a GPNode into a SNode.
// The SNode allows a variable number of children.
// The aim of the transformation is to group multiplications
// and divisions (respectively additions and substractions)
// in a minimal tree.
// This minimal tree is the division (respectively substraction) between
// two multiplications (respectively additions) and the children of
// the two multiplications (respectively additions) are neither a
// multiplication (respectively additions), nor a division (respectively
// substraction).
char code = root->opCode;
SNode* sRoot = (SNode*)malloc(sizeof(SNode));
// Just transforms root into an SNode by copying its members and transforming its children.
if (code != OP_ADD && code != OP_SUB && code != OP_MUL && code != OP_DIV) {
sRoot->arity = opArity[(int)code];
sRoot->opCode = code;
if (!opArity[(int)code]) {
if (code == OP_ERC) sRoot->erc_value = root->erc_value;
sRoot->children = NULL;
return sRoot;
}
sRoot->children = (SNode**)malloc(opArity[(int)code]*sizeof(SNode*));
for (int i = 0; i < (int)opArity[(int)code]; i++) {
sRoot->children[i] = createSNode(root->children[i], opArity);
}
return sRoot;
}
int arity0 = 0; // Future arity of children[0].
int arity1 = 0; // Future arity of children[1].
// leaves is the total number of leaves of the future SNode.
int leaves = numberOfLeaves(root, opArity);
// right and left are initialized in order to be large enough for
// containing all the leaves of the future SNode.
GPNode** left = (GPNode**)malloc(leaves*sizeof(GPNode*));
GPNode** right = (GPNode**)malloc(leaves*sizeof(GPNode*));
// The leaves are placed in the proper array (right or left)
// and arities are fixed.
placeNodes(root, true, &left, &right, &arity0, &arity1);
if (!arity0) return NULL; // Shouldn't happen because
// if the opCode is OP_DIV, or OP_MUL, or OP_ADD, or OP_SUB,
// there is at least two leaves and at least one of those is
// in the left array.
if (!arity1) { // In this case the SNode is a simple multiplication
// (respectively addition) without division (respectively
// substraction)
sRoot->arity = arity0;
if (code == OP_MUL) sRoot->opCode = OP_MUL;
else if (code == OP_ADD) sRoot->opCode = OP_ADD;
else return NULL; // Shouldn't happen.
sRoot->children = (SNode**)malloc(arity0*sizeof(SNode*));
for (int i = 0; i < arity0; i++) {
sRoot->children[i] = createSNode(left[i], opArity);
}
} else { // General case. The minimal tree is created.
sRoot->children = (SNode**)malloc(2*sizeof(SNode*));
sRoot->children[0] = (SNode*)malloc(sizeof(SNode));
sRoot->children[1] = (SNode*)malloc(sizeof(SNode));
if (code == OP_MUL || code == OP_DIV) {
sRoot->opCode = OP_DIV;
sRoot->children[0]->opCode = OP_MUL;
sRoot->children[1]->opCode = OP_MUL;
}
else if (code == OP_ADD || code == OP_SUB) {
sRoot->opCode = OP_SUB;
sRoot->children[0]->opCode = OP_ADD;
sRoot->children[1]->opCode = OP_ADD;
}
sRoot->arity = 2;
sRoot->children[0]->arity = arity0;
sRoot->children[1]->arity = arity1;
sRoot->children[0]->children = sortSNode(left, arity0, opArity);
sRoot->children[1]->children = sortSNode(right, arity1, opArity);
}
return sRoot;
}
/////////////////////// END CREATE SNODE /////////////////////////
/////////////////////// BEGIN FREE SNODE /////////////////////////
void freeSNode(SNode* root) {
for (int i = 0; i < root->arity; i++) {
freeSNode(root->children[i]);
free(root->children);
free(root);
}
}
/////////////////////// END FREE SNODE ///////////////////////////
/////////////////////// BEGIN PRINT SNODE /////////////////////////////
void sNodeToMatlab_r(std::ostringstream* oss, SNode* root) {
if (!root) return;
if ((int)root->opCode == OP_DIV) {
(*oss) << "protectedDiv(";
sNodeToMatlab_r(oss,root->children[0]);
(*oss) << ", ";
sNodeToMatlab_r(oss,root->children[1]);
(*oss) << ')';
} else if ((int)root->opCode == OP_MUL) {
for (int i = 0; i < root->arity-1; i++) {
sNodeToMatlab_r(oss, root->children[i]);
(*oss) << " * ";
}
sNodeToMatlab_r(oss, root->children[root->arity - 1]);
} else if ((int)root->opCode == OP_ADD) {
(*oss) << '(';
for (int i = 0; i < root->arity-1; i++) {
sNodeToMatlab_r(oss, root->children[i]);
(*oss) << " + ";
}
sNodeToMatlab_r(oss, root->children[root->arity - 1]);
(*oss) << ')';
} else if ((int)root->opCode == OP_SUB) {
(*oss) << '(';
sNodeToMatlab_r(oss,root->children[0]);
(*oss) << ' ';
(*oss) << opCodeName[(int)root->opCode];
(*oss) << ' ';
sNodeToMatlab_r(oss,root->children[1]);
(*oss) << ')';
/* } else if ((int)root->opCode == OP_SIN || (int)root->opCode == OP_COS) {
(*oss) << opCodeName[(int)root->opCode] << '(';
sNodeToMatlab_r(oss,root->children[0],opArity,opCodeName,OP_ERC);
(*oss) << ')';*/
} else if ((int)root->opCode == OP_ERC){
(*oss) << root->erc_value;
} else {
if (root->opCode == OP_PHI) (*oss) << "phi";
else if (root->opCode == OP_PSI) (*oss) << "psi";
else if (root->opCode == OP_TETA) (*oss) << "theta ";
else if (root->opCode == OP_DPHI) (*oss) << "dot{phi}";
else if (root->opCode == OP_DPSI) (*oss) << "dot{psi}";
else if (root->opCode == OP_DTETA) (*oss) << "dot{theta}";