aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/population/Chromosome.java
blob: 0dc3ff9b1b96fbd0dd649c74d5e579ecb3e393c1 (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
package jcgp.population;

import jcgp.Parameters;
import jcgp.Utilities;
import jcgp.fitness.ParameterMismatchException;

public class Chromosome {

	private Input[] inputs;
	private Node[][] nodes;
	private Output[] outputs;

	private int fitness = 0;

	/**
	 * Good citizen.
	 * 
	 * @param outputs 
	 * @param columns 
	 * @param rows 
	 * @param inputs 
	 * 
	 */
	public Chromosome(int inputCount, int rows, int columns, int outputCount) {

		instantiateElements(inputCount, rows, columns, outputCount);

		initialiseConnections();

	}

	/**
	 * @param inputCount
	 * @param rows
	 * @param columns
	 * @param outputCount
	 */
	private void instantiateElements(int inputCount, int rows, int columns,	int outputCount) {
		inputs = new Input[inputCount];
		for (int i = 0; i < inputCount; i++) {
			inputs[i] = new Input();
		}

		// rows first
		nodes = new Node[rows][columns];
		for (int r = 0; r < rows; r++) {
			//nodes[r] = new Node[Parameters.getColumns()];
			for (int c = 0; c < columns; c++) {
				nodes[r][c] = new Node(r, c);
			}
		}
		outputs = new Output[outputCount];
		for (int o = 0; o < outputCount; o++) {
			outputs[o] = new Output(o);
		}
	}

	private void initialiseConnections() {

		// initialise nodes - [rows][columns]
		for (int r = 0; r < nodes.length; r++) {
			for (int c = 0; c < nodes.length; c++) {
				Connection[] connections = new Connection[Parameters.getMaxArity()];
				for (int i = 0; i < connections.length; i++) {
					connections[i] = Utilities.getRandomConnection(this, c);
				}
				nodes[r][c].initialise(Utilities.getRandomFunction(), connections);
			}
		}

		for (Output output : outputs) {
			output.setConnection(Utilities.getRandomNode(this));
		}

	}

	public int getActiveNodeCount() {
		return 0;
	}

	public Node getNode(int row, int column) {
		return nodes[row][column];
	}

	public Output getOutput(int index) {
		return outputs[index];
	}

	public Input getInput(int index) {
		return inputs[index];
	}

	public int getFitness() {
		return fitness;
	}

	public void setFitness(int newFitness) {
		fitness = newFitness;
	}

	public void setInputs(int ... values) throws ParameterMismatchException {
		// if the values provided don't match the specified number of inputs, the user should be warned
		if (values.length == inputs.length) {
			// set inputs for evaluation
			for (int i = 0; i < values.length; i++) {
				inputs[i].setValue(values[i]);
			}
		} else {
			throw new ParameterMismatchException();
		}
	}

	public MutableElement getRandomMutableElement() {
		// choose output or node
		int index = Utilities.getRandomInt(outputs.length + Parameters.getNodeCount());

		if (index < outputs.length) {
			// outputs
			return outputs[index];
		} else {
			// node	
			index -= outputs.length;
			return nodes[index / Parameters.getColumns()][index % Parameters.getColumns()];
		}
	}
	
	/**
	 * Returns a random allowed connection respecting levels back.
	 * This method may always pick inputs, as they can be picked
	 * regardless of the column.
	 * 
	 * @param column the column to use as reference
	 * @return a random connection
	 */
	public Connection getRandomConnection(int column) {
		
		
		
		return null;
		
	}
	
	/**
	 * Returns a random allowed connection. 
	 * 
	 * This method may always pick inputs, as they can be picked
	 * regardless of the column.
	 * 
	 * TODO optimise for less random generations
	 * 
	 * @param column the column to use as reference
	 * @param levelsBack whether or not to respect levels back
	 * @return a random connection
	 */
	public Connection getRandomConnection(int column, boolean levelsBack) {
		
		if (levelsBack) {
			return getRandomConnection(chromosome, column);
		} else {
			// choose input or node
			int connectionType = Utilities.getRandomInt(inputs.length + (nodes.length * column));
			if (connectionType < inputs.length) {
				// input
				return chromosome.getInput(getRandomInt(Parameters.getInputs()));
			} else {
				// node				
				return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(column));
			}
		}
		
	}

}