| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.ignite.examples.ml.genetic.change; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| import org.apache.ignite.Ignite; |
| import org.apache.ignite.Ignition; |
| import org.apache.ignite.ml.genetic.Chromosome; |
| import org.apache.ignite.ml.genetic.GAGrid; |
| import org.apache.ignite.ml.genetic.Gene; |
| import org.apache.ignite.ml.genetic.parameter.ChromosomeCriteria; |
| import org.apache.ignite.ml.genetic.parameter.GAConfiguration; |
| import org.apache.ignite.ml.genetic.parameter.GAGridConstants; |
| |
| /** |
| * This example demonstrates how to use the {@link GAGrid} framework. It is inspired by |
| * <a href="https://github.com/martin-steghoefer/jgap/blob/master/examples/src/examples/MinimizingMakeChange.java"> |
| * JGAP's "Minimize Make Change"</a> example. |
| * <p> |
| * In this example, the objective is to calculate the minimum number of coins that equal user specified amount of change |
| * ie: {@code -DAMOUNTCHANGE}.</p> |
| * <p> |
| * {@code mvn exec:java -Dexec.mainClass="org.apache.ignite.examples.ml.genetic.change.OptimizeMakeChangeGAExample" |
| * -DAMOUNTCHANGE=75}</p> |
| * <p> |
| * Code in this example launches Ignite grid, prepares simple test data (gene pool) and configures GA grid.</p> |
| * <p> |
| * After that it launches the process of evolution on GA grid and outputs the progress and results.</p> |
| * <p> |
| * You can change the test data and parameters of GA grid used in this example and re-run it to explore this |
| * functionality further.</p> |
| * <p> |
| * Remote nodes should always be started with special configuration file which enables P2P class loading: {@code |
| * 'ignite.{sh|bat} examples/config/example-ignite.xml'}.</p> |
| * <p> |
| * Alternatively you can run ExampleNodeStartup in another JVM which will start node with {@code |
| * examples/config/example-ignite.xml} configuration.</p> |
| */ |
| public class OptimizeMakeChangeGAExample { |
| /** |
| * Executes example. |
| * <p> |
| * Specify value for {@code -DAMOUNTCHANGE} JVM system variable. |
| * |
| * @param args Command line arguments, none required. |
| */ |
| public static void main(String args[]) { |
| System.out.println(">>> OptimizeMakeChange GA grid example started."); |
| |
| String sAmountChange = "75"; |
| |
| StringBuilder sbErrorMsg = new StringBuilder(); |
| sbErrorMsg.append("AMOUNTCHANGE System property not set. Please provide a valid value between 1 and 99. "); |
| sbErrorMsg.append(" "); |
| sbErrorMsg.append("IE: -DAMOUNTCHANGE=75"); |
| sbErrorMsg.append("\n"); |
| sbErrorMsg.append("Using default value: 75"); |
| |
| //Check if -DAMOUNTCHANGE JVM system variable is provided. |
| if (System.getProperty("AMOUNTCHANGE") == null) |
| System.out.println(sbErrorMsg); |
| else |
| sAmountChange = System.getProperty("AMOUNTCHANGE"); |
| |
| try { |
| // Create an Ignite instance as you would in any other use case. |
| Ignite ignite = Ignition.start("examples/config/example-ignite.xml"); |
| |
| // Create GAConfiguration. |
| GAConfiguration gaCfg = new GAConfiguration(); |
| |
| // Set Gene Pool. |
| List<Gene> genes = getGenePool(); |
| |
| // Set selection method. |
| gaCfg.setSelectionMtd(GAGridConstants.SELECTION_METHOD.SELECTION_METHOD_ELITISM); |
| gaCfg.setElitismCnt(10); |
| |
| // Set the Chromosome Length to '4' since we have 4 coins. |
| gaCfg.setChromosomeLen(4); |
| |
| // Set population size. |
| gaCfg.setPopulationSize(500); |
| |
| // Initialize gene pool. |
| gaCfg.setGenePool(genes); |
| |
| // Set Truncate Rate. |
| gaCfg.setTruncateRate(.10); |
| |
| // Set Cross Over Rate. |
| gaCfg.setCrossOverRate(.50); |
| |
| // Set Mutation Rate. |
| gaCfg.setMutationRate(.50); |
| |
| // Create and set Fitness function. |
| OptimizeMakeChangeFitnessFunction function = new OptimizeMakeChangeFitnessFunction(new Integer(sAmountChange)); |
| gaCfg.setFitnessFunction(function); |
| |
| // Create and set TerminateCriteria. |
| OptimizeMakeChangeTerminateCriteria termCriteria = new OptimizeMakeChangeTerminateCriteria(ignite, |
| System.out::println); |
| |
| ChromosomeCriteria chromosomeCriteria = new ChromosomeCriteria(); |
| |
| List<String> values = new ArrayList<>(); |
| |
| values.add("coinType=QUARTER"); |
| values.add("coinType=DIME"); |
| values.add("coinType=NICKEL"); |
| values.add("coinType=PENNY"); |
| |
| chromosomeCriteria.setCriteria(values); |
| |
| gaCfg.setChromosomeCriteria(chromosomeCriteria); |
| gaCfg.setTerminateCriteria(termCriteria); |
| |
| // Initialize GAGrid. |
| GAGrid gaGrid = new GAGrid(gaCfg, ignite); |
| |
| System.out.println("##########################################################################################"); |
| |
| System.out.println("Calculating optimal set of coins where amount of change is " + sAmountChange); |
| |
| System.out.println("##########################################################################################"); |
| |
| Chromosome chromosome = gaGrid.evolve(); |
| |
| System.out.println(">>> Evolution result: " + chromosome); |
| |
| Ignition.stop(true); |
| |
| System.out.println(">>> OptimizeMakeChange GA grid example completed."); |
| } |
| catch (Exception e) { |
| System.out.println(e.getMessage()); |
| e.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Helper routine to initialize Gene pool. |
| * <p> |
| * In typical use case genes may be stored in database. |
| * |
| * @return List of Genes. |
| */ |
| private static List<Gene> getGenePool() { |
| List<Gene> list = new ArrayList<>(); |
| |
| Gene quarterGene1 = new Gene(new Coin(Coin.CoinType.QUARTER, 3)); |
| Gene quarterGene2 = new Gene(new Coin(Coin.CoinType.QUARTER, 2)); |
| Gene quarterGene3 = new Gene(new Coin(Coin.CoinType.QUARTER, 1)); |
| Gene quarterGene4 = new Gene(new Coin(Coin.CoinType.QUARTER, 0)); |
| |
| Gene dimeGene1 = new Gene(new Coin(Coin.CoinType.DIME, 2)); |
| Gene dimeGene2 = new Gene(new Coin(Coin.CoinType.DIME, 1)); |
| Gene dimeGene3 = new Gene(new Coin(Coin.CoinType.DIME, 0)); |
| |
| Gene nickelGene1 = new Gene(new Coin(Coin.CoinType.NICKEL, 1)); |
| Gene nickelGene2 = new Gene(new Coin(Coin.CoinType.NICKEL, 0)); |
| |
| Gene pennyGene1 = new Gene(new Coin(Coin.CoinType.PENNY, 4)); |
| Gene pennyGene2 = new Gene(new Coin(Coin.CoinType.PENNY, 3)); |
| Gene pennyGene3 = new Gene(new Coin(Coin.CoinType.PENNY, 2)); |
| Gene pennyGene4 = new Gene(new Coin(Coin.CoinType.PENNY, 1)); |
| Gene pennyGene5 = new Gene(new Coin(Coin.CoinType.PENNY, 0)); |
| |
| list.add(quarterGene1); |
| list.add(quarterGene2); |
| list.add(quarterGene3); |
| list.add(quarterGene4); |
| list.add(dimeGene1); |
| list.add(dimeGene2); |
| list.add(dimeGene3); |
| list.add(nickelGene1); |
| list.add(nickelGene2); |
| list.add(pennyGene1); |
| list.add(pennyGene2); |
| list.add(pennyGene3); |
| list.add(pennyGene4); |
| list.add(pennyGene5); |
| |
| return list; |
| } |
| } |