Commits

Jay Barra committed 2fe9dc4

PSO finished and tuned, using speed limiters to allow for convergence

  • Participants
  • Parent commits 6c9dcb4

Comments (0)

Files changed (2)

 #define MESSAGE_TAG 1000
 #define WORK_TAG    1001
 //---------------------------------------------------------------------------
-#define SWARM_WEIGHT 1.5f
-#define SELF_WEIGHT .5f
-#define GENERATIONS 16 
+#define SWARM_WEIGHT 2.5f
+#define SELF_WEIGHT 1.5f
+#define GENERATIONS 32 
+
+#define XMIN 0.0f
+#define XMAX 4.0f
+
+#define YMIN -2.0f
+#define YMAX 3.0f
+
+#define VEL_MAX 0.1f
+#define VEL_MIN -0.1f
 //---------------------------------------------------------------------------
 struct Position {
     float x;
 
 typedef struct Particle {
     struct Position current_pos;
+    struct Position velocity;
+
     float current_fitness;
     
     struct Position best_pos;
 } MPI_PARTICLE;
 //---------------------------------------------------------------------------
 // Algorithm Functions
-float fitness(struct Particle& f);
+float fitness(struct Particle& f, bool bSetBest = false);
+float randFloat(float max, float min);
+void  printParticle(struct Particle p);
 //---------------------------------------------------------------------------
 // MPI Functions
 void getStatus(MPI_Status status, char* pcStatus);
 //---------------------------------------------------------------------------
 main (int argc, char** argv)
 {
-  srand(time(NULL));
-
-  MPI_Init(&argc, &argv);
-	
   int iNameLen;
-  int iNodes;
+  int iSwarmSize;
+
+  Particle particle;
   int id;
   
-  MPI_Status status;
- 
   char* pcName    = (char*)malloc(1024);
   char* pcMessage = (char*)malloc(1024);
   char* pcStatus  = (char*)malloc(1024);
-
-  struct Particle vSwarm[8]; 
   
+  MPI_Init(&argc, &argv);
+  MPI_Status status;
+ 
+  srand(time(NULL));
+
   MPI_Comm_rank(MPI_COMM_WORLD, &id);
-  MPI_Comm_size(MPI_COMM_WORLD, &iNodes);
+  MPI_Comm_size(MPI_COMM_WORLD, &iSwarmSize);
   MPI_Get_processor_name(pcName, &iNameLen);
   
   bool bRoot = (id == ROOT);
-  vSwarm[id].current_pos.x = ((float)(rand() % 1000) / 1000.0);
-  vSwarm[id].current_pos.y = ((float)(rand() % 1000) / 1000.0);
-
-  fitness(vSwarm[id]);
-  vSwarm[id].best_fitness = vSwarm[id].current_fitness;
-  vSwarm[id].best_pos.x = vSwarm[id].current_pos.x;
-  vSwarm[id].best_pos.y = vSwarm[id].current_pos.y;
-
+  particle.current_pos.x = randFloat(0, 4.0); 
+  particle.velocity.x   = randFloat(0.0, 0.5); 
+  particle.current_pos.y = randFloat(0, 4.0); 
+  particle.velocity.y   = randFloat(0.0, 0.5); 
+  
+  if (particle.current_pos.x > XMAX) particle.current_pos.x = XMAX;
+  if (particle.current_pos.x < XMIN) particle.current_pos.x = XMIN;
+  if (particle.current_pos.y > YMAX) particle.current_pos.y= YMAX;
+  if (particle.current_pos.y < YMIN) particle.current_pos.y= YMIN;
+ 
+  fitness(particle, true);
+  
   if (!bRoot) {
     sprintf(pcMessage, "%i, %s", id, pcName);
     MPI_Send(pcMessage, strlen(pcMessage)+1, MPI_CHAR, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
     printf("*********************************************************\n");
     printf("Root Node: %s\n", pcName);
     printf("Awaiting worker node responses...\n");
-    for (int iSource = 1; iSource < iNodes; iSource++) {
+    for (int iSource = 1; iSource < iSwarmSize; iSource++) {
       MPI_Recv(pcMessage, 1024, MPI_CHAR, iSource, MESSAGE_TAG, MPI_COMM_WORLD, &status);
       getStatus(status, pcStatus);
       printf("AgentNode: %s\t| Status: %s\n", pcMessage, pcStatus);
     }
     printf("Node initialization complete...\n");
-    printf("%i Nodes Registered for work...\n", iNodes);
+    printf("%i Nodes Registered for work...\n", iSwarmSize);
     printf("*********************************************************\n");
   }
 
   int iSwarmBest = 0;
+  Particle pSwarmBest;
   
-  for (int iParticle = 1; iParticle < iNodes; iParticle++) {
-    if (vSwarm[iParticle].current_fitness > vSwarm[iSwarmBest].current_fitness) {
-      iSwarmBest = iParticle;
-    }
-  }
   if (bRoot) {
-    MPI_Bcast(&vSwarm[id].current_fitness, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
-    MPI_Bcast(&iSwarmBest, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
-  }
-  
+    pSwarmBest.best_fitness = particle.current_fitness;
+    pSwarmBest.best_pos.x   = particle.current_pos.x;
+    pSwarmBest.best_pos.y   = particle.current_pos.y;
+    
+    Particle tmpParticle;
+    for (int iParticle = 1; iParticle < iSwarmSize; iParticle++) {
+      MPI_Recv(&tmpParticle.current_fitness, 1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+      MPI_Recv(&tmpParticle.current_pos.x,   1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+      MPI_Recv(&tmpParticle.current_pos.y,   1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+      if (tmpParticle.current_fitness > pSwarmBest.best_fitness) {
+        iSwarmBest              = iParticle;
+        pSwarmBest.best_fitness = tmpParticle.current_fitness;
+        pSwarmBest.best_pos.x   = tmpParticle.current_pos.x;
+        pSwarmBest.best_pos.y   = tmpParticle.current_pos.y;
+      }
+    }
+    printParticle(pSwarmBest);
+  } else {
+    MPI_Send(&particle.current_fitness, 1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+    MPI_Send(&particle.current_pos.x,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+    MPI_Send(&particle.current_pos.y,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+  }  
+
+  MPI_Bcast(&pSwarmBest.best_fitness, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
+  MPI_Bcast(&pSwarmBest.best_pos.x,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
+  MPI_Bcast(&pSwarmBest.best_pos.y,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
+
   MPI_Barrier(MPI_COMM_WORLD);
 
   for (int iGeneration = 0; iGeneration < GENERATIONS; iGeneration++) {
-  if (bRoot) {
-    printf("Generation %i\n", iGeneration);
-  }
-   // Compare fitnesses
-    for (int iParticle = 0; iParticle < iNodes; iParticle++) {
-      vSwarm[id].current_pos.x = vSwarm[id].current_pos.x + 
-                                 SELF_WEIGHT  * (vSwarm[id].best_pos.x - vSwarm[id].best_pos.x) * (((rand() % 1000) / 1000.0) - 0.5) + 
-                                 SWARM_WEIGHT * (vSwarm[iSwarmBest].best_pos.x - vSwarm[iSwarmBest].best_pos.y) * (((rand() % 1000) / 1000.0) - 0.5);
-
-      vSwarm[id].current_pos.x = vSwarm[id].current_pos.y +
-                                 SELF_WEIGHT  * (vSwarm[id].current_pos.y  - vSwarm[id].best_pos.y) * (((rand() % 1000) / 1000.0) - 0.5) + 
-                                 SWARM_WEIGHT * (vSwarm[id].current_pos.y - vSwarm[iSwarmBest].best_pos.y) * (((rand() % 1000) / 1000.0) - 0.5);
+    if (bRoot) {
+      printf("Generation-> %i\n", iGeneration);
     }
-    fitness(vSwarm[id]);
+   
+    float fSwarmRand = randFloat(0, 1); 
+    float fSelfRand  = randFloat(0, 1);
+    float fNewVel;
+    fNewVel = particle.velocity.x + 
+              SELF_WEIGHT  * (particle.best_pos.x - particle.current_pos.x)  * fSelfRand + 
+              SWARM_WEIGHT * (pSwarmBest.best_pos.x - particle.current_pos.x) * fSwarmRand;
+
+    if (fNewVel > VEL_MAX) fNewVel = VEL_MAX;
+    if (fNewVel < VEL_MIN) fNewVel = VEL_MIN;
+    particle.current_pos.x += fNewVel;
+    particle.velocity.x = fNewVel;
+
+    if (particle.current_pos.x > XMAX) particle.current_pos.x = XMAX;
+    if (particle.current_pos.x < XMIN) particle.current_pos.x = XMIN;
+    if (particle.current_pos.y > YMAX) particle.current_pos.y = YMAX;
+    if (particle.current_pos.y < YMIN) particle.current_pos.y = YMIN;
+
+    fitness(particle);
+    printParticle(particle);
 
     if (bRoot) {
-      for (int i = 1; i < iNodes; i++) {
-        MPI_Recv(&vSwarm[i].current_pos.x,   1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
-        MPI_Recv(&vSwarm[i].current_pos.y,   1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
-        MPI_Recv(&vSwarm[i].current_fitness, 1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+      Particle tmpParticle;
+      for (int iParticle = 1; iParticle < iSwarmSize; iParticle++) {
+        MPI_Recv(&tmpParticle.current_fitness, 1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+        MPI_Recv(&tmpParticle.current_pos.x,   1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+        MPI_Recv(&tmpParticle.current_pos.y,   1, MPI_FLOAT, iParticle, MESSAGE_TAG, MPI_COMM_WORLD, &status);
+      
+        if (tmpParticle.current_fitness > pSwarmBest.best_fitness) {
+          iSwarmBest              = iParticle;
+          pSwarmBest.best_fitness = tmpParticle.current_fitness; 
+          pSwarmBest.best_pos.x   = tmpParticle.current_pos.x;
+          pSwarmBest.best_pos.y   = tmpParticle.current_pos.y;
+        }
       }
     } else {
-      MPI_Send(&vSwarm[id].current_pos.x,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
-      MPI_Send(&vSwarm[id].current_pos.y,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
-      MPI_Send(&vSwarm[id].current_fitness, 1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
-    }
+      MPI_Send(&particle.current_fitness, 1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+      MPI_Send(&particle.current_pos.x,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+      MPI_Send(&particle.current_pos.y,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
+    } 
+    
+    MPI_Bcast(&pSwarmBest.best_fitness, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
+    MPI_Bcast(&pSwarmBest.best_pos.x,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
+    MPI_Bcast(&pSwarmBest.best_pos.y,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
     if (bRoot) {
-      iSwarmBest = 0; 
-      for (int i = 1; i < iNodes; i++) {
-        if (vSwarm[i].best_fitness > vSwarm[iSwarmBest].best_fitness) {
-          iSwarmBest = i;
-        } 
-      }
+      printf("SwarmBest: ");
+      printParticle(pSwarmBest);
     }
-    MPI_Bcast(&iSwarmBest, 1, MPI_INT, ROOT, MPI_COMM_WORLD);
   }
 
-  // Find the best of the swarm
-  for (int iParticle = 1; iParticle < iNodes; iParticle++) {
-    if (vSwarm[iParticle].best_fitness > vSwarm[iSwarmBest].best_fitness) {
-      iSwarmBest = iParticle;
-    }
-  }
   if (bRoot) {
-    printf("And the winner is: %i (%f, %f) -> %f\n", iSwarmBest, vSwarm[iSwarmBest].best_pos.x, vSwarm[iSwarmBest].best_pos.y, vSwarm[iSwarmBest].best_fitness); }
+    printf("And the winner is: (%f, %f) -> %f\n",  pSwarmBest.best_pos.x, pSwarmBest.best_pos.y, pSwarmBest.best_fitness);
+  }
  
   MPI_Finalize();
   
   return 0; 
 }
 //-------------------------------------------------
-float fitness(struct Particle& f)
+float randFloat(float a, float b)
+{
+  float random = ((float) rand()) / (float) RAND_MAX;
+  float diff = b - a;
+  float r = random * diff;
+  return a + r; 
+}
+//-------------------------------------------------
+float fitness(struct Particle& f, bool bSetBest)
 {
-/*
- *(x^3-3*x + y^3-3*y)
- */
-    //f.current_fitness = pow(f.current_pos.x, 3) - (3 * f.current_pos.x) + //                   pow(f.current_pos.y, 3) - (3 * f.current_pos.y);
-    f.current_fitness = sin(sqrt(pow(f.current_pos.x, 2) + pow(f.current_pos.y, 2)));
-    if (f.current_fitness > f.best_fitness) {
-        f.best_fitness = f.current_fitness;
-        f.best_pos     = f.current_pos;
+    f.current_fitness =  -1 * pow(f.current_pos.x - 0.5, 3) + f.current_pos.x;
+    
+    if (f.current_fitness > f.best_fitness || bSetBest == true) {
+      f.best_fitness = f.current_fitness;
+      f.best_pos.x   = f.current_pos.x;
+      f.best_pos.y   = f.current_pos.y;
     }
-
     return f.current_fitness;
 }
 //-------------------------------------------------
+void printParticle(struct Particle p)
+{
+  printf("(%f @ %f) -> %f  best: (%f) -> %f\n", p.current_pos.x, p.velocity.x, p.current_fitness, p.best_pos.x, p.best_fitness);
+}
+//-------------------------------------------------
 void getStatus(MPI_Status status, char* pcStatus)
 {
 switch (status.MPI_ERROR) {
 #!/usr/local/bin/tcsh
 clear
-mpirun -np 8 ~/cs523/Firefly/mpi -machinefile cluster.hosts
+mpirun -np 8 ~/cs523/PSO/mpi -machinefile cluster.hosts