aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/backend/parsers
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/backend/parsers')
-rw-r--r--src/jcgp/backend/parsers/ChromosomeParser.java14
-rw-r--r--src/jcgp/backend/parsers/FunctionParser.java75
-rw-r--r--src/jcgp/backend/parsers/ParameterParser.java117
-rw-r--r--src/jcgp/backend/parsers/TestCaseParser.java74
4 files changed, 178 insertions, 102 deletions
diff --git a/src/jcgp/backend/parsers/ChromosomeParser.java b/src/jcgp/backend/parsers/ChromosomeParser.java
index ed1399a..92568cc 100644
--- a/src/jcgp/backend/parsers/ChromosomeParser.java
+++ b/src/jcgp/backend/parsers/ChromosomeParser.java
@@ -14,7 +14,7 @@ import jcgp.backend.resources.ModifiableResources;
import jcgp.backend.resources.Resources;
/**
- * This class includes a method for parsing .chr files and another
+ * This class contains a method for parsing .chr files and another
* for writing .chr files from given chromosomes.
*
* @author Eduardo Pedroni
@@ -50,7 +50,7 @@ public abstract class ChromosomeParser {
try {
fr = new FileReader(file);
} catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
return;
}
Scanner in = new Scanner(fr);
@@ -70,7 +70,7 @@ public abstract class ChromosomeParser {
try {
fr = new FileReader(file);
} catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
return;
}
in = new Scanner(fr);
@@ -122,10 +122,10 @@ public abstract class ChromosomeParser {
}
in.close();
- resources.println("[Parser] File parsed successfully.");
+ resources.println("[Parser] File parsed successfully");
} else {
- resources.println("[Parser] Error: the topology of the chromosome in " + file.getName() + " does not match that of the experiment.");
+ resources.println("[Parser] Error: the topology of the chromosome in " + file.getName() + " does not match that of the experiment");
}
}
@@ -143,7 +143,7 @@ public abstract class ChromosomeParser {
try {
writer = new PrintWriter(file);
} catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
return;
}
@@ -184,7 +184,7 @@ public abstract class ChromosomeParser {
writer.close();
- resources.println("[Parser] Chromosome saved successfully.");
+ resources.println("[Parser] Chromosome saved successfully");
}
}
diff --git a/src/jcgp/backend/parsers/FunctionParser.java b/src/jcgp/backend/parsers/FunctionParser.java
index cc52ce9..806099e 100644
--- a/src/jcgp/backend/parsers/FunctionParser.java
+++ b/src/jcgp/backend/parsers/FunctionParser.java
@@ -6,21 +6,35 @@ import java.io.FileReader;
import java.util.Scanner;
import jcgp.backend.function.FunctionSet;
-import jcgp.backend.modules.problem.Problem;
-import jcgp.backend.resources.ModifiableResources;
+import jcgp.backend.resources.Resources;
/**
- * Parses the functions from a .par file.
- * Functions marked with a 1 are enabled,
- * and those marked with 0 are disabled.
+ * Contains a static method for parsing functions from a
+ * .par file.
*
* @author Eduardo Pedroni
*
*/
public abstract class FunctionParser {
- public static void parseFunctions(File file, Problem problem, ModifiableResources resources) {
-
+ /**
+ * Reads the specified file and attempts to enable
+ * and disable the functions in the FunctionSet
+ * accordingly.
+ * <br><br>
+ * Standard CGP .par files do not contain enough information
+ * to determine if they match the currently selected function set.
+ * For this reason, the parser assumes the function set is correct
+ * and treats functions by their index rather than their name. Any
+ * index outside the bounds of the function set is ignored and a
+ * warning message is printed once parsing is complete.
+ *
+ * @param file the .par file to parse.
+ * @param functionSet the function set whose functions should be modified.
+ * @param resources used for printing console messages.
+ */
+ public static void parse(File file, FunctionSet functionSet, Resources resources) {
+ // create file reader and scanner to parse, return if file does not exist
FileReader fr;
try {
fr = new FileReader(file);
@@ -30,23 +44,56 @@ public abstract class FunctionParser {
}
Scanner in = new Scanner(fr);
- FunctionSet functionSet = problem.getFunctionSet();
+ boolean excessFunctions = false;
resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+ /*
+ * The encoding used in .par files is quite simple, so regex matches are used to extract
+ * the values.
+ *
+ * A standard .par file contains functions in the following format:
+ *
+ * 0 1 modulus-0
+ * 0 1 sqrt-1
+ * 0 1 reciprocal-2
+ *
+ * The first integer signals whether to enable or disable the function. Any non-zero value
+ * is treated as "enable". The second integer is the function arity. The integer following
+ * the function name is the function index.
+ *
+ * The scanner is used to return each line separately. Every line that ends in a number
+ * is treated as a function line and split into an array, which holds its composing integers.
+ * This array is then used to enable or disabled the indexed function.
+ *
+ * A flag is raised if the index exceeds the total number of functions, and a warning is
+ * printed once parsing is complete regarding the index mismatch.
+ *
+ */
while (in.hasNextLine()) {
String line = in.nextLine();
if (line.substring(line.length() - 1).matches("[0-9]")) {
String[] splitString = line.split("[^0-9]+");
int functionIndex = Integer.parseInt(splitString[splitString.length - 1]);
- if (Integer.parseInt(splitString[0]) != 0 && !functionSet.isEnabled(functionSet.getFunction(functionIndex))) {
- functionSet.enableFunction(functionIndex);
- resources.println("[Parser] Enabled function: " + functionSet.getFunction(functionIndex));
- } else if (Integer.parseInt(splitString[0]) == 0 && functionSet.isEnabled(functionSet.getFunction(functionIndex))) {
- functionSet.disableFunction(functionIndex);
- resources.println("[Parser] Disabled function: " + functionSet.getFunction(functionIndex));
+
+ if (functionIndex < functionSet.getTotalFunctionCount()) {
+ if (Integer.parseInt(splitString[0]) != 0) {
+ functionSet.enableFunction(functionIndex);
+ resources.println("[Parser] Enabled function: " + functionSet.getFunction(functionIndex));
+ } else if (Integer.parseInt(splitString[0]) == 0) {
+ functionSet.disableFunction(functionIndex);
+ resources.println("[Parser] Disabled function: " + functionSet.getFunction(functionIndex));
+ }
+ } else {
+ excessFunctions = true;
}
}
}
+
+ // warn the user function index went out of bounds
+ if (excessFunctions) {
+ resources.println("[Parser] Warning: the parameter file contained more functions than the current function set");
+ }
+
in.close();
resources.println("[Parser] Finished parsing functions");
}
diff --git a/src/jcgp/backend/parsers/ParameterParser.java b/src/jcgp/backend/parsers/ParameterParser.java
index ae72126..711b4d2 100644
--- a/src/jcgp/backend/parsers/ParameterParser.java
+++ b/src/jcgp/backend/parsers/ParameterParser.java
@@ -7,71 +7,94 @@ import java.util.Scanner;
import jcgp.backend.resources.ModifiableResources;
+/**
+ * Contains a static method for parsing parameters from a
+ * .par file.
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public abstract class ParameterParser {
- public static void parseParameters(File file, ModifiableResources resources) {
-
+ /**
+ * Parses the parameters from a specified CGP parameter file and
+ * modifies the experiment resources appropriately.
+ * <br><br>
+ * CGP .par files do not follow a very strict convention, so this
+ * parser does its best to cope with format irregularities. Parsing
+ * works even if the parameters are in the wrong order, and unknown
+ * parameters are simply ignored.
+ *
+ * @param file the .par file to parse.
+ * @param resources a reference to the resources object that must be modified.
+ */
+ public static void parse(File file, ModifiableResources resources) {
+ // create reader and scanner, print message if file is missing
FileReader fr;
try {
fr = new FileReader(file);
} catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
return;
}
Scanner in = new Scanner(fr);
resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
+ // parse line by line
while (in.hasNextLine()) {
+ // split if one or more tabs or one or more spaces are found
String[] splitString = in.nextLine().split("( |\t)+");
-
- switch (splitString[1]) {
- case "population_size":
- resources.setPopulationSize(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Population size is now " + resources.populationSize() + ".");
- break;
-
- case "num_generations":
- resources.setGenerations(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Total generations is now " + resources.generations() + ".");
- break;
-
- case "num_runs_total":
- resources.setRuns(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Total runs is now " + resources.runs() + ".");
- break;
-
- case "num_rows":
- resources.setRows(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Row number is now " + resources.rows() + ".");
- break;
-
- case "num_cols":
- resources.setColumns(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Column number is now " + resources.columns() + ".");
- break;
+ // expected length is 2, anything beyond that should also work
+ if (splitString.length >= 2) {
+ switch (splitString[1]) {
+ case "population_size":
+ resources.setPopulationSize(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Population size is now " + resources.populationSize());
+ break;
+
+ case "num_generations":
+ resources.setGenerations(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Total generations is now " + resources.generations());
+ break;
+
+ case "num_runs_total":
+ resources.setRuns(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Total runs is now " + resources.runs());
+ break;
+
+ case "num_rows":
+ resources.setRows(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Row number is now " + resources.rows());
+ break;
+
+ case "num_cols":
+ resources.setColumns(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Column number is now " + resources.columns());
+ break;
+
+ case "levels_back":
+ resources.setLevelsBack(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Levels back is now " + resources.levelsBack());
+ break;
+
+ case "report_interval":
+ resources.setReportInterval(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Report interval is now " + resources.levelsBack());
+ break;
+
+ case "global_seed":
+ resources.setSeed(Integer.parseInt(splitString[0]));
+ resources.println("[Parser] Seed is now " + resources.seed());
+ break;
- case "levels_back":
- resources.setLevelsBack(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Levels back is now " + resources.levelsBack() + ".");
- break;
-
- case "report_interval":
- resources.setReportInterval(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Report interval is now " + resources.levelsBack() + ".");
- break;
-
- case "global_seed":
- resources.setSeed(Integer.parseInt(splitString[0]));
- resources.println("[Parser] Seed is now " + resources.seed() + ".");
- break;
-
- default:
- break;
+ default:
+ break;
+ }
}
}
in.close();
- resources.println("[Parser] Finished parsing parameters.");
+ resources.println("[Parser] Finished parsing parameters");
}
}
diff --git a/src/jcgp/backend/parsers/TestCaseParser.java b/src/jcgp/backend/parsers/TestCaseParser.java
index cef018e..bcfa8a9 100644
--- a/src/jcgp/backend/parsers/TestCaseParser.java
+++ b/src/jcgp/backend/parsers/TestCaseParser.java
@@ -8,14 +8,34 @@ import java.util.Scanner;
import jcgp.backend.modules.problem.TestCaseProblem;
import jcgp.backend.resources.ModifiableResources;
+/**
+ * Contains a static method for parsing values from a
+ * CGP problem data file. The actual file extension
+ * varies from problem to problem, and is therefore
+ * defined in the experiment's Problem instance.
+ *
+ *
+ * @author Eduardo Pedroni
+ *
+ */
public abstract class TestCaseParser {
+ /**
+ * Sets the number of inputs and outputs in the resources
+ * to match the given file, and parses each test case
+ * from the file into the specified problem.
+ *
+ * @param file the problem file to parse.
+ * @param problem the problem into which to parse the problem data.
+ * @param resources a modifiable reference to the experiment's resources
+ */
public static void parse(File file, TestCaseProblem<?> problem, ModifiableResources resources) {
+ // create reader and scanner, print error message if file is missing
FileReader fr;
try {
fr = new FileReader(file);
} catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
+ resources.println("[Parser] Error: could not find " + file.getAbsolutePath());
return;
}
resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "...");
@@ -24,28 +44,44 @@ public abstract class TestCaseParser {
int inputs = 0, outputs = 0;
int cases = 0;
+ // this overwrites any previously added test cases
problem.clearTestCases();
while (in.hasNextLine()) {
String nextLine = in.nextLine();
-
+ // set resources input count to parsed value
if (nextLine.startsWith(".i")) {
String[] split = nextLine.split(" +");
inputs = Integer.parseInt(split[1]);
- } else if (nextLine.startsWith(".o")) {
+ resources.setInputs(inputs);
+ resources.println("[Parser] Number of inputs set to " + resources.inputs());
+ }
+ // set resources output count to parsed value
+ else if (nextLine.startsWith(".o")) {
String[] split = nextLine.split(" +");
outputs = Integer.parseInt(split[1]);
+ resources.setOutputs(outputs);
+ resources.println("[Parser] Number of outputs set to " + resources.outputs());
+
} else if (nextLine.startsWith(".p") || nextLine.startsWith(".t")) {
readingTestCases = true;
+
} else if (nextLine.startsWith(".e")) {
readingTestCases = false;
+
+ /*
+ * Split every line at one or more spaces or tabs, and
+ * parse the two sides into inputs and outputs.
+ */
} else if (readingTestCases) {
String[] split = nextLine.split("( |\t)+");
String[] inputCases = new String[inputs];
String[] outputCases = new String[outputs];
+
for (int i = 0; i < inputs; i++) {
inputCases[i] = split[i];
}
+
for (int o = 0; o < outputs; o++) {
outputCases[o] = split[o + inputs];
}
@@ -54,37 +90,7 @@ public abstract class TestCaseParser {
cases++;
}
}
- resources.println("[Parser] Finished, added " + cases + " test cases.");
- in.close();
- }
-
- public static void parseParameters(File file, ModifiableResources resources) {
-
- FileReader fr;
- try {
- fr = new FileReader(file);
- } catch (FileNotFoundException e) {
- resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + ".");
- return;
- }
-
- resources.println("[Parser] Parsing parameters...");
- Scanner in = new Scanner(fr);
-
- while (in.hasNextLine()) {
- String nextLine = in.nextLine();
- if (nextLine.startsWith(".i")) {
- String[] split = nextLine.split(" +");
- resources.setInputs(Integer.parseInt(split[1]));
- resources.println("[Parser] Number of inputs set to " + resources.inputs());
- } else if (nextLine.startsWith(".o")) {
- String[] split = nextLine.split(" +");
- resources.setOutputs(Integer.parseInt(split[1]));
- resources.println("[Parser] Number of outputs set to " + resources.outputs());
- }
- }
+ resources.println("[Parser] Finished, added " + cases + " test cases");
in.close();
-
- resources.println("[Parser] Finished parsing parameters.");
}
}