遗传算法 - 修改GAlib C ++库中的个体

时间:2014-10-24 09:49:58

标签: c++ algorithm openmpi

我正在尝试使用用C ++编写的MIT库GAlib在OpenMPI中运行一个非常简单的并行遗传算法。目前,我只是在每个核心上运行稳态遗传算法。但是,我还想在核心之间交换信息,即一些迁移的个体。我基本上试图在库外复制一个更简单的GADemeGA。尽管如此,虽然MPI发送/接收功能可以正常工作,但我无法用新的功能替换人口中的个人。所以我的问题是,是否有一种简单的方法可以简单地用不同的人替换一个人。我试图使用GAPopulation.C中的“替换”函数(在GAlib中),但在编译程序时遇到以下错误:

styblinski_tang_PA.cpp:208: error: no matching function for call to ‘GAPopulation::replace(GARealGenome&, GARealGenome&) const’
../../galib247/ga/GAPopulation.h:172: note: candidates are: GAGenome* GAPopulation::replace(GAGenome*, int, GAPopulation::SortBasis)
../../galib247/ga/GAPopulation.h:173: note:                 GAGenome* GAPopulation::replace(GAGenome*, GAGenome*)

通过创建整个群体的本地副本,修改它(实际上只是迁移的个体)然后将其输入遗传算法,解决了这个问题。

我现在将包含简单的makefile和代码。提前感谢您的帮助!

生成文件:

LIB   =libga.a

MKDEPEND    = makedepend
RM          = rm -rf

CXX         = mpic++
CXXFLAGS    = -g -Wall
LD          = mpic++ -w
AR          = ar rv


# Set these paths to the location of the GA library and headers.
GA_INC_DIR= ../../galib247
GA_LIB_DIR= ../../galib247/ga

INC_DIRS= -I$(GA_INC_DIR)
LIB_DIRS= -L$(GA_LIB_DIR)

EXS= styblinski_tang_PA

.SUFFIXES: .cpp    
.cpp.o:
    $(CXX) $(CXXFLAGS) $(INC_DIRS) -lm -c $<

all: $(EXS)



# Use this for gnu make
$(EXS): %: %.o
    $(CXX) $@.o -o $@ $(LIB_DIRS) -lga -lm 

clean:
    $(RM) $(EXS)
    $(RM) *.o *~ *.bak *.pixie core
    $(RM) *.dat
    $(RM) ../common_files/best_individual?.dat
    $(RM) *.out *.exe vc* *.pdb

计划:styblinski_tangPA.cpp:

#include <string>
#include <sstream>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <ga/std_stream.h>
#include <ga/GASStateGA.h>
#include <mpi.h>                   // Necessary for running the code in parallel

#define INSTANTIATE_REAL_GENOME
#include <ga/GARealGenome.h>

using namespace std;

#define MIN_VALUE -5
#define MAX_VALUE 5
#define INC       0.01
#define DIM       4      // Dimensions of search space


float Objective(GAGenome& );    // Declaration of the objective function.
                // The definition comes later in the file.

int main(int argc, char **argv){

  // Initialize the MPI environment
  MPI_Init(&argc, &argv);

  // Get the number of processes
  int mpi_tasks;
  MPI_Comm_size(MPI_COMM_WORLD, &mpi_tasks);

  // Get the rank of the process
  int mpi_rank;
  string rank;
  ostringstream convert;
  MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
  convert << mpi_rank;
  rank = convert.str();

  // Get the name of the processor
  char processor_name[MPI_MAX_PROCESSOR_NAME];
  int name_len;
  MPI_Get_processor_name(processor_name, &name_len);        


  // Termination parameters:
  int ngen = 200;         // Total number of generations for termination 
  int popsize = 10;      // Generation size
  //int npop = 8;           // Number of populations
  int nmigr = 5;          // Number of migrating individuals
  //int ncon = 40;          // no. generations the code looks back for
                           // convergence for
  //int pcon = 1.0e-02;     // Threshold value for convergence 

  ofstream outfile;             // Initialising the output stream
  ofstream imm;                 // Initialising the output stream for immigrants


  // At the moment, the master node is not used other than for communications
  if (mpi_rank !=0) {

    // Calculating the population size for each core:
    // popsize = popsize/ (mpi_tasks-1);      //note that it will remain an integer
    // In fact, as each population is run on a separate core, popsize is the 
    // size of each population.

    // Setting real alleles (bounds) type:
    GARealAlleleSet alleles(MIN_VALUE,MAX_VALUE); //Continuous, bounded variables
    //GARealAlleleSet alleles(MIN_VALUE,MAX_VALUE); //Discrete, bounded variables
    /* NB: The set of discrete alleles in fact increases in size because of the 
       mutator and crossover types used with real variables - bug! */

    // Creating a genome of real numbers (1D array):
    GARealGenome genome(DIM, alleles, Objective);
    /* Description: GARealGenome( int length of array, float alleles (bounds, 
       either continuous or discrete), float objective function) */
    GAPopulation swappop(genome,popsize);

    // Setting the type of mutator:
    genome.mutator(GARealGaussianMutator);
    //genome.mutator(GARealUniformMutator);
    //genome.mutator(GARealSwapMutator);

    // Creating the genetic algorithm and setting its parameters:
    GASteadyStateGA ga(genome);    // Steady state genetic algorithm

    // Setting the terminator conditions: either due to convergence or by no.
    // generations (default):
    //ga.terminator(GAGeneticAlgorithm::TerminateUponGeneration);    //default
    //ga.terminator(GAGeneticAlgorithm::TerminateUponConvergence);   //alternative
    //ga.terminator(GAGeneticAlgorithm::TerminateUponPopConvergence);

    ga.minimize();            // Minimization problem
    ga.populationSize(popsize);
    ga.nGenerations(ngen);    // When TerminateUponGeneration 
    //ga.nConvergence(ncon);    // When TerminateUponConvergence or
    //ga.pConvergence(pcon);    // TerminateUponPopConvergence

    // Setting the type of cross-over:
    ga.crossover(GARealArithmeticCrossover);
    //ga.crossover(GARealBlendCrossover);
    // The following options are not advised:
    //ga.crossover(GARealUniformCrossover);
    //ga.crossover(GARealEvenOddCrossover);
    //ga.crossover(GARealOnePointCrossover);
    //ga.crossover(GARealTwoPointCrossover);
    //ga.crossover(GARealPartialMatchCrossover);
    //ga.crossover(GARealOrderCrossover);
    //ga.crossover(GARealCycleCrossover);

    // Setting the variables for the mutation and crossover probabilities:
    ga.pMutation(0.05);         // likelihood of mutating new offspring
    ga.pCrossover(0.9);     // likelihood of crossing over parents 

    // Specifying settings for calculating the fitness function:
    ga.scoreFilename("generation.dat"); // name of output file for scores
    ga.scoreFrequency(1);       // keep the scores of every generation
    ga.flushFrequency(1);           // specify how often to write the score
                                        // to disk
    ga.selectScores(GAStatistics::AllScores); /* writing out average, maximum,
                                               minimum, standard deviation and
                                               divergence values of the fitness
                                               function for later plotting. */



    // Initializing the genetic algorithm: 
    ga.initialize();

    // Output the initial population to file:
    int counter=0;
    string pop_evo ="pop_evolution"+rank+".dat";
    outfile.open(pop_evo.c_str());
    for(int ii=0; ii<ga.population().size(); ii++){
      genome = ga.population().individual(ii);
      outfile <<  counter << "\t";
      for(int a=0; a<DIM; a++){

    outfile << genome.gene(a) << "\t";
      }
      outfile << genome.score() << "\n";

    }

    float emigrant [nmigr][DIM];
    float immigrant [nmigr][DIM];
    string immigrants ="immigrants"+rank+".dat";
    imm.open(immigrants.c_str());

    // Running the algorithm until the termination condition is met:
    while(!ga.done()) {
      counter++;
      //ga.step();
      swappop = ga.population();

      /* Migration - stepping stone approach, i.e. individuals are swapped 
     between neighbouring populations. The best individuals of one
     population are copied across to the next one in stead of the worst
     performing ones:*/
      for (int i=0;i<nmigr;i++){
    genome = ga.population().individual(i);
    for (int j=0;j<nmigr;j++){
      emigrant[i][j] = genome.gene(j); 
    }
      }
      // The following if-loops are required to avoid dead-lock
      if (mpi_rank == (mpi_tasks-1)){
    MPI_Send(&emigrant, (nmigr*DIM), MPI_FLOAT, 1, 1, MPI_COMM_WORLD);
    MPI_Recv(&immigrant, (nmigr*DIM), MPI_FLOAT, (mpi_rank-1), mpi_rank, 
         MPI_COMM_WORLD, MPI_STATUS_IGNORE);
      }
      else if (mpi_rank == 1){
    MPI_Send(&emigrant, (nmigr*DIM), MPI_FLOAT, (mpi_rank+1), (mpi_rank+1), 
         MPI_COMM_WORLD);
    MPI_Recv(&immigrant, (nmigr*DIM), MPI_FLOAT, (mpi_tasks-1), 1, 
         MPI_COMM_WORLD, MPI_STATUS_IGNORE);
      }
      else {
    MPI_Send(&emigrant, (nmigr*DIM), MPI_FLOAT, (mpi_rank+1), (mpi_rank+1), 
         MPI_COMM_WORLD);
    MPI_Recv(&immigrant, (nmigr*DIM), MPI_FLOAT, (mpi_rank-1), mpi_rank, 
         MPI_COMM_WORLD, MPI_STATUS_IGNORE);
      }
      //MPI_Barrier(MPI_COMM_WORLD);
      for (int i=0;i<nmigr;i++){
    imm << counter << "\t" << i;
    genome = swappop.individual((popsize-1)-i);
    for (int j=0;j<DIM;j++){
      genome.gene(j,immigrant[i][j]); //substituting the last (worst)
                                      //individuals with the best ones of 
                                      //another population
      //imm << "\t" << immigrant[i][j];
      imm << "\t" << genome.gene(j);
    }
    //ga.population();
    //imm << "\n" << ga.population().individual((popsize-1)-i);
    imm << "\n";
      }

      ga.population(swappop);
      ga.step();

      // Printing the population to file for each generation for later plotting:
      for(int ii=0; ii<popsize; ii++){  
    genome = ga.population().individual(ii);
    outfile <<  counter << "\t";
    for(int a=0; a<DIM; a++){
      outfile << genome.gene(a) << "\t";
    }
    outfile << genome.score() << "\n";
      }
    }
    imm.close();                      // Closing the output file stream
    outfile.close();                  // Closing the output file stream


    float best_individual [DIM];
    float best_score;
    for(int b=0; b<DIM; b++){
      genome = ga.statistics().bestIndividual();
      best_individual[b] = genome.gene(b);
      best_score = genome.score();
    }
    // Printing out the best genome that the GA found for the current population
    //  to file:
    string best_val = "../common_files/best_individual" + rank + ".dat";
    outfile.open(best_val.c_str());
    outfile << ga.statistics().bestIndividual() << "\n";
    outfile << ga.statistics().bestIndividual().score() << "\n";
    outfile.close();                    //closing the output file stream

    MPI_Send(&best_individual, DIM, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);
    MPI_Send(&best_score, 1, MPI_FLOAT, 0, 1, MPI_COMM_WORLD);
  }

  float individual [(mpi_tasks-1)][DIM];
  float score [(mpi_tasks-1)];
  if (mpi_rank==0){
    for (int i=0; i<(mpi_tasks-1); i++){
      MPI_Recv(&individual[i], DIM, MPI_FLOAT, (i+1), 0, MPI_COMM_WORLD,
           MPI_STATUS_IGNORE);
      MPI_Recv(&score[i], 1, MPI_FLOAT, (i+1), 1, MPI_COMM_WORLD,
           MPI_STATUS_IGNORE);
      cout << "\nBest individual population" <<  (i+1) << ":\n";
      for(int j=0; j<DIM; j++){cout << individual[i][j] << "\t";}
      cout << score[i] << "\n";
    }
  }

  MPI_Barrier(MPI_COMM_WORLD);

  if (mpi_rank==0){
    // Initialising the value for the minimum:
    float minimum = score[0];
    int pop = 0;
    for (int i=1; i<(mpi_tasks-1); i++){
      // Selecting the actual minimum:
      if (minimum>=score[i]){minimum=score[i]; pop=i;}
    }
    /*Printing the data to a file as well so that it can be used as the 
       starting point by the Nelder-Mead Simplex method in the hybrid
       optimization technique.*/
    outfile.open("../common_files/best_individual.dat");  
    for (int j=0; j<DIM; j++) {outfile << individual[pop][j] << "\t";}
    outfile << "\nBest score: " << minimum;
    outfile << "\nBelonging to population " << (pop+1);
    outfile.close();                  // Closing the output file stream*/
  }

  // Finalize the MPI environment.
  MPI_Finalize();

  return 0;
}


float Objective(GAGenome& g) {  // Definition of the objective function

  GARealGenome & genome = (GARealGenome &)g;
  float y = 0;                  // Defining Styblinski–Tang function
  for(int b=0; b<DIM; b++){
    float sum;
    sum = pow(genome.gene(b),4);
    sum += - 16 * genome.gene(b) * genome.gene(b) + 5 * genome.gene(b);
    y += sum;
  }
  return y;
}

运行命令:

make
mpirun -np 4 styblinski_tangPA

注意:将makefile中的目录更改为指向GAlib的位置。将styblinski_tangPA.cpp中输出文件的目录更改为所需位置。 编译时需要:OpenMPI或等效的GAlib。

0 个答案:

没有答案
相关问题