KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > examples > dynamicMutation > DynamicMutationFitnessFunction


1 /*
2  * This file is part of JGAP.
3  *
4  * JGAP offers a dual license model containing the LGPL as well as the MPL.
5  *
6  * For licencing information please see the file license.txt included with JGAP
7  * or have a look at the top of class org.jgap.Chromosome which representatively
8  * includes the JGAP license policy applicable for any file delivered with JGAP.
9  */

10 package examples.dynamicMutation;
11
12 import org.jgap.*;
13
14 /**
15  * Sample fitness function for the DynamicMutation example.
16  *
17  * @author Klaus Meffert
18  * @since 2.6
19  */

20 public class DynamicMutationFitnessFunction
21     extends FitnessFunction {
22   /** String containing the CVS revision. Read out via reflection!*/
23   private final static String JavaDoc CVS_REVISION = "$Revision: 1.3 $";
24
25   private final int m_targetAmount;
26
27   public static final int MAX_BOUND = 4000;
28
29   public DynamicMutationFitnessFunction(int a_targetAmount) {
30     if (a_targetAmount < 1 || a_targetAmount >= MAX_BOUND) {
31       throw new IllegalArgumentException JavaDoc(
32           "Change amount must be between 1 and " + MAX_BOUND + " cents.");
33     }
34     m_targetAmount = a_targetAmount;
35   }
36
37   /**
38    * Determine the fitness of the given Chromosome instance. The higher the
39    * return value, the more fit the instance. This method should always
40    * return the same fitness value for two equivalent Chromosome instances.
41    *
42    * @param a_subject the Chromosome instance to evaluate
43    *
44    * @return positive double reflecting the fitness rating of the given
45    * Chromosome
46    * @since 2.0 (until 1.1: return type int)
47    * @author Neil Rotstan, Klaus Meffert, John Serri
48    */

49   public double evaluate(IChromosome a_subject) {
50     // Take care of the fitness evaluator. It could either be weighting higher
51
// fitness values higher (e.g.DefaultFitnessEvaluator). Or it could weight
52
// lower fitness values higher, because the fitness value is seen as a
53
// defect rate (e.g. DeltaFitnessEvaluator)
54
boolean defaultComparation = a_subject.getConfiguration().
55         getFitnessEvaluator().isFitter(2, 1);
56
57     // The fitness value measures both how close the value is to the
58
// target amount supplied by the user and the total number of coins
59
// represented by the solution. We do this in two steps: first,
60
// we consider only the represented amount of change vs. the target
61
// amount of change and return higher fitness values for amounts
62
// closer to the target, and lower fitness values for amounts further
63
// away from the target. Then we go to step 2, which returns a higher
64
// fitness value for solutions representing fewer total coins, and
65
// lower fitness values for solutions representing more total coins.
66
// ------------------------------------------------------------------
67
int changeAmount = amountOfChange(a_subject);
68     int totalCoins = getTotalNumberOfCoins(a_subject);
69     int changeDifference = Math.abs(m_targetAmount - changeAmount);
70     double fitness;
71     if (defaultComparation) {
72       fitness = 0.0d;
73     }
74     else {
75       fitness = MAX_BOUND/2;
76     }
77     // Step 1: Determine distance of amount represented by solution from
78
// the target amount. If the change difference is greater than zero we
79
// will divide one by the difference in change between the
80
// solution amount and the target amount. That will give the desired
81
// effect of returning higher values for amounts closer to the target
82
// amount and lower values for amounts further away from the target
83
// amount.
84
// In the case where the change difference is zero it means that we have
85
// the correct amount and we assign a higher fitness value.
86
// ---------------------------------------------------------------------
87
if (defaultComparation) {
88       fitness += changeDifferenceBonus(MAX_BOUND/2, changeDifference);
89     }
90     else {
91       fitness -= changeDifferenceBonus(MAX_BOUND/2, changeDifference);
92     }
93     // Step 2: We divide the fitness value by a penalty based on the number of
94
// coins. The higher the number of coins the higher the penalty and the
95
// smaller the fitness value.
96
// And inversely the smaller number of coins in the solution the higher
97
// the resulting fitness value.
98
// -----------------------------------------------------------------------
99
if (defaultComparation) {
100       fitness -= computeCoinNumberPenalty(MAX_BOUND/2, totalCoins);
101     }
102     else {
103       fitness += computeCoinNumberPenalty(MAX_BOUND/2, totalCoins);
104     }
105     // Make sure fitness value is always positive.
106
// -------------------------------------------
107
return Math.max(1.0d, fitness);
108   }
109
110   /**
111    * Bonus calculation of fitness value.
112    * @param a_maxFitness maximum fitness value appliable
113    * @param a_changeDifference change difference in coins for the coins problem
114    * @return bonus for given change difference
115    *
116    * @author Klaus Meffert
117    * @since 2.3
118    */

119   protected double changeDifferenceBonus(double a_maxFitness,
120                                          int a_changeDifference) {
121     if (a_changeDifference == 0) {
122       return a_maxFitness;
123     }
124     else {
125       // we arbitrarily work with half of the maximum fitness as basis for non-
126
// optimal solutions (concerning change difference)
127
if (a_changeDifference * a_changeDifference >= a_maxFitness / 2) {
128         return 0.0d;
129       }
130       else {
131         return a_maxFitness / 2 - a_changeDifference * a_changeDifference;
132       }
133     }
134   }
135
136   /**
137    * Calculates the penalty to apply to the fitness value based on the ammount
138    * of coins in the solution
139    *
140    * @param a_maxFitness maximum fitness value allowed
141    * @param a_coins number of coins in the solution
142    * @return penalty for the fitness value base on the number of coins
143    *
144    * @author John Serri
145    * @since 2.2
146    */

147   protected double computeCoinNumberPenalty(double a_maxFitness, int a_coins) {
148     if (a_coins == 1) {
149       // we know the solution cannot have less than one coin
150
return 0;
151     }
152     else {
153       // The more coins the more penalty, but not more than the maximum fitness
154
// value possible. Let's avoid linear behavior and use
155
// exponential penalty calculation instead
156
return (Math.min(a_maxFitness, a_coins * a_coins));
157     }
158   }
159
160   /**
161    * Calculates the total amount of change (in cents) represented by
162    * the given potential solution and returns that amount.
163    *
164    * @param a_potentialSolution the potential solution to evaluate
165    * @return The total amount of change (in cents) represented by the
166    * given solution
167    *
168    * @author Neil Rotstan
169    * @since 1.0
170    */

171   public static int amountOfChange(IChromosome a_potentialSolution) {
172     int numQuarters = getNumberOfCoinsAtGene(a_potentialSolution, 0);
173     int numDimes = getNumberOfCoinsAtGene(a_potentialSolution, 1);
174     int numNickels = getNumberOfCoinsAtGene(a_potentialSolution, 2);
175     int numPennies = getNumberOfCoinsAtGene(a_potentialSolution, 3);
176     return (numQuarters * 25) + (numDimes * 10) + (numNickels * 5) +
177         numPennies;
178   }
179
180   /**
181    * Retrieves the number of coins represented by the given potential
182    * solution at the given gene position.
183    *
184    * @param a_potentialSolution the potential solution to evaluate
185    * @param a_position the gene position to evaluate
186    * @return the number of coins represented by the potential solution at the
187    * given gene position
188    *
189    * @author Neil Rotstan
190    * @since 1.0
191    */

192   public static int getNumberOfCoinsAtGene(IChromosome a_potentialSolution,
193                                            int a_position) {
194     Integer JavaDoc numCoins =
195         (Integer JavaDoc) a_potentialSolution.getGene(a_position).getAllele();
196     return numCoins.intValue();
197   }
198
199   /**
200    * Returns the total number of coins represented by all of the genes in
201    * the given potential solution.
202    *
203    * @param a_potentialsolution the potential solution to evaluate
204    * @return total number of coins represented by the given Chromosome
205    *
206    * @author Neil Rotstan
207    * @since 1.0
208    */

209   public static int getTotalNumberOfCoins(IChromosome a_potentialsolution) {
210     int totalCoins = 0;
211     int numberOfGenes = a_potentialsolution.size();
212     for (int i = 0; i < numberOfGenes; i++) {
213       totalCoins += getNumberOfCoinsAtGene(a_potentialsolution, i);
214     }
215     return totalCoins;
216   }
217 }
218
Popular Tags