/* * This file is part of n-genes2. * * n-genes2 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * n-genes2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with n-genes2. If not, see <http://www.gnu.org/licenses/>. * * Copyright 2010, Paradigmatic <paradigmatic@streum.org> * */ package ngenes2.examples; import java.util.List; import ngenes2.builder.BasicDIBuilder; import ngenes2.evolver.Evolver; import ngenes2.evolver.monitor.BasicBestMonitor; import ngenes2.evolver.monitor.NopMonitor; import ngenes2.evolver.stop.MaxGeneration; import ngenes2.individual.LinearIndividual; import ngenes2.individual.generator.integer.RandomIntegerGenerator; import ngenes2.ops.crossover.MidBreakCrossover; import ngenes2.ops.mutator.PointMutation; import ngenes2.ops.mutator.genes.integer.PlusOrMinus; import ngenes2.ops.selector.KTournament; import ngenes2.population.Population; import ngenes2.util.Properties; /** * Example implementation of a GA solving a small KnapSack instance. The * GA uses individuals with integers genes representing the amount of * each object kind in the bag. * @see <a href="http://en.wikipedia.org/wiki/Knapsack_problem">http://en.wikipedia.org/wiki/Knapsack_problem</a> */ public class KnapSack { /** * Knap Sack problem fitness. It must be supplied with two arrays of doubles: * (1) an array with the values of objects; (2) an array with the weight of objects. * Of course both arrays should have the same size. */ public static class Fitness implements ngenes2.fitness.Fitness<Integer> { private final double[] values; private final double[] weights; private final double maximumWeight; /** * Sole constructor. * @param values Object values. * @param weights Object weights. * @param maximumWeight Weight capacity of the bag. * @throws IllegalArgumentException when values and weight arrays have * different size. */ public Fitness(double[] values, double[] weights, double maximumWeight) { if (values.length != weights.length) { throw new IllegalArgumentException("Values and weights length must match"); } this.values = values; this.weights = weights; this.maximumWeight = maximumWeight; } public double compute(List<Integer> chromosome) { if( chromosome.size() != weights.length ) { throw new IllegalArgumentException("Chromosome length does not" + " match values and weights length"); } double value = 0; double weight = 0; for( int i=0; i<values.length; i++ ) { weight += chromosome.get(i)*weights[i]; if( weight > maximumWeight ) { return Double.POSITIVE_INFINITY; } value += chromosome.get(i)*values[i]; } return 1./value; } } @SuppressWarnings("unchecked") public static void main(String[] args) { final int indSize = 5; final int popSize = 100; final double maxWeight = 321; final int maxGen = 500; final double[] values = new double[] {1.0, 2.0, 3.0, 4.0, 5.0 }; final double[] weights = new double[] {4.0, 3.0, 10.0, 14.0, 20.0 }; Properties props = new Properties().put("chromosome_size", indSize) .put("population_size", popSize) .put("max_gene_value", 35) .put("tournament_size",5) .put("max_generation", maxGen); BasicDIBuilder builder = new BasicDIBuilder() .with(props) .with(LinearIndividual.Factory.class) .with(new Fitness(values, weights, maxWeight)) .with(RandomIntegerGenerator.class) .with(PlusOrMinus.class) .with(KTournament.class) .with(MaxGeneration.class) .with(MidBreakCrossover.class) .with(PointMutation.class) .with(BasicBestMonitor.class); Evolver evolver = builder.evolver(); Population pop = builder.population(); evolver.evolve(pop); System.out.println( pop.stats().best() ); } }