/**
   * Determine the fitness of the given Chromosome instance. The higher the return value, the more
   * fit the instance. This method should always return the same fitness value for two equivalent
   * Chromosome instances.
   *
   * @param a_subject the Chromosome instance to evaluate
   * @return positive double reflecting the fitness rating of the given Chromosome
   * @since 2.0 (until 1.1: return type int)
   * @author Neil Rotstan, Klaus Meffert, John Serri
   */
  public double evaluate(IChromosome a_subject) {
    int i = 0, j, k;

    for (j = 0; j < EvolvingSubsumptionForRobocode.numberOfEvents; j++) {
      eventPriority[j] = ((Integer) a_subject.getGene(i++).getAllele()).intValue();
    }
    for (j = 0; j < EvolvingSubsumptionForRobocode.numberOfBehaviours; j++) {
      behaviourOverwrite[j] = ((Integer) a_subject.getGene(i++).getAllele()).intValue() > 50;
    }
    for (j = 0; j < EvolvingSubsumptionForRobocode.numberOfBehaviours; j++) {
      for (k = 0; k < EvolvingSubsumptionForRobocode.behaviourSize; k++) {
        behaviourActions[j][k] = ((Integer) a_subject.getGene(i++).getAllele()).intValue();
      }
    }

    double tempFitness;
    double fitness = 0;
    for (j = 0; j < otherRobots.length; j++) {
      RobotSpecification[] tempRobots = new RobotSpecification[2];
      tempRobots[0] = evolvable;
      tempRobots[1] = otherRobots[j];
      battleSpecs = new BattleSpecification(1, new BattlefieldSpecification(800, 600), tempRobots);
      tempFitness = 0;
      System.out.println("Testing against " + otherRobots[j].getName() + "...");
      for (i = 0; i < EvolvingSubsumptionForRobocode.numberOfBattles; i++) {
        engine.runBattle(battleSpecs, true);
        tempFitness += battleObserver.getScoreRobot() / 500;
      }
      tempFitness /= EvolvingSubsumptionForRobocode.numberOfBattles;
      fitness += tempFitness;
    }
    fitness /= otherRobots.length;

    return Math.min(1.0d, fitness);
  }
 /**
  * Calculates the penalty to apply to the fitness value based on the ammount of coins in the
  * solution
  *
  * @param a_maxFitness maximum fitness value allowed
  * @param a_coins number of coins in the solution
  * @return penalty for the fitness value base on the number of coins
  * @author John Serri
  * @since 2.2
  */
 protected double computeCoinNumberPenalty(double a_maxFitness, int a_coins) {
   if (a_coins == 1) {
     // we know the solution cannot have less than one coin
     return 0;
   } else {
     // The more coins the more penalty, but not more than the maximum fitness
     // value possible. Let's avoid linear behavior and use
     // exponential penalty calculation instead
     return (Math.min(a_maxFitness, a_coins * a_coins));
   }
 }
Ejemplo n.º 3
0
  /**
   * Evolves the population of chromosomes within a genotype. This will execute all of the genetic
   * operators added to the present active configuration and then invoke the natural selector to
   * choose which chromosomes will be included in the next generation population.
   *
   * @param a_pop the population to evolve
   * @param a_conf the configuration to use for evolution
   * @return evolved population
   * @author Klaus Meffert
   * @since 3.2
   */
  public Population evolve(Population a_pop, Configuration a_conf) {
    Population pop = a_pop;
    int originalPopSize = a_conf.getPopulationSize();
    boolean monitorActive = a_conf.getMonitor() != null;
    IChromosome fittest = null;
    // If first generation: Set age to one to allow genetic operations,
    // see CrossoverOperator for an illustration.
    // ----------------------------------------------------------------
    if (a_conf.getGenerationNr() == 0) {
      int size = pop.size();
      for (int i = 0; i < size; i++) {
        IChromosome chrom = pop.getChromosome(i);
        chrom.increaseAge();
      }
    } else {
      // Select fittest chromosome in case it should be preserved and we are
      // not in the very first generation.
      // -------------------------------------------------------------------
      if (a_conf.isPreserveFittestIndividual()) {
        /** @todo utilize jobs. In pop do also utilize jobs, especially for fitness computation */
        fittest = pop.determineFittestChromosome(0, pop.size() - 1);
      }
    }
    if (a_conf.getGenerationNr() > 0) {
      // Adjust population size to configured size (if wanted).
      // Theoretically, this should be done at the end of this method.
      // But for optimization issues it is not. If it is the last call to
      // evolve() then the resulting population possibly contains more
      // chromosomes than the wanted number. But this is no bad thing as
      // more alternatives mean better chances having a fit candidate.
      // If it is not the last call to evolve() then the next call will
      // ensure the correct population size by calling keepPopSizeConstant.
      // ------------------------------------------------------------------
      keepPopSizeConstant(pop, a_conf);
    }
    // Ensure fitness value of all chromosomes is udpated.
    // ---------------------------------------------------
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES1,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    updateChromosomes(pop, a_conf);
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES1,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    // Apply certain NaturalSelectors before GeneticOperators will be executed.
    // ------------------------------------------------------------------------
    pop = applyNaturalSelectors(a_conf, pop, true);
    // Execute all of the Genetic Operators.
    // -------------------------------------
    applyGeneticOperators(a_conf, pop);
    // Reset fitness value of genetically operated chromosomes.
    // Normally, this should not be necessary as the Chromosome class
    // initializes each newly created chromosome with
    // FitnessFunction.NO_FITNESS_VALUE. But who knows which Chromosome
    // implementation is used...
    // ----------------------------------------------------------------
    int currentPopSize = pop.size();
    for (int i = originalPopSize; i < currentPopSize; i++) {
      IChromosome chrom = pop.getChromosome(i);
      chrom.setFitnessValueDirectly(FitnessFunction.NO_FITNESS_VALUE);
      // Mark chromosome as new-born.
      // ----------------------------
      chrom.resetAge();
      // Mark chromosome as being operated on.
      // -------------------------------------
      chrom.increaseOperatedOn();
    }
    // Increase age of all chromosomes which are not modified by genetic
    // operations.
    // -----------------------------------------------------------------
    int size = Math.min(originalPopSize, currentPopSize);
    for (int i = 0; i < size; i++) {
      IChromosome chrom = pop.getChromosome(i);
      chrom.increaseAge();
      // Mark chromosome as not being operated on.
      // -----------------------------------------
      chrom.resetOperatedOn();
    }
    // If a bulk fitness function has been provided, call it.
    // ------------------------------------------------------
    BulkFitnessFunction bulkFunction = a_conf.getBulkFitnessFunction();
    if (bulkFunction != null) {
      if (monitorActive) {
        // Monitor that bulk fitness will be called for evaluation.
        // --------------------------------------------------------
        a_conf
            .getMonitor()
            .event(
                IEvolutionMonitor.MONITOR_EVENT_BEFORE_BULK_EVAL,
                a_conf.getGenerationNr(),
                new Object[] {bulkFunction, pop});
      }
      /** @todo utilize jobs: bulk fitness function is not so important for a prototype! */
      bulkFunction.evaluate(pop);
      if (monitorActive) {
        // Monitor that bulk fitness has been called for evaluation.
        // ---------------------------------------------------------
        a_conf
            .getMonitor()
            .event(
                IEvolutionMonitor.MONITOR_EVENT_AFTER_BULK_EVAL,
                a_conf.getGenerationNr(),
                new Object[] {bulkFunction, pop});
      }
    }
    // Ensure fitness value of all chromosomes is udpated.
    // ---------------------------------------------------
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_BEFORE_UPDATE_CHROMOSOMES2,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    updateChromosomes(pop, a_conf);
    if (monitorActive) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_AFTER_UPDATE_CHROMOSOMES2,
              a_conf.getGenerationNr(),
              new Object[] {pop});
    }
    // Apply certain NaturalSelectors after GeneticOperators have been applied.
    // ------------------------------------------------------------------------
    pop = applyNaturalSelectors(a_conf, pop, false);
    // Fill up population randomly if size dropped below specified percentage
    // of original size.
    // ----------------------------------------------------------------------
    if (a_conf.getMinimumPopSizePercent() > 0) {
      int sizeWanted = a_conf.getPopulationSize();
      int popSize;
      int minSize = (int) Math.round(sizeWanted * (double) a_conf.getMinimumPopSizePercent() / 100);
      popSize = pop.size();
      if (popSize < minSize) {
        IChromosome newChrom;
        IChromosome sampleChrom = a_conf.getSampleChromosome();
        Class sampleChromClass = sampleChrom.getClass();
        IInitializer chromIniter =
            a_conf.getJGAPFactory().getInitializerFor(sampleChrom, sampleChromClass);
        while (pop.size() < minSize) {
          try {
            /**
             * @todo utilize jobs as initialization may be time-consuming as invalid combinations
             *     may have to be filtered out
             */
            newChrom = (IChromosome) chromIniter.perform(sampleChrom, sampleChromClass, null);
            if (monitorActive) {
              // Monitor that fitness value of chromosomes is being updated.
              // -----------------------------------------------------------
              a_conf
                  .getMonitor()
                  .event(
                      IEvolutionMonitor.MONITOR_EVENT_BEFORE_ADD_CHROMOSOME,
                      a_conf.getGenerationNr(),
                      new Object[] {pop, newChrom});
            }
            pop.addChromosome(newChrom);
          } catch (Exception ex) {
            throw new RuntimeException(ex);
          }
        }
      }
    }
    IChromosome newFittest = reAddFittest(pop, fittest);
    if (monitorActive && newFittest != null) {
      // Monitor that fitness value of chromosomes is being updated.
      // -----------------------------------------------------------
      a_conf
          .getMonitor()
          .event(
              IEvolutionMonitor.MONITOR_EVENT_READD_FITTEST,
              a_conf.getGenerationNr(),
              new Object[] {pop, fittest});
    }

    // Increase number of generations.
    // -------------------------------
    a_conf.incrementGenerationNr();
    // Fire an event to indicate we've performed an evolution.
    // -------------------------------------------------------
    m_lastPop = pop;
    m_lastConf = a_conf;
    a_conf
        .getEventManager()
        .fireGeneticEvent(new GeneticEvent(GeneticEvent.GENOTYPE_EVOLVED_EVENT, this));
    return pop;
  }
  public void operate(final Population a_population, final List a_candidateChromosomes) {
    // Work out the number of crossovers that should be performed.
    // -----------------------------------------------------------
    int m_crossoverRate = getCrossOverRate();
    double m_crossoverRatePercent = getCrossOverRatePercent();
    int size = Math.min(getConfiguration().getPopulationSize(), a_population.size());
    int numCrossovers = 0;

    if (m_crossoverRate >= 0) {
      numCrossovers = size / m_crossoverRate;
    } else if (m_crossoverRateCalc != null) {
      numCrossovers = size / 6;
    } else {
      numCrossovers = (int) (size * m_crossoverRatePercent);
    }
    RandomGenerator generator = getConfiguration().getRandomGenerator();
    IGeneticOperatorConstraint constraint =
        getConfiguration().getJGAPFactory().getGeneticOperatorConstraint();
    // For each crossover, grab two random chromosomes, pick a random
    // locus (gene location), and then swap that gene and all genes
    // to the "right" (those with greater loci) of that gene between
    // the two chromosomes.
    // --------------------------------------------------------------
    int index1, index2;

    crossoverValues = new int[size];

    for (int i = 0; i < size; i++) {
      crossoverValues[i] = 0;
    }

    List<Integer> chromeSel = new ArrayList<Integer>();
    for (int i = 0; i < size; i++) {
      if (m_crossoverRateCalc != null) {
        CrossoverRateCalculator ccalc = (CrossoverRateCalculator) m_crossoverRateCalc;
        ccalc.setCurrentFitness(a_population.getChromosome(i).getFitnessValue());

        int numbers = ccalc.calculateCurrentRate();
        crossoverValues[i] = numbers;
        while (numbers > 0) {
          chromeSel.add(i);
          numbers--;
        }
      }
    }
    int justtocheck = chromeSel.size();

    if (m_crossoverRateCalc != null) {
      if (justtocheck == 0) {
        System.out.println("Exception Caught.. Crossover.. chromesel array is null!!");
        for (int fix = 0; fix <= size - 2; fix++) {
          chromeSel.add(fix);
        }
      }
    }

    //
    for (int i = 0; i < numCrossovers; i++) {
      IChromosome chrom1;
      IChromosome chrom2;

      if (m_crossoverRateCalc != null) {
        index1 = generator.nextInt(chromeSel.size());
        index2 = generator.nextInt(chromeSel.size());
        chrom1 = a_population.getChromosome(chromeSel.get(index1));
        chrom2 = a_population.getChromosome(chromeSel.get(index2));
      } else {
        index1 = generator.nextInt(size);
        index2 = generator.nextInt(size);
        chrom1 = a_population.getChromosome(index1);
        chrom2 = a_population.getChromosome(index2);
      }
      // Verify that crossover is allowed.
      // ---------------------------------
      if (!isXoverNewAge() && chrom1.getAge() < 1 && chrom2.getAge() < 1) {
        // Crossing over two newly created chromosomes is not seen as helpful
        // here.
        // ------------------------------------------------------------------
        continue;
      }
      if (constraint != null) {
        List v = new Vector();
        v.add(chrom1);
        v.add(chrom2);
        if (!constraint.isValid(a_population, v, this)) {
          // Constraint forbids crossing over.
          // ---------------------------------
          continue;
        }
      }
      // Clone the chromosomes.
      // ----------------------
      IChromosome firstMate = (IChromosome) ((ICloneable) chrom1).clone();
      IChromosome secondMate = (IChromosome) ((ICloneable) chrom2).clone();

      // Cross over the chromosomes.
      // ---------------------------
      doCrossover(firstMate, secondMate, a_candidateChromosomes, generator);
    }
  }
 public float nextFloat() {
   return Math.min(Float.MAX_VALUE - 1, (float) (nextCauchy() * Float.MAX_VALUE));
 }
 public long nextLong() {
   return Math.min(Long.MAX_VALUE - 1, Math.round(nextCauchy() * Long.MAX_VALUE));
 }
 public int nextInt(final int a_ceiling) {
   return Math.min(a_ceiling - 1, (int) Math.round(nextCauchy() * a_ceiling));
 }
 public int nextInt() {
   return Math.min(Integer.MAX_VALUE - 1, (int) Math.round(nextCauchy() * Integer.MAX_VALUE));
 }