/* * JABM - Java Agent-Based Modeling Toolkit * Copyright (C) 2013 Steve Phelps * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. */ package net.sourceforge.jabm.evolution; import net.sourceforge.jabm.agent.Agent; import net.sourceforge.jabm.agent.AgentList; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Required; import cern.jet.random.engine.RandomEngine; /** * <p> * A breeder which implements Fitness-proportionate reproduction. Agents are * selected for inclusion in the next generation with a probability * proportionate to their fitness, as defined by an exogenous fitness function. * When agents reproduce they do so via an {@link ImitationOperator} which * specifies how agents are copied from one generation to the next. * </p> * * @author Steve Phelps */ public class RandomPairwiseBreeder implements Breeder { /** * The fitness function which specifies the fitness of each agent. */ protected FitnessFunction fitnessFunction; protected ImitationOperator imitationOperator = new StrategyImitationOperator(); protected RandomEngine prng; protected double mixing = 1.0; static Logger logger = Logger.getLogger(RandomPairwiseBreeder.class); public AgentList reproduce(AgentList currentGeneration) { int n = currentGeneration.size(); AgentList nextGeneration = new AgentList(currentGeneration); int numPairs = (int) Math.round(mixing * (n*n)); for(int i=0; i<numPairs; i++) { Agent x = chooseRandomAgent(currentGeneration); Agent y = chooseRandomAgent(currentGeneration); if (x != y) { if (getFitness(x) > getFitness(y)) { imitationOperator.inheritBehaviour(y, x); } else if (getFitness(x) < getFitness(y)) { imitationOperator.inheritBehaviour(x, y); } } } return nextGeneration; } public Agent chooseRandomAgent(AgentList agents) { int n = agents.size(); int i = (int) Math.round(prng.nextDouble() * (n-1)); return agents.get(i); } public double getFitness(Agent i) { double result = 0.0; if (fitnessFunction != null) { result = fitnessFunction.getFitness(i); } else { result = i.getPayoff(); } if (result < 0.0) { result = 0.0; } return result; } public FitnessFunction getFitnessFunction() { return fitnessFunction; } public void setFitnessFunction(FitnessFunction fitnessFunction) { this.fitnessFunction = fitnessFunction; } public RandomEngine getPrng() { return prng; } @Required public void setPrng(RandomEngine prng) { this.prng = prng; } public ImitationOperator getImitationOperator() { return imitationOperator; } public void setImitationOperator(ImitationOperator imitationFunction) { this.imitationOperator = imitationFunction; } public double getMixing() { return mixing; } public void setMixing(double mixing) { this.mixing = mixing; } }