Source

CS523 / Firefly / main.cpp

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <mpi.h>
//---------------------------------------------------------------------------
#define ROOT 0

#define MESSAGE_TAG 1000
#define WORK_TAG    1001
//---------------------------------------------------------------------------
#define GAMMA 0.2
#define GENERATIONS 16 
//---------------------------------------------------------------------------
struct Position {
    float x;
    float y;
};

typedef struct Firefly {
    float percieved_brightness;

    struct Position current_pos;
    float current_fitness;

    struct Position best_pos;
    float best_fitness;
} MPI_FIREFLY;
//---------------------------------------------------------------------------
// Algorithm Functions
float fitness(struct Firefly& f);
float randFloat(float a, float b);
//---------------------------------------------------------------------------
// MPI Functions
void getStatus(MPI_Status status, char* pcStatus);
//---------------------------------------------------------------------------
main (int argc, char** argv)
{

  MPI_Init(&argc, &argv);
  srand(time(NULL));
	
  int iNameLen;
  int iNodes;
  int id;
  
  MPI_Status status;
 
  char* pcName    = (char*)malloc(1024);
  char* pcMessage = (char*)malloc(1024);
  char* pcStatus  = (char*)malloc(1024);

  struct Firefly vFireflies[8]; 
  
  MPI_Comm_rank(MPI_COMM_WORLD, &id);
  MPI_Comm_size(MPI_COMM_WORLD, &iNodes);
  MPI_Get_processor_name(pcName, &iNameLen);
  
  bool bRoot = (id == ROOT);
  vFireflies[id].current_pos.x = randFloat(0.0, 4.0);
  vFireflies[id].current_pos.y = randFloat(0.0, 4.0);
 
  fitness(vFireflies[id]);
  vFireflies[id].best_fitness = vFireflies[id].current_fitness;
  vFireflies[id].best_pos.x = vFireflies[id].current_pos.x;
  vFireflies[id].best_pos.y = vFireflies[id].current_pos.y;

  if (!bRoot) {
    sprintf(pcMessage, "%i, %s", id, pcName);
    MPI_Send(pcMessage, strlen(pcMessage)+1, MPI_CHAR, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
  } else {
    printf("Initializing Nodes\n");
    printf("*********************************************************\n");
    printf("Root Node: %s\n", pcName);
    printf("Awaiting worker node responses...\n");
    for (int iSource = 1; iSource < iNodes; 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("*********************************************************\n");
  }

  if (!bRoot) {
    MPI_Send(&vFireflies[id].current_pos.x, 1, MPI_FLOAT , ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
    MPI_Send(&vFireflies[id].current_pos.y, 1, MPI_FLOAT , ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
    MPI_Send(&vFireflies[id].current_fitness, 1, MPI_FLOAT , ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
  } else {
    for (int iSource = 1; iSource < iNodes; iSource++) {
      MPI_Recv(&vFireflies[iSource].current_pos.x,   1, MPI_FLOAT, iSource, MESSAGE_TAG, MPI_COMM_WORLD, &status);
      MPI_Recv(&vFireflies[iSource].current_pos.y,   1, MPI_FLOAT, iSource, MESSAGE_TAG, MPI_COMM_WORLD, &status);
      MPI_Recv(&vFireflies[iSource].current_fitness, 1, MPI_FLOAT, iSource, MESSAGE_TAG, MPI_COMM_WORLD, &status);
    }
  }

  MPI_Bcast(&vFireflies[id].current_pos.x,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
  MPI_Bcast(&vFireflies[id].current_pos.y,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
  MPI_Bcast(&vFireflies[id].current_fitness, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);

  if (bRoot) {
    printf("\n");
    for (int iFirefly = 0; iFirefly < iNodes; iFirefly++) {
      printf("%i: (%f, %f) -> %f\n", iFirefly, vFireflies[iFirefly].current_pos.x, vFireflies[iFirefly].current_pos.y, vFireflies[iFirefly].current_fitness);
   }
  } 

  MPI_Barrier(MPI_COMM_WORLD);
  float beta;

  for (int iGeneration = 0; iGeneration < GENERATIONS; iGeneration++) {
  if (bRoot) {
    printf("Generation %i\n", iGeneration);
  }

   // Compare fitnesses
    for (int iFirefly = 0; iFirefly < iNodes; iFirefly++) {
      if (iFirefly == id) continue;
      float dx = vFireflies[id].current_pos.x - vFireflies[iFirefly].current_pos.x;
      float dy = vFireflies[id].current_pos.y - vFireflies[iFirefly].current_pos.y;
      float dist = sqrt((dx * dx) + (dy * dy));
      vFireflies[iFirefly].percieved_brightness = vFireflies[iFirefly].current_fitness * exp(-GAMMA * dist);

      if (vFireflies[iFirefly].percieved_brightness > vFireflies[id].current_fitness) {
        beta = 1;
      } else {
        beta = 0;
      }
      
      vFireflies[id].current_pos.x += beta * exp(-1 * GAMMA * dx * dx) + 0.1 * randFloat(0.0, 1.0);
      vFireflies[id].current_pos.y += beta * exp(-1 * GAMMA * dy * dy) + 0.1 * randFloat(0.0, 1.0);
      if (bRoot) {
        printf("calc:%f dx: %f  dy:%f  dist:%f  newx:%f  newy:%f\n", beta * exp(-1 * GAMMA * dx * dx), dx, dy, dist, vFireflies[id].current_pos.x, vFireflies[id].current_pos.y);
      }

      fitness(vFireflies[id]);
    
    }
    for (int i = 1; i < iNodes; i++) {
      if (bRoot) {
        MPI_Recv(&vFireflies[i].current_pos.x,   1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
        MPI_Recv(&vFireflies[i].current_pos.y,   1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
        MPI_Recv(&vFireflies[i].current_fitness, 1, MPI_FLOAT, i, MESSAGE_TAG, MPI_COMM_WORLD, &status);
      } else {
        if (i != id) continue;
        MPI_Send(&vFireflies[id].current_pos.x,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
        MPI_Send(&vFireflies[id].current_pos.y,   1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
        MPI_Send(&vFireflies[id].current_fitness, 1, MPI_FLOAT, ROOT, MESSAGE_TAG, MPI_COMM_WORLD);
      }
 
      for(int i = 0; i < iNodes; i++) {
        MPI_Bcast(&vFireflies[i].current_pos.x,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
        MPI_Bcast(&vFireflies[i].current_pos.y,   1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
        MPI_Bcast(&vFireflies[i].current_fitness, 1, MPI_FLOAT, ROOT, MPI_COMM_WORLD);
      }
      if (bRoot) { printf("\n"); }
      

    }
  //MPI_Barrier(MPI_COMM_WORLD); 
  }

  // Find the best of the swarm
  int iBest = 0;
  for (int i = 1; i < iNodes; i++) {
    if (vFireflies[i].best_fitness > vFireflies[iBest].best_fitness) {
      iBest = i;
    }
  }
  if (bRoot) {
    printf("And the winner is: %i (%f, %f) -> %f\n", iBest, vFireflies[iBest].best_pos.x, vFireflies[iBest].best_pos.y, vFireflies[iBest].best_fitness); }
 
  MPI_Finalize();
  
  return 0; 
}
//-------------------------------------------------
float fitness(struct Firefly& f)
{
    f.current_fitness =  -1 * pow(f.current_pos.x - .5, 2) + 4 * f.current_pos.x;
    if (f.current_fitness > f.best_fitness) {
        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;
}
//-------------------------------------------------
float randFloat(float a, float b)
{
  float random = ((float) rand()) / (float) RAND_MAX;
  float diff = b - a;
  float r = random * diff;
  return a + r;
}
//-------------------------------------------------
void getStatus(MPI_Status status, char* pcStatus)
{
switch (status.MPI_ERROR) {
	case MPI_SUCCESS:
		sprintf(pcStatus, "Success");
		break;
	case MPI_ERR_BUFFER:
		sprintf(pcStatus, "Buffer Error");
		break;
	case MPI_ERR_COUNT:
		sprintf(pcStatus, "Count Error");
		break;
	case MPI_ERR_TYPE:
		sprintf(pcStatus, "Type Error");
		break;
	case MPI_ERR_TAG:
		sprintf(pcStatus, "Tag Error");
		break;
	case MPI_ERR_COMM:
		sprintf(pcStatus, "COMM Error");
		break;
	case MPI_ERR_RANK:
		sprintf(pcStatus, "Rank Error");
		break;
	case MPI_ERR_REQUEST:
		sprintf(pcStatus, "Request Error");
		break;
	case MPI_ERR_ROOT:
		sprintf(pcStatus, "Root Error");
		break;
	case MPI_ERR_GROUP:
		sprintf(pcStatus, "Group Error");
		break;	
	case MPI_ERR_OP:
		sprintf(pcStatus, "OP Error");
		break;
	case MPI_ERR_TOPOLOGY:
		sprintf(pcStatus, "Topology Error");
		break;
	case MPI_ERR_DIMS:
		sprintf(pcStatus, "DIMS Error");
		break;
	case MPI_ERR_ARG:
		sprintf(pcStatus, "Args Error");
		break;
	case MPI_ERR_UNKNOWN:
		sprintf(pcStatus, "Unknown Error");
		break;
	case MPI_ERR_TRUNCATE:
		sprintf(pcStatus, "Truncate Error");
		break;	
	case MPI_ERR_OTHER:
		sprintf(pcStatus, "Other Error");
		break;	
	case MPI_ERR_INTERN:
		sprintf(pcStatus, "Internal Error");
		break;
	case MPI_ERR_IN_STATUS:
		sprintf(pcStatus, "In Status Error");
		break;
	case MPI_ERR_PENDING:
		sprintf(pcStatus, "Pending Error");
		break;
	default:
		sprintf(pcStatus, "Unknown Error");
  }
}
//------------------------------------------------
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.