aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/parser/ChromosomeParser.java
blob: 74f638c1d223f6d18ce65f6ec53875b74b545bc7 (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
package jcgp.backend.parser;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.Scanner;

import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Node;
import jcgp.backend.resources.Resources;

/**
 * This class includes a method for parsing .chr files and another
 * for writing .chr files from given chromosomes.
 * 
 * @author Eduardo Pedroni
 *
 */
public class ChromosomeParser {

	/**
	 * Use this method to parse .chr files into a given chromosome.
	 * <br><br>
	 * This is not fully defensive as it doesn't check for number of inputs, 
	 * doesn't compare rows and columns individually and doesn't account for levels back. It
	 * is not viable to implement these defensive measures with the chromosome format used 
	 * by CGP.
	 * 
	 * @param file the .chr file to parse from
	 * @param chromosome the chromosome to configure
	 * @param resources the experiment resources
	 */
	public static void parse(File file, Chromosome chromosome, Resources resources) {
		/* 
		 * Count the nodes to make sure the size of the .chr file matches the experiment parameters.
		 * 
		 * We do this by using the scanner to get the node and output portions of the file as they
		 * are separated by 3 tab characters. Every number is replaced by a single known character, 
		 * and the length of the string with the new characters is compared with that of a string
		 * where the new known character has been removed, yielding the total number of values.
		 * 
		 */
		FileReader fr;
		try {
			fr = new FileReader(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			return;
		}
		Scanner in = new Scanner(fr);
		in.useDelimiter("\\t\\t\\t");
		String geneString = in.next().replaceAll("[0-9]+", "g");
		String outString = in.next().replaceAll("[0-9]+", "o");
		int geneCount = geneString.length() - geneString.replace("g", "").length();
		int outCount = outString.length() - outString.replace("o", "").length();
		in.close();
		
		
		// if the acquired values match the current parameters, apply them to the chromosome
		if ((geneCount == resources.nodes() * (resources.arity() + 1))
				&& outCount == resources.outputs()) {
			// prepare a new scanner
			try {
				fr = new FileReader(file);
			} catch (FileNotFoundException e) {
				e.printStackTrace();
				return;
			}
			in = new Scanner(fr);
			
			int gene;
			Connection newConnection;
			Node changingNode;
			// for all nodes, columns first
			for (int c = 0; c < resources.columns(); c ++) {
				for (int r = 0; r < resources.rows(); r ++) {
					// store the changing node
					changingNode = chromosome.getNode(r, c);

					// for every connection
					for (int i = 0; i < resources.arity(); i ++) {
						// get connection number from the .chr file
						gene = in.nextInt();
						if (gene < resources.inputs()) {
							// connection was an input
							newConnection = chromosome.getInput(gene);
						} else {
							// connection was another node, calculate which from its number
							newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(), 
									(gene - resources.inputs()) / resources.rows());
						}
						changingNode.setConnection(i, newConnection);
					}

					// set the function, straight indexing should work - this is not entirely
					// safe, but it is not viable to check for functionset compatibility
					changingNode.setFunction(resources.getFunction(in.nextInt()));
				}
			}

			// outputs
			for (int o = 0; o < resources.outputs(); o ++) {
				gene = in.nextInt();
				if (gene < resources.inputs()) {
					// connection was an input
					newConnection = chromosome.getInput(gene);
				} else {
					// connection was another node, calculate which from its number
					newConnection = chromosome.getNode((gene - resources.inputs()) % resources.rows(), 
							(gene - resources.inputs()) / resources.rows());
				}
				chromosome.getOutput(o).setConnection(0, newConnection);
			}
			in.close();
		}
	}
	
	/**
	 * Writes a chromosome into the specified .chr file.
	 * 
	 * 
	 * 
	 * @param file
	 * @param chromosome
	 */
	public static void save(File file, Chromosome chromosome) {
		
	}
	
}