001: /*
002: * This file is part of JGAP.
003: *
004: * JGAP offers a dual license model containing the LGPL as well as the MPL.
005: *
006: * For licencing information please see the file license.txt included with JGAP
007: * or have a look at the top of class org.jgap.Chromosome which representatively
008: * includes the JGAP license policy applicable for any file delivered with JGAP.
009: */
010: package org.jgap.perf;
011:
012: import org.jgap.*;
013:
014: /**
015: * Sample fitness function for the MakeChange example.
016: *
017: * @author Klaus Meffert
018: * @since 2.0
019: */
020: public class TestOverallPerformanceFitnessFunc extends FitnessFunction {
021:
022: /** String containing the CVS revision. Read out via reflection!*/
023: private final static String CVS_REVISION = "$Revision: 1.3 $";
024:
025: private final int m_targetAmount;
026:
027: public TestOverallPerformanceFitnessFunc(int a_targetAmount) {
028: if (a_targetAmount < 1 || a_targetAmount > 999) {
029: throw new IllegalArgumentException(
030: "Change amount must be between 1 and 999 cents.");
031: }
032: m_targetAmount = a_targetAmount;
033: }
034:
035: /**
036: * Determine the fitness of the given Chromosome instance. The higher the
037: * return value, the more fit the instance. This method should always
038: * return the same fitness value for two equivalent Chromosome instances.
039: *
040: * @param a_subject the Chromosome instance to evaluate
041: * @return a positive integer reflecting the fitness rating of the given
042: * Chromosome
043: */
044: public double evaluate(IChromosome a_subject) {
045: // The fitness value measures both how close the value is to the
046: // target amount supplied by the user and the total number of coins
047: // represented by the solution. We do this in two steps: first,
048: // we consider only the represented amount of change vs. the target
049: // amount of change and return higher fitness values for amounts
050: // closer to the target, and lower fitness values for amounts further
051: // away from the target. If the amount equals the target, then we go
052: // to step 2, which returns a higher fitness value for solutions
053: // representing fewer total coins, and lower fitness values for
054: // solutions representing more total coins.
055: // ------------------------------------------------------------------
056: int changeAmount = amountOfChange(a_subject);
057: int totalCoins = getTotalNumberOfCoins(a_subject);
058: int changeDifference = Math.abs(m_targetAmount - changeAmount);
059: // Step 1: Determine distance of amount represented by solution from
060: // the target amount. Since we know the maximum amount of change is
061: // 99 cents, we'll subtract the difference in change between the
062: // solution amount and the target amount from 99. That will give
063: // the desired effect of returning higher values for amounts
064: // closer to the target amount and lower values for amounts
065: // further away from the target amount.
066: // -----------------------------------------------------------------
067: int fitness = (99 - changeDifference);
068: // Step 2: If the solution amount equals the target amount, then
069: // we add additional fitness points for solutions representing fewer
070: // total coins.
071: // -----------------------------------------------------------------
072: if (changeAmount == m_targetAmount) {
073: fitness += 100 - (10 * totalCoins);
074: }
075: // Make sure fitness value is always positive.
076: // -------------------------------------------
077: return Math.max(1, fitness);
078: }
079:
080: /**
081: * Calculates the total amount of change (in cents) represented by
082: * the given potential solution and returns that amount.
083: * Here we use "fantasy" coins just to have more genes and bloat the time
084: * consumed for test performance test
085: *
086: * @param a_potentialSolution the pontential solution to evaluate
087: * @return the total amount of change (in cents) represented by the
088: * given solution
089: */
090: public static int amountOfChange(IChromosome a_potentialSolution) {
091: int numQuarters = getNumberOfCoinsAtGene(a_potentialSolution, 0);
092: int numDimes = getNumberOfCoinsAtGene(a_potentialSolution, 1);
093: int numNickels = getNumberOfCoinsAtGene(a_potentialSolution, 2);
094: int numPennies = getNumberOfCoinsAtGene(a_potentialSolution, 3);
095: int A = getNumberOfCoinsAtGene(a_potentialSolution, 4);
096: int B = getNumberOfCoinsAtGene(a_potentialSolution, 5);
097: int C = getNumberOfCoinsAtGene(a_potentialSolution, 6);
098: int D = getNumberOfCoinsAtGene(a_potentialSolution, 7);
099: int E = getNumberOfCoinsAtGene(a_potentialSolution, 8);
100: int F = getNumberOfCoinsAtGene(a_potentialSolution, 9);
101: return (numQuarters * 25) + (numDimes * 10) + (numNickels * 5)
102: + numPennies + (A * 29) + (B * 31) + (C * 37)
103: + (D * 41) + (E * 43) + (F * 47);
104: }
105:
106: /**
107: * Retrieves the number of coins represented by the given potential
108: * solution at the given gene position.
109: *
110: * @param a_potentialSolution the potential solution to evaluate
111: * @param a_position the gene position to evaluate
112: * @return the number of coins represented by the potential solution
113: * at the given gene position
114: */
115: public static int getNumberOfCoinsAtGene(
116: IChromosome a_potentialSolution, int a_position) {
117: Integer numCoins = (Integer) a_potentialSolution.getGene(
118: a_position).getAllele();
119: return numCoins.intValue();
120: }
121:
122: /**
123: * Returns the total number of coins represented by all of the genes in
124: * the given potential solution.
125: *
126: * @param a_potentialsolution the potential solution to evaluate
127: * @return the total number of coins represented by the given Chromosome
128: */
129: public static int getTotalNumberOfCoins(
130: IChromosome a_potentialsolution) {
131: int totalCoins = 0;
132: int numberOfGenes = a_potentialsolution.size();
133: for (int i = 0; i < numberOfGenes; i++) {
134: totalCoins += getNumberOfCoinsAtGene(a_potentialsolution, i);
135: }
136: return totalCoins;
137: }
138: }
|