jenes.tutorials.problem3.TSPCityCenteredCrossover

001 /*
002  * JENES
003  * A time and memory efficient Java library for genetic algorithms and more 
004  * Copyright (C) 2011 Intelligentia srl
005  *
006  * This program is free software: you can redistribute it and/or modify
007  * it under the terms of the GNU General Public License as published by
008  * the Free Software Foundation, either version 3 of the License, or
009  * (at your option) any later version.
010  *
011  *  This program is distributed in the hope that it will be useful,
012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014  *  GNU General Public License for more details.
015  *
016  *  You should have received a copy of the GNU General Public License
017  *  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
018  */
019 package jenes.tutorials.problem3;
020 
021 import jenes.AlgorithmException;
022 import jenes.utils.Random;
023 import jenes.chromosome.IntegerChromosome;
024 import jenes.population.Individual;
025 import jenes.stage.operator.Crossover;
026 
027 /**
028  * Tutorial showing how to implement problem specific operators.
029  * The problem faced in this example is the well known Tavel Salesman Problem (TSP)
030  *
031  * This class implements a specific crossover aimed at preserving permutations.
032  *
033  * Algorithm description:
034  <pre>
035  *      parent1  5 2 1 4 6 3     parent2   1 3 2 4 6 5
036  *      child1   _ _ _ _ _ _     child2    _ _ _ _ _ _
037  *</pre>
038  * Step 1: a city is choosed randomly. We copy all the cities until the selected one from each parent to
039  * each child (parent1 in child1 and parent2 in child2)
040  <pre>
041  *      parent1  5 2 1 4 6 3     parent2   1 3 2 4 6 5
042  *      child1   5 2 _ _ _ _     child2    1 3 2 _ _ _
043  </pre>
044  * Step 2: we fill child1 getting missing elements from parent2; these ones will have the same parent2 order
045  <pre>
046  *      parent1  5 2 1 4 6 3     parent2  1 3 2 4 6 5
047  *      child1   5 2 1 3 4 6     child2   1 3 2 5 4 6
048  *</pre>
049  *
050  * We repeat these steps for child2
051  *
052  @author Luigi Troiano
053  *
054  @version 2.0
055  @since 1.0
056  */
057 public class TSPCityCenteredCrossover extends Crossover<IntegerChromosome>{
058     
059     public TSPCityCenteredCrossover(double pCross) {
060         super(pCross);
061     }
062     
063     /**
064      * Returns the number of chromosomes (i.e. 2) this operator entails.
065      */
066     @Override
067     public int spread() {
068         return 2;
069     }
070     
071     private IntegerChromosome chrom_parent1 = null;
072     private IntegerChromosome chrom_parent2 = null;
073     /**
074      * This method implements the crossover operation.
075      *
076      @param offsprings the chromosomes to be crossed.
077      */
078     protected void cross(Individual<IntegerChromosome> offsprings[]) {
079         
080         IntegerChromosome chrom_child1 = offsprings[0].getChromosome();
081         IntegerChromosome chrom_child2 = offsprings[1].getChromosome();
082         
083         ifchrom_parent1 == null ) {
084             chrom_parent1 = chrom_child1.clone();
085             chrom_parent2 = chrom_child2.clone();
086         else {
087             chrom_parent1.setAs(chrom_child1);
088             chrom_parent2.setAs(chrom_child2);
089         }
090         
091         final int size = chrom_child1.length();
092         ifchrom_child2.length() != size )
093             throw new AlgorithmException("Error: the two chromosomes are required to have the same length.");
094         
095         
096         //we choose a random city
097         int city = Random.getInstance().nextInt(0, size);
098         
099         //i1, i2 are the positions of the city respectively in child1 and child2
100         int i1 = findPositionOf(city, chrom_child1);
101         int i2 = findPositionOf(city, chrom_child2);
102         
103         int j1 = 0;
104         int j2 = 0;
105         forint i = 0; i < size; ++i ) {
106             // get the city c1 in position i for parent1
107             int c1 = chrom_parent1.getValue(i);
108             // find the position of c1 in parent 2
109             int p2 = findPositionOf(c1, chrom_parent2);
110             // if the position is over the cross-point, it copies c1 in child2
111             ifp2 > i2 ) {
112                 chrom_child2.setValue(i2 + (++j2), c1);
113             }
114             
115             // similarly we process the other pair
116             int c2 = chrom_parent2.getValue(i);
117             int p1 = findPositionOf(c2, chrom_parent1);
118             ifp1 > i1 ) {
119                 chrom_child1.setValue(i1 + (++j1), c2);
120             }
121         }
122     }
123     
124     /**
125      * Finds the position of one specific city in the chromosome.
126      <p>
127      @param city the city to find
128      @param chrom the chromosome to search
129      @return the city position
130      */
131     private int findPositionOf(int city, IntegerChromosome chrom){
132         final int size = chrom.length();
133         forint i = 0; i < size; ++i ) {
134             ifchrom.getValue(i== city )
135                 return i;
136         }
137         return -1;
138     }
139     
140 }