knowledge representation

The DNA of our individuals is a Vector of integers

 

Each integer is a key mapped to a Robot action in VREP

 

... but it is also  mapped to another int that defines a "Step" which is a value for any action

{
  { "LeftWheelJoint",  "Move left wheel forward",    1 },
  { "LeftWheelJoint",  "Move left wheel backward",  -1 },
  { "RightWheelJoint", "Move right wheel forward",   1 },
  { "RightWheelJoint", "Move right wheel backward", -1 },
  { "ShoulderMotor",   "Move shoulder forward",      1 },
  { "ShoulderMotor",   "Move shoulder backward",    -1 },
  { "ElbowMotor",      "Move elbow forward",         1 },
  { "ElbowMotor",      "Move elbow backward",       -1 },
  { "WristMotor",      "Move wrist forward",         1 },
  { "WristMotor",      "Move wrist backward",       -1 }
}

What we propose

CPP implementation using the remote API of VREP

Robot object to push commands and retrieve information to/from VREP

Simulation object to run the loop of the algorithm and GA components

An Individual object that stores its DNA data and can mutate (5%) and compute itself

A Population object which do operations on whole individuals -> sort, get the best and worst, mutate and evaluate everything, provide easy accessors

Logger object to write data structure into files

Parallelism with OpenMP to fully use your processor cores

Gnuplot to provide data visualisation

What we do

Our big fat Simulation::run method

int		Simulation::run() {
  Individual	best, worst;
  double	averageFitness = 0.0f;

  for (int generationIter = 0; generationIter < _maxGenerations; ++generationIter) {
    for (uint i = 0; i < _population.size();) {

      // Retrieving batch of individuals to run simulation on
      population_t individualsBatch;
      for (int robotId = 0; (robotId < _maxRobots) && (i + robotId < _population.size()); ++robotId) {
        individualsBatch.push_back(_population.at(i + robotId));
      }

      // Start the simulation
      if (simxStartSimulation(_clientID, simx_opmode_oneshot_wait) == -1) {
        throw "Failed to start simulation";
      }

      // Each robot processing an individual in parallel
      #pragma omp parallel for
      for (uint batchIter = 0; batchIter < individualsBatch.size(); ++batchIter) {
        auto &individual = individualsBatch.at(batchIter);
        const auto &robot = _robots[omp_get_thread_num()];

        simxFloat prevPos[3];
        robot.getPosition(prevPos, _floorHandler);

        robot.doActions(individual.getDna());

        simxFloat nextPos[3];
        robot.getPosition(nextPos, _floorHandler);

        double fitness = individual.evaluate(prevPos, nextPos);

        #pragma omp critical
        {
          averageFitness += fitness;
        }
        _population[i + batchIter].setScore(fitness);
      }
      i += _maxRobots;

      // Stop the simulation
      if (simxStopSimulation(_clientID, simx_opmode_oneshot_wait) == -1) {
        throw "Fail to stop simulation";
      }
    }
    averageFitness /= _population.size();

    _population.sort();

    // Finding the worst of the current generation
    worst = _population.at(_population.size() - 1);

    // Finding the best of the current generation
    best = _population.at(0);

    logStats(generationIter, best, worst, averageFitness);
    logPopulation(generationIter);

    // Replacing worst of this generation by best of this generation
    if (generationIter)
      worst = best;

    // Selection
    Population newPopulationGeneration;
    #pragma omp parallel for shared(newPopulationGeneration)
    for (unsigned int i = 0; i < _population.size(); i++) {
      couple_t selected = (this->*(selections.at("tournament")))();
      const Individual child = ((this->*crossovers.at("SinglePoint"))(selected.first,  selected.second)).first;
      newPopulationGeneration.addIndividual(child);
    }
   _population = newPopulationGeneration;

   // Mutation
    _population.mutateBatch();
  }
  return (0);
}

vrep-ga-ppt

By mb1475963

vrep-ga-ppt

  • 462