/****************************************************************** * * * 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 : algo.c Component : simulation Fonctionality : contains methods for objects refering to the simulations ******************************************************************/ #include "graph.h" #include "algo.h" #include "graphical.h" #include "ViewInt.h" #include "config.h" #include "view3d.h" #include #include #include #include #include #include #include # ifdef XPM_INC_X11 # include # else # include # endif /* ---------------------------------------------------- */ Cell::Cell () { val = EMPTY; appliedRule = -1; } Cell::~Cell() { } typeOfCell Cell::value() { return val; } int Cell::getAppliedRule () { return appliedRule; } int Cell::getCellId () { return cellId; } void Cell::set (typeOfCell setValue, int appliedRuleNumber, int aCellId) { val = setValue; appliedRule = appliedRuleNumber; cellId = aCellId; } /* ---------------------------------------------------- */ ViewParameters::ViewParameters () { /* dans le constructeur de la classe ViewParameters, on va mettre tous les parametres de vue par défaut */ org = init_position (); org.x = 5; org.y = -2; org.z = 3.5; /* 3 avant */ zoom = 30; alpha = M_PI; tx = 300; /* 0 */ ty = 100; /* -150 */ zCut = 0; tetaCut = 0; phiCut = 0; isCut = 0; /* par défaut, pas de coupe */ } ViewParameters::~ViewParameters () { /* rien a faire ici */ } /* ---------------------------------------------------- */ Architecture::Architecture(int init_size, SimulationType aSimuType) { int i; size = init_size; simuType = aSimuType; graph = new Graph (simuType, defaultMaxCells, size); cells = new Cell[size*size*size]; envCode = new int [3*size*size*size]; for (i=0; i<3*size*size*size; i++) envCode[i] = 0; minX = size; maxX = 0; minY = size; maxY = 0; minZ = size; maxZ = 0; showStats = 0; /* default mode: don't see the stats */ showConstruction = 0; /* default mode: don't see the construction */ cellsNumber = 1; for (i=0; i=0 && x=0 && y=0 && z %d %d %d not in range\n", x, y, z); return EMPTY; } } void Architecture::setCellWithNoChecking (int x, int y, int z, typeOfCell cellValue) { cells[x*size*size+y*size+z].set (cellValue, -1, -1); } void Architecture::clearWithNoChecking () { int i, j, k; for (i=0; imaxX-2) maxX=x+2; if (ymaxY-2) maxY=y+2; if (zmaxZ-2) maxZ=z+2; if (minX<0) minX=0; if (maxX>size-1) maxX=size-1; if (minY<0) minY=0; if (maxY>size-1) maxY=size-1; if (minZ<0) minZ=0; if (maxZ>size-1) maxZ=size-1; /* update of all environments */ if (simuType == cubic) { for (iz=-1; iz<2; iz++) for (iy=-1; iy<2; iy++) for (ix=-1; ix<2; ix++) setEnvCode (x+ix, y+iy, z+iz); } else if (simuType == hexa) { for (iz=-1; iz<2; iz++) for (iy=-1; iy<2; iy++) for (ix=-1; ix<2; ix++) /* if ( !((iy == -1) && (ix == -1)) && !((iy == -1) && (ix == 1)) ) */ /* en fait, pas besoin de ca */ setEnvCode (x+ix, y+iy, z+iz); } if (appliedRule != -3) { /* updating of graph structure */ graph->addNode (appliedRule, cellValue, x, y, z); if (simuType == cubic) { for (iz=-1; iz<2; iz++) for (iy=-1; iy<2; iy++) for (ix=-1; ix<2; ix++) { if ((getCellWithChecking (x+ix, y+iy, z+iz) != EMPTY) && !((ix == 0) && (iy == 0) && (iz == 0))) { /* on ajoute une arete */ graph->addEdge (cells[(x+ix)*size*size+(y+iy)*size+(z+iz)].getCellId (), cellsNumber, graph->posCodeCubic (ix, iy, iz)); } } } else { /* simuType == hexa */ for (iz=-1; iz<2; iz++) for (iy=-1; iy<2; iy++) for (ix=-1; ix<2; ix++) { if ((getCellWithChecking (x+ix, y+iy, z+iz) != EMPTY) && !((ix == 0) && (iy == 0) && (iz == 0))) { /* on ajoute une arete */ if (graph->posCodeHexa (ix, iy, iz, x%2) != -1) { graph->addEdge (cells[(x+ix)*size*size+(y+iy)*size+(z+iz)].getCellId (), cellsNumber, graph->posCodeHexa (ix, iy, iz, x%2)); } } } } } } void Architecture::setEnvCode (int x, int y, int z) { Environment currentEnv(simuType); if (x>=0 && x=0 && y=0 && z 0) && (cellsNumber < aMaxCells-toBuildRulesNumber) && (!abortSimulation)) { if (showStats && (iterations%100 == 0)) { /* Si on a a s'occuper de l'affichage de la barre de statistiques, alors on le fait ici */ infoBox->setStatWindow ((double)(anIterationsNumber-iterations)/ (double)(anIterationsNumber)); if (infoBox->refreshStatWindow () == 1) { abortSimulation = 1; } } if (showConstruction && (iterations%500 == 0)) { /* on affiche la structure, meme si rien ne se construit */ viewInterface->alreadyComputed = 0; viewInterface->displayView3d (); } /* une position est selectionnee aleatoirement */ aWaspPosition.randomPosition (minX, maxX, minY, maxY, minZ, maxZ); if (getCellWithoutChecking (aWaspPosition.x, aWaspPosition.y, aWaspPosition.z) == EMPTY) { /* on regarde si la regle peut s'appliquer (dans chacune des rotations possibles) */ ruleNumber = matchRule (aWaspPosition, anArray, &proba, noiseRate); if ((ruleNumber != -1) && ((double)randomGenerator.getNumber ()/10000.0 < proba)) { if (proba == 1.0) { ruleStats.detRules++; #ifdef DEBUG_ENABLED printf ("Regle %d appliquee de facon deterministe\n", ruleNumber); #endif } else { ruleStats.probRules++; #ifdef DEBUG_ENABLED printf ("Regle %d appliquee avec une probabilite de %f\n", ruleNumber, proba); #endif if (proba < 0.05) ruleStats.prob0_05Rules++; else if (proba < 0.1) ruleStats.prob0_1Rules++; else if (proba < 0.2) ruleStats.prob0_2Rules++; else if (proba < 0.3) ruleStats.prob0_3Rules++; else if (proba < 0.5) ruleStats.prob0_5Rules++; else ruleStats.prob1_0Rules++; } #ifdef DEBUG_ENABLED printf ("Regle appliquee\n"); (anArray->get (ruleNumber))->print (0); #endif /* on applique la regle */ applyRule (aWaspPosition, *(anArray->get (ruleNumber)), ruleNumber); #ifdef DEBUG_ENABLED printf ("Apply rule %d position: (%d %d %d) Fails: %d Iterations: %d \n", ruleNumber,aWaspPosition.x,aWaspPosition.y,aWaspPosition.z,fails, iterations); #endif /* on fait un refresh de la construction */ if ((showConstruction) && (iterations%showCellsSteps == 0)) { viewInterface->alreadyComputed = 0; viewInterface->displayView3d (); } /* on incremente les compteurs qui vont bien */ fails = 0; cellsNumber++; ruleOccurs[ruleNumber]++; #ifdef DEBUG_ENABLED printf ("\nStructure courante\n"); print (); #endif } else if ((fails > allowedFails) && (allowedFails > 0)) { /* alors, puisque c'est comme ca, on construit une nouvelle regle */ fails = 0; learnOneRule (anArray, 0); /* la regle n'est pas appliquee */ } else { fails++; } } } /* apprentissage en fin de simulation */ if (typeOfLearning == learnAfterSimulation) { for (i=0; isetCode (getTopEnvCode (aWaspPosition.x, aWaspPosition.y, aWaspPosition.z)); addedTop->decode (); addedMiddle->setCode (getMiddleEnvCode (aWaspPosition.x, aWaspPosition.y, aWaspPosition.z)); addedMiddle->decode (); addedBottom->setCode (getBottomEnvCode (aWaspPosition.x, aWaspPosition.y, aWaspPosition.z)); addedBottom->decode (); if (randomGenerator.getNumber () == 0) { aCellType = RED; } else if (randomGenerator.getNumber () == 1) { aCellType = YELLOW; } else { aCellType = BLUE; } addedRule->set (*addedTop, *addedMiddle, *addedBottom, aCellType); alreadyInArray = 0; for (i=0; i<(int)anArray->nbElements; i++) { if (addedRule->isSamePerRotation (anArray->get (i))) { alreadyInArray = 1; } } if ((addedRule->getInRuleCellNumber () > 0) && (addedRule->checkConnectivity ()) && (!alreadyInArray)) { /* est ce que la regle contient plus qu'une cellule, la connectivite est-elle bonne, et la regle est-elle nouvelle ? */ continueSearching = 0; /* on arrete de chercher une regle comme des fous */ } } } /* et on ajoute la regle a l'endroit de la premiere regle non encore utilisee */ i = 0; while (ruleOccurs[i] !=0) i++; if (i < (int)anArray->nbElements) { /* on ajoute effectivement la regle */ anArray->set (i, *addedRule); if (mustRuleBeApplied) { /* on applique la regle */ applyRule (aWaspPosition, *(anArray->get (i)), i); cellsNumber++; ruleOccurs[i]++; #ifdef DEBUG_ENABLED printf ("Une nouvelle regle a ete trouvee et appliquee\n"); #endif } else { #ifdef DEBUG_ENABLED printf ("Une nouvelle regle a ete trouvee\n"); #endif } returnedValue = 1; } else { /* on laisse tomber, toutes les regles sont utilisees */ #ifdef DEBUG_ENABLED printf ("L'apprentissage a echoue: toutes les regles sont deja utilisees\n"); #endif returnedValue = 0; } delete addedRule; delete addedTop; delete addedMiddle; delete addedBottom; return returnedValue; } void Architecture::setStats (InfoBox* anInfoBox) { infoBox = anInfoBox; showStats = 1; } void Architecture::setViewInterface (ViewInterface* aViewInterface, int showCellsStepsParam) { viewInterface = aViewInterface; showConstruction = 1; showCellsSteps = showCellsStepsParam; } double Architecture::dRuleEnv (int eTop, int eMiddle, int eBottom, int rTop, int rMiddle, int rBottom, int numberOfCellsInRule) { Environment diff (simuType); /* je sais plus du tout pourquoi c'etait ca */ /* if ((eTop != 0) && (eMiddle != 0) && (eBottom != 0)) { return 1.0; } */ diff.setCode (abs(eTop^rTop), abs(eMiddle^rMiddle), abs(eBottom^rBottom)); diff.decode (); return diff.distanceFactor (NOISE_FACTOR1, NOISE_FACTOR2, NOISE_FACTOR3) / numberOfCellsInRule; } int Architecture::matchRule (Position aPosition, RuleArray* aRuleArray, double* proba, double noiseRate) { int notFound; int currentRuleNumber; Rule currentRule (simuType); int returnedRuleNumber; int anAngle; /* modif bruit */ int eTop, eMiddle, eBottom; /* environnement rencontre */ int rTop, rMiddle, rBottom; /* regle testee */ double dMin; double currentDistance; returnedRuleNumber = -1; currentRuleNumber = 0; notFound =1; dMin = 2.0; eTop = getTopEnvCode (aPosition.x, aPosition.y, aPosition.z); eMiddle = getMiddleEnvCode (aPosition.x, aPosition.y, aPosition.z); eBottom = getBottomEnvCode (aPosition.x, aPosition.y, aPosition.z); if ((eTop == 0) && (eMiddle == 0) && (eBottom == 0)) { return -1; } else { /* la position choisie n'est pas isolee, on peut donc chercher une regle */ while (notFound) { currentRule = *(aRuleArray->get (currentRuleNumber)); /* modif bruit */ if (simuType == cubic) { for (anAngle=0; anAngle<4; anAngle++) { rTop = currentRule.getTopCode (anAngle); rMiddle = currentRule.getMiddleCode (anAngle); rBottom = currentRule.getBottomCode (anAngle); if (noiseRate == 0) { if ((rTop == eTop) && (rMiddle == eMiddle) && (rBottom == eBottom)) { returnedRuleNumber = currentRuleNumber; notFound = 0; } } else { currentDistance = dRuleEnv (eTop, eMiddle, eBottom, rTop, rMiddle, rBottom, currentRule.getInRuleCellNumber ()+1); if (currentDistance <= dMin) { returnedRuleNumber = currentRuleNumber; dMin = currentDistance; } } } } else if (simuType == hexa) { for (anAngle=0; anAngle<6; anAngle++) { rTop = currentRule.getTopCode (anAngle); rMiddle = currentRule.getMiddleCode (anAngle); rBottom = currentRule.getBottomCode (anAngle); if (noiseRate == 0) { if ((rTop == eTop) && (rMiddle == eMiddle) && (rBottom == eBottom)) { returnedRuleNumber = currentRuleNumber; notFound = 0; } } else { currentDistance = dRuleEnv (eTop, eMiddle, eBottom, rTop, rMiddle, rBottom, currentRule.getInRuleCellNumber ()+1); if (currentDistance <= dMin) { returnedRuleNumber = currentRuleNumber; dMin = currentDistance; } } } } currentRuleNumber++; if (currentRuleNumber >= aRuleArray->getElementsNb ()) notFound = 0; } if (noiseRate != 0) { *proba = exp (-dMin/noiseRate); } else { *proba = 1.0; } return returnedRuleNumber; } } void Architecture::applyRule (Position aPosition, Rule aRule, int ruleNumber) { if (aRule.getCellToBuild () == EMPTY) { //printf ("ERROR in rule definition (rule center should not be empty)\n"); aRule.setCellToBuild (RED); } setCell (aPosition.x, aPosition.y, aPosition.z, aRule.getCellToBuild (), ruleNumber); } void Architecture::initFirstCell () { int a; a = (int)((size-1)/2); setCell (a, a, 0, RED, -2); /* -2 because first cell created */ } void Architecture::initRandomGenerator () { time_t currentTime; currentTime = time (0); // printf ("time %d\n", currentTime); srand ((int)currentTime); } void Architecture::initializePixmap (Display* aDisplay, Window aWindow, unsigned int aDepth) { preview = XCreatePixmap (aDisplay, aWindow, PIXMAP_WIDTH, PIXMAP_HEIGHT, aDepth); pixmapInitialized = BTrue; } void Architecture::setPixmap (Display* aDisplay, Pixmap aPixmap, GC aGC) { if (pixmapInitialized == BFalse) { printf ("ERROR: preview pixmap not initialized\n"); } else { XCopyArea (aDisplay, aPixmap, preview, aGC, 0, 0, PIXMAP_WIDTH, PIXMAP_HEIGHT , 0, 0); } } void Architecture::freePixmap (Display* aDisplay) { if (pixmapInitialized == BTrue) { pixmapInitialized = BFalse; XFreePixmap (aDisplay, preview); } else { printf ("ERROR: request for free preview pixmap not initialized\n"); } } /* methode de sauvegarde de l'architecture */ int Architecture::saveArchitecture (char* aPathName, char* aFileName) { FILE *pf; char fname[256]; char line[256]; int i, j, k; typeOfCell cellType; GraphNode* currentNode; if (size > 255) { printf ("ERROR: Unable to save architecture: too big\n"); return 0; } strcpy (fname, aPathName); strcat (fname, aFileName); pf = fopen(fname,"w"); if (pf == NULL) { printf ("ERROR >> unable to write file %s\n", fname); return 0; } else { /* ecriture de l'architecture */ fprintf (pf, "architecture size = %d\n", size); fprintf (pf, "number of cells = %ld\n", cellsNumber); for (k=0; kgetNodesNumber ()); fprintf (pf, "edges number = %d\n", graph->getEdgesNumber ()); for (i=0; igetNodesNumber (); i++) { currentNode = graph->nodeAtIndex(i); fprintf (pf, "%d %d %d %d %d %d %f %f\n", currentNode->getNodeId (), currentNode->getRuleId (), currentNode->cellType, currentNode->x, currentNode->y, currentNode->z, currentNode->getPx (), currentNode->getPy ()); } k = 0; /* index de l'arete */ for (i=0; igetNodesNumber (); i++) { currentNode = graph->nodeAtIndex(i); for (j=0; j<26; j++) { /* j est le posCode */ if ((currentNode->indexOfNeighbour (j) != -1) && (currentNode->directionOfNeighbour (j) == Output)) { fprintf (pf, "%d %d %d %d\n", k, i, currentNode->indexOfNeighbour (j), j); k++; } } } fclose (pf); return 1; } } /* methode de chargement de l'architecture */ int Architecture::loadArchitecture (char* aPathName, char* aFileName) { FILE *pf; char fname[256]; int i, j, k; /* USELESS typeOfCell cellType; */ int readCells; int readInt; char temp[256]; int nodesNumber, edgesNumber; int nodeId, ruleId, readCellType, x, y, z; float px, py; int edgeId, startNodeId, endNodeId, posCode; strcpy (fname, aPathName); strcat (fname, aFileName); pf = fopen(fname,"r"); if (pf == NULL) { printf ("ERROR >> unable to read file %s\n", fname); return 0; } else { /* lecture de l'architecture */ fgets (temp, 256, pf); /* lecture du parametre archSize */ fgets (temp, 256, pf); /* lecture du parametre cellsNumber */ sscanf (temp, "number of cells = %d", &readCells); cellsNumber = readCells; for (k=0; kaddNode (ruleId, (typeOfCell)readCellType, x, y, z); (graph->nodeAtIndex (i))->setPx ((double)px); (graph->nodeAtIndex (i))->setPy ((double)py); } for (i=0; iaddEdge (startNodeId, endNodeId, posCode); } } fclose(pf); return 1; } } /* methode de sauvegarde de la previsualisation */ int Architecture::savePreview (char* aPathName, char* aFileName, Display* aDisplay) { char fname[256]; int screenNum; unsigned int defaultDepth; screenNum = DefaultScreen (aDisplay); defaultDepth = DefaultDepth (aDisplay, screenNum); strcpy (fname, aPathName); strcat (fname, aFileName); if (XpmWriteFileFromPixmap (aDisplay, fname, preview, 0, NULL) != 0) { printf ("ERROR >> unable to write file %s\n", fname); return 0; } return 1; } /* methode de chargement de la previsualisation */ int Architecture::loadPreview (char* aPathName, char* aFileName, Display* aDisplay, Window* aWindow) { char fname[256]; unsigned int defaultDepth; int screenNum; XpmAttributes xpma; screenNum = DefaultScreen (aDisplay); defaultDepth = DefaultDepth (aDisplay, screenNum); xpma.valuemask = XpmExactColors; strcpy (fname, aPathName); strcat (fname, aFileName); if (defaultDepth == 1) { XpmFreeAttributes (&xpma); return 0; } else { if (XpmReadFileToPixmap (aDisplay, *aWindow, fname, /* pixmap filename */ &preview, NULL, &xpma) != 0) { printf ("ERROR >> unable to read file %s\n", fname); XpmFreeAttributes (&xpma); return 0; } } XpmFreeAttributes (&xpma); pixmapInitialized = BTrue; return 1; } void Architecture::loadPreviewFromArch (Display* aDisplay, Window* aWindow, GC* aGC, unsigned long* aColorPointer, XFontStruct* aFontInfo) { View* previewView; position org, dest; int screenNum; unsigned int defaultDepth; screenNum = DefaultScreen (aDisplay); defaultDepth = DefaultDepth (aDisplay, screenNum); previewView = new View (aDisplay, *aWindow, *aGC, *aWindow, aColorPointer, colorMode, (unsigned int)PIXMAP_WIDTH, (unsigned int) PIXMAP_HEIGHT, aFontInfo, defaultDepth, this, simuType, *aWindow); org = init_position (); org.x = 5; org.y = -2; org.z = 3; dest = init_position (); previewView->init_view (dest, org, 50, 20, 50, 50); previewView->set_alpha (M_PI); previewView->resize (); previewView->setAxes (); previewView->drawNet (0, 0); previewView->displayTempScreen (); /* maintenant, on reserve de la place pour le Pixmap */ if (pixmapInitialized == BFalse) { initializePixmap (aDisplay, *aWindow, defaultDepth); } /* maintenant, on recopie le Pixmap */ XCopyArea (aDisplay, previewView->getTempScreen (), preview, *aGC, 0, 0, PIXMAP_WIDTH, PIXMAP_HEIGHT , 0, 0); delete previewView; } /* ---------------------------------------------------- */ PlanEnvironment::PlanEnvironment (SimulationType aSimuType) { if (aSimuType == cubic) { simuType = cubic; set (EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY); } else { simuType = hexa; set (EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY); } /* | ___ | ___/ 1 \___ | / 2 \___/ 6 \ | \___/ 0 \___/ | / 3 \___/ 5 \ | \___/ 4 \___/ | \___/ */ } PlanEnvironment::~PlanEnvironment () { } void PlanEnvironment::set (typeOfCell c00, typeOfCell c10, typeOfCell c20, typeOfCell c01, typeOfCell c11, typeOfCell c21, typeOfCell c02, typeOfCell c12, typeOfCell c22) { if (simuType == cubic) { cells[0][0] = c00; cells[1][0] = c10; cells[2][0] = c20; cells[0][1] = c01; cells[1][1] = c11; cells[2][1] = c21; cells[0][2] = c02; cells[1][2] = c12; cells[2][2] = c22; encode (); } else { printf ("Error: setting incompatible with type of simulation (hexa)\n"); } } void PlanEnvironment::set (typeOfCell c0, typeOfCell c1, typeOfCell c2, typeOfCell c3, typeOfCell c4, typeOfCell c5, typeOfCell c6) /* pour hexa */ { if (simuType == hexa) { /* cells[0][0] = c0; cells[1][0] = c1; cells[2][0] = c2; cells[0][1] = c3; cells[1][1] = c4; cells[2][1] = c5; cells[0][2] = EMPTY; cells[1][2] = c6; cells[2][2] = EMPTY; */ cells[1][1] = c0; cells[1][0] = c1; cells[0][0] = c2; cells[0][1] = c3; cells[1][2] = c4; cells[2][1] = c5; cells[2][0] = c6; cells[0][2] = EMPTY; cells[2][2] = EMPTY; encode (); /* on garde les memes notations que pour cubic, pour reutiliser le code au maximum */ } else { printf ("Error: setting incompatible with type of simulation (cubic)\n"); } } void PlanEnvironment::set (int i, int j, typeOfCell aCellType) /* pour cubic */ { cells[i][j] = aCellType; encode (); } void PlanEnvironment::set (int i, typeOfCell aCellType) /* pour hexa */ { switch(i) { case 0: cells[1][1] = aCellType; break; case 1: cells[1][0] = aCellType; break; case 2: cells[0][0] = aCellType; break; case 3: cells[0][1] = aCellType; break; case 4: cells[1][2] = aCellType; break; case 5: cells[2][1] = aCellType; break; case 6: cells[2][0] = aCellType; break; default: break; } } typeOfCell PlanEnvironment::get (int i, int j) /* pour cubic */ { return cells[i][j]; } typeOfCell PlanEnvironment::get (int i) /* pour hexa */ { switch(i) { case 0: return cells[1][1]; case 1: return cells[1][0]; case 2: return cells[0][0]; case 3: return cells[0][1]; case 4: return cells[1][2]; case 5: return cells[2][1]; case 6: return cells[2][0]; default: return EMPTY; } return EMPTY; } void PlanEnvironment::emptyCenter () { if (simuType == cubic) cells[1][1] = EMPTY; else if (simuType == hexa) cells[1][1] = EMPTY; } void PlanEnvironment::setCenter (typeOfCell cellToBuild) { if (simuType == cubic) cells[1][1] = cellToBuild; else if (simuType == hexa) cells[1][1] = cellToBuild; } void PlanEnvironment::print () { int ix, iy; if (simuType == cubic) { /* cubic */ for (iy=0; iy<3; iy++) { for (ix=0; ix<3; ix++) { if (cells[ix][iy] == 0) printf ("- "); else if (cells[ix][iy] == 1) printf ("R "); else printf ("Y "); } printf ("\n"); } } else { /* hexa */ printf (" ___ \n"); printf (" ___/ %d \\___ \n", cells[1][0]); printf (" / %d \\___/ %d \\ \n", cells[0][0], cells[2][0]); printf (" \\___/ %d \\___/ \n", cells[1][1]); printf (" / %d \\___/ %d \\ \n", cells[0][1], cells[2][1]); printf (" \\___/ %d \\___/ \n", cells[1][2]); printf (" \\___/ \n"); } } void PlanEnvironment::encode () { code = 4*4*4*4*4*4*4*4*cells[0][0] +4*4*4*4*4*4*4*cells[1][0] +4*4*4*4*4*4*cells[2][0] +4*4*4*4*4*cells[0][1] +4*4*4*4*cells[1][1] +4*4*4*cells[2][1] +4*4*cells[0][2] +4*cells[1][2] +cells[2][2]; // printf ("code = %d\n", code); } void PlanEnvironment::decode () { int ix,iy; int c; c = code; for (iy=2; iy>=0; iy--) for (ix=2; ix>=0; ix--){ cells[ix][iy] = (typeOfCell)(c%4); //printf ("resultat %d %d : %d\n", ix, iy, c%4); c = (c - c%4)/4; } } int PlanEnvironment::getCode () { return code; } void PlanEnvironment::setCode (int aCode) { code = aCode; decode (); } PlanEnvironment PlanEnvironment::rotate () { PlanEnvironment returned(simuType); if (simuType == cubic) { returned.set (cells[2][0], cells[2][1], cells[2][2], cells[1][0], cells[1][1], cells[1][2], cells[0][0], cells[0][1], cells[0][2]); return returned; } else if (simuType == hexa) { returned.set (cells[1][1], cells[0][0], cells[0][1], cells[1][2], cells[2][1], cells[2][0], cells[1][0]); return returned; } return returned; } int PlanEnvironment::notEmptyCells () { int i, ix, iy; int returnedValue; returnedValue = 0; if (simuType == cubic) { for (ix=0; ix<3; ix++) { for (iy=0; iy<3; iy++) { if (cells[ix][iy] != EMPTY) { returnedValue++; } } } } else if (simuType == hexa) { for (i=0; i<7; i++) { if (get(i) != EMPTY) { returnedValue++; } } } return returnedValue; } /* coefficients for cubic structures */ /* c1 c2 c1 c2 c3 c2 c1 c2 c1 */ /* coefficients for hexa structures */ /* | ___ | ___/c1 \___ | /c1 \___/c1 \ | \___/c2 \___/ | /c1 \___/c1 \ | \___/c1 \___/ | \___/ */ double PlanEnvironment::distanceFactor (double coeff1, double coeff2, double coeff3) { int i, ix, iy; double returnedValue; returnedValue = 0; if (simuType == cubic) { for (ix=0; ix<3; ix++) { for (iy=0; iy<3; iy++) { if (cells[ix][iy] != EMPTY) { if ((ix == 1) && (iy == 1)) { returnedValue += coeff3; } else { if ((ix+iy)%2 == 0) { returnedValue += coeff1; } else { returnedValue += coeff2; } } } } } } else if (simuType == hexa) { if (get (0) != EMPTY) { returnedValue += coeff2; } for (i=1; i<7; i++) { if (get(i) != EMPTY) { returnedValue += coeff1; } } } return returnedValue; } /* ---------------------------------------------------- */ Environment::Environment (SimulationType aSimuType) { simuType = aSimuType; top = new PlanEnvironment (simuType); middle = new PlanEnvironment (simuType); bottom = new PlanEnvironment (simuType); } Environment::~Environment () { delete top; delete middle; delete bottom; } void Environment::init (Architecture* initArch) { arch = initArch; } int Environment::setCode (int topCode, int middleCode, int bottomCode) { top->setCode (topCode); middle->setCode (middleCode); bottom->setCode (bottomCode); } void Environment::decode () { top->decode (); middle->decode (); bottom->decode (); } int Environment::notEmptyCells () { return (top->notEmptyCells () + middle->notEmptyCells () + bottom->notEmptyCells ()); } /* c1 c2 c1 c2 c3 c2 c1 c2 c1 */ /* | ___ | ___/c1 \___ | /c1 \___/c1 \ | \___/c2 \___/ | /c1 \___/c1 \ | \___/c1 \___/ | \___/ */ double Environment::distanceFactor (double coeff1, double coeff2, double coeff3) { if (simuType == cubic) { return top->distanceFactor (coeff1, coeff2, coeff3) + middle->distanceFactor (coeff2, coeff3, 0) + bottom->distanceFactor (coeff1, coeff2, coeff3); } else if (simuType == hexa) { return top->distanceFactor (coeff2, coeff3, 0) + middle->distanceFactor (coeff3, 0, 0) + bottom->distanceFactor (coeff2, coeff3, 0); } } void Environment::set (int x, int y, int z) { if (simuType == cubic) { top->set (arch->getCellWithChecking (x-1, y-1, z-1), arch->getCellWithChecking (x, y-1, z-1), arch->getCellWithChecking (x+1, y-1, z-1), arch->getCellWithChecking (x-1, y, z-1), arch->getCellWithChecking (x, y, z-1), arch->getCellWithChecking (x+1, y, z-1), arch->getCellWithChecking (x-1, y+1, z-1), arch->getCellWithChecking (x, y+1, z-1), arch->getCellWithChecking (x+1, y+1, z-1)); top->encode (); middle->set (arch->getCellWithChecking (x-1, y-1, z), arch->getCellWithChecking (x, y-1, z), arch->getCellWithChecking (x+1, y-1, z), arch->getCellWithChecking (x-1, y, z), arch->getCellWithChecking (x, y, z), arch->getCellWithChecking (x+1, y, z), arch->getCellWithChecking (x-1, y+1, z), arch->getCellWithChecking (x, y+1, z), arch->getCellWithChecking (x+1, y+1, z)); middle->emptyCenter (); middle->encode (); bottom->set (arch->getCellWithChecking (x-1, y-1, z+1), arch->getCellWithChecking (x, y-1, z+1), arch->getCellWithChecking (x+1, y-1, z+1), arch->getCellWithChecking (x-1, y, z+1), arch->getCellWithChecking (x, y, z+1), arch->getCellWithChecking (x+1, y, z+1), arch->getCellWithChecking (x-1, y+1, z+1), arch->getCellWithChecking (x, y+1, z+1), arch->getCellWithChecking (x+1, y+1, z+1)); bottom->encode (); } else if (simuType == hexa) { if (x%2 == 1) { top->set (arch->getCellWithChecking (x, y, z-1), arch->getCellWithChecking (x, y-1, z-1), arch->getCellWithChecking (x-1, y-1, z-1), arch->getCellWithChecking (x-1, y, z-1), arch->getCellWithChecking (x, y+1, z-1), arch->getCellWithChecking (x+1, y, z-1), arch->getCellWithChecking (x+1, y-1, z-1)); top->encode (); middle->set (arch->getCellWithChecking (x, y, z), arch->getCellWithChecking (x, y-1, z), arch->getCellWithChecking (x-1, y-1, z), arch->getCellWithChecking (x-1, y, z), arch->getCellWithChecking (x, y+1, z), arch->getCellWithChecking (x+1, y, z), arch->getCellWithChecking (x+1, y-1, z)); middle->encode (); bottom->set (arch->getCellWithChecking (x, y, z+1), arch->getCellWithChecking (x, y-1, z+1), arch->getCellWithChecking (x-1, y-1, z+1), arch->getCellWithChecking (x-1, y, z+1), arch->getCellWithChecking (x, y+1, z+1), arch->getCellWithChecking (x+1, y, z+1), arch->getCellWithChecking (x+1, y-1, z+1)); bottom->encode (); } else { top->set (arch->getCellWithChecking (x, y, z-1), arch->getCellWithChecking (x, y-1, z-1), arch->getCellWithChecking (x-1, y, z-1), arch->getCellWithChecking (x-1, y+1, z-1), arch->getCellWithChecking (x, y+1, z-1), arch->getCellWithChecking (x+1, y+1, z-1), arch->getCellWithChecking (x+1, y, z-1)); top->encode (); middle->set (arch->getCellWithChecking (x, y, z), arch->getCellWithChecking (x, y-1, z), arch->getCellWithChecking (x-1, y, z), arch->getCellWithChecking (x-1, y+1, z), arch->getCellWithChecking (x, y+1, z), arch->getCellWithChecking (x+1, y+1, z), arch->getCellWithChecking (x+1, y, z)); middle->encode (); bottom->set (arch->getCellWithChecking (x, y, z+1), arch->getCellWithChecking (x, y-1, z+1), arch->getCellWithChecking (x-1, y, z+1), arch->getCellWithChecking (x-1, y+1, z+1), arch->getCellWithChecking (x, y+1, z+1), arch->getCellWithChecking (x+1, y+1, z+1), arch->getCellWithChecking (x+1, y, z+1)); bottom->encode (); } } } void Environment::print () { top->print (); printf ("\n"); middle->print (); printf ("\n"); bottom->print (); printf ("\n"); } int Environment::getTopCode () { return top->getCode(); } int Environment::getMiddleCode () { return middle->getCode(); } int Environment::getBottomCode () { return bottom->getCode(); } /* ---------------------------------------------------- */ Rule::Rule (SimulationType aSimuType) { int i; simuType = aSimuType; ruleClass = unusedClass; if (aSimuType == cubic) { facesNumber = 4; } else { /* hexa */ facesNumber = 6; } for (i=0; i<6; i++) { topCode[i] = 0; middleCode[i] = 0; bottomCode[i] = 0; } toBuild = RED; } Rule::~Rule () { } void Rule::set (PlanEnvironment top, PlanEnvironment middle, PlanEnvironment bottom, typeOfCell cellToBuild) { int i; PlanEnvironment currentTop(simuType); PlanEnvironment currentMiddle(simuType); PlanEnvironment currentBottom(simuType) ; currentTop = top; currentMiddle = middle; currentBottom = bottom; for (i=0; iinstanciate (); ruleTemplate->setRule (this); delete ruleTemplate; } } void Rule::firstRuleRandomGenerate () { int x, y, z; int choice; RandomGenerator randomGenerator1 (PSEUDO, 0, 2); RandomGenerator randomGenerator2 (PSEUDO, 0, 2); for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { set (x,y,z,EMPTY); } } } x = randomGenerator2.getNumber (); y = randomGenerator2.getNumber (); z = randomGenerator2.getNumber (); choice = randomGenerator1.getNumber (); if (choice == 0) { set (x,y,z,RED); } else if (choice == 1) { set (x,y,z,YELLOW); } else if (choice == 2) { set (x,y,z,BLUE); } choice = randomGenerator1.getNumber (); if (choice == 0) { set (1,1,1,RED); } else if (choice == 1) { set (1,1,1,YELLOW); } else if (choice == 2) { set (1,1,1,BLUE); } if (!checkConnectivity ()) { firstRuleRandomGenerate (); } /* if rule doesn't follow connectivity constraints, then generate again */ } int Rule::checkConnectivity () /* return 1 if connected else 0 */ { int x, y, z; int connected; int nearCells; connected = 1; for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { if (get (x,y,z) != EMPTY) { nearCells = 0; if ((x>0) && (get (x-1, y, z) != EMPTY)) nearCells++; if ((x<2) && (get (x+1, y, z) != EMPTY)) nearCells++; if ((y>0) && (get (x, y-1, z) != EMPTY)) nearCells++; if ((y<2) && (get (x, y+1, z) != EMPTY)) nearCells++; if ((z>0) && (get (x, y, z-1) != EMPTY)) nearCells++; if ((z<2) && (get (x, y, z+1) != EMPTY)) nearCells++; if (nearCells == 0) connected=0; } } } } return connected; } int Rule::getInRuleCellNumber () { int returned; int x, y, z; returned = 0; for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { if (get (x,y,z) != EMPTY) { returned++; } } } } return returned-1; } int Rule::isSamePerRotation (Rule* aRule) { int i; int returned; if (simuType != aRule->simuType) { printf ("ERROR: comparaison for two type-different rules\n"); return 0; } else { returned = 0; for (i=0; igetTopCode (i)) && (getMiddleCode (0) == aRule->getMiddleCode (i)) && (getBottomCode (0) == aRule->getBottomCode (i))) { returned = 1; } } return returned; } } void Rule::setRuleClass (RuleClass aRuleClass) { ruleClass = aRuleClass; } RuleClass Rule::getRuleClass () { return ruleClass; } /* ---------------------------------------------------- */ GenRule::GenRule (SimulationType aSimuType) : Rule (aSimuType) { int x, y, z; adjCells[0][0][0] = 7; adjCells[1][0][0] = 11; adjCells[2][0][0] = 7; adjCells[0][1][0] = 11; adjCells[1][1][0] = 17; adjCells[2][1][0] = 11; adjCells[0][2][0] = 7; adjCells[1][2][0] = 11; adjCells[2][2][0] = 7; adjCells[0][0][1] = 11; adjCells[1][0][1] = 17; adjCells[2][0][1] = 11; adjCells[0][1][1] = 17; adjCells[1][1][1] = 26; adjCells[2][1][1] = 17; adjCells[0][2][1] = 11; adjCells[1][2][1] = 17; adjCells[2][2][1] = 11; adjCells[0][0][2] = 7; adjCells[1][0][2] = 11; adjCells[2][0][2] = 7; adjCells[0][1][2] = 11; adjCells[1][1][2] = 17; adjCells[2][1][2] = 11; adjCells[0][2][2] = 7; adjCells[1][2][2] = 11; adjCells[2][2][2] = 7; for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { pCell[x][y][z] = 0.0; } } } for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { set (x, y, z, EMPTY); } } } } GenRule::~GenRule () { } void GenRule::updateProba (int x, int y, int z) { int i, j, k; int nearCells; nearCells = 0; for (i = -1; i <= 1; i++) { for (j = -1; j <=1 ; j++) { for (k = -1; k <= 1; k++) { if (((i+x >= 0) && (i+x <=2)) && ((j+y >= 0) && (j+y <=2)) && ((k+z >= 0) && (k+z <=2))) { if (get (i+x, j+y, k+z) != EMPTY) { nearCells++; } } } } } pCell[x][y][z] = (double)(nearCells)/(double)(adjCells[x][y][z]); } void GenRule::setCell (int x, int y, int z, typeOfCell aCellType) { int i, j, k; set (x, y, z, aCellType); for (i = -1; i <= 1; i++) { for (j = -1; j <=1 ; j++) { for (k = -1; k <= 1; k++) { if (((i+x >= 0) && (i+x <=2)) && ((j+y >= 0) && (j+y <=2)) && ((k+z >= 0) && (k+z <=2))) { updateProba (i+x, j+y, k+z); } } } } } int GenRule::probSet (int x, int y, int z, typeOfCell aCellType) { RandomGenerator randomGenerator (PSEUDO, 0, 9999); int choice; /* USELESS int a, b, c; */ // printf ("Trying to build a new cell\n"); /* for (a=0; a<3; a++) { for (b=0; b<3; b++) { for (c=0; c<3; c++) { printf ("%.2f ", pCell[a][b][c]); } printf ("\n"); } printf ("\n"); } printf ("\n"); */ choice = randomGenerator.getNumber (); if ((double)choice/10000.0 < pCell[x][y][z]) { setCell (x, y, z, aCellType); return 1; } else { return 0; } } void GenRule::setRule (Rule* aRule) { int x, y, z; typeOfCell aCellType; for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { aCellType = get (x, y, z); aRule->set (x, y, z, aCellType); } } } } /* ---------------------------------------------------- */ TemplateRule::TemplateRule (SimulationType aSimuType, TemplateType aTemplateType, double pRedCell, double pYellowCell) : Rule (aSimuType) { RandomGenerator randomGenerator1 (PSEUDO, 0, 9999); RandomGenerator randomGenerator2 (PSEUDO, 0, 3); int angle; pRed = pRedCell; pYellow = pYellowCell; gamma = (double)randomGenerator1.getNumber ()/30000; betaRed = (double)randomGenerator1.getNumber ()/(10000/(1/pRed-1))+1; betaYellow = (double)randomGenerator1.getNumber ()/(10000/(1/pYellow-1))+1; /* printf ("gamma = %f\nbetaRed = %f\nbetaYellow = %f\n", gamma, betaRed, betaYellow); */ angle = randomGenerator2.getNumber (); switch (aTemplateType) { case Center: setCenterTemplate (); break; case Top: setTopTemplate (); break; case Bottom: setBottomTemplate (); break; case Side: setSideTemplate (angle); break; case TopSide: setTopSideTemplate (angle); break; case BottomSide: setBottomSideTemplate (angle); break; } } TemplateRule::~TemplateRule () { } void TemplateRule::instanciate () { int i, j, k; int choice; RandomGenerator randomGenerator1 (PSEUDO, 0, 2); RandomGenerator randomGenerator2 (PSEUDO, 0, 9999); int builtCells; builtCells = 0; for (k=0; k<3; k++) { for (i=0; i<3; i++) { for (j=0; j<3; j++) { choice = randomGenerator1.getNumber (); if (choice == 0) { /* red */ if (randomGenerator2.getNumber () < pCellForRed[i][j][k]*10000) { set (i, j, k, RED); builtCells++; } else { set (i, j, k, EMPTY); } } else if (choice == 1) { /* yellow */ if (randomGenerator2.getNumber () < pCellForYellow[i][j][k]*10000) { set (i, j, k, YELLOW); builtCells++; } else { set (i, j, k, EMPTY); } } else if (choice == 2) { /* blue */ if (randomGenerator2.getNumber () < pCellForRed[i][j][k]*10000) { set (i, j, k, BLUE); builtCells++; } else { set (i, j, k, EMPTY); } } } } } /* si il n'y a qu'une seule cellule, on recommence */ if (builtCells < 2) { instanciate (); } /* si pas connexe, on recommence */ if (!checkConnectivity ()) { instanciate (); } } void TemplateRule::setRule (Rule* aRule) { int x, y, z; typeOfCell aCellType; for (x=0; x<3; x++) { for (y=0; y<3; y++) { for (z=0; z<3; z++) { aCellType = get (x, y, z); aRule->set (x, y, z, aCellType); } } } } void TemplateRule::setPRedCell (int x, int y, int z, double aProba) { if ((x == 1) && (y == 1) && (z == 1)) { pCellForRed[1][1][1] = 1; } else { pCellForRed[x][y][z] = pRed*aProba; } } void TemplateRule::setPYellowCell (int x, int y, int z, double aProba) { if ((x == 1) && (y == 1) && (z == 1)) { pCellForYellow[1][1][1] = 1; } else { pCellForYellow[x][y][z] = pYellow*aProba; } } void TemplateRule::setPRedPlane (int z, double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8) { setPRedCell (0, 0, z, p0); setPRedCell (1, 0, z, p1); setPRedCell (2, 0, z, p2); setPRedCell (0, 1, z, p3); setPRedCell (1, 1, z, p4); setPRedCell (2, 1, z, p5); setPRedCell (0, 2, z, p6); setPRedCell (1, 2, z, p7); setPRedCell (2, 2, z, p8); } void TemplateRule::setPYellowPlane (int z, double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8) { setPYellowCell (0, 0, z, p0); setPYellowCell (1, 0, z, p1); setPYellowCell (2, 0, z, p2); setPYellowCell (0, 1, z, p3); setPYellowCell (1, 1, z, p4); setPYellowCell (2, 1, z, p5); setPYellowCell (0, 2, z, p6); setPYellowCell (1, 2, z, p7); setPYellowCell (2, 2, z, p8); } void TemplateRule::print () { int i, j, k; printf ("RED\n\n"); for (k=0; k<3; k++) { for (i=0; i<3; i++) { for (j=0; j<3; j++) { printf ("%f |", pCellForRed[i][j][k]); } printf ("\n"); } printf ("\n"); } printf ("YELLOW\n\n"); for (k=0; k<3; k++) { for (i=0; i<3; i++) { for (j=0; j<3; j++) { printf ("%f | ", pCellForYellow[i][j][k]); } printf ("\n"); } printf ("\n"); } } void TemplateRule::setCenterTemplate () { double gamma2; // printf ("Center template chosen\n"); gamma2 = gamma*gamma; setPRedPlane (0, gamma2, gamma, gamma2, gamma, 1, gamma, gamma2, gamma, gamma2); setPRedPlane (1, gamma, 1, gamma, 1, 1, 1, gamma, 1, gamma); setPRedPlane (2, gamma2, gamma, gamma2, gamma, 1, gamma, gamma2, gamma, gamma2); setPYellowPlane (0, gamma2, gamma, gamma2, gamma, 1, gamma, gamma2, gamma, gamma2); setPYellowPlane (1, gamma, 1, gamma, 1, 1, 1, gamma, 1, gamma); setPYellowPlane (2, gamma2, gamma, gamma2, gamma, 1, gamma, gamma2, gamma, gamma2); } void TemplateRule::setTopTemplate () { double gamma2; // printf ("Top template chosen\n"); gamma2 = gamma*gamma; setPRedPlane (0, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2); setPRedPlane (1, gamma, gamma, gamma, gamma, 1, gamma, gamma, gamma, gamma); setPRedPlane (2, 1, 1, 1, 1, betaRed, 1, 1, 1, 1); setPYellowPlane (0, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2); setPYellowPlane (1, gamma, gamma, gamma, gamma, 1, gamma, gamma, gamma, gamma); setPYellowPlane (2, 1, 1, 1, 1, betaYellow, 1, 1, 1, 1); } void TemplateRule::setBottomTemplate () { double gamma2; // printf ("Bottom template chosen\n"); gamma2 = gamma*gamma; setPRedPlane (0, 1, 1, 1, 1, betaRed, 1, 1, 1, 1); setPRedPlane (1, gamma, gamma, gamma, gamma, 1, gamma, gamma, gamma, gamma); setPRedPlane (2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2); setPYellowPlane (0, 1, 1, 1, 1, betaYellow, 1, 1, 1, 1); setPYellowPlane (1, gamma, gamma, gamma, gamma, 1, gamma, gamma, gamma, gamma); setPYellowPlane (2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2, gamma2); } void TemplateRule::setSideTemplate (int anAngle) { double gamma2; int i; // printf ("Side template chosen [%d]\n", anAngle); gamma2 = gamma*gamma; setPRedPlane (0, gamma2, gamma, 1, gamma2, gamma, 1, gamma2, gamma, 1); setPRedPlane (1, gamma2, gamma, 1, gamma2, 1, betaRed, gamma2, gamma, 1); setPRedPlane (2, gamma2, gamma, 1, gamma2, gamma, 1, gamma2, gamma, 1); setPYellowPlane (0, gamma2, gamma, 1, gamma2, gamma, 1, gamma2, gamma, 1); setPYellowPlane (1, gamma2, gamma, 1, gamma2, 1, betaYellow, gamma2, gamma, 1); setPYellowPlane (2, gamma2, gamma, 1, gamma2, gamma, 1, gamma2, gamma, 1); for (i=0; i ", nbElements); for (i=0; i<(int)nbElements; i++) { get(i, &aRule); printf ("[%2d(%d)]", (aRule.getTopCode(0) +aRule.getMiddleCode(0) +aRule.getBottomCode(0))%87, aRule.getRuleClass ()); } printf ("\n"); } unsigned int RuleArray::getElementsNb () { return nbElements; } unsigned int RuleArray::getMaxElements () { return maxElements; } SimulationType RuleArray::getSimuType () { return simuType; } void RuleArray::add (Rule aRule) { if (nbElements >= maxElements) { printf ("ERROR >> Array is full: unable to add one more element\n"); } else { element[nbElements]->set (aRule); element[nbElements]->setRuleClass (aRule.getRuleClass ()); nbElements++; } } Rule* RuleArray::get (unsigned int i) { if (i >= nbElements) exit (1); /* This element does not exist */ return element[i]; } void RuleArray::get (unsigned int i, Rule* aRule) { PlanEnvironment TEnv (simuType), MEnv (simuType), BEnv (simuType); if (i>=nbElements) { printf ("ERROR >> This element does not exist\n"); } else { TEnv.setCode (element[i]->getTopCode (0)); TEnv.decode (); MEnv.setCode (element[i]->getMiddleCode (0)); MEnv.decode (); BEnv.setCode (element[i]->getBottomCode (0)); BEnv.decode (); aRule->set (TEnv, MEnv, BEnv, element[i]->getCellToBuild ()); aRule->setRuleClass (element[i]->getRuleClass ()); } } void RuleArray::insert (Rule aRule, unsigned int i) { int j; Rule endRule (simuType); if (i>=nbElements) { printf ("ERROR >> This element does not exist\n"); } else { get (nbElements-1, &endRule); add (endRule); for (j=nbElements-1; j>(int)i; j--) { element[j]->set(*element[j-1]); } set (i, aRule); } } void RuleArray::del (unsigned int i) { unsigned int j; if (i>=nbElements) { printf ("ERROR >> This element does not exist\n"); } else { for (j=i; jset(*element[j+1]); } nbElements--; } } void RuleArray::set (unsigned int i, Rule aRule) { if (i>=nbElements) { printf ("ERROR >> This element does not exist\n"); } else { element[i]->set (aRule); element[i]->setRuleClass (aRule.getRuleClass ()); } } int RuleArray::removeFirstTwiceRule () { unsigned int i, j; for (i=0; iisSamePerRotation (get (j))) { /* on a trouve deux regles pareilles, on vire la deuxieme */ del (j); return 1; } } } return 0; } void RuleArray::removeTwiceRules (double pRedCell, double pYellowCell, RandomGenerationType randomGenerationType) { /* on enleve les regles en double et on regenere autant de regles qu'il le faut pour qu'il y ait autant de regles qu'avant */ /* USELESS int i, j; */ int removedRules; removedRules = 0; while (removeFirstTwiceRule () == 1) { removedRules++; } if (removedRules == 0) { return; } else { randomInsert (removedRules, pRedCell, pYellowCell, randomGenerationType); removeTwiceRules (pRedCell, pYellowCell, randomGenerationType); } } /* Cette methode permet d'ecrire les fichiers sur disque */ int RuleArray::saveInFile (char* aPathName, char* aFileName, double aFitness, char* aName, FileFormat aFileFormat) { FILE *pf; char fname[256]; if (nbElements < 1) { printf ("ERROR >> no rules to save %s\n", fname); return 0; } strcpy (fname, aPathName); strcat (fname, aFileName); pf = fopen(fname,"w"); if (pf == NULL) { printf ("ERROR >> unable to write file %s\n", fname); return 0; } else { fclose (pf); } if (aFileFormat == rulFile) { if (simuType == cubic) { return writeCubicRulData (aPathName, aFileName, aName, aFitness); } else if (simuType == hexa) { return writeHexaRulData (aPathName, aFileName, aName, aFitness); } else { printf ("Error: unknown format\n"); return 2; } } else if (aFileFormat == thrFile) { if (simuType == cubic) { return writeCubicThrData (aPathName, aFileName, aName, aFitness); } else if (simuType == hexa) { return writeHexaThrData (aPathName, aFileName, aName, aFitness); } else { printf ("Error: unknown format\n"); return 2; } } else { printf ("Error: unknown format\n"); return 2; } return 1; } /* Cette methode permet de lire les fichiers stockes sur disque. Bon alors, c'est pas evident parce qu'il y a plein de formats qu'il faut detecter: - les fichiers .rul en cubic - les fichiers .thr en cubic - les fichiers .rul en hexa - les fichiers .thr en hexa Sinon le type de la simulation (cubic ou hexa) est deja connu (voir dans la procedure loadNewFile dans l'interface principale) A noter que les fichiers a lire doivent etre dans un format bien cool, sinon ca chiera irremediablement et la methode renverra le code 2, qui signifie que ce n'est pas le bon format. A bon entendeur.... */ int RuleArray::loadFromFile (char* aPathName, char* aFileName, double* aFitness, char* returnedName) { FILE *pf; int ruleNumber; char fname[70]; char temp[16]; char temp2[256]; char* readFitness; FileFormat fileFormat; int lenght; lenght = strlen (aFileName); if ( (aFileName[lenght-3] == 'r') && (aFileName[lenght-2] == 'u') && (aFileName[lenght-1] == 'l')) { fileFormat = rulFile; /* .rul file detected */ } else if ( (aFileName[lenght-3] == 't') && (aFileName[lenght-2] == 'h') && (aFileName[lenght-1] == 'r')) { fileFormat = thrFile; /* .thr file detected */ } else { return 2; /* wrong format */ } /* on reinitialise les regles */ clear (); ruleNumber = 0; /* on ouvre le fichier */ strcpy (fname, aPathName); strcat (fname, aFileName); pf = fopen(fname,"r"); if (pf == NULL) { //char errorChar[256]; //printf ("System error: errno = %d file [%s]\n", errno, fname); //perror (errorChar); return 0; } else { /* le fichier est ouvert, on commence la lecture */ /* lecture du nom de l'architecture */ fgets (temp2, 256, pf); /* mise a jour du nom */ strcpy (returnedName, temp2); returnedName[strlen (returnedName)-1] = '\0'; /* lecture du type de l'architecture (on le connait deja, mais c'est juste pour le decalage de la lecture du fichier) */ fgets (temp2, 256, pf); /* lecture de la fitness */ fgets (temp2, 256, pf); temp2[255] = '\0'; readFitness = &(temp2[10]); *aFitness = atof (readFitness); /* lecture de la ligne suivante et verification du format associe */ fgets (temp, 15, pf); if (fileFormat == rulFile) { if (strcmp (temp, "#Rule number 1") != 0) { fclose (pf); return 2; } } else if (fileFormat == thrFile) { if (strncmp (temp, "MAXWALL", 7) != 0) { fclose (pf); return 2; } } else { printf ("Error: unknown format\n"); fclose (pf); return 2; } fclose (pf); /* maintenant que l'on a fait toutes les verifications d'usage on peut se permettre d'aller lire le fichier */ /* lecture du fichier .rul */ if (fileFormat == rulFile) { if (simuType == cubic) { return readCubicRulData (aPathName, aFileName); } else if (simuType == hexa) { return readHexaRulData (aPathName, aFileName); } else { printf ("Error: unknown format\n"); return 2; } } /* lecture du fichier .thr */ else if (fileFormat == thrFile) { if (simuType == cubic) { return readCubicThrData (aPathName, aFileName); } else if (simuType == hexa) { return readHexaThrData (aPathName, aFileName); } else { printf ("Error: unknown format\n"); return 2; } } } return 2; } /* Cette petite methode permet de lire les fichiers de type .rul en cubic */ int RuleArray::readCubicRulData (char* aPathName, char* aFileName) { FILE *pf; int i,j,k,ruleNumber; Rule currentRule (simuType); PlanEnvironment currentTop (simuType); PlanEnvironment currentMiddle (simuType); PlanEnvironment currentBottom (simuType); typeOfCell readValue[27]; typeOfCell centerCell; char fname[70]; /* USELESS char temp[16]; */ char temp2[256]; char buf[80],*res; ruleNumber = 0; centerCell = EMPTY; /* needed by g++ -O2 */ strcpy (fname, aPathName); strcat (fname, aFileName); /* pour commencer, on ouvre le fichier. Si ca ne marche pas, on renvoie le code 0 (erreur a l'ouverture du fichier) */ pf = fopen(fname,"r"); if (pf == NULL) { return 0; } else { /* le fichier est ouvert, on commence la lecture */ fgets (temp2, 256, pf); /* lecture du nom de la simulation */ fgets (temp2, 256, pf); /* lecture du type de la simulation */ fgets (temp2, 256, pf); /* lecture de la fitness de la simulation */ while (isspace(fgetc(pf))){ } fseek(pf,-1,SEEK_CUR); while (!feof(pf)) { while (isspace(fgetc(pf))) { } if (!feof(pf)) fseek(pf,-1,SEEK_CUR); res = fgets(buf,80,pf); if ((buf[0] != '#') && !feof(pf)) { if (!feof(pf)) fseek(pf,-1 * strlen(buf),SEEK_CUR); for (i=0;i<3;i++) { for (j=0;j<9;j++) { while (isspace(fgetc(pf))) { } if (!feof(pf)) fseek(pf,-1,SEEK_CUR); k = 0; do { buf[k] = (char)fgetc(pf); k++; } while (isdigit((int)buf[k-1])); buf[k] = '\0'; readValue[j] = (typeOfCell)atoi(buf); } if (i==0) { currentTop.set (readValue[7], readValue[0], readValue[1], readValue[6], readValue[8], readValue[2], readValue[5], readValue[4], readValue[3]); } else if (i==1) { currentMiddle.set (readValue[7], readValue[0], readValue[1], readValue[6], EMPTY, readValue[2], readValue[5], readValue[4], readValue[3]); centerCell = readValue[8]; if (centerCell == EMPTY) centerCell=RED; } else { currentBottom.set (readValue[7], readValue[0], readValue[1], readValue[6], readValue[8], readValue[2], readValue[5], readValue[4], readValue[3]); } } ruleNumber++; currentRule.set (currentTop, currentMiddle, currentBottom, centerCell); add (currentRule); } } fclose(pf); return 1; } } int RuleArray::readCubicThrData (char* aPathName, char* aFileName) { FILE *pf; int i,j,k,ruleNumber; Rule currentRule (simuType); PlanEnvironment currentTop (simuType); PlanEnvironment currentMiddle (simuType); PlanEnvironment currentBottom (simuType); typeOfCell readValue[27]; typeOfCell centerCell; char fname[70]; /* USELESS char temp[16]; */ char temp2[256]; int maxWall; int maxComb; int rv[27]; ruleNumber = 0; centerCell = EMPTY; /* needed by g++ -O2 */ strcpy (fname, aPathName); strcat (fname, aFileName); /* pour commencer, on ouvre le fichier. Si ca ne marche pas, on renvoie le code 0 (erreur a l'ouverture du fichier) */ pf = fopen(fname,"r"); if (pf == NULL) { return 0; } else { /* le fichier est ouvert, on commence la lecture */ fgets (temp2, 256, pf); /* lecture du nom de la simulation */ fgets (temp2, 256, pf); /* lecture du type de la simulation */ fgets (temp2, 256, pf); /* lecture de la fitness de la simulation */ fgets (temp2, 256, pf); /* lecture du parametre MAXWALL */ sscanf (temp2, "MAXWALL %d", &maxWall); fgets (temp2, 256, pf); /* lecture du parametre MAXCOMB */ sscanf (temp2, "MAXCOMB %d", &maxComb); /* lecture des regles */ int r; int toRead; for (k=0; k<2; k++) { if (k==0) { toRead = maxWall; } else { toRead = maxComb; } fgets (temp2, 256, pf); /* lecture saut de ligne */ fgets (temp2, 256, pf); /* lecture BEGIN */ for (i=0; i> unable to write file %s\n", fname); return 0; } else { /* sauvegarde du nom */ fprintf (pf, "%s\n", aName); /* sauvegarde du type de la simulation */ fprintf (pf, "type = cubic\n"); /* sauvegarde de la fitness */ fprintf (pf, "fitness = %f\n", aFitness); for (k=0;k<(int)nbElements;k++) { get (k, ¤tRule); currentTop.setCode (currentRule.getTopCode (0)); currentMiddle.setCode (currentRule.getMiddleCode (0)); currentBottom.setCode (currentRule.getBottomCode (0)); currentMiddle.setCenter (currentRule.getCellToBuild ()); fprintf(pf,"#Rule number %i :\n",k+1); for (i=0;i<3;i++) { if (i==0) { toBeWritten = currentTop; } else if (i==1) { toBeWritten = currentMiddle; } else { toBeWritten = currentBottom; } buf[0]='\0'; sprintf (buf, "%s %i", buf, toBeWritten.get(1,0)); sprintf (buf, "%s %i", buf, toBeWritten.get(2,0)); sprintf (buf, "%s %i", buf, toBeWritten.get(2,1)); sprintf (buf, "%s %i", buf, toBeWritten.get(2,2)); sprintf (buf, "%s %i", buf, toBeWritten.get(1,2)); sprintf (buf, "%s %i", buf, toBeWritten.get(0,2)); sprintf (buf, "%s %i", buf, toBeWritten.get(0,1)); sprintf (buf, "%s %i", buf, toBeWritten.get(0,0)); sprintf (buf, "%s %i", buf, toBeWritten.get(1,1)); fprintf(pf,"%s\n",buf); } } fclose(pf); return 1; } } int RuleArray::writeCubicThrData (char* aPathName, char* aFileName, char* aName, double aFitness) { FILE *pf; /* USELESS char buf[20]; */ int k; /* USELESS int i,j; */ Rule currentRule (simuType); PlanEnvironment currentTop (simuType); PlanEnvironment currentMiddle (simuType); PlanEnvironment currentBottom (simuType); PlanEnvironment toBeWritten (simuType); char fname[70]; int maxWall; int maxComb; int ruleNb; strcpy (fname, aPathName); strcat (fname, aFileName); pf = fopen(fname,"w"); if (pf == NULL) { printf ("ERROR >> unable to write file %s\n", fname); return 0; } else { /* sauvegarde du nom */ fprintf (pf, "%s\n", aName); /* sauvegarde du type de la simulation */ fprintf (pf, "type = cubic\n"); /* sauvegarde de la fitness */ fprintf (pf, "fitness = %f\n", aFitness); /* on calcule les maxWall et maxComb - maxWall: regles construisant une cellule rouge - maxComb: regles construisant une cellule jaune ou bleue */ maxWall = 0; maxComb = 0; for (k=0; k<(int)nbElements; k++) { get (k, ¤tRule); if (currentRule.getCellToBuild () == RED) { maxWall++; } else { maxComb++; } } fprintf (pf, "MAXWALL %d\n", maxWall); fprintf (pf, "MAXCOMB %d\n", maxComb); /* on s'occupe de MAXWALL */ ruleNb = 0; fprintf (pf, "\nWALL_BEGIN\n"); for (k=0; k> unable to write file %s\n", fname); return 0; } else { /* sauvegarde du nom */ fprintf (pf, "%s\n", aName); /* sauvegarde du type de la simulation */ fprintf (pf, "type = hexa\n"); /* sauvegarde de la fitness */ fprintf (pf, "fitness = %f\n", aFitness); for (k=0;k<(int)nbElements;k++) { get (k, ¤tRule); currentTop.setCode (currentRule.getTopCode (0)); currentMiddle.setCode (currentRule.getMiddleCode (0)); currentBottom.setCode (currentRule.getBottomCode (0)); currentMiddle.setCenter (currentRule.getCellToBuild ()); fprintf(pf,"#Rule number %i :\n",k+1); for (i=0;i<3;i++) { if (i==0) { toBeWritten = currentTop; } else if (i==1) { toBeWritten = currentMiddle; } else { toBeWritten = currentBottom; } buf[0]='\0'; sprintf (buf, "%s %i", buf, toBeWritten.get(0)); sprintf (buf, "%s %i", buf, toBeWritten.get(1)); sprintf (buf, "%s %i", buf, toBeWritten.get(2)); sprintf (buf, "%s %i", buf, toBeWritten.get(3)); sprintf (buf, "%s %i", buf, toBeWritten.get(4)); sprintf (buf, "%s %i", buf, toBeWritten.get(5)); sprintf (buf, "%s %i", buf, toBeWritten.get(6)); fprintf(pf,"%s\n",buf); } } fclose(pf); return 1; } } int RuleArray::writeHexaThrData (char* aPathName, char* aFileName, char* aName, double aFitness) { if (aPathName == aFileName || aName == aPathName || aFitness == 0) {} /* avoid warnings about unused parameters */ printf ("ERROR: not implemented\n"); return 0; } void RuleArray::setFromOtherRuleArray (RuleArray* aRuleArray) { int i; Rule aRule (simuType); clear (); for (i=0; i<(int)aRuleArray->getElementsNb (); i++) { aRuleArray->get (i, &aRule); add (aRule); } } void RuleArray::randomGenerate (double pRedCell, double pYellowCell, double average, double variance, RandomGenerationType randomGenerationType) { RandomGenerator randomGenerator1 (GAUSS, 2, 80, average, variance); int i; clear (); nbElements = randomGenerator1.getNumber (); for (i=1; i<(int)nbElements; i++) { element[i]->randomGenerate (pRedCell, pYellowCell, randomGenerationType); } element[0]->firstRuleRandomGenerate (); removeTwiceRules (pRedCell, pYellowCell, randomGenerationType); } void RuleArray::randomInsert (int insertedRulesNumber, double pRedCell, double pYellowCell, RandomGenerationType randomGenerationType) { unsigned int i; for (i=nbElements; irandomGenerate (pRedCell, pYellowCell, randomGenerationType); } } /* ---------------------------------------------------- */ Position::Position (int aSize) { size = aSize; } void Position::randomPosition (int minX, int maxX, int minY, int maxY, int minZ, int maxZ) { x = rand()%(maxX-minX+1)+minX; y = rand()%(maxY-minY+1)+minY; z = rand()%(maxZ-minZ+1)+minZ; //printf ("x entre %d et %d: %d\n", minX, maxX, x); //printf ("y entre %d et %d: %d\n", minY, maxY, y); //printf ("z entre %d et %d: %d\n", minZ, maxZ, z); //x = rand()%size; //y = rand()%size; //z = rand()%size; } /* ---------------------------------------------------- */ RandomGenerator::RandomGenerator (RandomModeType aRandomMode, int aMin, int aMax) { if (aRandomMode != PSEUDO) { printf ("ERROR: type mismatch in Random Generator\n"); } else { randomMode = PSEUDO; min = aMin; max = aMax; initGenerator (); } } RandomGenerator::RandomGenerator (RandomModeType aRandomMode, int aMin, int aMax, double anAverage, double aVariance) { if (aRandomMode != GAUSS) { printf ("ERROR: type mismatch in Random Generator\n"); } else { randomMode = GAUSS; min = aMin; max = aMax; average = anAverage; variance = aVariance; initGenerator (); } } RandomGenerator::RandomGenerator (RandomModeType aRandomMode, double ap1, double ap2, double ap3, int aMin, int aMax) { if (aRandomMode != TRIVAL) { printf ("ERROR: type mismatch in Random Generator\n"); } else { randomMode = TRIVAL; min = aMin; max = aMax; p1 = ap1; p2 = ap2; p3 = ap3; initGenerator (); } } RandomGenerator::~RandomGenerator () { } int RandomGenerator::getNumber () { int currentChoice; int end; int proba; int randomTry; proba = 0; /* needed by g++ -O2 */ if (randomMode == PSEUDO) { return rand()%(max-min+1)+min; } else if (randomMode == GAUSS) { end = 0; while (!end) { currentChoice = rand()%(max-min+1)+min; randomTry = rand()%(1000); proba = (int)(1000/sqrt (2*M_PI*variance)*exp ((-0.5)*((currentChoice-average)/variance*(currentChoice-average)/variance))); if (randomTry <= proba) { end = 1; } } return currentChoice; } else if (randomMode == TRIVAL) { end = 0; while (!end) { currentChoice = rand()%(max-min+1)+min; randomTry = rand()%(1000); if (currentChoice == 0) { proba = (int)(p1*1000); } else if (currentChoice == 1) { proba = (int)(p2*1000); } else if (currentChoice == 2) { proba = (int)(p3*1000); } if (randomTry <= proba) { end = 1; } } return currentChoice; } return -1; } void RandomGenerator::initGenerator () { }