aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/modules/mutator/PointMutator.java
blob: 5aba0d1bd9c0e8b6c3589814394d6bc106cb86ae (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
package jcgp.backend.modules.mutator;

import jcgp.backend.parameters.BooleanParameter;
import jcgp.backend.parameters.IntegerParameter;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Mutable;
import jcgp.backend.population.Node;
import jcgp.backend.population.Output;
import jcgp.backend.resources.Resources;

/**
 * Point mutator
 * <br><br>
 * In point mutation, a number of random genes
 * is picked and mutated until all required
 * mutations have been performed. The actual number
 * of genes to be mutated can be defined in any
 * arbitrary way.
 * 
 * @author Eduardo Pedroni
 *
 */
public abstract class PointMutator extends Mutator {

	protected IntegerParameter genesMutated;
	protected BooleanParameter report;
	
	/**
	 * For internal use only, initialises the resources field.
	 * 
	 * @param resources the experiment's resources.
	 */
	protected PointMutator(Resources resources) {
		super(resources);
	}

	@Override
	public void mutate(Chromosome chromosome) {
		if (report.get()) getResources().reportln("[Mutator] Number of mutations to be performed: " + genesMutated.get());
		
		// for however many genes must be mutated
		for (int i = 0; i < genesMutated.get(); i++) {
			
			Mutable m = chromosome.getRandomMutable();
			
			if (report.get()) getResources().report("[Mutator] Mutation " + i + " selected " + m + ", ");
			
			// outputs and nodes are mutated differently
			if (m instanceof Output) {
				if (report.get()) getResources().report("changed source from " + ((Output) m).getSource() + " ");
				
				// outputs are easy, simply set to a different random connection, any will do
				m.setConnection(0, chromosome.getRandomConnection());
				
				if (report.get()) getResources().reportln("to " + ((Output) m).getSource());
			} else if (m instanceof Node) {
				/* nodes are more complicated, first we must decide whether to mutate the function
				 * or a connection
				 * we do this by generating a random int between 0 and 1 + arity
				 */
				int geneType = getResources().getRandomInt(1 + getResources().arity());
				
				// if the int is less than 1, mutate function, else mutate connections 
				if (geneType < 1) {
					if (report.get()) getResources().report("changed function from " + ((Node) m).getFunction() + " ");
					
					((Node) m).setFunction(getResources().getRandomFunction());
					
					if (report.get()) getResources().reportln("to " + ((Node) m).getFunction());
				} else {
					// if we decided to mutate connection, subtract 1 from geneType so it fits into the arity range
					geneType--;
					if (report.get()) getResources().report("changed connection " + geneType + " from " + ((Node) m).getConnection(geneType) + " ");
					
					m.setConnection(geneType, chromosome.getRandomConnection(((Node) m).getColumn()));
					
					if (report.get()) getResources().reportln("to " + ((Node) m).getConnection(geneType));
				}
			}
		}
	}

}