blob: e9415e0a2c690f196aa7a180c888fa3fa64e2e39 [file] [log] [blame]
/*
* 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;
}
}