KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > examples > energy > CoinsEnergy


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.energy;
11
12 import org.jgap.*;
13 import org.jgap.impl.*;
14
15 /**
16  * THIS EXAMPLE IS NOT IMPLEMENTED FULLY!
17  * For general description, see examples.MinimizingMakeChange.<p>
18  * Additionally, each to coin an energy value is assigned (new feature since
19  * JGAP version 2.4). Energy is interpreted here as weight of a coin. You could
20  * think of a coins holder that wants a low total weight as possible and that
21  * is capable of only holding a given maximum weight.
22  *
23  * @author Klaus Meffert
24  * @since 2.4
25  */

26 public class CoinsEnergy {
27   /** String containing the CVS revision. Read out via reflection!*/
28   private final static String JavaDoc CVS_REVISION = "$Revision: 1.8 $";
29
30   /**
31    * The total number of times we'll let the population evolve.
32    */

33   private static final int MAX_ALLOWED_EVOLUTIONS = 200;
34
35   /**
36    * Executes the genetic algorithm to determine the minimum number of
37    * coins necessary to make up the given target amount of change. The
38    * solution will then be written to System.out.
39    *
40    * @param a_targetChangeAmount the target amount of change for which this
41    * method is attempting to produce the minimum number of coins
42    * @param a_maxWeight the maximum weight allowed in sum over all coins
43    * @throws Exception
44    *
45    * @author Neil Rotstan
46    * @author Klaus Meffert
47    * @since 1.0
48    */

49   public static void makeChangeForAmount(int a_targetChangeAmount,
50                                          double a_maxWeight)
51       throws Exception JavaDoc {
52     // Start with a DefaultConfiguration, which comes setup with the
53
// most common settings.
54
// -------------------------------------------------------------
55
Configuration conf = new DefaultConfiguration();
56     conf.setPreservFittestIndividual(true);
57     conf.setKeepPopulationSizeConstant(false);
58     // Set the fitness function we want to use, which is our
59
// MinimizingMakeChangeFitnessFunction. We construct it with
60
// the target amount of change passed in to this method.
61
// ---------------------------------------------------------
62
FitnessFunction myFunc =
63         new CoinsEnergyFitnessFunction(a_targetChangeAmount, a_maxWeight);
64 // conf.setFitnessFunction(myFunc);
65
conf.setBulkFitnessFunction(new BulkFitnessOffsetRemover(myFunc));
66     // Now we need to tell the Configuration object how we want our
67
// Chromosomes to be setup. We do that by actually creating a
68
// sample Chromosome and then setting it on the Configuration
69
// object. As mentioned earlier, we want our Chromosomes to each
70
// have four genes, one for each of the coin types. We want the
71
// values (alleles) of those genes to be integers, which represent
72
// how many coins of that type we have. We therefore use the
73
// IntegerGene class to represent each of the genes. That class
74
// also lets us specify a lower and upper bound, which we set
75
// to sensible values for each coin type.
76
// --------------------------------------------------------------
77
Gene[] sampleGenes = new Gene[4];
78     IntegerGene gene = new IntegerGene(conf, 0, 3 * 10);
79     gene.setConstraintChecker(new EnergyGeneConstraintChecker());
80     // Initialize energys of Gene's. Each Gene represents a coin with a
81
// specific value, and each coin with different value has a specific
82
// weight. Not necessarily a higher weight for higher coin values!
83
// (as in real life!).
84
sampleGenes[0] = gene; // Quarters
85
sampleGenes[0].setEnergy(20.0d);
86     sampleGenes[1] = new IntegerGene(conf, 0, 2 * 10); // Dimes
87
sampleGenes[1].setEnergy(10.0d);
88     sampleGenes[2] = new IntegerGene(conf, 0, 1 * 10); // Nickels
89
sampleGenes[2].setEnergy(11.0d);
90     sampleGenes[3] = new IntegerGene(conf, 0, 4 * 10); // Pennies
91
sampleGenes[3].setEnergy(7.0d);
92     IChromosome sampleChromosome = new Chromosome(conf, sampleGenes);
93     conf.setSampleChromosome(sampleChromosome);
94     // Finally, we need to tell the Configuration object how many
95
// Chromosomes we want in our population. The more Chromosomes,
96
// the larger number of potential solutions (which is good for
97
// finding the answer), but the longer it will take to evolve
98
// the population (which could be seen as bad).
99
// ------------------------------------------------------------
100
conf.setPopulationSize(80);
101     // Create random initial population of Chromosomes.
102
// ------------------------------------------------
103
Genotype population = Genotype.randomInitialGenotype(conf);
104
105     // Evolve the population. Since we don't know what the best answer
106
// is going to be, we just evolve the max number of times.
107
// ---------------------------------------------------------------
108
for (int i = 0; i < MAX_ALLOWED_EVOLUTIONS; i++) {
109       population.evolve();
110     }
111     // Display the best solution we found.
112
// -----------------------------------
113
IChromosome bestSolutionSoFar = population.getFittestChromosome();
114     System.out.println("The best solution has a fitness value of "
115                        + bestSolutionSoFar.getFitnessValue());
116     System.out.println("It contains the following: ");
117     System.out.println("\t" + CoinsEnergyFitnessFunction.getNumberOfCoinsAtGene(
118         bestSolutionSoFar, 0) + " quarters.");
119     System.out.println("\t" + CoinsEnergyFitnessFunction.getNumberOfCoinsAtGene(
120         bestSolutionSoFar, 1) + " dimes.");
121     System.out.println("\t" + CoinsEnergyFitnessFunction.getNumberOfCoinsAtGene(
122         bestSolutionSoFar, 2) + " nickels.");
123     System.out.println("\t" + CoinsEnergyFitnessFunction.getNumberOfCoinsAtGene(
124         bestSolutionSoFar, 3) + " pennies.");
125     System.out.println("For a total of "
126                        + CoinsEnergyFitnessFunction.amountOfChange(
127         bestSolutionSoFar)
128                        + " cents in "
129                        + CoinsEnergyFitnessFunction.getTotalNumberOfCoins(
130         bestSolutionSoFar)
131                        + " coins with a total weight of "
132                        + CoinsEnergyFitnessFunction.getTotalWeight(
133         bestSolutionSoFar)
134                        + ")");
135   }
136
137   /**
138    * Main method. A single command-line argument is expected, which is the
139    * amount of change to create (in other words, 75 would be equal to 75
140    * cents).
141    *
142    * @param args amount of change in cents to create
143    * @throws Exception
144    *
145    * @author Neil Rotstan
146    * @author Klaus Meffert
147    * @since 1.0
148    */

149   public static void main(String JavaDoc[] args)
150       throws Exception JavaDoc {
151     if (args.length != 2) {
152       System.out.println("Syntax: CoinsEnergy <amount> <max weight>");
153     }
154     else {
155       int amount = getValue(args, 0);
156       int weight = getValue(args, 1);
157       makeChangeForAmount(amount, weight);
158     }
159   }
160
161   protected static int getValue(String JavaDoc[] args, int index) {
162     int value;
163     try {
164       value = Integer.parseInt(args[index]);
165       return value;
166     }
167     catch (NumberFormatException JavaDoc e) {
168       System.out.println(
169           "The " + (index + 1) + ". argument must be a valid integer value");
170       System.exit(1);
171       return -1; // does not matter
172
}
173   }
174
175   /**
176    * Uses to set the energy when a new allele is set
177    * @author Klaus Meffert
178    * @since 2.4
179    */

180   public static class EnergyGeneConstraintChecker
181       implements IGeneConstraintChecker {
182     public final static double[] coinWeights = {
183         1.0d, 2.0d, 8.0d, 3.0d};
184
185     /**
186      * Check if a given allele value is valid for the given gene instance.
187      * @param a_gene the gene the given allele is to be validated for
188      * @param a_alleleValue the allele value to be validated
189      * @param a_chrom not used yet
190      * @param a_geneIndex not used yet
191      * @return true: allele may be set for gene; false: validity check failed
192      * @throws RuntimeException if the checker cannot decide whether the given
193      * allele is valid or not
194      *
195      * @author Klaus Meffert
196      * @since 2.4
197      */

198     public boolean verify(Gene a_gene, final Object JavaDoc a_alleleValue,
199                           final IChromosome a_chrom, final int a_geneIndex)
200         throws RuntimeException JavaDoc {
201       double computedWeight = 0.0d;
202       // We need to figure out what type of coin (penny, nickle, dime, quarter)
203
// the current Gene represents. This is not trivial as it depends on the
204
// index of the Gene within the Chromosome. The Chromosome is not
205
// accessible by the Gene!
206
// ----------------------------------------------------------------------
207
/**todo compute*/
208 // a_gene.setEnergy(computedWeight);
209
// No verification here, always conform.
210
// -------------------------------------
211
return true;
212     }
213   }
214 }
215
Popular Tags