aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/population/Population.java
blob: 70cfda85f269de602d4bcde2d9013d93571e2e71 (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
package jcgp.backend.population;

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

import jcgp.backend.modules.problem.BestFitness;
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}.
 * 
 * 
 * @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 get(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();
		}
	}
		
	/**
	 * Sorts the population in ascending order of fitness quality.
	 * What this means is that the best fitness chromosome will be
	 * in the last position, even though it might have the lowest
	 * fitness value. Fitness orientation as specified in the resources
	 * is respected.
	 */
	public void sort() {
		if (resources.fitnessOrientation() == BestFitness.HIGH) {
			Arrays.sort(chromosomes);
		} else {
			Arrays.sort(chromosomes, Collections.reverseOrder());
		}
	}
}