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 --- README | 214 --------------------- res/README | 214 +++++++++++++++++++++ res/cgp0.chr | 1 + res/epar3.plu | 5 + res/mult2.plu | 5 + res/parameters.par | 32 +++ res/quintic-polynomial.dat | 26 +++ res/test | 1 + res/test.chr | 1 + res/test~ | 1 + src/cgp0.chr | 1 - src/epar3.plu | 5 - src/jcgp/JCGP.java | 6 +- .../InsufficientConnectionsException.java | 10 - .../exceptions/InvalidArgumentsException.java | 20 -- .../exceptions/ParameterMismatchException.java | 10 - src/jcgp/backend/modules/es/MuPlusLambda.java | 10 +- .../modules/mutator/ProbabilisticMutator.java | 8 +- src/jcgp/backend/modules/problem/Problem.java | 21 +- .../backend/modules/problem/TestCaseProblem.java | 3 +- .../modules/problem/TravellingSalesmanProblem.java | 2 +- 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 +++---- src/jcgp/backend/population/Chromosome.java | 5 +- src/jcgp/backend/population/Node.java | 19 +- src/jcgp/backend/tests/ChromosomeTests.java | 10 +- src/jcgp/backend/tests/NodeTests.java | 13 +- src/jcgp/backend/tests/TestFunctionSet.java | 54 ++++++ src/mult2.plu | 5 - src/parameters.par | 32 --- src/quintic-polynomial.dat | 26 --- test | 1 - test.chr | 1 - test~ | 1 - 36 files changed, 573 insertions(+), 470 deletions(-) delete mode 100644 README create mode 100644 res/README create mode 100644 res/cgp0.chr create mode 100644 res/epar3.plu create mode 100644 res/mult2.plu create mode 100644 res/parameters.par create mode 100644 res/quintic-polynomial.dat create mode 100644 res/test create mode 100644 res/test.chr create mode 100644 res/test~ delete mode 100644 src/cgp0.chr delete mode 100644 src/epar3.plu delete mode 100644 src/jcgp/backend/exceptions/InsufficientConnectionsException.java delete mode 100644 src/jcgp/backend/exceptions/InvalidArgumentsException.java delete mode 100644 src/jcgp/backend/exceptions/ParameterMismatchException.java create mode 100644 src/jcgp/backend/tests/TestFunctionSet.java delete mode 100644 src/mult2.plu delete mode 100644 src/parameters.par delete mode 100644 src/quintic-polynomial.dat delete mode 100644 test delete mode 100644 test.chr delete mode 100644 test~ diff --git a/README b/README deleted file mode 100644 index b73e257..0000000 --- a/README +++ /dev/null @@ -1,214 +0,0 @@ -- Development Branch - - -29/1 - -Started formal development based on data_struct spike. - -The first goal is to produce the data structure that represents a chromosome. This structure will rely on a range -of other classes, which will be developed and tested as well. - -Chromosome tests: - - a data structure called Chromosome exists - - the chromosome instance can return the right outputs based on given inputs - -ChromosomeElement tests: - - Node is capable of processing its connections using its function and returning the result - - Input returns the value it is set to - - Outputs returns a single value from its source Node - - - -30/1 - -Added class representations of functions and mutators, as well as the program itself (CGP). -Modified the way the chromosome stores its data to allow for more flexible mutations. - -31/1 - -Parity will be considered constant, at 2, for now. - -Added static nested classes for system-wide resources such as a random number generator, the function set -and the parameter set. These can be accessed from anywhere within the program, but not modified by any class -but CGP. - -Utilities class has lots of handy methods for getting random elements with fair probability. - -Modularized design: - -Modules for fitness function, mutation operator, evolutionary algorithm and population. - -FF, EA and mutation modules act as callbacks; the user may specify how the module does its job, -but must comply with the interface. - -Population is slightly more complex: the user may define a custom chromosome and use it to generate a population, -so long as it extends Chromosome. In conjunction with modularized FF, EA and mutation, this makes for a very -flexible and versatile system. The Population class itself is immutable, since the system relies heavily on it. -Finally, it is Iterable to for access to the chromosomes within. - - -Arity may vary across functions, but all nodes contain enough connections to cope with the largest arity. - -FunctionSet presents a bit of a problem in case the user retains references to the Functions passed into it. - - -3/2 - -Solved the FunctionSet problem; since Function does not specify a way to modify the function once it is instantiated, -concurrent accesses should not be a problem. Should the user extend Function and implement a way to modify it at -runtime, the CGP program won't really use it; if the user modifies the CGP program to use it, then the user must -be ready to deal with the consequences. - -A fitness evaluation testbench of sorts will be implemented next. This testbench will take a set of "stimuli" (inputs), -use them to compute outputs with each chromosome, and compare those with the expected outputs, thus assigning fitness. - -This will be achieved for now using a TestCase object which contains a set of inputs and outputs. The evaluator simply -sets the chromosome inputs and compares outputs for all TestCase objects given, and computes a fitness function -accordingly. - - -4/2 - -TestCase has been implemented with a fair degree of defensiveness. A TruthTable class contains the test cases and provides -a way to evaluate fitness. - -TruthTable is a system-wide resource, which may or may not be used by FitnessFunction to assign fitness values to the -population; that is up to the user. - -A standard fitness function which uses TruthTable is defined in TruthTableEvaluator. - -StandardMutator has been implemented, though it looks like it may need refactoring in the future. - -StandardEA presents a problem: mutating the highest fitness chromosome to generate a new population requires the -chromosome to be copied, which is not straightforward in OOP. This could be addressed by creating a shallow copy -and instantiating new Nodes during the mutation process. This is actually an implementation of a lazy copy which -takes advantage of common Nodes to save memory. Additionally, this will require the mutation to actually occur within -the chromosome and simply be triggered from the Mutator. This reduces the number of Utilities functions, which is not -necessarily a problem. - -7/2 - -The resource classes have been refactored so that tests can be implemented more easily. Parameters, Utilities and TruthTable -are now top-level classes and work independently from CGP, allowing them to be initialised for testing purposes. Some -chromosome tests have been written and more tests will be written in the next few days. - -11/2 - -Methods to get random connections and mutable elements have been moved into Chromosome, as well as refactored to require -less random number generations. - -Chromosome and its associated members (Node, Output, Input) have been refactored to allow copying. A copy constructor has been -written which initialises a new chromosome as an exact copy of a given chromosome. - -Cloning has been tested and is working. - -Active node detection will be implemented via a getActiveNodes() method in Chromosome. The chromosome is notified whenever -one of its nodes or outputs is mutated, and re-computes the list of active elements when it is required. It does so by recursively -acquiring node connections and copying them to a separate list, unless they are already on the list. - -All chromosome tests have been implemented. - - -12/2 - -Node tests done. Added exception support for Function in case not enough argument connections are given. -Chromosome tests refactored to include the special case where columns = 1. -Input and output tests written. - -Population tests under way. - - -13/2 - -Writing the test for the population copy constructor will require the production of a method which compares two chromosomes. - -Therefore, two new methods will be written for Chromosome: compareTo and compareActiveTo. Compare returns true if the two chromosomes -are exclusively equivalent, and compareActive returns true if the active nodes within the two chromosomes are exclusively equivalent. - -Compare methods done, including their "dependency": copyOf method in MutableElement. This method is akin to equals(), with the exception that -it returns false when the compared objects are pointers to a common instance. - -Minor update: Node now passes only the necessary number of arguments into its function; this allows the node to compute its active -connections as it knows which connections the function will use (based on arity). - - -14/2 - -Support for generic data types implemented. - -Tests have been refactored to deal with the new data system. The system uses Object as its data type, allowing absolutely -any class to be used (and also primitive types). - - -15/2 - -The Population class will be refactored to contain two collections of chromosomes, one for parents and one for offpsring. This allows -for (1+λ) and (1,λ) EAs, for example. It no longer makes sense for Population to implement Iterable, so the tests will be changed to reflect -the specification change. Population can still return an addressed chromosome in general, which it does by returning parents followed by offspring. - -The chromosome copyConnections method has been made public to facilitate the EA implementation. - - -16/2 - -Methods were added to Chromosome and Connection to allow the chromosome to be printed to the console. This way its behaviour can be verified to make -sure the fitness evaluations are working correctly and any perfect solution found really is producing perfect outputs. - -A test case has been calculated by hand from the printed chromosome, and indeed the system appears to be working. - -However, if the implemented run() in Function subclasses is set to print the operation it has carried out, the first function execution of each output -prints twice -> because it needs to check what it is to cast it. Very inefficient... -Instead, we'll attempt to cast it without checking, and a ClassCastException will be raised if a problem happens, telling the user they did something wrong. -This can be caught by the GUI to display an error message, if necessary. - -Added a new parameter, debug. When set to true, the system prints a lot of information to the console for debugging purposes. - -Added some more functions. - -8/3 - -Adding GUI package, refactoring CGP class to interact appropriately with GUI. - -15/3 - -Currently refactoring Parameters. It is now a part of CGP.class as stated in the phase report. The rest of the program will now be refactored to accommodate -these changes. Inversion of control will be employed to avoid static accesses to CGP, and the tests will be modified accordingly. -This will allow multiple instances of CGP to co-exist. - -18/3 - -The current state of parameters is not yet perfect. One more refactoring will be carried out to speed up GUI updates. -Modules will be required to return a hashmap of parameters so the GUI can be re-built easily whenever modules change. -Modules should instantiate their parameters in their constructor and use direct referencing internally for extra speed. -The hashmap may be pre-built to save time when getParameters() is called, though this is not critical. - -19/3 - -Refactoring is complete, population tests have been refactored as well. It is worth noting that the new resources -framework leads to a lot of confusing casting. Utility methods will be written to hide away the casting in the CGP -class and simplify the programmer's life. -Registering parameters is no longer necessary. The CGP class will query modules for their parameters when necessary. - - -21/3 - -FunctionSet has been rewritten to allow only certain functions to be deactivated, the GUI will now be integrated. - - -25/3 - -http://andrewtill.blogspot.ch/2012/12/dragging-to-resize-javafx-region.html - -Looking into drag-to-resize for the console and the menu. All sorted. - -Settings and console can be resized but not beyond a minimum value, and the -grid node grows to fill the void. - - -26/3 - -Sorted out the console, resizing is mint, settings are nearing completion and the node grid has been refactored multiple times. - - -28/3 - -Refactoring parameters to overhaul the mechanism that allows modules to manage parameters. \ No newline at end of file diff --git a/res/README b/res/README new file mode 100644 index 0000000..b73e257 --- /dev/null +++ b/res/README @@ -0,0 +1,214 @@ +- Development Branch - + +29/1 + +Started formal development based on data_struct spike. + +The first goal is to produce the data structure that represents a chromosome. This structure will rely on a range +of other classes, which will be developed and tested as well. + +Chromosome tests: + - a data structure called Chromosome exists + - the chromosome instance can return the right outputs based on given inputs + +ChromosomeElement tests: + - Node is capable of processing its connections using its function and returning the result + - Input returns the value it is set to + - Outputs returns a single value from its source Node + + + +30/1 + +Added class representations of functions and mutators, as well as the program itself (CGP). +Modified the way the chromosome stores its data to allow for more flexible mutations. + +31/1 + +Parity will be considered constant, at 2, for now. + +Added static nested classes for system-wide resources such as a random number generator, the function set +and the parameter set. These can be accessed from anywhere within the program, but not modified by any class +but CGP. + +Utilities class has lots of handy methods for getting random elements with fair probability. + +Modularized design: + +Modules for fitness function, mutation operator, evolutionary algorithm and population. + +FF, EA and mutation modules act as callbacks; the user may specify how the module does its job, +but must comply with the interface. + +Population is slightly more complex: the user may define a custom chromosome and use it to generate a population, +so long as it extends Chromosome. In conjunction with modularized FF, EA and mutation, this makes for a very +flexible and versatile system. The Population class itself is immutable, since the system relies heavily on it. +Finally, it is Iterable to for access to the chromosomes within. + + +Arity may vary across functions, but all nodes contain enough connections to cope with the largest arity. + +FunctionSet presents a bit of a problem in case the user retains references to the Functions passed into it. + + +3/2 + +Solved the FunctionSet problem; since Function does not specify a way to modify the function once it is instantiated, +concurrent accesses should not be a problem. Should the user extend Function and implement a way to modify it at +runtime, the CGP program won't really use it; if the user modifies the CGP program to use it, then the user must +be ready to deal with the consequences. + +A fitness evaluation testbench of sorts will be implemented next. This testbench will take a set of "stimuli" (inputs), +use them to compute outputs with each chromosome, and compare those with the expected outputs, thus assigning fitness. + +This will be achieved for now using a TestCase object which contains a set of inputs and outputs. The evaluator simply +sets the chromosome inputs and compares outputs for all TestCase objects given, and computes a fitness function +accordingly. + + +4/2 + +TestCase has been implemented with a fair degree of defensiveness. A TruthTable class contains the test cases and provides +a way to evaluate fitness. + +TruthTable is a system-wide resource, which may or may not be used by FitnessFunction to assign fitness values to the +population; that is up to the user. + +A standard fitness function which uses TruthTable is defined in TruthTableEvaluator. + +StandardMutator has been implemented, though it looks like it may need refactoring in the future. + +StandardEA presents a problem: mutating the highest fitness chromosome to generate a new population requires the +chromosome to be copied, which is not straightforward in OOP. This could be addressed by creating a shallow copy +and instantiating new Nodes during the mutation process. This is actually an implementation of a lazy copy which +takes advantage of common Nodes to save memory. Additionally, this will require the mutation to actually occur within +the chromosome and simply be triggered from the Mutator. This reduces the number of Utilities functions, which is not +necessarily a problem. + +7/2 + +The resource classes have been refactored so that tests can be implemented more easily. Parameters, Utilities and TruthTable +are now top-level classes and work independently from CGP, allowing them to be initialised for testing purposes. Some +chromosome tests have been written and more tests will be written in the next few days. + +11/2 + +Methods to get random connections and mutable elements have been moved into Chromosome, as well as refactored to require +less random number generations. + +Chromosome and its associated members (Node, Output, Input) have been refactored to allow copying. A copy constructor has been +written which initialises a new chromosome as an exact copy of a given chromosome. + +Cloning has been tested and is working. + +Active node detection will be implemented via a getActiveNodes() method in Chromosome. The chromosome is notified whenever +one of its nodes or outputs is mutated, and re-computes the list of active elements when it is required. It does so by recursively +acquiring node connections and copying them to a separate list, unless they are already on the list. + +All chromosome tests have been implemented. + + +12/2 + +Node tests done. Added exception support for Function in case not enough argument connections are given. +Chromosome tests refactored to include the special case where columns = 1. +Input and output tests written. + +Population tests under way. + + +13/2 + +Writing the test for the population copy constructor will require the production of a method which compares two chromosomes. + +Therefore, two new methods will be written for Chromosome: compareTo and compareActiveTo. Compare returns true if the two chromosomes +are exclusively equivalent, and compareActive returns true if the active nodes within the two chromosomes are exclusively equivalent. + +Compare methods done, including their "dependency": copyOf method in MutableElement. This method is akin to equals(), with the exception that +it returns false when the compared objects are pointers to a common instance. + +Minor update: Node now passes only the necessary number of arguments into its function; this allows the node to compute its active +connections as it knows which connections the function will use (based on arity). + + +14/2 + +Support for generic data types implemented. + +Tests have been refactored to deal with the new data system. The system uses Object as its data type, allowing absolutely +any class to be used (and also primitive types). + + +15/2 + +The Population class will be refactored to contain two collections of chromosomes, one for parents and one for offpsring. This allows +for (1+λ) and (1,λ) EAs, for example. It no longer makes sense for Population to implement Iterable, so the tests will be changed to reflect +the specification change. Population can still return an addressed chromosome in general, which it does by returning parents followed by offspring. + +The chromosome copyConnections method has been made public to facilitate the EA implementation. + + +16/2 + +Methods were added to Chromosome and Connection to allow the chromosome to be printed to the console. This way its behaviour can be verified to make +sure the fitness evaluations are working correctly and any perfect solution found really is producing perfect outputs. + +A test case has been calculated by hand from the printed chromosome, and indeed the system appears to be working. + +However, if the implemented run() in Function subclasses is set to print the operation it has carried out, the first function execution of each output +prints twice -> because it needs to check what it is to cast it. Very inefficient... +Instead, we'll attempt to cast it without checking, and a ClassCastException will be raised if a problem happens, telling the user they did something wrong. +This can be caught by the GUI to display an error message, if necessary. + +Added a new parameter, debug. When set to true, the system prints a lot of information to the console for debugging purposes. + +Added some more functions. + +8/3 + +Adding GUI package, refactoring CGP class to interact appropriately with GUI. + +15/3 + +Currently refactoring Parameters. It is now a part of CGP.class as stated in the phase report. The rest of the program will now be refactored to accommodate +these changes. Inversion of control will be employed to avoid static accesses to CGP, and the tests will be modified accordingly. +This will allow multiple instances of CGP to co-exist. + +18/3 + +The current state of parameters is not yet perfect. One more refactoring will be carried out to speed up GUI updates. +Modules will be required to return a hashmap of parameters so the GUI can be re-built easily whenever modules change. +Modules should instantiate their parameters in their constructor and use direct referencing internally for extra speed. +The hashmap may be pre-built to save time when getParameters() is called, though this is not critical. + +19/3 + +Refactoring is complete, population tests have been refactored as well. It is worth noting that the new resources +framework leads to a lot of confusing casting. Utility methods will be written to hide away the casting in the CGP +class and simplify the programmer's life. +Registering parameters is no longer necessary. The CGP class will query modules for their parameters when necessary. + + +21/3 + +FunctionSet has been rewritten to allow only certain functions to be deactivated, the GUI will now be integrated. + + +25/3 + +http://andrewtill.blogspot.ch/2012/12/dragging-to-resize-javafx-region.html + +Looking into drag-to-resize for the console and the menu. All sorted. + +Settings and console can be resized but not beyond a minimum value, and the +grid node grows to fill the void. + + +26/3 + +Sorted out the console, resizing is mint, settings are nearing completion and the node grid has been refactored multiple times. + + +28/3 + +Refactoring parameters to overhaul the mechanism that allows modules to manage parameters. \ No newline at end of file diff --git a/res/cgp0.chr b/res/cgp0.chr new file mode 100644 index 0000000..3157c03 --- /dev/null +++ b/res/cgp0.chr @@ -0,0 +1 @@ + 1 2 7 1 2 6 2 2 7 3 2 7 2 0 7 3 0 7 0 1 7 7 1 10 6 0 7 10 11 7 2 11 7 0 11 6 13 0 7 13 12 10 14 1 7 16 \ No newline at end of file diff --git a/res/epar3.plu b/res/epar3.plu new file mode 100644 index 0000000..b554b66 --- /dev/null +++ b/res/epar3.plu @@ -0,0 +1,5 @@ +.i 3 +.o 1 +.p 1 +240 204 170 105 +.e \ No newline at end of file diff --git a/res/mult2.plu b/res/mult2.plu new file mode 100644 index 0000000..e629d28 --- /dev/null +++ b/res/mult2.plu @@ -0,0 +1,5 @@ +.i 4 +.o 4 +.p 1 +65280 61680 52428 43690 32768 19456 27328 41120 +.e \ No newline at end of file diff --git a/res/parameters.par b/res/parameters.par new file mode 100644 index 0000000..bf38c11 --- /dev/null +++ b/res/parameters.par @@ -0,0 +1,32 @@ +5 population_size +1.0 per_cent_mutate +10000 num_generations +10 num_runs_total +1 num_rows +100 num_cols +100 levels_back +1 progress_report +1000 report_interval +173156789 global_seed +0 run_from_chrom +0 shrink_phenotype +0 1 modulus-0 +0 1 sqrt-1 +0 1 reciprocal-2 +0 1 sin-3 +0 1 cos-4 +0 1 tan-5 +0 1 exp-6 +0 1 sinh-7 +0 1 cosh-8 +0 1 tanh-9 +0 1 nat-log-10 +0 1 logbase10-11 +0 2 sin(a+b)-12 +0 2 cos(a+b)-13 +0 2 hypoteneuse-14 +0 2 power-15 +1 2 addition-16 +1 2 subtraction-17 +1 2 multiplication-18 +1 2 division-19 \ No newline at end of file diff --git a/res/quintic-polynomial.dat b/res/quintic-polynomial.dat new file mode 100644 index 0000000..347b95a --- /dev/null +++ b/res/quintic-polynomial.dat @@ -0,0 +1,26 @@ +.i 1 +.o 1 +.t 21 +-1.0 0.0 +-0.9 -0.03249 +-0.8 -0.10368 +-0.7 -0.18207 +-0.6 -0.24576 +-0.5 -0.28125 +-0.4 -0.28224 +-0.3 -0.24843 +-0.2 -0.18432 +-0.1 -0.09801 +0.0 0.0 +0.1 0.09801 +0.2 0.18432 +0.3 0.24843 +0.4 0.28224 +0.5 0.28125 +0.6 0.24576 +0.7 0.18207 +0.8 0.10368 +0.9 0.03249 +1.0 0.0 +.e + diff --git a/res/test b/res/test new file mode 100644 index 0000000..2957b44 --- /dev/null +++ b/res/test @@ -0,0 +1 @@ + 2 2 13 0 1 12 0 1 14 1 2 10 2 0 9 1 6 13 0 1 14 10 10 14 12 0 17 14 1 10 9 9 17 12 12 6 15 2 13 18 18 16 0 2 15 12 12 18 16 2 12 1 0 10 1 1 18 1 28 18 15 15 9 20 20 6 0 2 10 1 30 19 35 35 4 0 1 2 \ No newline at end of file diff --git a/res/test.chr b/res/test.chr new file mode 100644 index 0000000..34664df --- /dev/null +++ b/res/test.chr @@ -0,0 +1 @@ + 0 0 7 0 0 6 0 0 15 0 0 6 0 0 18 2 0 6 2 0 8 1 3 14 5 0 13 2 4 11 4 2 14 4 2 0 3 6 2 2 5 1 3 1 6 6 5 3 5 5 9 3 3 13 4 2 19 3 4 18 5 5 11 7 6 5 4 7 12 0 5 4 3 5 7 3 \ No newline at end of file diff --git a/res/test~ b/res/test~ new file mode 100644 index 0000000..2957b44 --- /dev/null +++ b/res/test~ @@ -0,0 +1 @@ + 2 2 13 0 1 12 0 1 14 1 2 10 2 0 9 1 6 13 0 1 14 10 10 14 12 0 17 14 1 10 9 9 17 12 12 6 15 2 13 18 18 16 0 2 15 12 12 18 16 2 12 1 0 10 1 1 18 1 28 18 15 15 9 20 20 6 0 2 10 1 30 19 35 35 4 0 1 2 \ No newline at end of file diff --git a/src/cgp0.chr b/src/cgp0.chr deleted file mode 100644 index 3157c03..0000000 --- a/src/cgp0.chr +++ /dev/null @@ -1 +0,0 @@ - 1 2 7 1 2 6 2 2 7 3 2 7 2 0 7 3 0 7 0 1 7 7 1 10 6 0 7 10 11 7 2 11 7 0 11 6 13 0 7 13 12 10 14 1 7 16 \ No newline at end of file diff --git a/src/epar3.plu b/src/epar3.plu deleted file mode 100644 index b554b66..0000000 --- a/src/epar3.plu +++ /dev/null @@ -1,5 +0,0 @@ -.i 3 -.o 1 -.p 1 -240 204 170 105 -.e \ No newline at end of file diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index 1e6d628..f36ac7c 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -264,13 +264,13 @@ public class JCGP { } public void loadParameters(File file) { - ParameterParser.parseParameters(file, resources); - FunctionParser.parseFunctions(file, problem, resources); + ParameterParser.parse(file, resources); + FunctionParser.parse(file, problem.getFunctionSet(), resources); reset(); } public void loadProblemData(File file) { - problem.parse(file, resources); + problem.parseProblemData(file, resources); reset(); } diff --git a/src/jcgp/backend/exceptions/InsufficientConnectionsException.java b/src/jcgp/backend/exceptions/InsufficientConnectionsException.java deleted file mode 100644 index 15ac845..0000000 --- a/src/jcgp/backend/exceptions/InsufficientConnectionsException.java +++ /dev/null @@ -1,10 +0,0 @@ -package jcgp.backend.exceptions; - -public class InsufficientConnectionsException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 660740514800883541L; - -} diff --git a/src/jcgp/backend/exceptions/InvalidArgumentsException.java b/src/jcgp/backend/exceptions/InvalidArgumentsException.java deleted file mode 100644 index bbae976..0000000 --- a/src/jcgp/backend/exceptions/InvalidArgumentsException.java +++ /dev/null @@ -1,20 +0,0 @@ -package jcgp.backend.exceptions; - -public class InvalidArgumentsException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 2675108124600817777L; - private String reason; - - public InvalidArgumentsException(String reason) { - super(); - this.reason = reason; - } - - public String getReason() { - return reason; - } - -} diff --git a/src/jcgp/backend/exceptions/ParameterMismatchException.java b/src/jcgp/backend/exceptions/ParameterMismatchException.java deleted file mode 100644 index 83e2ba2..0000000 --- a/src/jcgp/backend/exceptions/ParameterMismatchException.java +++ /dev/null @@ -1,10 +0,0 @@ -package jcgp.backend.exceptions; - -public class ParameterMismatchException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = -3161318886125868134L; - -} diff --git a/src/jcgp/backend/modules/es/MuPlusLambda.java b/src/jcgp/backend/modules/es/MuPlusLambda.java index 50bf265..754e89b 100644 --- a/src/jcgp/backend/modules/es/MuPlusLambda.java +++ b/src/jcgp/backend/modules/es/MuPlusLambda.java @@ -75,6 +75,11 @@ public class MuPlusLambda implements EvolutionaryStrategy { }; } + @Override + public Parameter[] getLocalParameters() { + return new Parameter[] {mu, lambda, report}; + } + @Override public void evolve(Population population, Mutator mutator, Resources resources) { /* Population is sorted in ascending order of fitness, so leave the last @@ -94,11 +99,6 @@ public class MuPlusLambda implements EvolutionaryStrategy { if (report.get()) resources.reportln("[ES] Generation is complete"); } - @Override - public Parameter[] getLocalParameters() { - return new Parameter[] {mu, lambda, report}; - } - @Override public String toString() { return "(μ + λ)"; diff --git a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java index e3c1d03..cacb451 100644 --- a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java +++ b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java @@ -70,7 +70,7 @@ public class ProbabilisticMutator implements Mutator { for (int c = 0; c < resources.columns(); c++) { // go through all connections for (int a = 0; a < resources.arity(); a++) { - if (mutate()) { + if (mutateGene()) { Node n = chromosome.getNode(r, c); if (report.get()) resources.report("[Mutator] Mutating " + n + @@ -83,7 +83,7 @@ public class ProbabilisticMutator implements Mutator { } } // deal with node function next - if (mutate()) { + if (mutateGene()) { Node n = chromosome.getNode(r, c); if (report.get()) resources.report("[Mutator] Mutating " + n + ", changed function from " + n.getFunction()); @@ -96,7 +96,7 @@ public class ProbabilisticMutator implements Mutator { } // finally, mutate outputs for (int o = 0; o < resources.outputs(); o++) { - if (mutate()) { + if (mutateGene()) { Output out = chromosome.getOutput(o); if (report.get()) resources.report("[Mutator] Mutating " + out + @@ -120,7 +120,7 @@ public class ProbabilisticMutator implements Mutator { * * @return true if a mutation should be performed, false if otherwise. */ - private boolean mutate() { + private boolean mutateGene() { return resources.getRandomDouble(100) < mutationProbability.get(); } diff --git a/src/jcgp/backend/modules/problem/Problem.java b/src/jcgp/backend/modules/problem/Problem.java index 07183ea..368d512 100644 --- a/src/jcgp/backend/modules/problem/Problem.java +++ b/src/jcgp/backend/modules/problem/Problem.java @@ -9,6 +9,25 @@ import jcgp.backend.population.Population; import jcgp.backend.resources.ModifiableResources; import jcgp.backend.resources.Resources; +/** + * Defines the general behaviour of a CGP problem. The primary function of Problem + * is to evaluate a population and assign + *

+ * Parameters may be specified to control the implemented problem. Any parameters + * returned by {@code getLocalParameters()} should be displayed by the user interface, + * if it is being used. See {@link Parameter} for more information. + *

+ * It is advisable to use {@code Resources.reportln()} and {@code Resources.report()} + * to print any relevant information. Note that reportln() and report() are affected + * by the report interval base parameter. Use {@code Resources.println()} and + * {@code Resources.print()} to print information regardless of the current generation. + * See {@link Resources} for more information. + * + * @see Module + * + * @author Eduardo Pedroni + * + */ public abstract class Problem implements Module { protected FunctionSet functionSet; @@ -23,7 +42,7 @@ public abstract class Problem implements Module { public abstract boolean isPerfectSolution(Chromosome fittest); - public abstract void parse(File file, ModifiableResources resources); + public abstract void parseProblemData(File file, ModifiableResources resources); public void setFileExtension(String fileExtension) { this.fileExtension = fileExtension; diff --git a/src/jcgp/backend/modules/problem/TestCaseProblem.java b/src/jcgp/backend/modules/problem/TestCaseProblem.java index 6c4a7dc..7ce0327 100644 --- a/src/jcgp/backend/modules/problem/TestCaseProblem.java +++ b/src/jcgp/backend/modules/problem/TestCaseProblem.java @@ -119,8 +119,7 @@ public abstract class TestCaseProblem extends Problem { testCases.clear(); } - public void parse(File file, ModifiableResources resources) { - TestCaseParser.parseParameters(file, resources); + public void parseProblemData(File file, ModifiableResources resources) { TestCaseParser.parse(file, this, resources); } } diff --git a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java b/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java index 6491ec6..8363ef8 100644 --- a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java +++ b/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java @@ -36,7 +36,7 @@ public class TravellingSalesmanProblem extends Problem { } @Override - public void parse(File file, ModifiableResources resources) { + public void parseProblemData(File file, ModifiableResources resources) { // TODO Auto-generated method stub } 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."); } } diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java index 9e53f85..d23f43c 100644 --- a/src/jcgp/backend/population/Chromosome.java +++ b/src/jcgp/backend/population/Chromosome.java @@ -2,7 +2,6 @@ package jcgp.backend.population; import java.util.ArrayList; -import jcgp.backend.exceptions.ParameterMismatchException; import jcgp.backend.resources.Resources; public class Chromosome implements Comparable { @@ -168,7 +167,7 @@ public class Chromosome implements Comparable { * @param values * @throws ParameterMismatchException */ - public void setInputs(Object ... values) throws ParameterMismatchException { + public void setInputs(Object ... values) { // 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 @@ -176,7 +175,7 @@ public class Chromosome implements Comparable { inputs[i].setValue(values[i]); } } else { - throw new ParameterMismatchException(); + throw new IllegalArgumentException("Received " + values.length + " inputs but needed exactly " + inputs.length); } } diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java index 1ac5b10..74f6b54 100644 --- a/src/jcgp/backend/population/Node.java +++ b/src/jcgp/backend/population/Node.java @@ -1,9 +1,7 @@ package jcgp.backend.population; import java.util.ArrayList; -import java.util.Arrays; -import jcgp.backend.exceptions.InsufficientConnectionsException; import jcgp.backend.function.Function; @@ -22,7 +20,11 @@ public class Node extends Gene implements MutableElement, Connection { @Override public Object getValue() { - return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); + Object[] args = new Object[function.getArity()]; + for (int i = 0; i < function.getArity(); i++) { + args[i] = connections[i].getValue(); + } + return function.run(args); } public void setFunction(Function newFunction) { @@ -31,23 +33,18 @@ public class Node extends Gene implements MutableElement, Connection { @Override public void setConnection(int index, Connection newConnection) { - if (newConnection instanceof Node) { - if (((Node) newConnection).getColumn() < column) { - connections[index] = newConnection; - chromosome.recomputeActiveNodes(); - } - } else if (newConnection instanceof Input) { + if (newConnection != null) { connections[index] = newConnection; chromosome.recomputeActiveNodes(); } } - public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException { + public void initialise(Function newFunction, Connection ... newConnections) { function = newFunction; if (newConnections.length == chromosome.getResources().arity()) { connections = newConnections; } else { - throw new InsufficientConnectionsException(); + throw new IllegalArgumentException("Received " + newConnections.length + " connections but needed exactly " + chromosome.getResources().arity()); } } diff --git a/src/jcgp/backend/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java index bc0c57d..c326805 100644 --- a/src/jcgp/backend/tests/ChromosomeTests.java +++ b/src/jcgp/backend/tests/ChromosomeTests.java @@ -2,7 +2,6 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import jcgp.backend.function.SymbolicRegressionFunctions; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; import jcgp.backend.population.Input; @@ -46,7 +45,7 @@ public class ChromosomeTests { @BeforeClass public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new SymbolicRegressionFunctions()); + resources.setFunctionSet(new TestFunctionSet()); } @Before @@ -225,9 +224,12 @@ public class ChromosomeTests { chromosome.setInputs(5, 8, 4); + Integer output0 = (Integer) chromosome.getOutput(0).calculate(); + Integer output1 = (Integer) chromosome.getOutput(1).calculate(); + // with this configuration, the outputs should be 13 and 25. - assertTrue("Incorrect output returned.", (Integer) chromosome.getOutput(0).calculate() == 13); - assertTrue("Incorrect output returned.", (Integer) chromosome.getOutput(1).calculate() == 25); + assertTrue("Incorrect output returned: " + output0, output0 == 13.0); + assertTrue("Incorrect output returned: " + output1, output1 == 25.0); } /** diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java index c63b41e..ee940a0 100644 --- a/src/jcgp/backend/tests/NodeTests.java +++ b/src/jcgp/backend/tests/NodeTests.java @@ -1,8 +1,6 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; -import jcgp.backend.exceptions.InvalidArgumentsException; -import jcgp.backend.function.SymbolicRegressionFunctions; import jcgp.backend.function.Function; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; @@ -41,15 +39,15 @@ public class NodeTests { public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new SymbolicRegressionFunctions()); + resources.setFunctionSet(new TestFunctionSet()); chromosome = new Chromosome(resources); } @Before public void setUp() throws Exception { node = new Node(chromosome, 0, 0, resources.arity()); - // make node with anonymous addition function and hard-coded value connections - node.initialise(new SymbolicRegressionFunctions.Addition(), + // make node with addition function and hard-coded value connections + node.initialise(resources.getFunction(0), new Connection[]{new Connection() { @Override @@ -107,7 +105,7 @@ public class NodeTests { ((int) node.getValue()) == arg1 + arg2); // put in a different function, check the output has changed appropriately - node.setFunction(new SymbolicRegressionFunctions.Subtraction()); + node.setFunction(resources.getFunction(1)); assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2); @@ -136,8 +134,7 @@ public class NodeTests { Function function = new Function() { @Override - public Object run(Object... connections) - throws InvalidArgumentsException { + public Object run(Object... connections) { // blank return null; } diff --git a/src/jcgp/backend/tests/TestFunctionSet.java b/src/jcgp/backend/tests/TestFunctionSet.java new file mode 100644 index 0000000..1910d2a --- /dev/null +++ b/src/jcgp/backend/tests/TestFunctionSet.java @@ -0,0 +1,54 @@ +package jcgp.backend.tests; + +import jcgp.backend.function.Function; +import jcgp.backend.function.FunctionSet; + +public class TestFunctionSet extends FunctionSet { + + public TestFunctionSet() { + + functionList = new Function[] { + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] + (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] - (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] * (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] / (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + } + }; + enableAll(); + } +} \ No newline at end of file diff --git a/src/mult2.plu b/src/mult2.plu deleted file mode 100644 index e629d28..0000000 --- a/src/mult2.plu +++ /dev/null @@ -1,5 +0,0 @@ -.i 4 -.o 4 -.p 1 -65280 61680 52428 43690 32768 19456 27328 41120 -.e \ No newline at end of file diff --git a/src/parameters.par b/src/parameters.par deleted file mode 100644 index bf38c11..0000000 --- a/src/parameters.par +++ /dev/null @@ -1,32 +0,0 @@ -5 population_size -1.0 per_cent_mutate -10000 num_generations -10 num_runs_total -1 num_rows -100 num_cols -100 levels_back -1 progress_report -1000 report_interval -173156789 global_seed -0 run_from_chrom -0 shrink_phenotype -0 1 modulus-0 -0 1 sqrt-1 -0 1 reciprocal-2 -0 1 sin-3 -0 1 cos-4 -0 1 tan-5 -0 1 exp-6 -0 1 sinh-7 -0 1 cosh-8 -0 1 tanh-9 -0 1 nat-log-10 -0 1 logbase10-11 -0 2 sin(a+b)-12 -0 2 cos(a+b)-13 -0 2 hypoteneuse-14 -0 2 power-15 -1 2 addition-16 -1 2 subtraction-17 -1 2 multiplication-18 -1 2 division-19 \ No newline at end of file diff --git a/src/quintic-polynomial.dat b/src/quintic-polynomial.dat deleted file mode 100644 index 347b95a..0000000 --- a/src/quintic-polynomial.dat +++ /dev/null @@ -1,26 +0,0 @@ -.i 1 -.o 1 -.t 21 --1.0 0.0 --0.9 -0.03249 --0.8 -0.10368 --0.7 -0.18207 --0.6 -0.24576 --0.5 -0.28125 --0.4 -0.28224 --0.3 -0.24843 --0.2 -0.18432 --0.1 -0.09801 -0.0 0.0 -0.1 0.09801 -0.2 0.18432 -0.3 0.24843 -0.4 0.28224 -0.5 0.28125 -0.6 0.24576 -0.7 0.18207 -0.8 0.10368 -0.9 0.03249 -1.0 0.0 -.e - diff --git a/test b/test deleted file mode 100644 index 2957b44..0000000 --- a/test +++ /dev/null @@ -1 +0,0 @@ - 2 2 13 0 1 12 0 1 14 1 2 10 2 0 9 1 6 13 0 1 14 10 10 14 12 0 17 14 1 10 9 9 17 12 12 6 15 2 13 18 18 16 0 2 15 12 12 18 16 2 12 1 0 10 1 1 18 1 28 18 15 15 9 20 20 6 0 2 10 1 30 19 35 35 4 0 1 2 \ No newline at end of file diff --git a/test.chr b/test.chr deleted file mode 100644 index 34664df..0000000 --- a/test.chr +++ /dev/null @@ -1 +0,0 @@ - 0 0 7 0 0 6 0 0 15 0 0 6 0 0 18 2 0 6 2 0 8 1 3 14 5 0 13 2 4 11 4 2 14 4 2 0 3 6 2 2 5 1 3 1 6 6 5 3 5 5 9 3 3 13 4 2 19 3 4 18 5 5 11 7 6 5 4 7 12 0 5 4 3 5 7 3 \ No newline at end of file diff --git a/test~ b/test~ deleted file mode 100644 index 2957b44..0000000 --- a/test~ +++ /dev/null @@ -1 +0,0 @@ - 2 2 13 0 1 12 0 1 14 1 2 10 2 0 9 1 6 13 0 1 14 10 10 14 12 0 17 14 1 10 9 9 17 12 12 6 15 2 13 18 18 16 0 2 15 12 12 18 16 2 12 1 0 10 1 1 18 1 28 18 15 15 9 20 20 6 0 2 10 1 30 19 35 35 4 0 1 2 \ No newline at end of file -- cgit v1.2.3