From 4c8de2402f2878cde7587c7f3bbf4ffaea86efd4 Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Sat, 26 Apr 2014 19:56:24 +0100 Subject: Moved files around to different folders, and commented some more packages. Aiming to have the entire backend fully commented by the end of today --- src/jcgp/backend/parsers/ChromosomeParser.java | 14 +-- src/jcgp/backend/parsers/FunctionParser.java | 75 +++++++++++++--- src/jcgp/backend/parsers/ParameterParser.java | 117 +++++++++++++++---------- src/jcgp/backend/parsers/TestCaseParser.java | 74 +++++++++------- 4 files changed, 178 insertions(+), 102 deletions(-) (limited to 'src/jcgp/backend/parsers') 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. + *

+ * 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. + *

+ * 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."); } } -- cgit v1.2.3