aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/JCGP.java
blob: f94994440148a56f97076011ceadc900475c9d0f (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
package jcgp;

import java.io.File;

import jcgp.backend.modules.es.EvolutionaryStrategy;
import jcgp.backend.modules.es.MuPlusLambda;
import jcgp.backend.modules.es.TournamentSelection;
import jcgp.backend.modules.mutator.Mutator;
import jcgp.backend.modules.mutator.PointMutator;
import jcgp.backend.modules.problem.DigitalCircuitProblem;
import jcgp.backend.modules.problem.Problem;
import jcgp.backend.modules.problem.SymbolicRegressionProblem;
import jcgp.backend.modules.problem.TestCaseProblem;
import jcgp.backend.parser.ChromosomeParser;
import jcgp.backend.parser.FunctionParser;
import jcgp.backend.parser.ParameterParser;
import jcgp.backend.parser.TestCaseParser;
import jcgp.backend.population.Population;
import jcgp.backend.resources.Console;
import jcgp.backend.resources.ModifiableResources;
import jcgp.backend.resources.Resources;

/**
 * 
 * Top-level CGP class. This class is the entry point for a CGP experiment. 
 * <br>
 * An instance of JCGP encapsulates the entire experiment. It contains a Resources
 * object which can be retrieved via a getter. Modules can be selected using their
 * respective setters and function sets can be selected through the resources.
 * 
 * The flow of the experiment is controlled using start() and nextGeneration(). The
 * experiment can be reset with reset(), TODO comment
 * 
 * 
 * @author Eduardo Pedroni
 * @see Resources, Module, FunctionSet
 */
public class JCGP {
	
	// make resources
	private final ModifiableResources resources = new ModifiableResources();
	
	/*
	 * The following arrays contain all available modules. These collections are read by the GUI
	 * when generating menus, so modules not added here will *NOT* be selectable in the GUI.
	 * 
	 * Each array is accompanied by a field which contains a reference to the currently selected
	 * module, 0 by default.
	 */
	// mutators
	private Mutator[] mutators = new Mutator[] {
			new PointMutator(resources) };
	private Mutator mutator;
	
	// evolutionary algorithms
	private EvolutionaryStrategy[] evolutionaryStrategies = new EvolutionaryStrategy[] {
			new MuPlusLambda(resources),
			new TournamentSelection() };
	private EvolutionaryStrategy evolutionaryStrategy;
	
	// problem types
	private Problem[] problems = new Problem[] {
			new SymbolicRegressionProblem(resources),
			new DigitalCircuitProblem(resources) };
	private Problem problem;

	/*
	 * the population of chromosomes
	 */
	private Population population;
	private boolean finished = false;
	
	/**
	 * TODO comment this!
	 * 
	 * @param args
	 */
	public static void main(String... args) {
		if (args.length < 1) {
			System.err.println("JCGP requires at least a .par file.");
			System.exit(1);
		}
		JCGP jcgp = new JCGP();
		jcgp.loadParameters(new File(args[0]));
		
		if (jcgp.getProblem() instanceof TestCaseProblem) {
			((TestCaseProblem<?>) jcgp.getProblem()).parse(new File(args[2]));
		}
		
		jcgp.start();
	}
	
	public JCGP() {
		setEvolutionaryStrategy(0);
		setMutator(0);
		setProblem(0);
		
		population = new Population(resources);
	}

	public ModifiableResources getResources() {
		return resources;
	}
	
	public Population getPopulation() {
		return population;
	}

	/**
	 * @return the mutators
	 */
	public Mutator[] getMutators() {
		return mutators;
	}


	/**
	 * @return the mutator
	 */
	public Mutator getMutator() {
		return mutator;
	}


	/**
	 * @return the evolutionaryAlgorithms
	 */
	public EvolutionaryStrategy[] getEvolutionaryStrategies() {
		return evolutionaryStrategies;
	}


	/**
	 * @return the evolutionaryAlgorithm
	 */
	public EvolutionaryStrategy getEvolutionaryStrategy() {
		return evolutionaryStrategy;
	}


	/**
	 * @return the fitnessFunctions
	 */
	public Problem[] getProblems() {
		return problems;
	}


	/**
	 * @return the fitnessFunction
	 */
	public Problem getProblem() {
		return problem;
	}
	
	
	/**
	 * @param mutator the mutator to set
	 */
	public void setMutator(int index) {
		this.mutator = mutators[index];
	}


	/**
	 * @param evolutionaryStrategy the evolutionaryAlgorithm to set
	 */
	public void setEvolutionaryStrategy(int index) {		
		this.evolutionaryStrategy = evolutionaryStrategies[index];
	}


	/**
	 * @param problem the fitnessFunction to set
	 */
	public void setProblem(int index) {
		this.problem = problems[index];
		resources.setFunctionSet(problem.getFunctionSet());
	}
	
	public void nextGeneration() {
		if (!finished) {
			problem.evaluate(population, (Resources) resources);
			reportGeneration();

			if (resources.currentGeneration() < resources.generations()) {
				// we still have generations left to go
				if (problem.isPerfectSolution(population.getFittest())) {
					// solution has been found, start next run
					resources.println("[CGP] Solution found, generation " + resources.currentGeneration() + ", chromosome " + population.getFittestIndex());
					
					if (resources.currentRun() < resources.runs()) {
						// there are still runs left
						resources.setCurrentRun(resources.currentRun() + 1);
						resources.setCurrentGeneration(0);
						
						// start a new population
						population.reinitialise();
					} else {
						// no more generations and no more runs, we're done
						finished = true;
					}
				} else {
					resources.setCurrentGeneration(resources.currentGeneration() + 1);
				}
			} else {
				// the run has ended, check if any more runs must be done
				resources.println("[CGP] Solution not found, highest fitness achieved was "
						+ population.getFittest().getFitness()
						+ " by chromosome " + population.getFittestIndex());

				if (resources.currentRun() < resources.runs()) {
					// the run has ended but there are still runs left
					resources.setCurrentRun(resources.currentRun() + 1);
					resources.setCurrentGeneration(0);
					
					// start a new population
					population.reinitialise();
				} else {
					// no more generations and no more runs, we're done
					finished = true;
				}
			}
		}

		evolutionaryStrategy.evolve(population, mutator, (Resources) resources);
		
	}
	
	private void reportGeneration() {
		if (resources.reportInterval() > 0) {
			if (resources.currentGeneration() % resources.reportInterval() == 0) {
				resources.println("[CGP] Generation: " + resources.currentGeneration() + ", fittest chromosome (" 
			+ population.getFittestIndex() + ") has fitness: " + population.getFittest().getFitness());
			}
		}
	}

	public void start() {
		if (!finished) {
			while (!finished) {
				nextGeneration();
			}
		}
	}
	
	public void reset() {
		finished = false;
		population = new Population(resources);
		resources.setCurrentGeneration(1);
		resources.setCurrentRun(1);
		resources.println("-----------------------------");
		resources.println("New experiment: " + problem.toString());
	}
	
	public void loadParameters(File file) {
		ParameterParser.parseParameters(file, resources);
		FunctionParser.parseFunctions(file, problem);
		reset();
	}
	
	public void loadTestCases(File file) {
		if (problem instanceof TestCaseProblem) {
			TestCaseParser.parseParameters(file, resources);
			reset();
			((TestCaseProblem<?>) problem).parse(file);
		}
	}
	
	public void loadChromosome(File file) {
		ChromosomeParser.parse(file, population.getChromosome(0), resources);
	}
	
	public void saveChromosome(File file, int chromosomeIndex) {
		ChromosomeParser.save(file, population.getChromosome(chromosomeIndex));
	}

	public boolean isFinished() {
		return finished;
	}
	
	public void setConsole(Console console) {
		resources.setConsole(console);
	}
}