aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/population/Population.java
blob: 5d549e9ee72dc66e046d13617e891f6ea56bfe0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package jcgp.backend.population;

import java.util.Arrays;
import java.util.Collections;

import jcgp.backend.resources.Resources;

/**
 * This class primarily holds a collection of chromosomes. In addition, 
 * it provides a few utility methods for manipulating and copying 
 * chromosomes, useful for evolutionary strategies.
 * <br><br>
 * {@code copyChromosome()} is used to create copies of chromosomes, 
 * though it is also possible to create a new instance of population
 * directly from a seed chromosome using the right constructor. 
 * <br><br>
 * For convenience, a random chromosome can be retrieved using
 * {@code getRandomChromosome()}, which is guaranteed to use the
 * experiment's specified seed. If an entirely random population
 * is needed, {@code reinitialise()} should be used to randomise
 * all chromosomes without creating a new instance of {@code Population}.
 * <br><br>
 * By convention the population's chromosomes should always be sorted in
 * order of fitness, from worst to best. This cannot be done automatically
 * since a higher fitness value does not necessarily mean better fitness;
 * some problem types might instead interpret fitness 0 as a perfect solution.
 * Sorting the population is done easily using {@code sortAscending()} and
 * {@code sortDescending()}, and should be done by the problem type as appropriate.
 * It is <b>critical</b> to sort the population after it is evaluated as 
 * evolutionary strategies will obey the convention and assume the population
 * is sorted in order of fitness.
 * 
 * 
 * @author Eduardo Pedroni
 *
 */
public class Population {
	
	private final Chromosome[] chromosomes;
	private final Resources resources;
	
	/**
	 * Initialise a random population according to the parameters specified
	 * in the resources.
	 * 
	 * @param resources the experiment's resources.
	 */
	public Population(Resources resources) {
		this.resources = resources;
		
		chromosomes = new Chromosome[resources.populationSize()];
		for (int c = 0; c < chromosomes.length; c++) {
			chromosomes[c] = new Chromosome(resources);
		}
	}
	
	/**
	 * Initialise a population of copies of the given chromosome.
	 * 
	 * @param parent the chromosome to use as a model.
	 * @param resources a reference to the experiment's resources.
	 */
	public Population(Chromosome parent, Resources resources) {
		this.resources = resources;
		
		chromosomes = new Chromosome[resources.populationSize()];
		for (int c = 0; c < chromosomes.length; c++) {
			chromosomes[c] = new Chromosome(parent);
		}
	}

	/**
	 * Returns the indexed chromosome.
	 * 
	 * @param index the chromosome to return.
	 * @return the indexed chromosome.
	 */
	public Chromosome getChromosome(int index) {
		return chromosomes[index];
	}
	
	/**
	 * @return a random chromosome from this population.
	 */
	public Chromosome getRandomChromosome() {
		return chromosomes[resources.getRandomInt(chromosomes.length)];
	}

	/**
	 * Copy a chromosome into a different position.
	 * After this returns, the target chromosome has
	 * identical connections and functions to the source
	 * one, though they are separate instances.
	 * 
	 * This method does nothing if source == target.
	 * 
	 * @param source the chromosome to copy from.
	 * @param target the chromosome to copy to.
	 */
	public void copyChromosome(int source, int target) {
		if (source != target) {
			chromosomes[target].copyGenes(chromosomes[source]);
		}
	}
	
	/**
	 * Loop through all chromosomes and randomise all connections
	 * and functions.
	 */
	public void reinitialise() {
		for (int c = 0; c < chromosomes.length; c++) {
			chromosomes[c].reinitialiseConnections();
		}
	}
	
	/**
	 * The fittest chromosome, by convention, is the last one
	 * in the array. Problem evaluation methods are expected to
	 * sort the population into ascending order of fitness, such
	 * that the best chromosome is in the last position (size - 1).
	 * This method assumes that the population is sorted as such
	 * and returns the last chromosome in the array.
	 * 
	 * @return the fittest chromosome in the population.
	 */
	public Chromosome getFittest() {
		return chromosomes[chromosomes.length - 1];
	}
	
	/**
	 * The fittest chromosome, by convention, is the last one
	 * in the array. Problem evaluation methods are expected to
	 * sort the population into ascending order of fitness, such
	 * that the best chromosome is in the last position (size - 1).
	 * This method assumes that the population is sorted as such
	 * and returns the last index in the array.
	 * 
	 * @return the index of the fittest chromosome.
	 */
	public int getFittestIndex() {
		return chromosomes.length - 1;
	}

	/**
	 * Sort the population into ascending order of fitness.
	 */
	public void sortAscending() {
		Arrays.sort(chromosomes);
	}
	
	/**
	 * Sort the population into descending order of fitness.
	 */
	public void sortDescending() {
		Arrays.sort(chromosomes, Collections.reverseOrder());
	}
}