├── README.md ├── src ├── ro │ └── jgal │ │ ├── Initializer.java │ │ ├── FitnessFunction.java │ │ ├── Selector.java │ │ ├── TerminationCriteria.java │ │ ├── Crossover.java │ │ ├── Mutator.java │ │ ├── ConvergenceCriteria.java │ │ ├── TerminationCriterias.java │ │ ├── Consts.java │ │ ├── MutatorFlip.java │ │ ├── InitializerBinaryString.java │ │ ├── InitializerIntegerPermutation.java │ │ ├── Statistics.java │ │ ├── MutatorSwap.java │ │ ├── ScoreCriteria.java │ │ ├── InitializerString.java │ │ ├── MutatorString.java │ │ ├── SelectorUniform.java │ │ ├── SelectorRouletteWheelSA.java │ │ ├── InitializerReal.java │ │ ├── Crossovers.java │ │ ├── InitializerInteger.java │ │ ├── Selectors.java │ │ ├── Mutators.java │ │ ├── SelectorStochasticUniversalSampling.java │ │ ├── CrossoverSinglePoint.java │ │ ├── CrossoverUniform.java │ │ ├── CrossoverTwoPoint.java │ │ ├── MutatorRealRange.java │ │ ├── MutatorRealGaussian.java │ │ ├── Initializers.java │ │ ├── SelectorRouletteWheel.java │ │ ├── CrossoverCX.java │ │ ├── SelectorTournament.java │ │ ├── CrossoverOX.java │ │ ├── Utils.java │ │ ├── Population.java │ │ ├── CrossoverEdge.java │ │ ├── Chromosome.java │ │ └── GeneticAlgorithm.java └── examples │ ├── OneMax.java │ ├── Rosenbrock.java │ ├── Sphere.java │ ├── DropWave.java │ ├── WeaselProgram.java │ ├── SchafferN2.java │ ├── RealGauss.java │ ├── Easom.java │ ├── Ackley.java │ ├── SchafferN4.java │ ├── CrossInTray.java │ ├── NQueens.java │ ├── TSP.java │ └── 58cities.txt ├── .gitignore └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # JGAL 2 | This is an extensible and easy to use Genetic Algorithms Library. 3 | -------------------------------------------------------------------------------- /src/ro/jgal/Initializer.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing initializers. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | @SuppressWarnings("rawtypes") 10 | public interface Initializer { 11 | 12 | /** 13 | * Creates a new chromosome. 14 | * 15 | * @return - new chromosome 16 | */ 17 | public Chromosome initialize(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/ro/jgal/FitnessFunction.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing the fitness function. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | @SuppressWarnings("rawtypes") 10 | public interface FitnessFunction { 11 | 12 | /** 13 | * Computes the fitness value of the given chromosome. 14 | * 15 | * @param chromosome 16 | * @return - fitness value 17 | */ 18 | double evaluate(Chromosome chromosome); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/ro/jgal/Selector.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing selection operators. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public interface Selector { 10 | 11 | /** 12 | * Selects the parents from a given population 13 | * 14 | * @param pop - the population from which the parents are chosen 15 | * @return parents - the parents population 16 | */ 17 | public Population select(Population pop); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/ro/jgal/TerminationCriteria.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing termination criterias. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public interface TerminationCriteria { 10 | 11 | /** 12 | * Checks if the termination criteria has been reached. 13 | * 14 | * @param pop - checked population 15 | * @return - true if criteria is reached 16 | */ 17 | public boolean terminate(Population pop); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/ro/jgal/Crossover.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing crossover operators. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public interface Crossover { 10 | 11 | /** 12 | * Recombines the given parents population. Each 13 | * individual has a probability pc of recombining. 14 | * 15 | * @param parents - the parents population 16 | * @param pc - recombination probability 17 | * @return - children population 18 | */ 19 | public Population crossover(Population parents, double pc); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/ro/jgal/Mutator.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Interface for implementing mutators. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public interface Mutator { 10 | 11 | /** 12 | * Mutates the chromosomes from a given population. Each 13 | * individual has a probability pm of mutating. 14 | * 15 | * @param pop - the population which will be mutated 16 | * @param pm - the probability of each individual to mutate 17 | * @return - the mutated population 18 | */ 19 | public Population mutate(Population pop, double pm); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/ro/jgal/ConvergenceCriteria.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Terminates when the population converges. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public class ConvergenceCriteria implements TerminationCriteria { 10 | 11 | /** 12 | * Checks if the termination criteria has been reached. 13 | * 14 | * @param pop - checked population 15 | * @return - true if criteria is reached 16 | */ 17 | @Override 18 | public boolean terminate(Population pop) { 19 | pop.sort(); 20 | 21 | return pop.get(0).equals(pop.get(pop.length()-1)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/ro/jgal/TerminationCriterias.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | public class TerminationCriterias { 4 | 5 | /** 6 | * Convergence Criteria. Terminates when the population converges. 7 | * 8 | * @return - termination criteria 9 | */ 10 | public static TerminationCriteria convergenceCriteria() { 11 | return new ConvergenceCriteria(); 12 | } 13 | 14 | /** 15 | * Score Criteria. Terminates when the given score is reached. 16 | * 17 | * @param score - target score 18 | * @param roundDecimals - number of decimas to be rounded to 19 | * @return - termination criteria 20 | */ 21 | public static TerminationCriteria scoreCriteria(double score, int roundDecimals) { 22 | return new ScoreCriteria(score, roundDecimals); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/ro/jgal/Consts.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Constants class. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public class Consts { 10 | 11 | public static final int MINIMIZE = 1; 12 | public static final int MAXIMIZE = 2; 13 | 14 | public static final double MINRANGE = 0; 15 | public static final double MAXRANGE = 100; 16 | 17 | //probability of gene swap for uniform crossover 18 | public static final double UNIFORM_CX = 0.5; 19 | 20 | //number of elitism replacements 21 | public static final int NELITISM = 1; 22 | 23 | //remove duplicates after n iterations 24 | public static final int NITERATIONS = 100; 25 | 26 | //tournament size 27 | public static final int TOURNAMENT_SIZE = 2; 28 | //probability to select the best individual from 29 | //the tournament pool 30 | public static final int TOURNAMENT_P = 1; 31 | 32 | //binary string length 33 | public static final int BINARY_STRING_LENGTH = 5; 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/ro/jgal/MutatorFlip.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Flip Mutator. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | public class MutatorFlip implements Mutator { 12 | 13 | /** 14 | * Mutates the chromosomes from a given population. Each 15 | * individual has a probability pm of mutating. 16 | * 17 | * @param pop - the population which will be mutated 18 | * @param pm - the probability of each individual to mutate 19 | * @return - the mutated population 20 | */ 21 | @Override 22 | @SuppressWarnings({"unchecked"}) 23 | public Population mutate(Population pop, double pm) { 24 | 25 | Random r = new Random(); 26 | 27 | for (int i = 0; i < pop.length(); i++) { 28 | if (r.nextDouble() < pm) { 29 | Chromosome mutant = pop.get(i); 30 | 31 | int pos = Utils.randInt(0, mutant.length()); 32 | 33 | mutant.setGene(pos, (mutant.getGene(pos) + 1) % 2); 34 | } 35 | } 36 | 37 | return pop; 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.jar 8 | *.war 9 | *.ear 10 | 11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 12 | hs_err_pid* 13 | 14 | *.pydevproject 15 | .metadata 16 | .gradle 17 | bin/ 18 | tmp/ 19 | *.tmp 20 | *.bak 21 | *.swp 22 | *~.nib 23 | local.properties 24 | .settings/ 25 | .loadpath 26 | 27 | # Eclipse Core 28 | .project 29 | 30 | # External tool builders 31 | .externalToolBuilders/ 32 | 33 | # Locally stored "Eclipse launch configurations" 34 | *.launch 35 | 36 | # CDT-specific 37 | .cproject 38 | 39 | # JDT-specific (Eclipse Java Development Tools) 40 | .classpath 41 | 42 | # Java annotation processor (APT) 43 | .factorypath 44 | 45 | # PDT-specific 46 | .buildpath 47 | 48 | # sbteclipse plugin 49 | .target 50 | 51 | # TeXlipse plugin 52 | .texlipse 53 | *.class 54 | 55 | # Mobile Tools for Java (J2ME) 56 | .mtj.tmp/ 57 | 58 | # Package Files # 59 | *.jar 60 | *.war 61 | *.ear 62 | 63 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 64 | hs_err_pid* 65 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mihail Cristian Dumitru 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /src/ro/jgal/InitializerBinaryString.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Binary String Initializer. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings("rawtypes") 12 | public class InitializerBinaryString implements Initializer { 13 | 14 | int length; 15 | 16 | /** 17 | * Binary String Initializer. Default parameters: 18 | * length - 5 19 | */ 20 | public InitializerBinaryString() { 21 | this(Consts.BINARY_STRING_LENGTH); 22 | } 23 | 24 | /** 25 | * Binary String Initializer. 26 | * 27 | * @param length - length of the chromosome 28 | */ 29 | public InitializerBinaryString(int length) { 30 | this.length = length; 31 | } 32 | 33 | /** 34 | * Creates a new chromosome. 35 | * 36 | * @return - new chromosome 37 | */ 38 | @Override 39 | public Chromosome initialize() { 40 | ArrayList genes = new ArrayList(); 41 | for (int i = 0; i < length; i++) { 42 | int bit = Utils.randInt(2); 43 | genes.add(bit); 44 | } 45 | 46 | Chromosome c = new Chromosome(genes); 47 | return c; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/ro/jgal/InitializerIntegerPermutation.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | 6 | /** 7 | * Integer Permutation Initializer. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | @SuppressWarnings({"rawtypes"}) 13 | public class InitializerIntegerPermutation implements Initializer { 14 | 15 | int minrange; 16 | int maxrange; 17 | 18 | /** 19 | * Integer Permutation Initializer. 20 | * 21 | * @param minrange - minimum value (inclusive) 22 | * @param maxrange - maximum value (exclusive) 23 | */ 24 | public InitializerIntegerPermutation(int minrange, int maxrange) { 25 | this.minrange = minrange; 26 | this.maxrange = maxrange; 27 | } 28 | 29 | /** 30 | * Creates a new chromosome. 31 | * 32 | * @return - new chromosome 33 | */ 34 | @Override 35 | public Chromosome initialize() { 36 | ArrayList genes = new ArrayList(); 37 | 38 | for (int i = minrange; i < maxrange; i++) { 39 | genes.add(i); 40 | } 41 | Collections.shuffle(genes); 42 | 43 | Chromosome c = new Chromosome(genes); 44 | return c; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/ro/jgal/Statistics.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Statistics object. Keeps the min/max/avg/sum statistics 5 | * of a generation. 6 | * 7 | * @author Mihail Cristian Dumitru 8 | * 9 | */ 10 | public class Statistics { 11 | 12 | int gen; 13 | double min; 14 | double max; 15 | double avg; 16 | double sum; 17 | 18 | public int getGen() { 19 | return gen; 20 | } 21 | public void setGen(int gen) { 22 | this.gen = gen; 23 | } 24 | public double getMin() { 25 | return min; 26 | } 27 | public void setMin(double min) { 28 | this.min = min; 29 | } 30 | public double getMax() { 31 | return max; 32 | } 33 | public void setMax(double max) { 34 | this.max = max; 35 | } 36 | public double getAvg() { 37 | return avg; 38 | } 39 | public void setAvg(double avg) { 40 | this.avg = avg; 41 | } 42 | public double getSum() { 43 | return sum; 44 | } 45 | public void setSum(double sum) { 46 | this.sum = sum; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | String stats = "Gen. " + gen + " : Max/Min/Avg [" + max + "/" + min + "/" + avg + "]"; 52 | return stats; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/ro/jgal/MutatorSwap.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Swap Mutator. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | public class MutatorSwap implements Mutator { 12 | 13 | /** 14 | * Mutates the chromosomes from a given population. Each 15 | * individual has a probability pm of mutating. 16 | * 17 | * @param pop - the population which will be mutated 18 | * @param pm - the probability of each individual to mutate 19 | * @return - the mutated population 20 | */ 21 | @Override 22 | @SuppressWarnings({"rawtypes","unchecked"}) 23 | public Population mutate(Population pop, double pm) { 24 | 25 | Random r = new Random(); 26 | 27 | for (int i = 0; i < pop.length(); i++) { 28 | if (r.nextDouble() < pm) { 29 | Chromosome mutant = pop.get(i); 30 | 31 | int pos1 = Utils.randInt(0, mutant.length()); 32 | int pos2 = Utils.randInt(0, mutant.length()); 33 | 34 | Object temp; 35 | 36 | temp = mutant.getGene(pos1); 37 | 38 | mutant.setGene(pos1, mutant.getGene(pos2)); 39 | mutant.setGene(pos2, temp); 40 | } 41 | } 42 | 43 | return pop; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/ro/jgal/ScoreCriteria.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.math.BigDecimal; 4 | import java.math.RoundingMode; 5 | 6 | /** 7 | * Terminates when the given score is reached. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | public class ScoreCriteria implements TerminationCriteria { 13 | 14 | double score; 15 | int roundDecimals; 16 | 17 | /** 18 | * Score Criteria. Terminates when the given score is reached. 19 | * 20 | * @param score - target score 21 | * @param roundDecimals - number of decimas to be rounded to 22 | */ 23 | public ScoreCriteria(double score, int roundDecimals) { 24 | this.score = score; 25 | this.roundDecimals = roundDecimals; 26 | } 27 | 28 | /** 29 | * Checks if the termination criteria has been reached. 30 | * 31 | * @param pop - checked population 32 | * @return - true if criteria is reached 33 | */ 34 | @Override 35 | public boolean terminate(Population pop) { 36 | 37 | BigDecimal value = new BigDecimal(pop.getBestIndividual().getRawFitnessValue()); 38 | value = value.setScale(roundDecimals, RoundingMode.HALF_UP); 39 | 40 | BigDecimal target = new BigDecimal(score); 41 | target = target.setScale(roundDecimals, RoundingMode.HALF_UP); 42 | 43 | return value.equals(target); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/ro/jgal/InitializerString.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * String Initializer. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings({"rawtypes"}) 12 | public class InitializerString implements Initializer { 13 | 14 | char[] chars; 15 | int length; 16 | 17 | public InitializerString() { 18 | this("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", 5); 19 | } 20 | 21 | /** 22 | * String Initializer. 23 | * 24 | * @param allowedCharacters - allowed characters 25 | * @param length - length of the string 26 | */ 27 | InitializerString(String allowedCharacters, int length) { 28 | this.length = length; 29 | this.chars = new char[allowedCharacters.length()]; 30 | for (int i = 0; i < allowedCharacters.length(); i++) { 31 | chars[i] = allowedCharacters.charAt(i); 32 | } 33 | } 34 | 35 | /** 36 | * Creates a new chromosome. 37 | * 38 | * @return - new chromosome 39 | */ 40 | @Override 41 | public Chromosome initialize() { 42 | ArrayList string = new ArrayList(); 43 | while (string.size() < length) { 44 | char c = chars[Utils.randInt(chars.length)]; 45 | string.add(c); 46 | } 47 | 48 | return new Chromosome(string); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/ro/jgal/MutatorString.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * String Mutator. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public class MutatorString implements Mutator { 10 | 11 | char[] chars; 12 | 13 | /** 14 | * String Mutator. 15 | * 16 | * @param allowedCharacters - allowed characters 17 | */ 18 | public MutatorString(String allowedCharacters) { 19 | this.chars = new char[allowedCharacters.length()]; 20 | for (int i = 0; i < allowedCharacters.length(); i++) { 21 | chars[i] = allowedCharacters.charAt(i); 22 | } 23 | } 24 | 25 | /** 26 | * Mutates the chromosomes from a given population. Each 27 | * individual has a probability pm of mutating. 28 | * 29 | * @param pop - the population which will be mutated 30 | * @param pm - the probability of each individual to mutate 31 | * @return - the mutated population 32 | */ 33 | @Override 34 | @SuppressWarnings({"unchecked"}) 35 | public Population mutate(Population pop, double pm) { 36 | 37 | for (int i = 0; i < pop.length(); i++) { 38 | if (Math.random() < pm) { 39 | Chromosome mutant = pop.get(i); 40 | 41 | int pos = Utils.randInt(0, mutant.length()); 42 | 43 | mutant.setGene(pos, chars[Utils.randInt(chars.length)]); 44 | } 45 | } 46 | 47 | return pop; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/ro/jgal/SelectorUniform.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Uniform Selector. 7 | * 8 | * The parents are selected randomly from the population. 9 | * 10 | * @author Mihail Cristian Dumitru 11 | * 12 | */ 13 | @SuppressWarnings("rawtypes") 14 | public class SelectorUniform implements Selector { 15 | 16 | /** 17 | * Selects the parents from a given population. 18 | * 19 | * @param pop - the population from which the parents are chosen 20 | * @return parents - the parents population 21 | */ 22 | @Override 23 | public Population select(Population pop) { 24 | Random rand = new Random(); 25 | Population parents = new Population(); 26 | 27 | try { 28 | for (int i = 0; i < pop.length(); i++) { 29 | int p1 = rand.nextInt(pop.length()); 30 | int p2 = rand.nextInt(pop.length()); 31 | while (p2 == p1) { 32 | p2 = rand.nextInt(pop.length()); 33 | } 34 | 35 | if (pop.get(p1).getFitnessValue() > pop.get(p2).getFitnessValue()) { 36 | parents.add((Chromosome) pop.get(p1).clone()); 37 | } else { 38 | parents.add((Chromosome) pop.get(p2).clone()); 39 | } 40 | } 41 | } catch (CloneNotSupportedException e) { 42 | e.printStackTrace(); 43 | } 44 | 45 | return parents; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/ro/jgal/SelectorRouletteWheelSA.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Roulette Wheel Selector using stochastic acceptance. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings("rawtypes") 12 | public class SelectorRouletteWheelSA implements Selector { 13 | 14 | /** 15 | * Selects the parents from a given population. 16 | * 17 | * @param pop - the population from which the parents are chosen 18 | * @return parents - the parents population 19 | */ 20 | @Override 21 | public Population select(Population pop) { 22 | 23 | Population parents = new Population(); 24 | Random rand = new Random(); 25 | boolean notAccepted; 26 | int index = 0; 27 | 28 | try { 29 | for (int i = 0; i < pop.length(); i++) { 30 | notAccepted = true; 31 | 32 | while (notAccepted) { 33 | index = rand.nextInt(pop.length()); 34 | if (rand.nextDouble() < Math.abs(pop.get(index).getFitnessValue() / 35 | Math.abs(pop.getBestValue()))) { 36 | notAccepted = false; 37 | } 38 | } 39 | 40 | parents.add((Chromosome) pop.get(index).clone()); 41 | } 42 | } catch (CloneNotSupportedException e) { 43 | e.printStackTrace(); 44 | } 45 | 46 | return parents; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/ro/jgal/InitializerReal.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | 6 | /** 7 | * Real Initializer. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | @SuppressWarnings("rawtypes") 13 | public class InitializerReal implements Initializer { 14 | 15 | double minrange; 16 | double maxrange; 17 | int length; 18 | 19 | /** 20 | * Real Initializer. Default parameters: 21 | * minrange = 0, 22 | * maxrange = 100, 23 | * length = 2 24 | */ 25 | public InitializerReal() { 26 | this(Consts.MINRANGE, Consts.MAXRANGE, 2); 27 | } 28 | 29 | /** 30 | * Real Initializer. 31 | * 32 | * @param minrange - minimum value (inclusive) 33 | * @param maxrange - maximum value (exclusive) 34 | * @param length - length of the chromosome 35 | */ 36 | public InitializerReal(double _minrange, double _maxrange, int _length) { 37 | minrange = _minrange; 38 | maxrange = _maxrange; 39 | length = _length; 40 | } 41 | 42 | /** 43 | * Creates a new chromosome. 44 | * 45 | * @return - new chromosome 46 | */ 47 | @Override 48 | public Chromosome initialize() { 49 | 50 | ArrayList genes = new ArrayList(); 51 | for (int i = 0; i < length; i++) { 52 | genes.add(Utils.randRealUniform(minrange, maxrange)); 53 | } 54 | 55 | Chromosome c = new Chromosome(genes); 56 | return c; 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/ro/jgal/Crossovers.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | public class Crossovers { 4 | 5 | /** 6 | * Single Point Crossover. 7 | * 8 | * @return - crossover 9 | */ 10 | public static Crossover singlePoint() { 11 | return new CrossoverSinglePoint(); 12 | } 13 | 14 | /** 15 | * Two Point Crossover. 16 | * 17 | * @return - crossover 18 | */ 19 | public static Crossover twoPoint() { 20 | return new CrossoverTwoPoint(); 21 | } 22 | 23 | /** 24 | * Uniform Crossover. 25 | * 26 | * @return - crossover 27 | */ 28 | public static Crossover uniform() { 29 | return new CrossoverUniform(); 30 | } 31 | 32 | /** 33 | * Order Crossover. Works well for order optimizations. 34 | * Use it for integer permutations only. 35 | * 36 | * @return - crossover 37 | */ 38 | public static Crossover OX() { 39 | return new CrossoverOX(); 40 | } 41 | 42 | /** 43 | * Cycle Crossover. Works well for order optimizations. 44 | * Use it for integer permutations only. 45 | * 46 | * @return - crossover 47 | */ 48 | public static Crossover CX() { 49 | return new CrossoverCX(); 50 | } 51 | 52 | /** 53 | * Edge Crossover. Works well for order optimizations. 54 | * Use it for integer permutations only. 55 | * 56 | * @return - crossover 57 | */ 58 | public static Crossover edge() { 59 | return new CrossoverEdge(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/ro/jgal/InitializerInteger.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Integer Initializer. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings({"rawtypes"}) 12 | public class InitializerInteger implements Initializer { 13 | 14 | int minrange; 15 | int maxrange; 16 | int length; 17 | 18 | /** 19 | * Integer Initializer. Default parameters: 20 | * minrange = 0, 21 | * maxrange = 100, 22 | * length = 2. 23 | */ 24 | public InitializerInteger() { 25 | this((int) Consts.MINRANGE, (int) Consts.MAXRANGE, 2); 26 | } 27 | 28 | /** 29 | * Integer Initializer. 30 | * 31 | * @param minrange - minimum value (inclusive) 32 | * @param maxrange - maximum value (exclusive) 33 | * @param length - length of the chromosome 34 | */ 35 | public InitializerInteger(int minrange, int maxrange, int length) { 36 | this.minrange = minrange; 37 | this.maxrange = maxrange; 38 | this.length = length; 39 | } 40 | 41 | /** 42 | * Creates a new chromosome. 43 | * 44 | * @return - new chromosome 45 | */ 46 | @Override 47 | public Chromosome initialize() { 48 | ArrayList genes = new ArrayList(); 49 | for (int i = 0; i < length; i++) { 50 | genes.add(Utils.randInt(minrange, maxrange)); 51 | } 52 | 53 | Chromosome c = new Chromosome(genes); 54 | return c; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /src/ro/jgal/Selectors.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | public class Selectors { 4 | 5 | /** 6 | * Roulette Wheel Selector. 7 | * 8 | * @return - selector 9 | */ 10 | public static Selector rouletteWheel() { 11 | return new SelectorRouletteWheel(); 12 | } 13 | 14 | /** 15 | * Roulette Wheel Selector using stochastic acceptance. 16 | * 17 | * @return - selector 18 | */ 19 | public static Selector rouletteWheelSA() { 20 | return new SelectorRouletteWheelSA(); 21 | } 22 | 23 | /** 24 | * Uniform Selector. 25 | * 26 | * @return - selector 27 | */ 28 | public static Selector uniform() { 29 | return new SelectorUniform(); 30 | } 31 | 32 | /** 33 | * Stochastic Universal Sampling Selector. 34 | * 35 | * @return - selector 36 | */ 37 | public static Selector stochasticUniversalSampling() { 38 | return new SelectorStochasticUniversalSampling(); 39 | } 40 | 41 | /** 42 | * Tournament Selector. Default parameters: 43 | * poolSize = 2, 44 | * probability = 1.0 45 | * 46 | * @return - selector 47 | */ 48 | public static Selector tournament() { 49 | return new SelectorTournament(); 50 | } 51 | 52 | /** 53 | * Tournament Selector. 54 | * 55 | * @param poolSize - the size of the tournament pool 56 | * @param probability - the probability of the i'th best individual 57 | * to be chosen (1.0 -> the best one will always be chosen) 58 | * @return - selector 59 | */ 60 | public static Selector tournament(int poolSize, double probability) { 61 | return new SelectorTournament(poolSize, probability); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/ro/jgal/Mutators.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | public class Mutators { 4 | 5 | /** 6 | * Real Gaussian Mutator. Default paramenters: 7 | * minrange = 0, 8 | * maxrange = 100. 9 | * 10 | * @return - mutator 11 | */ 12 | public static Mutator realGaussian() { 13 | return new MutatorRealGaussian(); 14 | } 15 | 16 | /** 17 | * Real Gaussian Mutator. 18 | * 19 | * @param minrange - minimum value 20 | * @param maxrange - maximum value 21 | * @return - mutator 22 | */ 23 | public static Mutator realGaussian(double minrange, double maxrange) { 24 | return new MutatorRealGaussian(minrange, maxrange); 25 | } 26 | 27 | /** 28 | * Real Range Mutator. Default paramenters: 29 | * minrange = 0, 30 | * maxrange = 100. 31 | * 32 | * @return - mutator 33 | */ 34 | public static Mutator realRange() { 35 | return new MutatorRealRange(); 36 | } 37 | 38 | /** 39 | * Real Range Mutator. 40 | * 41 | * @param minrange - minimum value 42 | * @param maxrange - maximum value 43 | * @return - mutator 44 | */ 45 | public static Mutator realRange(double minrange, double maxrange) { 46 | return new MutatorRealRange(minrange, maxrange); 47 | } 48 | 49 | /** 50 | * Swap Mutator. 51 | * 52 | * @return - mutator 53 | */ 54 | public static Mutator swap() { 55 | return new MutatorSwap(); 56 | } 57 | 58 | /** 59 | * Flip Mutator. 60 | * 61 | * @return - mutator 62 | */ 63 | public static Mutator flip() { 64 | return new MutatorFlip(); 65 | } 66 | 67 | /** 68 | * String Mutator. 69 | * 70 | * @param allowedCharacters - allowed characters 71 | * @return - mutator 72 | */ 73 | public static Mutator string(String allowedCharacters) { 74 | return new MutatorString(allowedCharacters); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/ro/jgal/SelectorStochasticUniversalSampling.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Stochastic Universal Sampling Selector. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings("rawtypes") 12 | public class SelectorStochasticUniversalSampling implements Selector { 13 | 14 | double sum; 15 | double[] probability; 16 | double[] cumulatedProbability; 17 | double sumOfProbability; 18 | 19 | /** 20 | * Selects the parents from a given population. 21 | * 22 | * @param pop - the population from which the parents are chosen 23 | * @return parents - the parents population 24 | */ 25 | @Override 26 | public Population select(Population pop) { 27 | Population parents = new Population(); 28 | Random r = new Random(); 29 | 30 | try { 31 | sum = 0; 32 | probability = new double[pop.length()]; 33 | cumulatedProbability = new double[pop.length()]; 34 | sumOfProbability = 0; 35 | 36 | for (Chromosome c : pop) { 37 | sum += c.getFitnessValue(); 38 | } 39 | 40 | for (int i = 0; i < pop.length(); i++) { 41 | probability[i] = pop.get(i).getFitnessValue() / sum; 42 | sumOfProbability += probability[i]; 43 | probability[i] += sumOfProbability; 44 | cumulatedProbability[i] = sumOfProbability; 45 | } 46 | 47 | double step = 1.0 / pop.length(); 48 | double rand = r.nextDouble() * step; 49 | int i = 0; 50 | while (parents.length() < pop.length()) { 51 | while (rand < cumulatedProbability[i]) { 52 | parents.add((Chromosome) pop.get(i).clone()); 53 | rand += step; 54 | } 55 | i++; 56 | } 57 | } catch (CloneNotSupportedException e) { 58 | e.printStackTrace(); 59 | } 60 | 61 | return parents; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverSinglePoint.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Single Point Crossover. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | @SuppressWarnings({"unchecked"}) 10 | public class CrossoverSinglePoint implements Crossover { 11 | 12 | /** 13 | * Recombines the given parents population. Each 14 | * individual has a probability pc of recombining. 15 | * 16 | * @param parents - the parents population 17 | * @param pc - recombination probability 18 | * @return - children population 19 | */ 20 | @Override 21 | public Population crossover( 22 | Population parents, double pc) { 23 | if (pc < 0.0) { 24 | return parents; 25 | } 26 | if (parents.length() < 2) { 27 | return parents; 28 | } 29 | if (parents.get(0).length() == 1) { 30 | throw new IllegalStateException("Can't use Single Point Crossover on a chromosome with 1 gene."); 31 | } 32 | 33 | try { 34 | 35 | Population children = (Population) parents.clone(); 36 | 37 | for (int i = 0; i < parents.length(); i+=2) { 38 | if (Math.random() < pc) { 39 | if (i+1 == parents.length()) { 40 | break; 41 | } 42 | Chromosome mom = parents.get(i); 43 | Chromosome dad = parents.get(i+1); 44 | 45 | Chromosome sister = children.get(i); 46 | Chromosome brother = children.get(i+1); 47 | 48 | int pos = (int) (Math.random() * mom.length()); 49 | 50 | for (int j = pos; j < sister.length(); j++) { 51 | sister.setGene(j, dad.getGene(j)); 52 | brother.setGene(j, mom.getGene(j)); 53 | } 54 | } 55 | } 56 | 57 | return children; 58 | 59 | } catch (CloneNotSupportedException e) { 60 | e.printStackTrace(); 61 | } 62 | 63 | return null; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverUniform.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Uniform Crossover. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public class CrossoverUniform implements Crossover { 10 | 11 | /** 12 | * Recombines the given parents population. Each 13 | * individual has a probability pc of recombining. 14 | * 15 | * @param parents - the parents population 16 | * @param pc - recombination probability 17 | * @return - children population 18 | */ 19 | @Override 20 | @SuppressWarnings({"unchecked"}) 21 | public Population crossover(Population parents, double pc) { 22 | if (pc == 0.0) { 23 | return parents; 24 | } 25 | if (parents.length() < 2) { 26 | return parents; 27 | } 28 | if (parents.get(0).length() == 1) { 29 | throw new IllegalStateException("Can't use Two Point Crossover on a chromosome with less than 2 genes."); 30 | } 31 | 32 | try { 33 | 34 | Population children = (Population) parents.clone(); 35 | 36 | for (int i = 0; i < parents.length(); i+=2) { 37 | if (Math.random() < pc) { 38 | if (i+1 == parents.length()) { 39 | break; 40 | } 41 | Chromosome mom = parents.get(i); 42 | Chromosome dad = parents.get(i+1); 43 | 44 | Chromosome sister = children.get(i); 45 | Chromosome brother = children.get(i+1); 46 | 47 | for (int j = 0; j < mom.length(); j++) { 48 | if (Math.random() < Consts.UNIFORM_CX) { 49 | sister.setGene(j, dad.getGene(j)); 50 | brother.setGene(j, mom.getGene(j)); 51 | } 52 | } 53 | } 54 | } 55 | 56 | return children; 57 | 58 | } catch (CloneNotSupportedException e) { 59 | e.printStackTrace(); 60 | } 61 | return null; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverTwoPoint.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | /** 4 | * Two Point Crossover. 5 | * 6 | * @author Mihail Cristian Dumitru 7 | * 8 | */ 9 | public class CrossoverTwoPoint implements Crossover { 10 | 11 | /** 12 | * Recombines the given parents population. Each 13 | * individual has a probability pc of recombining. 14 | * 15 | * @param parents - the parents population 16 | * @param pc - recombination probability 17 | * @return - children population 18 | */ 19 | @Override 20 | @SuppressWarnings({"unchecked"}) 21 | public Population crossover(Population parents, double pc) { 22 | if (pc == 0.0) { 23 | return parents; 24 | } 25 | if (parents.length() < 2) { 26 | return parents; 27 | } 28 | if (parents.get(0).length() == 1) { 29 | throw new IllegalStateException("Can't use Two Point Crossover on a chromosome with less than 2 genes."); 30 | } 31 | 32 | try { 33 | 34 | Population children = (Population) parents.clone(); 35 | 36 | for (int i = 0; i < parents.length(); i+=2) { 37 | if (Math.random() < pc) { 38 | if (i+1 == parents.length()) { 39 | break; 40 | } 41 | Chromosome mom = parents.get(i); 42 | Chromosome dad = parents.get(i+1); 43 | 44 | Chromosome sister = children.get(i); 45 | Chromosome brother = children.get(i+1); 46 | 47 | int pos1 = Utils.randInt(1, mom.length()); 48 | int pos2 = Utils.randInt(1, mom.length()); 49 | 50 | if (pos1 > pos2) { 51 | int temp = pos1; 52 | pos1 = pos2; 53 | pos2 = temp; 54 | } 55 | 56 | for (int j = pos1; j < pos2; j++) { 57 | sister.setGene(j, dad.getGene(j)); 58 | brother.setGene(j, mom.getGene(j)); 59 | } 60 | } 61 | } 62 | 63 | return children; 64 | 65 | } catch (CloneNotSupportedException e) { 66 | e.printStackTrace(); 67 | } 68 | 69 | return null; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/ro/jgal/MutatorRealRange.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Real Range Mutator. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings({"rawtypes", "unchecked"}) 12 | public class MutatorRealRange implements Mutator { 13 | 14 | double minrange; 15 | double maxrange; 16 | 17 | /** 18 | * Real Range Mutator. Default paramenters: 19 | * minrange = 0, 20 | * maxrange = 100. 21 | */ 22 | public MutatorRealRange() { 23 | this(Consts.MINRANGE, Consts.MAXRANGE); 24 | } 25 | 26 | /** 27 | * Real Range Mutator. 28 | * 29 | * @param minrange - minimum value 30 | * @param maxrange - maximum value 31 | */ 32 | public MutatorRealRange(double minrange, double maxrange) { 33 | this.minrange = minrange; 34 | this.maxrange = maxrange; 35 | } 36 | 37 | /** 38 | * Mutates the chromosomes from a given population. Each 39 | * individual has a probability pm of mutating. 40 | * 41 | * @param pop - the population which will be mutated 42 | * @param pm - the probability of each individual to mutate 43 | * @return - the mutated population 44 | */ 45 | @Override 46 | public Population mutate(Population pop, double pm) { 47 | 48 | Random r = new Random(); 49 | 50 | for (Chromosome c : pop) { 51 | int len = c.length(); 52 | double mutations = pm * len; 53 | 54 | if (mutations < 1.0) { 55 | mutations = 0; 56 | for (int i = 0; i < len; i++) { 57 | if (r.nextDouble() < pm) { 58 | c.getGenes().set( 59 | i, 60 | Utils.randRealUniform(minrange, maxrange) 61 | ); 62 | mutations += 1; 63 | } 64 | } 65 | } else { 66 | int bound = (int) Math.round(mutations); 67 | for (int i = 0; i < bound; i++) { 68 | int index = Utils.randInt(len); 69 | c.getGenes().set( 70 | index, 71 | Utils.randRealUniform(minrange, maxrange) 72 | ); 73 | } 74 | } 75 | } 76 | 77 | return pop; 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/examples/OneMax.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * One-Max problem is a simple problem consisting in 17 | * maximizing the number of ones of a binary string. 18 | * 19 | * @author Mihail Cristian Dumitru 20 | * 21 | */ 22 | @SuppressWarnings({"rawtypes", "unchecked"}) 23 | public class OneMax { 24 | 25 | public static void main(String[] args) { 26 | 27 | int n = 100; //number of genes 28 | double targetScore = n; //target score, the evolution will terminate when it is reached 29 | int precision = 1; //precision of the target score 30 | int generations = 10000; //number of generations 31 | int populationSize = 100; //population size 32 | double crossoverProbability = 0.8; //crossover probability 33 | double mutationProbability = 1.0 / n; //mutation probability 34 | int elitismReplacements = 5; //number of elitism replacements 35 | 36 | GeneticAlgorithm ga = new GeneticAlgorithm() 37 | .setCrossover(Crossovers.singlePoint()) 38 | .setSelector(Selectors.uniform()) 39 | .setMutator(Mutators.flip()) 40 | .setMinimax(Consts.MAXIMIZE) 41 | .setInitializer(Initializers.binaryString(n)) 42 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 43 | .setFitnessFunction(new FitnessFunction() { 44 | @Override 45 | public double evaluate(Chromosome chromosome) { 46 | ArrayList genes = chromosome.getGenes(); 47 | double score = 0; 48 | 49 | for (int i = 0; i < genes.size(); i++) { 50 | score += genes.get(i) * 1; 51 | } 52 | 53 | return score; 54 | } 55 | }) 56 | .setGenerations(generations) 57 | .setPopulationSize(populationSize) 58 | .setCrossoverProbability(crossoverProbability) 59 | .setMutationProbability(mutationProbability) 60 | .setElitismReplacements(elitismReplacements); 61 | 62 | ga.evolve(500); 63 | 64 | System.out.println(ga.getSolution()); 65 | System.out.println(ga.getSolution().getRawFitnessValue()); 66 | 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/examples/Rosenbrock.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | 14 | /** 15 | * Rosenbrock Function. The global minimum is f(x) = 0, at 16 | * x=(1,..,1). 17 | * More info at: http://www.sfu.ca/~ssurjano/rosen.html 18 | * 19 | * @author Mihail Cristian Dumitru 20 | * 21 | */ 22 | @SuppressWarnings({"rawtypes","unchecked"}) 23 | public class Rosenbrock { 24 | 25 | public static void main(String[] args) { 26 | 27 | int n = 15; //number of genes 28 | double minrange = -2.048; //minimum value 29 | double maxrange = 2.048; //maximum value 30 | int generations = 10000; //number of generations 31 | int populationSize = 100; //population size 32 | double crossoverProbability = 0.9; //crossover probability 33 | double mutationProbability = 0.1; //mutation probability 34 | int elitismReplacements = 5; //number of elitism replacements 35 | 36 | GeneticAlgorithm ga = new GeneticAlgorithm() 37 | .setCrossover(Crossovers.singlePoint()) 38 | .setSelector(Selectors.uniform()) 39 | .setMutator(Mutators.realRange(minrange, maxrange)) 40 | .setMinimax(Consts.MINIMIZE) 41 | .setInitializer(Initializers.real(minrange, maxrange, n)) 42 | .setFitnessFunction(new FitnessFunction() { 43 | @Override 44 | public double evaluate(Chromosome chromosome) { 45 | ArrayList genes = chromosome.getGenes(); 46 | 47 | double score = 0; 48 | for (int i = 1; i < genes.size(); i++) { 49 | Double x = genes.get(i); 50 | Double y = genes.get(i-1); 51 | score += 100.0 * Math.pow(x - y*y, 2) + Math.pow(1 - y, 2); 52 | } 53 | 54 | return score; 55 | } 56 | }) 57 | .setGenerations(generations) 58 | .setPopulationSize(populationSize) 59 | .setCrossoverProbability(crossoverProbability) 60 | .setMutationProbability(mutationProbability) 61 | .setElitismReplacements(elitismReplacements); 62 | 63 | ga.evolve(); 64 | 65 | System.out.println(ga.getSolution()); 66 | System.out.println(ga.getSolution().getRawFitnessValue()); 67 | 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/ro/jgal/MutatorRealGaussian.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.Random; 4 | 5 | /** 6 | * Real Gaussian Mutator. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings("unchecked") 12 | public class MutatorRealGaussian implements Mutator { 13 | 14 | double mu; 15 | double sigma; 16 | double minrange; 17 | double maxrange; 18 | 19 | /** 20 | * Real Gaussian Mutator. Default paramenters: 21 | * minrange = 0, 22 | * maxrange = 100. 23 | */ 24 | public MutatorRealGaussian() { 25 | this(Consts.MINRANGE, Consts.MAXRANGE); 26 | } 27 | 28 | /** 29 | * Real Gaussian Mutator. 30 | * 31 | * @param minrange - minimum value 32 | * @param maxrange - maximum value 33 | */ 34 | public MutatorRealGaussian(double minrange, double maxrange) { 35 | this.minrange = minrange; 36 | this.maxrange = maxrange; 37 | } 38 | 39 | /** 40 | * Mutates the chromosomes from a given population. Each 41 | * individual has a probability pm of mutating. 42 | * 43 | * @param pop - the population which will be mutated 44 | * @param pm - the probability of each individual to mutate 45 | * @return - the mutated population 46 | */ 47 | @Override 48 | public Population mutate(Population pop, double pm) { 49 | 50 | if (pm < 0.0) { 51 | return pop; 52 | } 53 | 54 | Random r = new Random(); 55 | for (Chromosome c : pop) { 56 | 57 | double mutations = pm * c.length(); 58 | 59 | if (mutations < 1.0) { 60 | if (r.nextDouble() < pm) { 61 | for (int i = 0; i < c.length(); i++) { 62 | double finalValue = (Double) c.getGene(i) + r.nextGaussian(); 63 | 64 | finalValue = Math.min(finalValue, maxrange); 65 | finalValue = Math.max(finalValue, minrange); 66 | 67 | c.setGene(i, finalValue); 68 | } 69 | } 70 | } else { 71 | int bound = (int) Math.round(mutations); 72 | for (int i = 0; i < bound; i++) { 73 | int index = r.nextInt(c.length()); 74 | double finalValue = (Double) c.getGene(index) + r.nextGaussian(); 75 | 76 | finalValue = Math.min(finalValue, maxrange); 77 | finalValue = Math.max(finalValue, minrange); 78 | 79 | c.setGene(index, finalValue); 80 | } 81 | } 82 | } 83 | 84 | return pop; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/examples/Sphere.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * Sphere Function. The global minimum is f(x) = 0, at 17 | * x = (0,..,0). 18 | * More info at: http://www.sfu.ca/~ssurjano/spheref.html 19 | * 20 | * @author Mihail Cristian Dumitru 21 | * 22 | */ 23 | @SuppressWarnings({"rawtypes","unchecked"}) 24 | public class Sphere { 25 | 26 | public static void main(String[] args) { 27 | 28 | int n = 5; //number of genes 29 | double minrange = -100; //minimum value 30 | double maxrange = 100; //maximum value 31 | double targetScore = 0.0; //target score, the evolution will terminate when it is reached 32 | int precision = 2; //precision of the target score 33 | int generations = 10000; //number of generations 34 | int populationSize = 100; //population size 35 | double crossoverProbability = 0.8; //crossover probability 36 | double mutationProbability = 0.05; //mutation probability 37 | int elitismReplacements = 5; //number of elitism replacements 38 | 39 | GeneticAlgorithm ga = new GeneticAlgorithm() 40 | .setCrossover(Crossovers.singlePoint()) 41 | .setSelector(Selectors.uniform()) 42 | .setMutator(Mutators.realRange(minrange, maxrange)) 43 | .setMinimax(Consts.MINIMIZE) 44 | .setInitializer(Initializers.real(minrange, maxrange, n)) 45 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 46 | .setFitnessFunction(new FitnessFunction() { 47 | @Override 48 | public double evaluate(Chromosome chromosome) { 49 | ArrayList genes = (ArrayList)chromosome.getGenes(); 50 | 51 | double score = 0; 52 | for (int i = 0; i < genes.size(); i++) { 53 | score += genes.get(i) * genes.get(i); 54 | } 55 | 56 | return score; 57 | } 58 | }) 59 | .setGenerations(generations) 60 | .setPopulationSize(populationSize) 61 | .setCrossoverProbability(crossoverProbability) 62 | .setMutationProbability(mutationProbability) 63 | .setElitismReplacements(elitismReplacements); 64 | 65 | ga.evolve(); 66 | 67 | System.out.println(ga.getSolution()); 68 | System.out.println(ga.getSolution().getRawFitnessValue()); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/examples/DropWave.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import static java.lang.Math.cos; 4 | import static java.lang.Math.sqrt; 5 | 6 | import java.util.ArrayList; 7 | 8 | import ro.jgal.Chromosome; 9 | import ro.jgal.Consts; 10 | import ro.jgal.Crossovers; 11 | import ro.jgal.FitnessFunction; 12 | import ro.jgal.GeneticAlgorithm; 13 | import ro.jgal.Initializers; 14 | import ro.jgal.Mutators; 15 | import ro.jgal.Selectors; 16 | import ro.jgal.TerminationCriterias; 17 | 18 | /** 19 | * Drop-Wave Function. Global minimum is f(x) = -1, at x=(0,0). 20 | * More info at: http://www.sfu.ca/~ssurjano/drop.html 21 | * 22 | * @author Mihail Cristian Dumitru 23 | * 24 | */ 25 | @SuppressWarnings({"rawtypes","unchecked"}) 26 | public class DropWave { 27 | 28 | public static void main(String[] args) { 29 | 30 | int n = 2; //number of genes 31 | double minrange = -5.12; //minimum value 32 | double maxrange = 5.12; //maximum value 33 | double targetScore = -1.0; //target score, the evolution will terminate when it is reached 34 | int precision = 4; //precision of the target score 35 | int generations = 10000; //number of generations 36 | int populationSize = 100; //population size 37 | double crossoverProbability = 1; //crossover probability 38 | double mutationProbability = 0.05; //mutation probability 39 | int elitismReplacements = 5; //number of elitism replacements 40 | 41 | GeneticAlgorithm ga = new GeneticAlgorithm() 42 | .setCrossover(Crossovers.singlePoint()) 43 | .setSelector(Selectors.uniform()) 44 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 45 | .setMinimax(Consts.MINIMIZE) 46 | .setInitializer(Initializers.real(minrange, maxrange, n)) 47 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 48 | .setFitnessFunction(new FitnessFunction() { 49 | @Override 50 | public double evaluate(Chromosome chromosome) { 51 | ArrayList genes = chromosome.getGenes(); 52 | 53 | double x = genes.get(0); 54 | double y = genes.get(1); 55 | 56 | double score = - ((1 + cos(12 * sqrt(x*x + y*y))) / (0.5 * (x*x + y*y) + 2)); 57 | 58 | return score; 59 | } 60 | }) 61 | .setGenerations(generations) 62 | .setPopulationSize(populationSize) 63 | .setCrossoverProbability(crossoverProbability) 64 | .setMutationProbability(mutationProbability) 65 | .setElitismReplacements(elitismReplacements); 66 | 67 | ga.evolve(500); 68 | 69 | System.out.println(ga.getSolution()); 70 | System.out.println(ga.getSolution().getRawFitnessValue()); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/ro/jgal/Initializers.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | public class Initializers { 4 | 5 | /** 6 | * Real Initializer. Default parameters: 7 | * minrange = 0, 8 | * maxrange = 100, 9 | * length = 2 10 | * 11 | * @return - initializer 12 | */ 13 | public static Initializer real() { 14 | return new InitializerReal(); 15 | } 16 | 17 | /** 18 | * Real Initializer. 19 | * 20 | * @param minrange - minimum value (inclusive) 21 | * @param maxrange - maximum value (exclusive) 22 | * @param length - length of the chromosome 23 | * @return - initializer 24 | */ 25 | public static Initializer real(double minrange, double maxrange, int length) { 26 | return new InitializerReal(minrange, maxrange, length); 27 | } 28 | 29 | /** 30 | * Integer Initializer. Default parameters: 31 | * minrange = 0, 32 | * maxrange = 100, 33 | * length = 2 34 | * 35 | * @return - initializer 36 | */ 37 | public static Initializer integer() { 38 | return new InitializerInteger(); 39 | } 40 | 41 | /** 42 | * Integer Initializer. 43 | * 44 | * @param minrange - minimum value (inclusive) 45 | * @param maxrange - maximum value (exclusive) 46 | * @param length - length of the chromosome 47 | * @return - initializer 48 | */ 49 | public static Initializer integer(int minrange, int maxrange, int length) { 50 | return new InitializerInteger(minrange, maxrange, length); 51 | } 52 | 53 | /** 54 | * Integer Permutation Initializer. 55 | * 56 | * @param minrange - minimum value (inclusive) 57 | * @param maxrange - maximum value (exclusive) 58 | * @return - initializer 59 | */ 60 | public static Initializer integerPermutation(int minrange, int maxrange) { 61 | return new InitializerIntegerPermutation(minrange, maxrange); 62 | } 63 | 64 | /** 65 | * Binary String Initializer. Default parameters: 66 | * length - 5 67 | */ 68 | public static Initializer binaryString() { 69 | return new InitializerBinaryString(); 70 | } 71 | 72 | /** 73 | * Binary String Initializer. 74 | * 75 | * @param length - length of the chromosome 76 | */ 77 | public static Initializer binaryString(int length) { 78 | return new InitializerBinaryString(length); 79 | } 80 | 81 | /** 82 | * String Initializer. 83 | * 84 | * @param allowedCharacters - allowed characters 85 | * @param length - length of the string 86 | * @return - initializer 87 | */ 88 | public static Initializer string(String allowedCharacters, int length) { 89 | return new InitializerString(allowedCharacters, length); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/examples/WeaselProgram.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * Richard Dawkins's Weasel Program. 17 | * More info at: https://en.wikipedia.org/wiki/Weasel_program 18 | * 19 | * @author Mihail Cristian Dumitru 20 | * 21 | */ 22 | @SuppressWarnings({"unchecked", "rawtypes"}) 23 | public class WeaselProgram { 24 | 25 | public static void main(String[] args) { 26 | 27 | int n = 28; //number of genes 28 | int generations = 10000; //number of generations 29 | int populationSize = 100; //population size 30 | double targetScore = n; //target score, the evolution will terminate when it is reached 31 | int precision = 2; //precision of the target score 32 | String allowedCharacters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "; 33 | double crossoverProbability = 1; //crossover probability 34 | double mutationProbability = 0.05; //mutation probability 35 | int elitismReplacements = 5; //number of elitism replacements 36 | 37 | GeneticAlgorithm ga = new GeneticAlgorithm() 38 | .setCrossover(Crossovers.singlePoint()) 39 | .setSelector(Selectors.uniform()) 40 | .setMutator(Mutators.string(allowedCharacters)) 41 | .setMinimax(Consts.MAXIMIZE) 42 | .setInitializer(Initializers.string(allowedCharacters, n)) 43 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 44 | .setFitnessFunction(new FitnessFunction() { 45 | 46 | String targetString = "METHINKS IT IS LIKE A WEASEL"; 47 | 48 | @Override 49 | public double evaluate(Chromosome chromosome) { 50 | ArrayList genes = chromosome.getGenes(); 51 | 52 | double score = 0; 53 | 54 | for (int i = 0; i < genes.size(); i++) { 55 | if (genes.get(i).equals(targetString.charAt(i))) { 56 | score += 1; 57 | } 58 | } 59 | 60 | return score; 61 | } 62 | }) 63 | .setGenerations(generations) 64 | .setPopulationSize(populationSize) 65 | .setCrossoverProbability(crossoverProbability) 66 | .setMutationProbability(mutationProbability) 67 | .setElitismReplacements(elitismReplacements); 68 | 69 | ga.evolve(500); 70 | 71 | System.out.println(ga.getSolution()); 72 | System.out.println(ga.getSolution().getRawFitnessValue()); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/examples/SchafferN2.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import static java.lang.Math.pow; 4 | import static java.lang.Math.sin; 5 | 6 | import java.util.ArrayList; 7 | 8 | import ro.jgal.Chromosome; 9 | import ro.jgal.Consts; 10 | import ro.jgal.Crossovers; 11 | import ro.jgal.FitnessFunction; 12 | import ro.jgal.GeneticAlgorithm; 13 | import ro.jgal.Initializers; 14 | import ro.jgal.Mutators; 15 | import ro.jgal.Selectors; 16 | import ro.jgal.TerminationCriterias; 17 | 18 | /** 19 | * Schaffer Function 2. The global minimum is f(x) = 0, at 20 | * x = (0,0). 21 | * More info at: http://www.sfu.ca/~ssurjano/schaffer2.html 22 | * 23 | * @author Mihail Cristian Dumitru 24 | * 25 | */ 26 | @SuppressWarnings({"rawtypes","unchecked"}) 27 | public class SchafferN2 { 28 | 29 | public static void main(String[] args) { 30 | 31 | int n = 2; //number of genes 32 | double minrange = -100; //minimum value 33 | double maxrange = 100; //maximum value 34 | double targetScore = 0.0; //target score, the evolution will terminate when it is reached 35 | int precision = 2; //precision of the target score 36 | int generations = 10000; //number of generations 37 | int populationSize = 100; //population size 38 | double crossoverProbability = 0.8; //crossover probability 39 | double mutationProbability = 0.2; //mutation probability 40 | int elitismReplacements = 5; //number of elitism replacements 41 | 42 | GeneticAlgorithm ga = new GeneticAlgorithm() 43 | .setCrossover(Crossovers.singlePoint()) 44 | .setSelector(Selectors.rouletteWheel()) 45 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 46 | .setMinimax(Consts.MINIMIZE) 47 | .setInitializer(Initializers.real(minrange, maxrange, n)) 48 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 49 | .setFitnessFunction(new FitnessFunction() { 50 | @Override 51 | public double evaluate(Chromosome chromosome) { 52 | ArrayList genes = chromosome.getGenes(); 53 | 54 | double x = genes.get(0); 55 | double y = genes.get(1); 56 | 57 | double score = 0.5 + (pow(sin(x * x - y * y), 2) - 0.5) / 58 | pow(1 + 0.001 * (x * x + y * y), 2); 59 | 60 | return score; 61 | } 62 | }) 63 | .setGenerations(generations) 64 | .setPopulationSize(populationSize) 65 | .setCrossoverProbability(crossoverProbability) 66 | .setMutationProbability(mutationProbability) 67 | .setElitismReplacements(elitismReplacements); 68 | 69 | ga.evolve(); 70 | 71 | System.out.println(ga.getSolution()); 72 | System.out.println(ga.getSolution().getRawFitnessValue()); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/examples/RealGauss.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * A simple problem demonstrating the real initializer and the 17 | * real gaussian mutation operator. The fitness function consists 18 | * in maximizing the function f(xi)= sum of 0.1 for all xi < 0, 19 | * xi=[-5,5]. The global maximum is 5. 20 | * 21 | * @author Mihail Cristian Dumitru 22 | * 23 | */ 24 | @SuppressWarnings({"rawtypes", "unchecked"}) 25 | public class RealGauss { 26 | 27 | public static void main(String[] args) { 28 | 29 | int n = 50; //number of genes 30 | double minrange = -5; //minimum value 31 | double maxrange = 5; //maximum value 32 | double targetScore = n / 10; //target score, the evolution will terminate when it is reached 33 | int precision = 2; //precision of the target score 34 | int generations = 10000; //number of generations 35 | int populationSize = 100; //population size 36 | double crossoverProbability = 1; //crossover probability 37 | double mutationProbability = 0.05; //mutation probability 38 | int elitismReplacements = 5; //number of elitism replacements 39 | 40 | GeneticAlgorithm ga = new GeneticAlgorithm() 41 | .setCrossover(Crossovers.singlePoint()) 42 | .setSelector(Selectors.uniform()) 43 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 44 | .setInitializer(Initializers.real(minrange, maxrange, n)) 45 | .setMinimax(Consts.MAXIMIZE) 46 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 47 | .setFitnessFunction(new FitnessFunction() { 48 | @Override 49 | public double evaluate(Chromosome chromosome) { 50 | ArrayList genes = chromosome.getGenes(); 51 | 52 | double score = 0; 53 | 54 | for (int i = 0; i < genes.size(); i++) { 55 | if (genes.get(i) < 0) { 56 | score += 0.1; 57 | } 58 | } 59 | 60 | return score; 61 | } 62 | }) 63 | .setGenerations(generations) 64 | .setPopulationSize(populationSize) 65 | .setCrossoverProbability(crossoverProbability) 66 | .setMutationProbability(mutationProbability) 67 | .setElitismReplacements(elitismReplacements); 68 | 69 | ga.evolve(500); 70 | 71 | System.out.println(ga.getSolution()); 72 | System.out.println(ga.getSolution().getRawFitnessValue()); 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/examples/Easom.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import static java.lang.Math.PI; 4 | import static java.lang.Math.cos; 5 | import static java.lang.Math.exp; 6 | import static java.lang.Math.pow; 7 | 8 | import java.util.ArrayList; 9 | 10 | import ro.jgal.Chromosome; 11 | import ro.jgal.Consts; 12 | import ro.jgal.Crossovers; 13 | import ro.jgal.FitnessFunction; 14 | import ro.jgal.GeneticAlgorithm; 15 | import ro.jgal.Initializers; 16 | import ro.jgal.Mutators; 17 | import ro.jgal.Selectors; 18 | import ro.jgal.TerminationCriterias; 19 | 20 | /** 21 | * Eason Function. Global minimum is f(x) = -1, at x=(pi,pi). 22 | * More info at: http://www.sfu.ca/~ssurjano/easom.html 23 | * 24 | * @author Mihail Cristian Dumitru 25 | * 26 | */ 27 | @SuppressWarnings({"rawtypes","unchecked"}) 28 | public class Easom { 29 | 30 | public static void main(String[] args) { 31 | 32 | int n = 2; //number of genes 33 | double minrange = -100; //minimum value 34 | double maxrange = 100; //maximum value 35 | double targetScore = -1.0; //target score, the evolution will terminate when it is reached 36 | int precision = 2; //precision of the target score 37 | int generations = 10000; //number of generations 38 | int populationSize = 100; //population size 39 | double crossoverProbability = 0.8; //crossover probability 40 | double mutationProbability = 0.05; //mutation probability 41 | int elitismReplacements = 5; //number of elitism replacements 42 | 43 | GeneticAlgorithm ga = new GeneticAlgorithm() 44 | .setCrossover(Crossovers.singlePoint()) 45 | .setSelector(Selectors.uniform()) 46 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 47 | .setMinimax(Consts.MINIMIZE) 48 | .setInitializer(Initializers.real(minrange, maxrange, n)) 49 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 50 | .setFitnessFunction(new FitnessFunction() { 51 | @Override 52 | public double evaluate(Chromosome chromosome) { 53 | ArrayList genes = chromosome.getGenes(); 54 | 55 | double x = genes.get(0); 56 | double y = genes.get(1); 57 | 58 | double score = -cos(x) * cos(y) * 59 | exp(-(pow(x - PI, 2) + pow(y - PI, 2))); 60 | 61 | return score; 62 | } 63 | }) 64 | .setGenerations(generations) 65 | .setPopulationSize(populationSize) 66 | .setCrossoverProbability(crossoverProbability) 67 | .setMutationProbability(mutationProbability) 68 | .setElitismReplacements(elitismReplacements); 69 | 70 | ga.evolve(); 71 | 72 | System.out.println(ga.getSolution()); 73 | System.out.println(ga.getSolution().getRawFitnessValue()); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /src/examples/Ackley.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * Ackley Function. Global minimum is f(x) = 0, for x = (0,..,0). 17 | * More info at: http://www.sfu.ca/~ssurjano/ackley.html 18 | * 19 | * @author Mihail Cristian Dumitru 20 | * 21 | */ 22 | @SuppressWarnings({"rawtypes","unchecked"}) 23 | public class Ackley { 24 | 25 | public static void main(String[] args) { 26 | 27 | int n = 2; //number of genes 28 | double minrange = -5; //minimum value 29 | double maxrange = 5; //maximum value 30 | double targetScore = 0.0; //target score, the evolution will terminate when it is reached 31 | int precision = 2; //precision of the target score 32 | int generations = 10000; //number of generations 33 | int populationSize = 100; //population size 34 | double crossoverProbability = 1; //crossover probability 35 | double mutationProbability = 0.05; //mutation probability 36 | int elitismReplacements = 5; //number of elitism replacements 37 | 38 | 39 | GeneticAlgorithm ga = new GeneticAlgorithm() 40 | .setCrossover(Crossovers.singlePoint()) 41 | .setSelector(Selectors.uniform()) 42 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 43 | .setMinimax(Consts.MINIMIZE) 44 | .setInitializer(Initializers.real(minrange, maxrange, n)) 45 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 46 | .setFitnessFunction(new FitnessFunction() { 47 | @Override 48 | public double evaluate(Chromosome chromosome) { 49 | ArrayList genes = chromosome.getGenes(); 50 | 51 | double x = genes.get(0); 52 | double y = genes.get(1); 53 | 54 | double score = -20 * Math.exp(-0.2 * Math.sqrt(0.5 * (x*x + y*y))) - 55 | Math.exp(0.5 * (Math.cos(2 * Math.PI * x) + Math.cos(2 * Math.PI * y))) + 56 | Math.E + 20; 57 | 58 | return score; 59 | } 60 | }) 61 | .setGenerations(generations) 62 | .setPopulationSize(populationSize) 63 | .setCrossoverProbability(crossoverProbability) 64 | .setMutationProbability(mutationProbability) 65 | .setElitismReplacements(elitismReplacements); 66 | 67 | ga.evolve(500); 68 | 69 | System.out.println(ga.getSolution()); 70 | System.out.println(ga.getSolution().getRawFitnessValue()); 71 | 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/examples/SchafferN4.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import static java.lang.Math.abs; 4 | import static java.lang.Math.cos; 5 | import static java.lang.Math.pow; 6 | import static java.lang.Math.sin; 7 | 8 | import java.util.ArrayList; 9 | 10 | import ro.jgal.Chromosome; 11 | import ro.jgal.Consts; 12 | import ro.jgal.Crossovers; 13 | import ro.jgal.FitnessFunction; 14 | import ro.jgal.GeneticAlgorithm; 15 | import ro.jgal.Initializers; 16 | import ro.jgal.Mutators; 17 | import ro.jgal.Selectors; 18 | import ro.jgal.TerminationCriterias; 19 | 20 | /** 21 | * Schaffer Function 4. The global minimum is f(x) = 0.292579, at 22 | * x = (0,1.25313). 23 | * More info at: http://www.sfu.ca/~ssurjano/schaffer4.html 24 | * 25 | * @author Mihail Cristian Dumitru 26 | * 27 | */ 28 | @SuppressWarnings({"rawtypes","unchecked"}) 29 | public class SchafferN4 { 30 | 31 | public static void main(String[] args) { 32 | 33 | int n = 2; //number of genes 34 | double minrange = -100; //minimum value 35 | double maxrange = 100; //maximum value 36 | double targetScore = 0.292579; //target score, the evolution will terminate when it is reached 37 | int precision = 6; //precision of the target score 38 | int generations = 10000; //number of generations 39 | int populationSize = 100; //population size 40 | double crossoverProbability = 0.8; //crossover probability 41 | double mutationProbability = 0.2; //mutation probability 42 | int elitismReplacements = 5; //number of elitism replacements 43 | 44 | GeneticAlgorithm ga = new GeneticAlgorithm() 45 | .setCrossover(Crossovers.singlePoint()) 46 | .setSelector(Selectors.rouletteWheel()) 47 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 48 | .setMinimax(Consts.MINIMIZE) 49 | .setInitializer(Initializers.real(minrange, maxrange, n)) 50 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 51 | .setFitnessFunction(new FitnessFunction() { 52 | @Override 53 | public double evaluate(Chromosome chromosome) { 54 | ArrayList genes = chromosome.getGenes(); 55 | 56 | double x = genes.get(0); 57 | double y = genes.get(1); 58 | 59 | double score = 0.5 + (pow(cos(sin(abs(x * x - y * y))), 2) - 0.5) / 60 | pow(1 + 0.001 * (x * x + y * y), 2); 61 | 62 | return score; 63 | } 64 | }) 65 | .setGenerations(generations) 66 | .setPopulationSize(populationSize) 67 | .setCrossoverProbability(crossoverProbability) 68 | .setMutationProbability(mutationProbability) 69 | .setElitismReplacements(elitismReplacements); 70 | 71 | ga.evolve(); 72 | 73 | System.out.println(ga.getSolution()); 74 | System.out.println(ga.getSolution().getRawFitnessValue()); 75 | 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/examples/CrossInTray.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import static java.lang.Math.PI; 4 | import static java.lang.Math.abs; 5 | import static java.lang.Math.exp; 6 | import static java.lang.Math.pow; 7 | import static java.lang.Math.sin; 8 | import static java.lang.Math.sqrt; 9 | 10 | import java.util.ArrayList; 11 | 12 | import ro.jgal.Chromosome; 13 | import ro.jgal.Consts; 14 | import ro.jgal.Crossovers; 15 | import ro.jgal.FitnessFunction; 16 | import ro.jgal.GeneticAlgorithm; 17 | import ro.jgal.Initializers; 18 | import ro.jgal.Mutators; 19 | import ro.jgal.Selectors; 20 | import ro.jgal.TerminationCriterias; 21 | 22 | /** 23 | * Cross-In-Tray Function. Global minimum is f(x) = -2.06261 for 24 | * x=(1.3491,-1.3491), (1.3491,1.3491), (-1.3491,1.3491). 25 | * More info at: http://www.sfu.ca/~ssurjano/crossit.html 26 | * 27 | * @author Mihail Cristian Dumitru 28 | * 29 | */ 30 | @SuppressWarnings({"rawtypes","unchecked"}) 31 | public class CrossInTray { 32 | 33 | public static void main(String[] args) { 34 | 35 | int n = 2; //number of genes 36 | double minrange = -10; //minimum value 37 | double maxrange = 10; //maximum value 38 | double targetScore = -2.06261; //target score, the evolution will terminate when it is reached 39 | int precision = 5; //precision of the target score 40 | int generations = 10000; //number of generations 41 | int populationSize = 100; //population size 42 | double crossoverProbability = 0.8; //crossover probability 43 | double mutationProbability = 0.05; //mutation probability 44 | int elitismReplacements = 5; //number of elitism replacements 45 | 46 | GeneticAlgorithm ga = new GeneticAlgorithm() 47 | .setCrossover(Crossovers.singlePoint()) 48 | .setSelector(Selectors.uniform()) 49 | .setMutator(Mutators.realGaussian(minrange, maxrange)) 50 | .setMinimax(Consts.MINIMIZE) 51 | .setInitializer(Initializers.real(minrange, maxrange, n)) 52 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 53 | .setFitnessFunction(new FitnessFunction() { 54 | @Override 55 | public double evaluate(Chromosome chromosome) { 56 | ArrayList genes = chromosome.getGenes(); 57 | 58 | double x = genes.get(0); 59 | double y = genes.get(1); 60 | 61 | double score = -0.0001 * pow(abs(sin(x) * sin(y) * 62 | exp(abs(100 - sqrt(x*x + y*y) / PI))) + 1, 0.1); 63 | 64 | return score; 65 | } 66 | }) 67 | .setGenerations(generations) 68 | .setPopulationSize(populationSize) 69 | .setCrossoverProbability(crossoverProbability) 70 | .setMutationProbability(mutationProbability) 71 | .setElitismReplacements(elitismReplacements); 72 | 73 | ga.evolve(500); 74 | 75 | System.out.println(ga.getSolution()); 76 | System.out.println(ga.getSolution().getRawFitnessValue()); 77 | 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/ro/jgal/SelectorRouletteWheel.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | 4 | /** 5 | * Roulette Wheel Selector. 6 | * 7 | * @author Mihail Cristian Dumitru 8 | * 9 | */ 10 | @SuppressWarnings("rawtypes") 11 | public class SelectorRouletteWheel implements Selector { 12 | 13 | double sum; 14 | double[] probability; 15 | double sumOfProbability; 16 | 17 | /** 18 | * Selects the parents from a given population. 19 | * 20 | * @param pop - the population from which the parents are chosen 21 | * @return parents - the parents population 22 | */ 23 | @Override 24 | public Population select(Population pop) { 25 | 26 | Population parents = new Population(); 27 | parents.setMinimax(pop.getMinimax()); 28 | 29 | try { 30 | 31 | initialize(pop); 32 | 33 | int lower = 0; 34 | int upper = pop.length() - 1; 35 | double cut; 36 | 37 | while (parents.length() < pop.length()) { 38 | cut = Math.random(); 39 | 40 | while (upper >= lower) { 41 | int i = lower + ((upper - lower) / 2); 42 | if (probability[i] > cut) { 43 | upper = i - 1; 44 | } else { 45 | lower = i + 1; 46 | } 47 | } 48 | 49 | lower = Math.min(pop.length() - 1, lower); 50 | lower = Math.max(0, lower); 51 | 52 | parents.add((Chromosome) pop.get(lower).clone()); 53 | } 54 | 55 | } catch (CloneNotSupportedException e) { 56 | e.printStackTrace(); 57 | } 58 | 59 | return parents; 60 | } 61 | 62 | /** 63 | * Computes the probability of each individual and the 64 | * cumulated probability required by the algorithm. 65 | * 66 | * @param pop 67 | */ 68 | void initialize(Population pop) { 69 | int len = pop.length(); 70 | 71 | probability = new double[len]; 72 | 73 | double pop_min = pop.getWorstValue(); 74 | double pop_max = pop.getBestValue(); 75 | 76 | if (pop_max == pop_min) { 77 | for (int i = 0; i < len; i++) { 78 | probability[i] = (i + 1) / ((float) len); 79 | } 80 | } else if ((pop_max > 0 && pop_min >= 0) || (pop_max <= 0 && pop_min < 0)) { 81 | pop.sort(); 82 | 83 | if (pop.minimax == Consts.MAXIMIZE) { 84 | sumOfProbability = 0; 85 | for (int i = 0; i < len; i++) { 86 | sumOfProbability += pop.get(i).getFitnessValue(); 87 | probability[i] = sumOfProbability; 88 | } 89 | for (int i = 0; i < len; i++) { 90 | probability[i] /= probability[len-1]; 91 | } 92 | } else { 93 | sumOfProbability = 0; 94 | for (int i = 0; i < len; i++) { 95 | sumOfProbability += - pop.get(i).getFitnessValue() + pop_max + pop_min; 96 | probability[i] = sumOfProbability; 97 | } 98 | for (int i = 0; i < len; i++) { 99 | probability[i] /= probability[len-1]; 100 | } 101 | } 102 | } 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverCX.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Cycle Crossover. Works well for order optimizations. 7 | * Use it for integer permutations only. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | @SuppressWarnings({"unchecked", "rawtypes"}) 13 | public class CrossoverCX implements Crossover { 14 | 15 | int index; 16 | 17 | /** 18 | * Recombines the given parents population. Each 19 | * individual has a probability pc of recombining. 20 | * 21 | * @param parents - the parents population 22 | * @param pc - recombination probability 23 | * @return - children population 24 | */ 25 | @Override 26 | public Population crossover(Population parents, double pc) { 27 | if (pc == 0.0) { 28 | return parents; 29 | } 30 | if (parents.length() < 2) { 31 | return parents; 32 | } 33 | 34 | try { 35 | 36 | Population children = (Population) parents.clone(); 37 | 38 | for (int i = 0; i < parents.length(); i+=2) { 39 | if (Math.random() < pc) { 40 | if (i+1 == parents.length()) { 41 | break; 42 | } 43 | Chromosome mom = parents.get(i); 44 | Chromosome dad = parents.get(i+1); 45 | 46 | Chromosome sister = children.get(i); 47 | Chromosome brother = children.get(i+1); 48 | 49 | int[] cycle = findCycles(mom.getGenes(), dad.getGenes()); 50 | 51 | for (int j = 1; j < index; j+=2) { 52 | for (int k = 0; k < cycle.length; k++) { 53 | if (cycle[k] == j) { 54 | sister.setGene(k, dad.getGene(k)); 55 | brother.setGene(k, mom.getGene(k)); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | 62 | return children; 63 | 64 | } catch (CloneNotSupportedException e) { 65 | e.printStackTrace(); 66 | } 67 | return null; 68 | } 69 | 70 | /** 71 | * Finds the cycles in two given parents genes. 72 | * 73 | * @param mom - first parent's genes 74 | * @param dad - second parent's genes 75 | * @return - integer array of cycles 76 | */ 77 | private int[] findCycles(ArrayList mom, ArrayList dad) { 78 | int i = 0; 79 | int j = 0; 80 | index = 0; 81 | boolean notDone = true; 82 | int[] cycle = new int[mom.size()]; 83 | 84 | while (notDone) { 85 | Object a = dad.get(i); 86 | cycle[i] = index; 87 | while (!mom.get(i).equals(a)) { 88 | for (int k = 0; k < cycle.length; k++) { 89 | if (mom.get(k).equals(a)) { 90 | j = k; 91 | break; 92 | } 93 | } 94 | cycle[j] = index; 95 | a = dad.get(j); 96 | } 97 | 98 | notDone = false; 99 | 100 | for (int k = 0; k < cycle.length; k++) { 101 | if (cycle[k] == 0) { 102 | i = k; 103 | index++; 104 | notDone = true; 105 | break; 106 | } 107 | } 108 | } 109 | return cycle; 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/ro/jgal/SelectorTournament.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | 6 | /** 7 | * Tournament Selection. 8 | * 9 | * The parents are selected by creating random tournament pools 10 | * of n individuals (default is 2) and choosing the i'th best of 11 | * them with the probability p^i (default probability is 1.0, 12 | * so the best individual will always be chosen). 13 | * 14 | * @author Mihail Cristian Dumitru 15 | * 16 | */ 17 | @SuppressWarnings("rawtypes") 18 | public class SelectorTournament implements Selector { 19 | 20 | int poolSize; 21 | double probability; 22 | 23 | /** 24 | * Tournament Selector. Default parameters: 25 | * poolSize = 2, 26 | * probability = 1.0 27 | */ 28 | public SelectorTournament() { 29 | this(Consts.TOURNAMENT_SIZE, Consts.TOURNAMENT_P); 30 | } 31 | 32 | /** 33 | * Tournament Selector. 34 | * 35 | * @param poolSize - the size of the tournament pool 36 | * @param probability - the probability of the i'th best individual 37 | * to be chosen (1.0 -> the best one will always be chosen) 38 | */ 39 | public SelectorTournament(int poolSize, double probability) { 40 | this.poolSize = poolSize; 41 | this.probability = probability; 42 | } 43 | 44 | /** 45 | * Selects the parents from a given population. 46 | * 47 | * @param pop - the population from which the parents are chosen 48 | * @return parents - the parents population 49 | */ 50 | @Override 51 | public Population select(Population pop) { 52 | 53 | if (probability < 0.0) { 54 | return pop; 55 | } 56 | if (poolSize < 1) { 57 | return pop; 58 | } 59 | 60 | Population parents = new Population(); 61 | parents.setMinimax(pop.getMinimax()); 62 | 63 | try { 64 | ArrayList tournamentPool; 65 | 66 | int len = pop.length(); 67 | 68 | while (parents.length() < pop.length()) { 69 | 70 | tournamentPool = new ArrayList(); 71 | 72 | //add random individuals to the pool 73 | for (int i = 0; i < poolSize; i++) { 74 | tournamentPool.add(pop.get(Utils.randInt(len))); 75 | } 76 | 77 | //sort the individuals in the pool in descending order 78 | sortDescendingOrder(tournamentPool); 79 | 80 | //select i'th best individual with the probability p^i 81 | double p = Math.random(); 82 | for (int i = 0; i < poolSize; i++) { 83 | if (p < (Math.pow(probability, i+1))) { 84 | parents.add((Chromosome) tournamentPool.get(i).clone()); 85 | break; 86 | } 87 | } 88 | } 89 | } catch (CloneNotSupportedException e) { 90 | e.printStackTrace(); 91 | } 92 | 93 | return parents; 94 | } 95 | 96 | /** 97 | * Sorts the given array in descending order by their fitness value. 98 | * 99 | * @param tournamentPool 100 | */ 101 | private void sortDescendingOrder(ArrayList tournamentPool) { 102 | Collections.sort(tournamentPool, (x,y) -> { 103 | if (x.getFitnessValue() > y.getFitnessValue()) { 104 | return -1; 105 | } else if (x.getFitnessValue() < y.getFitnessValue()) { 106 | return 1; 107 | } 108 | return 0; 109 | }); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/examples/NQueens.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.util.ArrayList; 4 | 5 | import ro.jgal.Chromosome; 6 | import ro.jgal.Consts; 7 | import ro.jgal.Crossovers; 8 | import ro.jgal.FitnessFunction; 9 | import ro.jgal.GeneticAlgorithm; 10 | import ro.jgal.Initializers; 11 | import ro.jgal.Mutators; 12 | import ro.jgal.Selectors; 13 | import ro.jgal.TerminationCriterias; 14 | 15 | /** 16 | * N-Queens Problem. 17 | * 18 | * The N-Queens is the problem of placing N chess queens on an 19 | * N x N chessboard so that no two queens threaten each other. 20 | * 21 | * @author Mihail Cristian Dumitru 22 | * 23 | */ 24 | @SuppressWarnings({"rawtypes","unchecked"}) 25 | public class NQueens { 26 | 27 | public static void printSolution(Chromosome solution) { 28 | ArrayList genes = solution.getGenes(); 29 | 30 | System.out.println(); 31 | for (int i = 0; i < genes.size(); i++) { 32 | System.out.printf("%3d", (i+1)); 33 | } 34 | System.out.println(); 35 | 36 | for (int i = 0; i < genes.size(); i++) { 37 | int q = genes.get(i); 38 | System.out.printf("%d", (i+1)); 39 | for (int j = 0; j < genes.size(); j++) { 40 | if (q == j) { 41 | System.out.printf("%2s", "Q"); 42 | } else { 43 | System.out.printf(" "); 44 | } 45 | } 46 | System.out.println(); 47 | } 48 | } 49 | 50 | public static void main(String[] args) { 51 | 52 | int n = 8; //number of genes (queens) 53 | int minrange = 0; //minimum value 54 | int maxrange = n; //maximum value 55 | double targetScore = 0.0; //target score, the evolution will terminate when it is reached 56 | int precision = 2; //precision of the target score 57 | int generations = 10000; //number of generations 58 | int populationSize = 100; //population size 59 | double crossoverProbability = 1; //crossover probability 60 | double mutationProbability = 0.1; //mutation probability 61 | int elitismReplacements = 5; //number of elitism replacements 62 | 63 | GeneticAlgorithm ga = new GeneticAlgorithm() 64 | .setCrossover(Crossovers.CX()) 65 | .setSelector(Selectors.uniform()) 66 | .setMutator(Mutators.swap()) 67 | .setMinimax(Consts.MINIMIZE) 68 | .setInitializer(Initializers.integerPermutation(minrange, maxrange)) 69 | .setTerminationCriteria(TerminationCriterias.scoreCriteria(targetScore, precision)) 70 | .setFitnessFunction(new FitnessFunction() { 71 | @Override 72 | public double evaluate(Chromosome chromosome) { 73 | ArrayList genes = chromosome.getGenes(); 74 | 75 | int n = genes.size(); 76 | 77 | double score = 0; 78 | 79 | for (int i = 0; i < n-1; i++) { 80 | for (int j = i + 1; j < n; j++) { 81 | if (Math.abs(i-j) == Math.abs(genes.get(i) - genes.get(j))) { 82 | score += 1; 83 | } 84 | } 85 | } 86 | 87 | return score; 88 | } 89 | }) 90 | .setGenerations(generations) 91 | .setPopulationSize(populationSize) 92 | .setCrossoverProbability(crossoverProbability) 93 | .setMutationProbability(mutationProbability) 94 | .setElitismReplacements(elitismReplacements); 95 | 96 | ga.evolve(500); 97 | 98 | System.out.println(ga.getSolution()); 99 | System.out.println(ga.getSolution().getRawFitnessValue()); 100 | 101 | printSolution(ga.getSolution()); 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverOX.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * Order Crossover. Works well for order optimizations. 7 | * Use it for integer permutations only. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | @SuppressWarnings({"rawtypes", "unchecked"}) 13 | public class CrossoverOX implements Crossover { 14 | 15 | /** 16 | * Recombines the given parents population. Each 17 | * individual has a probability pc of recombining. 18 | * 19 | * @param parents - the parents population 20 | * @param pc - recombination probability 21 | * @return - children population 22 | */ 23 | @Override 24 | public Population crossover(Population parents, double pc) { 25 | if (pc == 0.0) { 26 | return parents; 27 | } 28 | if (parents.length() < 2) { 29 | return parents; 30 | } 31 | 32 | try { 33 | 34 | Population children = (Population) parents.clone(); 35 | int len = children.get(0).length(); 36 | 37 | for (int i = 0; i < parents.length(); i+=2) { 38 | if (Math.random() < pc) { 39 | if (i+1 == parents.length()) { 40 | break; 41 | } 42 | Chromosome mom = parents.get(i); 43 | Chromosome dad = parents.get(i+1); 44 | 45 | Chromosome sister = children.get(i); 46 | Chromosome brother = children.get(i+1); 47 | 48 | int c1 = Utils.randInt(1, mom.length()); 49 | int c2 = Utils.randInt(1, mom.length()); 50 | 51 | while (c1 == c2) { 52 | c2 = Utils.randInt(1, mom.length()); 53 | } 54 | 55 | if (c1 > c2) { 56 | int temp = c1; 57 | c1 = c2; 58 | c2 = temp; 59 | } 60 | 61 | Chromosome[] a_parents = new Chromosome[] {mom, dad}; 62 | Chromosome[] a_children = new Chromosome[] {sister, brother}; 63 | 64 | for (int k = 0; k < 2; k++) { 65 | ArrayList P1 = new ArrayList(); 66 | ArrayList parent = new ArrayList(a_parents[k].getGenes()); 67 | ArrayList reversedParent = new ArrayList(); 68 | reversedParent.addAll(parent.subList(c2, parent.size())); 69 | reversedParent.addAll(parent.subList(0, c2)); 70 | 71 | boolean flag; 72 | for (Object g : reversedParent) { 73 | flag = false; 74 | for (int j = c1; j < c2; j++) { 75 | if (g.equals(a_parents[(k + 1) % 2].getGene(j))) { 76 | flag = true; 77 | break; 78 | } 79 | } 80 | if (!flag) { 81 | P1.add(g); 82 | } 83 | } 84 | 85 | ArrayList P1G = new ArrayList(); 86 | P1G.addAll(P1.subList(len - c2, P1.size())); 87 | for (int j = c1; j < c2; j++) { 88 | P1G.add(a_parents[(k + 1) % 2].getGene(j)); 89 | } 90 | P1G.addAll(P1.subList(0, len - c2)); 91 | 92 | ArrayList genes = new ArrayList(); 93 | for (int j = 0; j < len; j++) { 94 | genes.add(P1G.get(j)); 95 | } 96 | 97 | a_children[k].setGenes(genes); 98 | } 99 | } 100 | } 101 | 102 | return children; 103 | 104 | } catch (CloneNotSupportedException e) { 105 | e.printStackTrace(); 106 | } 107 | 108 | return null; 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/ro/jgal/Utils.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * Utility class. 8 | * 9 | * @author Mihail Cristian Dumitru 10 | * 11 | */ 12 | @SuppressWarnings({"rawtypes", "unchecked"}) 13 | public class Utils { 14 | 15 | /** 16 | * Generates a random real number in the given range. 17 | * 18 | * @param minrange - minimum value 19 | * @param maxrange - maximum value 20 | * @return - random number 21 | */ 22 | public static double randRealUniform(double minrange, double maxrange) { 23 | return minrange + (Math.random() * (maxrange - minrange)); 24 | } 25 | 26 | /** 27 | * Generates a random integer in the range [0,n). 28 | * 29 | * @param n - maximum value (exclusive) 30 | * @return - random integer 31 | */ 32 | public static int randInt(int n) { 33 | return (int) randInt(0, n); 34 | } 35 | 36 | /** 37 | * Generates a random integer in the given range. 38 | * 39 | * @param minrange - minumum value (inclusive) 40 | * @param maxrange - maximum value (exclusive) 41 | * @return - random integer 42 | */ 43 | public static int randInt(int minrange, int maxrange) { 44 | return (int) randRealUniform(minrange, maxrange); 45 | } 46 | 47 | /** 48 | * Calculates the edges for EdgeCrossover. 49 | * 50 | * @param mom - first parent 51 | * @param dad - second parent 52 | * @return - edges hashmap 53 | */ 54 | public static HashMap>> getEdgesComposite(Chromosome mom, Chromosome dad) { 55 | HashMap> mom_edges = getEdges(mom); 56 | HashMap> dad_edges = getEdges(dad); 57 | 58 | HashMap>> map = new HashMap>>(); 59 | map.put("momEdges", mom_edges); 60 | map.put("dadEdges", dad_edges); 61 | map.put("edges", mergeEdges(mom_edges, dad_edges)); 62 | 63 | return map; 64 | } 65 | 66 | /** 67 | * Calculates the edges of a given individual. 68 | * 69 | * @param ind - chromosome for which to calculate the edges 70 | * @return - edges hashmap 71 | */ 72 | public static HashMap> getEdges(Chromosome ind) { 73 | HashMap> edg = new HashMap>(); 74 | ArrayList genes = ind.getGenes(); 75 | 76 | for (int i = 0; i < genes.size(); i++) { 77 | Object a = genes.get(i); 78 | Object b = null; 79 | if (i == 0) { 80 | b = genes.get(genes.size()-1); 81 | } else { 82 | b = genes.get(i - 1); 83 | } 84 | 85 | if (!edg.containsKey(a)) { 86 | edg.put(a, new ArrayList()); 87 | } 88 | edg.get(a).add(b); 89 | 90 | 91 | if (!edg.containsKey(b)) { 92 | edg.put(b, new ArrayList()); 93 | } 94 | edg.get(b).add(a); 95 | 96 | } 97 | return edg; 98 | } 99 | 100 | /** 101 | * Merges two edge hashmaps. 102 | * 103 | * @param eda - first map 104 | * @param edb - second map 105 | * @return - merged edges hashmap 106 | */ 107 | public static HashMap> mergeEdges(HashMap> eda, HashMap> edb) { 108 | HashMap> edges = new HashMap>(); 109 | 110 | for (Object key : eda.keySet()) { 111 | edges.put(key, new ArrayList()); 112 | for (Object g : eda.get(key)) { 113 | if (!edges.get(key).contains(g)) { 114 | edges.get(key).add(g); 115 | } 116 | } 117 | } 118 | 119 | for (Object key : edb.keySet()) { 120 | for (Object g : edb.get(key)) { 121 | if (!edges.get(key).contains(g)) { 122 | edges.get(key).add(g); 123 | } 124 | } 125 | } 126 | 127 | return edges; 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/ro/jgal/Population.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | import java.util.Iterator; 7 | 8 | import sun.security.util.Length; 9 | 10 | /** 11 | * Chromosome population. Contains all the chromosomes in a generation and 12 | * the best/worst chromosomes. 13 | * 14 | * @author Mihail Cristian Dumitru 15 | * 16 | */ 17 | @SuppressWarnings("rawtypes") 18 | public class Population implements Length, Iterable, Cloneable { 19 | 20 | ArrayList population; 21 | Chromosome bestIndividual; 22 | Chromosome worstIndividual; 23 | double bestValue; 24 | double worstValue; 25 | 26 | int minimax; 27 | 28 | /** 29 | * Chromosome population. 30 | */ 31 | public Population() { 32 | population = new ArrayList(); 33 | minimax = Consts.MAXIMIZE; 34 | } 35 | 36 | /** 37 | * Sets the objective of the problem. 38 | * 39 | * @param minimax - the objective (Consts.MINIMIZE/Consts.MAXIMIZE) 40 | */ 41 | public void setMinimax(int minimax) { 42 | this.minimax = minimax; 43 | } 44 | 45 | public int getMinimax() { 46 | return minimax; 47 | } 48 | 49 | public void add(Chromosome chrom) { 50 | population.add(chrom); 51 | } 52 | 53 | public Chromosome get(int index) { 54 | return population.get(index); 55 | } 56 | 57 | public void set(int index, Chromosome that) { 58 | population.set(index, that); 59 | } 60 | 61 | public void setPopulation(Chromosome[] population) { 62 | this.population = new ArrayList(); 63 | for (int i = 0; i < population.length; i++) { 64 | this.population.add(population[i]); 65 | } 66 | } 67 | 68 | public void setPopulation(ArrayList population) { 69 | this.population = population; 70 | } 71 | 72 | public ArrayList getPopulation() { 73 | return population; 74 | } 75 | 76 | public void setBestIndividual(Chromosome best) { 77 | this.bestIndividual = best; 78 | } 79 | 80 | public Chromosome getBestIndividual() { 81 | return bestIndividual; 82 | } 83 | 84 | public void setBestValue(double bestValue) { 85 | this.bestValue = bestValue; 86 | } 87 | 88 | public double getBestValue() { 89 | return bestValue; 90 | } 91 | 92 | public void setWorstIndividual(Chromosome worst) { 93 | this.worstIndividual = worst; 94 | } 95 | 96 | public Chromosome getWorstIndividual() { 97 | return worstIndividual; 98 | } 99 | 100 | public void setWorstValue(double worstValue) { 101 | this.worstValue = worstValue; 102 | } 103 | 104 | public double getWorstValue() { 105 | return worstValue; 106 | } 107 | 108 | public void sort() { 109 | Collections.sort(population, new Comparator() { 110 | @Override 111 | public int compare(Chromosome o1, Chromosome o2) { 112 | if (o1.getFitnessValue() > o2.getFitnessValue()) { 113 | return minimax == Consts.MAXIMIZE ? -1 : 1; 114 | } else if (o1.getFitnessValue() < o2.getFitnessValue()) { 115 | return minimax == Consts.MAXIMIZE ? 1 : -1; 116 | } else { 117 | return 0; 118 | } 119 | }; 120 | }); 121 | } 122 | 123 | @Override 124 | public int length() { 125 | if (population != null) { 126 | return population.size(); 127 | } 128 | return 0; 129 | } 130 | 131 | @Override 132 | public Iterator iterator() { 133 | return population.iterator(); 134 | } 135 | 136 | @Override 137 | public Object clone() throws CloneNotSupportedException { 138 | Population clone = new Population(); 139 | try { 140 | for (Chromosome c : population) { 141 | clone.add((Chromosome) c.clone()); 142 | } 143 | if (bestIndividual != null) { 144 | clone.setBestIndividual((Chromosome) bestIndividual.clone()); 145 | } 146 | clone.setBestValue(bestValue); 147 | } catch (CloneNotSupportedException e) { 148 | e.printStackTrace(); 149 | } 150 | clone.setMinimax(minimax); 151 | 152 | return clone; 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/examples/TSP.java: -------------------------------------------------------------------------------- 1 | package examples; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.FileNotFoundException; 6 | import java.io.FileReader; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | 10 | import ro.jgal.Chromosome; 11 | import ro.jgal.Consts; 12 | import ro.jgal.Crossovers; 13 | import ro.jgal.FitnessFunction; 14 | import ro.jgal.GeneticAlgorithm; 15 | import ro.jgal.Initializers; 16 | import ro.jgal.Mutators; 17 | import ro.jgal.Selectors; 18 | 19 | /** 20 | * Traveling Salesman Problem with 58 cities. 21 | * 22 | * @author Mihail Cristian Dumitru 23 | * 24 | */ 25 | @SuppressWarnings({"rawtypes","unchecked"}) 26 | public class TSP { 27 | 28 | /** 29 | * Reads the distance matrix from a file. 30 | * 31 | * @return - distance matrix 32 | */ 33 | private double[][] readMatrix() { 34 | try { 35 | FileReader fr = new FileReader(new File("").getAbsolutePath() + "/src/examples/58cities.txt"); 36 | BufferedReader bf = new BufferedReader(fr); 37 | 38 | int n = Integer.parseInt(bf.readLine()); 39 | double[][] matrix = new double[n][n]; 40 | for (int i = 0; i < n-1; i++) { 41 | String line = bf.readLine(); 42 | String[] row = line.split(","); 43 | int k = 0; 44 | for (int j = i; j < n; j++) { 45 | if (i == j) { 46 | matrix[i][j] = 0; 47 | } else { 48 | matrix[i][j] = Integer.parseInt(row[k++]); 49 | matrix[j][i] = matrix[i][j]; 50 | } 51 | } 52 | } 53 | 54 | bf.close(); 55 | fr.close(); 56 | 57 | return matrix; 58 | 59 | } catch (FileNotFoundException e) { 60 | e.printStackTrace(); 61 | } catch (NumberFormatException e) { 62 | e.printStackTrace(); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | 67 | return null; 68 | } 69 | 70 | /** 71 | * Fitness function for TSP. 72 | * 73 | * @author Mihail Cristian Dumitru 74 | * 75 | */ 76 | class FitnessFunctionTSP implements FitnessFunction { 77 | 78 | double[][] matrix; 79 | 80 | public FitnessFunctionTSP(double[][] matrix) { 81 | this.matrix = matrix; 82 | } 83 | 84 | @Override 85 | public double evaluate(Chromosome chromosome) { 86 | ArrayList genes = chromosome.getGenes(); 87 | 88 | double score = matrix[0][genes.get(0)]; 89 | 90 | for (int i = 0; i < genes.size() - 1; i++) { 91 | int from = genes.get(i); 92 | int to = genes.get(i+1); 93 | 94 | score += matrix[from][to]; 95 | } 96 | 97 | return score; 98 | } 99 | } 100 | 101 | public Chromosome execute() { 102 | double[][] matrix = readMatrix(); 103 | 104 | int n = matrix.length; //number of cities 105 | int minrange = 0; //minimum value 106 | int maxrange = n; //maximum value 107 | int generations = 10000; //number of generations 108 | int populationSize = 100; //population size 109 | double crossoverProbability = 1; //crossover probability 110 | double mutationProbability = 0.5; //mutation probability 111 | int elitismReplacements = 5; //number of elitism replacements 112 | 113 | GeneticAlgorithm ga = new GeneticAlgorithm() 114 | .setCrossover(Crossovers.OX()) 115 | .setSelector(Selectors.uniform()) 116 | .setMutator(Mutators.swap()) 117 | .setMinimax(Consts.MINIMIZE) 118 | .setInitializer(Initializers.integerPermutation(minrange, maxrange)) 119 | .setFitnessFunction(new FitnessFunctionTSP(matrix)) 120 | .setGenerations(generations) 121 | .setPopulationSize(populationSize) 122 | .setCrossoverProbability(crossoverProbability) 123 | .setMutationProbability(mutationProbability) 124 | .setElitismReplacements(elitismReplacements); 125 | 126 | ga.evolve(500); 127 | 128 | return ga.getSolution(); 129 | } 130 | 131 | public static void main(String[] args) { 132 | TSP tsp = new TSP(); 133 | 134 | Chromosome best = tsp.execute(); 135 | 136 | System.out.println(best); 137 | System.out.println(best.getRawFitnessValue()); 138 | } 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/ro/jgal/CrossoverEdge.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | 6 | /** 7 | * Edge Crossover. Works well for order optimizations. 8 | * Use it for integer permutations only. 9 | * 10 | * @author Mihail Cristian Dumitru 11 | * 12 | */ 13 | public class CrossoverEdge implements Crossover { 14 | 15 | /** 16 | * Recombines the given parents population. Each 17 | * individual has a probability pc of recombining. 18 | * 19 | * @param parents - the parents population 20 | * @param pc - recombination probability 21 | * @return - children population 22 | */ 23 | @Override 24 | @SuppressWarnings({"unchecked", "rawtypes"}) 25 | public Population crossover(Population parents, double pc) { 26 | if (pc == 0.0) { 27 | return parents; 28 | } 29 | if (parents.length() < 2) { 30 | return parents; 31 | } 32 | 33 | try { 34 | 35 | Population children = (Population) parents.clone(); 36 | int len = children.get(0).length(); 37 | 38 | for (int i = 0; i < parents.length(); i+=2) { 39 | if (Math.random() < pc) { 40 | if (i+1 == parents.length()) { 41 | break; 42 | } 43 | Chromosome mom = parents.get(i); 44 | Chromosome dad = parents.get(i+1); 45 | 46 | Chromosome sister = children.get(i); 47 | Chromosome brother = children.get(i+1); 48 | 49 | HashMap>> map = Utils.getEdgesComposite(mom, dad); 50 | HashMap> mom_edges = map.get("momEdges"); 51 | HashMap> dad_edges = map.get("dadEdges"); 52 | HashMap> edges = map.get("edges"); 53 | 54 | ArrayList[] a_children = new ArrayList[] { 55 | new ArrayList(), 56 | new ArrayList() 57 | }; 58 | ArrayList[] a_parents = new ArrayList[] { 59 | mom.getGenes(), 60 | dad.getGenes() 61 | }; 62 | 63 | for (int j = 0; j < 2; j++) { 64 | Object current = null; 65 | for (int k = 0; k < len; k++) { 66 | if (current == null) { 67 | current = a_parents[j].get(Utils.randInt(a_parents[j].size())); 68 | } 69 | a_children[j].add(current); 70 | a_parents[j].remove(current); 71 | 72 | ArrayList d = new ArrayList(); 73 | if (edges.containsKey(current)) { 74 | for (Object g : edges.get(current)) { 75 | if (a_parents[j].contains(g)) { 76 | d.add(g); 77 | } 78 | } 79 | } 80 | 81 | if (!d.isEmpty()) { 82 | current = d.get(Utils.randInt(d.size())); 83 | } else { 84 | ArrayList s = new ArrayList(); 85 | if (mom_edges.containsKey(current)) { 86 | for (Object g : mom_edges.get(current)) { 87 | if (a_parents[j].contains(g)) { 88 | s.add(g); 89 | } 90 | } 91 | } 92 | if (dad_edges.containsKey(current)) { 93 | for (Object g : dad_edges.get(current)) { 94 | if (a_parents[j].contains(g)) { 95 | s.add(g); 96 | } 97 | } 98 | } 99 | if (!s.isEmpty()) { 100 | current = s.get(Utils.randInt(s.size())); 101 | } else { 102 | current = null; 103 | } 104 | } 105 | } 106 | } 107 | 108 | sister.setGenes(a_children[0]); 109 | brother.setGenes(a_children[1]); 110 | 111 | } 112 | } 113 | 114 | return children; 115 | 116 | } catch (CloneNotSupportedException e) { 117 | e.printStackTrace(); 118 | } 119 | return null; 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/ro/jgal/Chromosome.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | import sun.security.util.Length; 6 | 7 | /** 8 | * Chromosome. 9 | * 10 | * @author Mihail Cristian Dumitru 11 | * 12 | * @param 13 | */ 14 | @SuppressWarnings({"unchecked"}) 15 | public class Chromosome implements Length, Cloneable, Comparable> { 16 | 17 | ArrayList genes; //the genes 18 | double fitnessValue; //value used for ranking solutions (if the objective is minimization, it will be equal to -rawFitnessValue) 19 | double rawFitnessValue; //the result from the fitness function 20 | 21 | /** 22 | * Empty chromosome. 23 | */ 24 | public Chromosome() { 25 | genes = new ArrayList(); 26 | fitnessValue = 0; 27 | } 28 | 29 | /** 30 | * Chromosome. 31 | * 32 | * @param genes - the genes of the chromosome 33 | */ 34 | public Chromosome(ArrayList genes) { 35 | setGenes(genes); 36 | } 37 | 38 | /** 39 | * Chromosome. 40 | * 41 | * @param genes - the genes of the chromosome 42 | */ 43 | public Chromosome(T[] genes) { 44 | setGenes(genes); 45 | } 46 | 47 | /** 48 | * Sets the genes of the chromosome. 49 | * 50 | * @param genes - the genes 51 | */ 52 | public void setGenes(T[] genes) { 53 | this.genes = new ArrayList(); 54 | for (int i = 0; i < genes.length; i++) { 55 | this.genes.add(genes[i]); 56 | } 57 | fitnessValue = 0; 58 | } 59 | 60 | /** 61 | * Sets the genes of the chromosome. 62 | * 63 | * @param genes - the genes 64 | */ 65 | public void setGenes(ArrayList genes) { 66 | this.genes = genes; 67 | } 68 | 69 | /** 70 | * Sets the gene at the given index. 71 | * 72 | * @param index - index of the gene 73 | * @param gene - the gene 74 | */ 75 | public void setGene(int index, T gene) { 76 | if (index < 0 || index > length() - 1) { 77 | throw new IndexOutOfBoundsException(); 78 | } 79 | genes.set(index, gene); 80 | } 81 | 82 | /** 83 | * Getter for the chromosome's genes. 84 | * 85 | * @return - the genes of the chromosome 86 | */ 87 | public ArrayList getGenes() { 88 | return genes; 89 | } 90 | 91 | /** 92 | * 93 | * @param index - index of the gene to be returned 94 | * @return - the gene at the given index 95 | */ 96 | public T getGene(int index) { 97 | return genes.get(index); 98 | } 99 | 100 | /** 101 | * Setter for the fitness value. 102 | * 103 | * @param fitnessValue - fitness value 104 | */ 105 | public void setFitnessValue(double fitnessValue) { 106 | this.fitnessValue = fitnessValue; 107 | } 108 | 109 | /** 110 | * Gets the fitness value. This is equal to the raw 111 | * fitness value if the objective is maximization, and 112 | * negative raw fitness value if the objective is 113 | * minimization. It's used for ranking the solutions. 114 | * 115 | * @return - fitness value 116 | */ 117 | public double getFitnessValue() { 118 | return fitnessValue; 119 | } 120 | 121 | /** 122 | * Setter for the raw fitness value. 123 | * 124 | * @param rawFitnessValue - raw fitness value 125 | */ 126 | public void setRawFitnessValue(double rawFitnessValue) { 127 | this.rawFitnessValue = rawFitnessValue; 128 | } 129 | 130 | /** 131 | * Gets the raw fitness value. This is equal to 132 | * the value returned by the fitness function. 133 | * 134 | * @return - raw fitness value 135 | */ 136 | public double getRawFitnessValue() { 137 | return rawFitnessValue; 138 | } 139 | 140 | @Override 141 | public String toString() { 142 | return genes.toString(); 143 | } 144 | 145 | @Override 146 | public boolean equals(Object obj) { 147 | if (obj == null){ 148 | return false; 149 | } 150 | if (this == obj) { 151 | return true; 152 | } 153 | Chromosome that = (Chromosome) obj; 154 | return genes.equals(that.getGenes()); 155 | } 156 | 157 | @Override 158 | public int length() { 159 | if (genes != null) { 160 | return genes.size(); 161 | } 162 | return 0; 163 | } 164 | 165 | @Override 166 | public Object clone() throws CloneNotSupportedException { 167 | ArrayList genesClone = new ArrayList(); 168 | for (T g : genes) { 169 | genesClone.add(g); 170 | } 171 | Chromosome c = new Chromosome(genesClone); 172 | c.setFitnessValue(fitnessValue); 173 | return c; 174 | } 175 | 176 | @Override 177 | public int hashCode() { 178 | return genes.hashCode(); 179 | } 180 | 181 | @Override 182 | public int compareTo(Chromosome o) { 183 | if (this.fitnessValue > o.getFitnessValue()) { 184 | return -1; 185 | } else if (this.fitnessValue < o.getFitnessValue()) { 186 | return 1; 187 | } 188 | return 0; 189 | } 190 | 191 | } 192 | -------------------------------------------------------------------------------- /src/examples/58cities.txt: -------------------------------------------------------------------------------- 1 | 58 2 | 1849,852,2667,1878,342,1232,978,3129,2923,2619,1249,742,279,696,288,367,671,3568,2691,1039,750,2939,718,705,287,921,1592,2973,448,194,1863,946,2020,520,2495,2522,4353,1074,1266,1797,1216,1525,3043,2349,383,239,517,3114,543,3201,800,2093,1148,345,2931,2235,192, 3 | 1802,4002,2899,1352,547,730,4503,4041,3828,394,1200,1505,1935,1931,1293,965,4971,3716,606,1959,4148,2288,1016,1444,855,257,4128,1139,1811,229,1637,2686,1356,4065,4092,5756,2293,1932,300,2624,354,4004,3433,1423,1839,2087,4320,1475,4604,908,262,2082,1493,4501,3319,1638, 4 | 3481,1123,533,1402,1140,2804,2409,2204,1420,1470,771,1433,993,949,846,4615,1937,1210,434,2524,1145,971,567,1063,1553,2492,429,856,2037,184,1275,554,2571,3236,5167,600,527,1967,2035,1698,2267,1834,502,889,1348,2696,339,4015,969,2073,279,1014,3004,1720,722, 5 | 3718,3083,3579,3495,4962,4848,4549,3752,3024,2902,2149,2513,2808,3190,901,4316,3535,3060,4959,2551,3061,2942,3440,3825,4835,3073,2959,4505,3307,4038,3145,4328,4391,1686,3385,3590,4144,1456,3875,4701,4182,3140,2613,2388,5060,3236,544,3314,4408,4265,2590,4764,4068,2761, 6 | 1543,2725,2159,1681,1211,1006,2901,2951,1557,2286,1408,2266,1860,4619,739,2532,851,1326,1199,1974,2049,2098,2570,1447,1441,1517,3351,1460,259,1434,1446,2390,5404,1394,962,2986,2278,3033,1337,636,1435,1345,1350,1498,1339,4252,1189,3554,1210,2331,1882,522,2042, 7 | 949,687,3209,2753,2537,967,976,235,950,497,523,388,3986,2263,756,668,2857,960,502,107,754,1095,2891,102,335,1580,600,1642,170,2770,3026,4771,992,888,1514,1639,942,2697,2074,80,389,880,3162,199,3617,517,1747,802,488,3206,1960,217, 8 | 531,4108,3639,3434,176,938,1102,1444,1511,478,561,4480,3305,283,1565,3754,1839,675,1041,489,290,3724,970,1407,435,1468,2517,802,3616,3643,5265,1889,1763,413,2133,213,3590,3039,1019,1407,1634,3926,1072,4113,709,818,1678,1152,4052,2925,1230, 9 | 3841,3371,3165,474,945,846,1353,1249,652,300,4396,3049,254,1297,3486,1651,374,1079,138,476,3462,707,1127,960,1214,2393,691,3428,3512,5181,1627,1646,1096,2044,806,3328,2566,757,1145,1507,3658,810,4029,178,992,1416,856,3864,2678,968, 10 | 800,1052,4116,3998,3333,3586,2846,3487,3542,5893,1302,3906,2535,693,2423,3635,3201,3786,4249,681,3122,3104,4739,2676,1647,3199,634,1571,6678,2217,2395,4673,3544,4401,817,1273,3125,2948,2620,537,3032,5536,3665,4774,2636,3366,1070,1385,3064, 11 | 257,3744,3585,2780,3380,2651,3070,3072,5687,512,3441,2068,125,2217,3180,2734,3316,3784,184,2649,2740,4270,2209,1141,2721,1146,2083,6472,1750,1889,4204,3338,3935,135,953,2658,2568,2414,297,2559,5330,3200,4306,2130,3065,1582,839,2597, 12 | 3547,3380,2575,3173,2305,2865,2866,5480,307,3236,1863,372,2010,2975,2529,3110,3579,343,2444,2535,4065,2004,936,2527,1172,2109,6265,1545,1684,3999,3131,3730,211,770,2453,2406,2211,549,2354,5123,2995,4099,1925,2860,1608,656,2392, 13 | 1216,1119,1609,1421,968,578,4648,3334,224,1577,3848,1906,692,1153,347,137,3741,982,1424,629,1480,2693,1059,3683,3710,5423,1901,1939,771,2300,479,3607,2845,1036,1424,1705,4020,1079,4291,652,665,1695,1169,4119,3047,1301, 14 | 578,887,1174,520,638,3925,3399,788,1511,3846,1588,524,842,888,943,3734,1046,1484,1438,1771,2627,1118,3365,3392,4720,1835,1989,1185,1578,1288,3600,2905,1096,1076,1383,3872,1143,3558,767,1471,1755,607,3801,2871,892, 15 | 760,546,287,5410,3803,2713,909,706,2895,922,439,158,791,1248,2991,337,314,1740,835,1990,407,2699,2730,4588,1030,2699,1882,1451,1395,2915,2182,217,451,721,3067,334,3436,670,1776,1050,287,3135,2066,276, 16 | 964,673,1041,3045,2906,1398,1442,3583,1175,926,941,1298,1686,3459,1009,772,2070,1488,2624,1081,2952,2973,3830,2553,1972,2009,693,1740,3322,2585,1004,1063,974,3684,1101,2688,1177,2266,2128,455,3388,2692,894, 17 | 728,950,3414,2166,1311,557,2746,436,1064,419,1191,1672,2655,590,234,2134,817,1811,662,2213,2364,4199,881,1057,2076,1062,1798,2623,2031,508,112,359,2918,692,3047,1078,2179,1248,589,2649,1917,282, 18 | 390,3709,2878,758,996,3185,1112,274,354,640,1036,3219,525,599,837,1023,2058,577,2889,2884,4494,1546,1304,1635,1362,708,3120,2470,455,631,875,3036,623,3342,519,1564,1225,366,3325,2356,447, 19 | 4091,2601,368,1003,3187,1352,114,480,250,711,3163,408,846,1192,915,2094,392,3129,3207,4876,1328,1347,1126,1734,854,3029,2267,458,846,1202,3359,511,3724,129,1236,1117,591,3565,2379,669, 20 | 5217,4436,3961,5890,3482,3962,3843,4341,4791,5766,3969,3860,5106,4208,4929,4117,5259,5298,785,4286,4708,5045,2357,4776,5632,5113,4041,3514,3289,5991,4137,1445,4215,5304,5166,3491,5695,4999,3662, 21 | 3124,1600,627,1743,2878,2251,2845,3467,594,2358,2635,3936,1737,669,2430,1425,2437,6002,1278,1417,3870,2870,3601,464,330,2182,2266,1946,799,2087,4850,2878,3987,1658,2963,1861,367,2515, 22 | 1367,3551,1716,482,848,189,359,3531,777,1214,851,1275,2324,702,3493,3500,5221,2243,1570,1494,2089,701,3397,2841,826,1214,1495,4225,879,4069,432,887,1485,959,3929,2727,1037, 23 | 2183,716,1106,660,1247,1710,2223,586,666,2196,260,1116,658,2493,2824,4746,324,524,2130,1609,1861,2089,1260,584,494,908,2355,563,3594,1126,2230,694,991,2929,1354,523, 24 | 2420,3295,2849,3431,3899,130,2764,2855,4385,2324,1256,2836,1233,2170,6675,1865,2004,4319,3304,4050,200,1068,2773,2683,2617,190,2644,5533,3310,4589,2245,3180,1669,954,2712, 25 | 1289,1000,1653,2039,2296,1015,693,2466,965,1461,1087,1789,2120,4267,1030,1238,2400,1133,2131,2162,1422,923,537,209,2521,1083,3125,1538,2559,1282,955,2225,1529,715, 26 | 594,364,759,3277,524,1060,1306,1022,2057,506,3066,3093,4747,1542,1303,1240,1615,968,3134,2580,572,960,1109,3467,625,3595,243,1350,1231,705,3502,2466,635, 27 | 730,1187,2883,171,359,1672,669,1841,243,2777,2934,4628,984,1087,1606,1491,1335,2766,2134,75,315,774,3021,268,3476,609,1716,871,329,3213,2020,148, 28 | 598,3545,652,1096,1090,1165,2336,722,3430,3457,5126,1671,1582,1232,1989,940,3451,2736,708,1096,1452,3603,761,3974,124,1126,1342,841,3866,2620,919, 29 | 3870,1115,1557,492,1627,2806,1099,3816,3843,5511,2040,1908,634,2379,342,3736,3184,1165,1560,1838,4171,1218,4359,639,528,1824,1236,4252,3070,1381, 30 | 2913,2889,4362,2449,1377,2985,1103,2040,6553,1934,1972,4504,3417,4017,147,924,2869,2717,2493,228,2831,4875,3402,4399,2366,3214,1544,925,2746, 31 | 435,1596,498,1542,72,2791,2936,4759,1021,8700,1535,1622,1258,2595,2068,98,486,919,2936,97,3607,536,1645,700,590,3227,1954,319, 32 | 1733,926,1950,508,2470,2636,4645,990,1196,2072,1193,1710,2875,2142,287,137,490,3027,532,3538,975,2185,1135,394,2906,2026,98, 33 | 2094,3143,1668,4243,4274,5891,2510,2389,254,2759,273,4221,3670,1650,2038,2265,4557,1693,4739,1138,607,2309,1783,4679,3556,1783, 34 | 1252,570,2742,3503,4993,554,498,2033,1861,1756,2339,1638,844,754,1174,2496,523,3841,1044,2151,257,1088,3178,1524,783, 35 | 1610,1422,2368,5724,801,754,3082,2582,2805,1267,564,1702,1748,1612,1428,1612,4572,2083,3346,1002,2123,1869,452,1849, 36 | 2864,3008,4902,1093,856,1489,1770,1340,2667,2388,170,558,991,3008,86,3750,528,1717,772,602,3299,2274,391, 37 | 947,6044,1994,2105,4181,2910,3908,1011,1284,2700,2314,1986,1171,2859,4902,3315,4036,2413,2732,446,1170,2492, 38 | 6083,2922,3116,4208,2941,3939,1958,1991,2844,2464,2013,2108,3006,4925,3336,4363,3937,2763,806,2107,2543, 39 | 5071,5271,5830,3142,5561,6417,5676,4826,4299,4074,6776,4922,2230,5000,6089,5951,4276,6480,5784,4447, 40 | 432,2454,1939,2182,1876,1175,908,818,1238,2037,887,3919,1450,2654,456,1315,2425,1061,847, 41 | 2328,2139,2051,1834,1340,948,994,1438,2176,858,4124,1329,2592,248,1369,2417,1226,1095, 42 | 2698,312,4155,3604,1584,1972,2199,4491,1637,4678,1274,760,2243,1717,4617,3490,1795, 43 | 2429,3283,2543,1694,1162,932,3642,1790,1990,1868,2957,2819,1144,3346,2650,1310, 44 | 3883,3335,1312,1700,1930,4222,1355,4409,984,562,1971,1445,4344,3221,1423, 45 | 931,2793,2563,2359,366,2606,5274,3158,4265,2265,3185,1451,815,2914, 46 | 1844,1968,1619,1240,1984,4756,2600,3706,1557,2465,1715,114,1997, 47 | 411,827,2945,169,3674,587,1694,781,560,3136,1944,227, 48 | 459,2855,588,3147,975,2082,1188,498,2750,1854,184, 49 | 2718,983,2922,1332,2358,1608,754,2422,1726,607, 50 | 2846,5634,3487,4591,2417,3352,1607,1126,2884, 51 | 3770,640,1742,618,688,3295,1870,416, 52 | 3848,4947,4799,3124,5338,4642,3294, 53 | 1177,1246,720,3751,2486,798, 54 | 2353,1827,4772,3590,1905, 55 | 1290,2844,1441,1019, 56 | 3168,2351,432, 57 | 1601,2928, 58 | 1883, -------------------------------------------------------------------------------- /src/ro/jgal/GeneticAlgorithm.java: -------------------------------------------------------------------------------- 1 | package ro.jgal; 2 | 3 | import java.util.ArrayList; 4 | 5 | /** 6 | * The genetic algorithm. 7 | * 8 | * @author Mihail Cristian Dumitru 9 | * 10 | */ 11 | @SuppressWarnings({"rawtypes"}) 12 | public class GeneticAlgorithm { 13 | 14 | ArrayList statistics; //holds statistics object for each generation 15 | 16 | Crossover crossover; 17 | Mutator mutator; 18 | Selector selector; 19 | Initializer initializer; 20 | FitnessFunction fitnessFunction; 21 | Population population; 22 | TerminationCriteria terminationCriteria; //termination criteria 23 | 24 | double p_crossover; //crossover probability 25 | double p_mutation; //mutation probability 26 | int popSize; //population size 27 | int generations; //number of iterations 28 | int minimax; //minimize/maximize 29 | boolean elitism = true; //perform elitism ? 30 | int nElitism = Consts.NELITISM; //number of elitism replacements 31 | 32 | public GeneticAlgorithm() { 33 | this(100, 1.0, 0.02, 200); 34 | } 35 | 36 | /** 37 | * 38 | * @param pop_size - Population size 39 | * @param p_cx - Crossover probability 40 | * @param p_mut - Mutation probability 41 | * @param ngen - Generations number 42 | */ 43 | public GeneticAlgorithm(int pop_size, double p_cx, double p_mut, int ngen) { 44 | this.popSize = pop_size; 45 | this.p_crossover = p_cx; 46 | this.p_mutation = p_mut; 47 | this.generations = ngen; 48 | this.minimax = 0; 49 | this.statistics = new ArrayList(); 50 | } 51 | 52 | /** 53 | * Evolves the population. Default parameters: 54 | * statsFrequency = 100 55 | */ 56 | public void evolve() { 57 | evolve(100); 58 | } 59 | 60 | /** 61 | * Evolves the population. 62 | * 63 | * @param statsFrequency - prints the statistics after the given number of generations 64 | */ 65 | public void evolve(int statsFrequency) { 66 | //check to make sure all operators are set 67 | check(); 68 | 69 | //initialize population 70 | initialize(); 71 | 72 | //calculate the fitness of the population 73 | calculateFitness(population); 74 | 75 | for (int i = 0; i < generations; i++) { 76 | 77 | //check if a termination criteria exists 78 | if (terminationCriteria != null) { 79 | //check if it has been reached 80 | if (terminationCriteria.terminate(population)) { 81 | System.out.println("Termination criteria reached after " + i + " generations."); 82 | return; 83 | } 84 | } 85 | 86 | //print stats 87 | if (i % statsFrequency == 0) { 88 | System.out.println(statistics.get(statistics.size()-1).toString()); 89 | } 90 | 91 | Population newPopulation = null; 92 | 93 | //select parents 94 | newPopulation = selector.select(population); 95 | 96 | //perform crossover 97 | newPopulation = crossover.crossover(newPopulation, p_crossover); 98 | 99 | //perform mutation 100 | newPopulation = mutator.mutate(newPopulation, p_mutation); 101 | 102 | //perform elitism 103 | if (elitism) { 104 | elitism(newPopulation); 105 | } 106 | 107 | //assign the new population to the current population 108 | population = newPopulation; 109 | 110 | 111 | //calculate the fitness of the new population 112 | calculateFitness(population); 113 | 114 | } 115 | 116 | } 117 | 118 | /** 119 | * Initializes the population. 120 | */ 121 | public void initialize() { 122 | population = new Population(); 123 | 124 | for (int i = 0; i < popSize; i++) { 125 | population.add(initializer.initialize()); 126 | } 127 | 128 | population.sort(); 129 | } 130 | 131 | /** 132 | * Calculates the fitness of the given population. 133 | * 134 | * @param population 135 | */ 136 | public void calculateFitness(Population population) { 137 | if (population.length() < 1) { 138 | return; 139 | } 140 | 141 | double sum = 0; 142 | double min = Double.POSITIVE_INFINITY; 143 | double max = Double.NEGATIVE_INFINITY; 144 | 145 | Chromosome bestChromosome = null; 146 | Chromosome worstChromosome = null; 147 | double bestValue = Double.NEGATIVE_INFINITY; 148 | double worstValue = Double.POSITIVE_INFINITY; 149 | 150 | for (Chromosome c : population) { 151 | double val = fitnessFunction.evaluate(c); 152 | double rawVal = val; 153 | 154 | if (minimax == Consts.MINIMIZE) { 155 | val = -1 * val; 156 | } 157 | 158 | c.setFitnessValue(val); 159 | c.setRawFitnessValue(rawVal); 160 | 161 | sum += rawVal; 162 | 163 | if (val > bestValue) { 164 | bestChromosome = c; 165 | bestValue = val; 166 | } 167 | if (val < worstValue) { 168 | worstChromosome = c; 169 | worstValue = val; 170 | } 171 | 172 | if (rawVal > max) { 173 | max = rawVal; 174 | } 175 | if (rawVal < min) { 176 | min = rawVal; 177 | } 178 | } 179 | 180 | Statistics stat = new Statistics(); 181 | stat.setSum(sum); 182 | stat.setAvg(sum / popSize); 183 | stat.setMin(min); 184 | stat.setMax(max); 185 | stat.setGen(statistics.size()); 186 | statistics.add(stat); 187 | 188 | population.setBestIndividual(bestChromosome); 189 | population.setBestValue(bestValue); 190 | population.setWorstIndividual(worstChromosome); 191 | population.setWorstValue(worstValue); 192 | } 193 | 194 | /** 195 | * Performs elitism. 196 | * 197 | * @param pop 198 | */ 199 | private void elitism(Population pop) { 200 | population.sort(); 201 | pop.sort(); 202 | for (int i = 0; i < nElitism; i++) { 203 | population.get(i).setFitnessValue( 204 | fitnessFunction.evaluate(population.get(i)) 205 | ); 206 | 207 | if (population.get(i).getFitnessValue() > pop.get(i).getFitnessValue()) { 208 | pop.set(pop.length() - i - 1, population.get(i)); 209 | } 210 | } 211 | } 212 | 213 | public Chromosome getSolution() { 214 | return population.getBestIndividual(); 215 | } 216 | 217 | void check() { 218 | if (crossover == null) { 219 | throw new IllegalStateException("Crossover operator not set."); 220 | } 221 | if (mutator == null) { 222 | throw new IllegalStateException("Mutation operator not set."); 223 | } 224 | if (selector == null) { 225 | throw new IllegalStateException("Selection operator not set."); 226 | } 227 | if (initializer == null) { 228 | throw new IllegalStateException("Initializer not set."); 229 | } 230 | if (fitnessFunction == null) { 231 | throw new IllegalStateException("Fitness function not set."); 232 | } 233 | if (minimax == 0) { 234 | throw new IllegalStateException("Minimax condition not set."); 235 | } 236 | } 237 | 238 | public GeneticAlgorithm setCrossover(Crossover crossover) { 239 | this.crossover = crossover; 240 | return this; 241 | } 242 | 243 | public Crossover getCrossover() { 244 | return crossover; 245 | } 246 | 247 | public GeneticAlgorithm setCrossoverProbability(double p) { 248 | this.p_crossover = p; 249 | return this; 250 | } 251 | 252 | public double getCrossoverProbability() { 253 | return p_crossover; 254 | } 255 | 256 | public GeneticAlgorithm setMutator(Mutator mutator) { 257 | this.mutator = mutator; 258 | return this; 259 | } 260 | 261 | public Mutator getMutator() { 262 | return mutator; 263 | } 264 | 265 | public GeneticAlgorithm setMutationProbability(double p) { 266 | this.p_mutation = p; 267 | return this; 268 | } 269 | 270 | public double getMutationProbability() { 271 | return p_mutation; 272 | } 273 | 274 | public GeneticAlgorithm setSelector(Selector selector) { 275 | this.selector = selector; 276 | return this; 277 | } 278 | 279 | public Selector getSelector() { 280 | return selector; 281 | } 282 | 283 | public GeneticAlgorithm setInitializer(Initializer initializer) { 284 | this.initializer = initializer; 285 | return this; 286 | } 287 | 288 | public Initializer getInitializer() { 289 | return initializer; 290 | } 291 | 292 | public GeneticAlgorithm setFitnessFunction(FitnessFunction fitnessFunction) { 293 | this.fitnessFunction = fitnessFunction; 294 | return this; 295 | } 296 | 297 | public FitnessFunction getFitnessFunction() { 298 | return fitnessFunction; 299 | } 300 | 301 | public GeneticAlgorithm setPopulationSize(int pop_size) { 302 | this.popSize = pop_size; 303 | return this; 304 | } 305 | 306 | public int getPopulationSize() { 307 | return popSize; 308 | } 309 | 310 | public GeneticAlgorithm setGenerations(int generations) { 311 | this.generations = generations; 312 | return this; 313 | } 314 | 315 | public int getGenerations() { 316 | return generations; 317 | } 318 | 319 | public GeneticAlgorithm setPopulation(Population population) { 320 | this.population = population; 321 | return this; 322 | } 323 | 324 | public Population getPopulation() { 325 | return population; 326 | } 327 | 328 | public GeneticAlgorithm setMinimax(int minimax) { 329 | this.minimax = minimax; 330 | return this; 331 | } 332 | 333 | public int getMinimax() { 334 | return minimax; 335 | } 336 | 337 | public GeneticAlgorithm setElitism(boolean elitism) { 338 | this.elitism = elitism; 339 | return this; 340 | } 341 | 342 | public boolean getElitism() { 343 | return elitism; 344 | } 345 | 346 | public GeneticAlgorithm setElitismReplacements(int n) { 347 | this.nElitism = n; 348 | return this; 349 | } 350 | 351 | public int getElitismReplacements() { 352 | return nElitism; 353 | } 354 | 355 | public GeneticAlgorithm setTerminationCriteria(TerminationCriteria criteria) { 356 | this.terminationCriteria = criteria; 357 | return this; 358 | } 359 | 360 | public TerminationCriteria getTerminationCriteria() { 361 | return terminationCriteria; 362 | } 363 | 364 | } 365 | --------------------------------------------------------------------------------