/****************************************************************** * * * Nest version 2 - 3D Wasp Nest Simulator * * Copyright (C) 1997 Sylvain GUERIN * * LIASC, ENST Bretagne & Santa Fe Institute * * * ****************************************************************** E-mail: Sylvain.Guerin@enst-bretagne.fr or: Sylvain Guerin 13 rue des Monts Lorgeaux, 51460 L'EPINE, FRANCE ****************************************************************** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ****************************************************************** Name : classify.c Component : crossover in genetic simulations Fonctionality : partionning algorithm - code ******************************************************************/ #include "classify.h" /* classe RuleNode */ RuleNode::RuleNode (int aNodeId, ClusterType aCluster, int aMaxEdges, RuleGraph* aRuleGraph) { int i; nodeId = aNodeId; edgesNumber = 0; cluster = aCluster; gain = 0; entropy = 0; maxEdges = aMaxEdges; ruleGraph = aRuleGraph; neighbourId = new int[maxEdges]; neighbourWeight = new int[maxEdges]; for (i=0; igetCluster () == cluster) { /* s'ils sont dans le meme cluster */ gain -= getNeighbourWeight (i); } else { gain += getNeighbourWeight (i); } } } void RuleNode::computeEntropy () { int i; RuleNode* currentNeighbour; entropy = 0; for (i=0; igetCluster () != cluster) { entropy += getNeighbourWeight (i); } } } void RuleNode::connectToNode (int aNeighbourId, int aWeight) { if (edgesNumber < maxEdges) { neighbourId[edgesNumber] = aNeighbourId; neighbourWeight[edgesNumber] = aWeight; edgesNumber++; } else { printf ("ERROR: maxEdges exceeded\n"); } } int RuleNode::getNodeId () { return nodeId; } int RuleNode::getEdgesNumber () { return edgesNumber; } ClusterType RuleNode::getCluster () { return cluster; } int RuleNode::getGain () { return gain; } int RuleNode::getEntropy () { return entropy; } int RuleNode::getLocked () { return locked; } int RuleNode::getNeighbourId (int anIndex) { if ((anIndex < edgesNumber) && (anIndex >= 0)) return neighbourId[anIndex]; /* printf ("ERROR: incoherent index number\n"); */ exit(1); } int RuleNode::getNeighbourWeight (int anIndex) { if ((anIndex < edgesNumber) && (anIndex >= 0)) return neighbourWeight[anIndex]; /* printf ("ERROR: incoherent index number\n"); */ exit(1); } RuleNode* RuleNode::getNeighbour (int anIndex) { return ruleGraph->nodeWhichIdIs (getNeighbourId (anIndex)); } void RuleNode::lock () { locked = 1; } void RuleNode::unlock () { locked = 0; } void RuleNode::swapCluster () { int i; if (locked) { printf ("ERROR: unable to swap locked node\n"); } else { // lock (); if (cluster == clusterA) { cluster = clusterB; ruleGraph->decNodesInClusterA (); ruleGraph->incNodesInClusterB (); } else { cluster = clusterA; ruleGraph->incNodesInClusterA (); ruleGraph->decNodesInClusterB (); } computeGain (); computeEntropy (); for (i=0; icomputeGain (); (getNeighbour (i))->computeEntropy (); } } } void RuleNode::debug () { int i; if (locked) { printf ("*"); } else { printf (" "); } if (cluster == clusterA) { printf ("Node: %2d [cluster A] gain=%3d entropy=%3d (%d edges: ", nodeId, gain, entropy, edgesNumber); } else { printf ("Node: %2d [cluster B] gain=%3d entropy=%3d (%d edges: ", nodeId, gain, entropy, edgesNumber); } for (i=0; iconnectToNode (endNodeId, weight); } if (endNode != NULL) { endNode->connectToNode (startNodeId, weight); } edgesNumber++; } RuleNode* RuleGraph::nodeWhichIdIs (int nodeId) { int i; RuleNode* currentNode; RuleNode* returnedNode; returnedNode = NULL; for (i=0; igetNodeId () == nodeId) { returnedNode = currentNode; } } return returnedNode; } void RuleGraph::computeAllGains () { int i; for (i=0; icomputeGain (); } } void RuleGraph::computeAllEntropies () { int i; for (i=0; icomputeEntropy (); } } int RuleGraph::getGlobalEntropy () { int returnedInt; int i; returnedInt = 0; for (i=0; igetEntropy (); } return returnedInt/2; } void RuleGraph::debug () { int i; computeAllGains (); computeAllEntropies (); printf ("RuleGraph - %d nodes and %d edges\n", nodesNumber, edgesNumber); for (i=0; idebug (); } printf ("Global entropy: %d\n", getGlobalEntropy ()); } RuleNode* RuleGraph::nodeWithBestGain (ClusterType aCluster, int* foundGain) { int i; int maxGain; RuleNode* returnedNode; RuleNode* currentNode; int nodesNbInCurrentCluster; if (nodesNumber == 0) { return NULL; } maxGain = -32000; *foundGain = -32000; returnedNode = NULL; for (i=0; igetCluster () == aCluster) { if (currentNode->getCluster () == clusterA) { nodesNbInCurrentCluster = nodesInClusterA; } else { nodesNbInCurrentCluster = nodesInClusterB; } if ((currentNode->getGain () >= maxGain) && (!(currentNode->getLocked ())) && (nodesNbInCurrentCluster-1 >= miniNodesPerCluster)) { returnedNode = nodes[i]; maxGain = currentNode->getGain (); *foundGain = maxGain; } } } return returnedNode; } void RuleGraph::incNodesInClusterA () { nodesInClusterA++; } void RuleGraph::decNodesInClusterA () { nodesInClusterA--; } void RuleGraph::incNodesInClusterB () { nodesInClusterB++; } void RuleGraph::decNodesInClusterB () { nodesInClusterB--; } void RuleGraph::partitionning (int aMiniNodesPerCluster) { int i; RuleNode* currentNodeInClusterA; RuleNode* currentNodeInClusterB; RuleNode* swappedNode; int swappedNodeId; int previousSwappedNodeId; int foundGainA; int foundGainB; int oldEntropy; int newEntropy; computeAllGains (); computeAllEntropies (); miniNodesPerCluster = aMiniNodesPerCluster; i = 1; // printf ("Iteration 0 - Entropy=%d\n", getGlobalEntropy ()); newEntropy = getGlobalEntropy (); previousSwappedNodeId = -1; do { oldEntropy = newEntropy; // printf ("Iteration %d ", i); currentNodeInClusterA = nodeWithBestGain (clusterA, &foundGainA); currentNodeInClusterB = nodeWithBestGain (clusterB, &foundGainB); if ((foundGainA >= foundGainB) && (currentNodeInClusterA != NULL)) { swappedNode = currentNodeInClusterA; swappedNodeId = swappedNode->getNodeId (); } else if (currentNodeInClusterB != NULL) { swappedNode = currentNodeInClusterB; swappedNodeId = swappedNode->getNodeId (); } else { swappedNode = NULL; swappedNodeId = -1; } if (swappedNode != NULL) { swappedNode->swapCluster (); // printf ("- swap node %d ", swappedNodeId); newEntropy = getGlobalEntropy (); if (previousSwappedNodeId == swappedNodeId) { if (newEntropy > oldEntropy) { swappedNode->swapCluster (); // printf ("- swap node %d ", swappedNodeId); } swappedNode->lock (); } previousSwappedNodeId = swappedNodeId; } i++; // printf ("- Entropy=%d\n", getGlobalEntropy ()); } while ((swappedNode != NULL) && (i<500)); }