From 8189116ea4b5db4675e31dfd04a5687d55e29262 Mon Sep 17 00:00:00 2001
From: Eduardo Pedroni <ep625@york.ac.uk>
Date: Tue, 6 May 2014 14:29:37 +0100
Subject: Added javadocs, made minor changes to the comments

---
 src/jcgp/backend/modules/Module.java               | 22 +++++++++
 .../backend/modules/es/EvolutionaryStrategy.java   | 13 ++++-
 src/jcgp/backend/modules/es/MuPlusLambda.java      | 43 ++++++++--------
 .../backend/modules/es/TournamentSelection.java    | 33 +++++++------
 .../backend/modules/mutator/FixedPointMutator.java |  2 +-
 src/jcgp/backend/modules/mutator/Mutator.java      | 12 ++++-
 .../modules/mutator/PercentPointMutator.java       |  4 +-
 src/jcgp/backend/modules/mutator/PointMutator.java | 31 +++++++-----
 .../modules/mutator/ProbabilisticMutator.java      | 37 +++++++-------
 .../modules/problem/DigitalCircuitProblem.java     | 52 ++++++++++----------
 src/jcgp/backend/modules/problem/Problem.java      | 57 ++++++++++++++--------
 .../modules/problem/SymbolicRegressionProblem.java | 46 +++++++++--------
 .../backend/modules/problem/TestCaseProblem.java   | 14 +++---
 .../modules/problem/TravellingSalesmanProblem.java | 56 ---------------------
 14 files changed, 217 insertions(+), 205 deletions(-)
 delete mode 100644 src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java

(limited to 'src/jcgp/backend/modules')

diff --git a/src/jcgp/backend/modules/Module.java b/src/jcgp/backend/modules/Module.java
index b53184e..a4d36c1 100644
--- a/src/jcgp/backend/modules/Module.java
+++ b/src/jcgp/backend/modules/Module.java
@@ -3,6 +3,7 @@ package jcgp.backend.modules;
 import java.util.ArrayList;
 
 import jcgp.backend.parameters.Parameter;
+import jcgp.backend.resources.Resources;
 
 /**
  * This class defines the expected behaviour of a module. Generally, modules
@@ -15,6 +16,9 @@ import jcgp.backend.parameters.Parameter;
  * In addition, implementations of {@code Module} should specify a module name
  * in their constructor using {@code setName()}. If a name is not provided, 
  * the simple name of the class will be used.
+ * <br>
+ * All modules, by definition, contain a reference to the experiment's resources, which
+ * must be passed at construction. The resources should be accessed with {@code getResources()}.
  * 
  * @see Parameter
  * @author Eduardo Pedroni
@@ -24,6 +28,17 @@ public abstract class Module {
 	
 	private ArrayList<Parameter<?>> localParameters = new ArrayList<Parameter<?>>();
 	private String name = getClass().getSimpleName();
+	private Resources resources;
+	
+	/**
+	 * Makes a new instance of this class. This should never
+	 * be called directly, and should instead be used by subclasses.
+	 * 
+	 * @param resources a reference to the experiment's resources.
+	 */
+	protected Module(Resources resources) {
+		this.resources = resources;
+	}
 		
 	/**
 	 * This method is used by the GUI in order to build visual
@@ -66,6 +81,13 @@ public abstract class Module {
 		this.name = name;
 	}
 	
+	/**
+	 * @return the experiment's resources.
+	 */
+	protected Resources getResources() {
+		return resources;
+	}
+	
 	@Override
 	public String toString() {
 		return name;
diff --git a/src/jcgp/backend/modules/es/EvolutionaryStrategy.java b/src/jcgp/backend/modules/es/EvolutionaryStrategy.java
index 1a14552..30a3c4a 100644
--- a/src/jcgp/backend/modules/es/EvolutionaryStrategy.java
+++ b/src/jcgp/backend/modules/es/EvolutionaryStrategy.java
@@ -32,13 +32,22 @@ import jcgp.backend.resources.Resources;
  */
 public abstract class EvolutionaryStrategy extends Module {
 	
+	/**
+	 * For internal use only, initialises the resources field.
+	 * 
+	 * @param resources the experiment's resources.
+	 */
+	protected EvolutionaryStrategy(Resources resources) {
+		super(resources);
+	}
+	
 	/**
 	 * Performs the selection algorithm and uses the mutator to create
 	 * the next generation of solutions.
 	 * 
 	 * @param population the population to evolve.
 	 * @param mutator the mutator with which to mutate the promoted individuals.
-	 * @param resources parameters and utilities for optional reference.
 	 */
-	public abstract void evolve(Population population, Mutator mutator, Resources resources);
+	public abstract void evolve(Population population, Mutator mutator);
+
 }
diff --git a/src/jcgp/backend/modules/es/MuPlusLambda.java b/src/jcgp/backend/modules/es/MuPlusLambda.java
index 8186b11..3743ee6 100644
--- a/src/jcgp/backend/modules/es/MuPlusLambda.java
+++ b/src/jcgp/backend/modules/es/MuPlusLambda.java
@@ -28,21 +28,21 @@ import jcgp.backend.resources.Resources;
  *
  */
 public class MuPlusLambda extends EvolutionaryStrategy {
-	
+
 	private IntegerParameter mu, lambda;
 	private BooleanParameter report;
-		
+
 	/**
 	 * Creates a new instance of MuPlusLambda. 
 	 * 
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public MuPlusLambda(final Resources resources) {
-		super();
+		super(resources);
 		mu = new IntegerParameter(1, "Parents (μ)") {
 			@Override
 			public void validate(Number newValue) {
-				if (newValue.intValue() + lambda.get() != resources.populationSize()) {
+				if (newValue.intValue() + lambda.get() != getResources().populationSize()) {
 					status = ParameterStatus.INVALID;
 					status.setDetails("Parents + offspring must equal population size.");
 				} else if (newValue.intValue() <= 0) {
@@ -53,11 +53,11 @@ public class MuPlusLambda extends EvolutionaryStrategy {
 				}
 			}
 		};
-		
+
 		lambda = new IntegerParameter(4, "Offspring (λ)") {
 			@Override
 			public void validate(Number newValue) {
-				if (newValue.intValue() + mu.get() != resources.populationSize()) {
+				if (newValue.intValue() + mu.get() != getResources().populationSize()) {
 					status = ParameterStatus.INVALID;
 					status.setDetails("Parents + offspring must equal population size.");
 				} else if (newValue.intValue() <= 0) {
@@ -68,29 +68,30 @@ public class MuPlusLambda extends EvolutionaryStrategy {
 				}
 			}
 		};
-		
+
 		report = new BooleanParameter(false, "Report");
-		
+
 		setName("(μ + λ)");
 		registerParameters(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
-		 * mu chromosomes intact
-		 */
-		for (int i = 0; i < resources.populationSize() - mu.get(); i++) {
+	public void evolve(Population population, Mutator mutator) {	
+		// sort the population in order of best fitness
+		population.sort();
+		
+		// population is now sorted in ascending order of fitness, the last chromosomes are the fittest
+		for (int i = 0; i < getResources().populationSize() - mu.get(); i++) {
 			// select a random parent out of the lambda offspring individuals
-			int randomParent = resources.populationSize() - 1 - resources.getRandomInt(mu.get());
-			if (report.get()) resources.reportln("[ES] Copying Chr " + randomParent + " to population position " + i);
+			int randomParent = getResources().populationSize() - 1 - getResources().getRandomInt(mu.get());
+			if (report.get()) getResources().reportln("[ES] Copying Chr " + randomParent + " to population position " + i);
 			population.copyChromosome(randomParent, i);
-			
+
 			// mutate selected chromosome
-			if (report.get()) resources.reportln("[ES] Mutating copied chromosome");
-			mutator.mutate(population.getChromosome(i), resources);
+			if (report.get()) getResources().reportln("[ES] Mutating copied chromosome");
+			mutator.mutate(population.get(i));
 		}
-		
-		if (report.get()) resources.reportln("[ES] Generation is complete");
+
+		if (report.get()) getResources().reportln("[ES] Generation is complete");
 	}
 }
diff --git a/src/jcgp/backend/modules/es/TournamentSelection.java b/src/jcgp/backend/modules/es/TournamentSelection.java
index 209caca..6d467f5 100644
--- a/src/jcgp/backend/modules/es/TournamentSelection.java
+++ b/src/jcgp/backend/modules/es/TournamentSelection.java
@@ -44,7 +44,7 @@ public class TournamentSelection extends EvolutionaryStrategy {
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public TournamentSelection(final Resources resources) {	
-		super();
+		super(resources);
 		tournamentSize = new IntegerParameter(1, "Tournament size") {
 			@Override
 			public void validate(Number newValue) {
@@ -73,17 +73,22 @@ public class TournamentSelection extends EvolutionaryStrategy {
 	}
 
 	@Override
-	public void evolve(Population population, Mutator mutator, Resources resources) {
+	public void evolve(Population population, Mutator mutator) {
 		/* Create an entirely new population by isolating random subsets of
 		 * the original population and choosing the fittest individual within
 		 * that subset. Each chosen individual is mutated and copied back into the
 		 * population.
 		 */
-		Chromosome[] newPopulation = new Chromosome[resources.populationSize()];
+		
+		// sort the population by fitness to make things easier
+		population.sort();
+		
+		// this array holds the new population temporarily, until it is copied over
+		Chromosome[] newPopulation = new Chromosome[getResources().populationSize()];
 		
 		// start by selecting all of the chromosomes that will be promoted
-		for (int i = 0; i < resources.populationSize(); i++) {
-			if (report.get()) resources.reportln("[ES] Starting tournament " + i);
+		for (int i = 0; i < getResources().populationSize(); i++) {
+			if (report.get()) getResources().reportln("[ES] Starting tournament " + i);
 			
 			/* the population is sorted in ascending order of fitness,
 			 * meaning the higher the index of the contender, the fitter
@@ -91,21 +96,21 @@ public class TournamentSelection extends EvolutionaryStrategy {
 			 */
 			int[] contenders = new int[tournamentSize.get()];
 			for (int t = 0; t < tournamentSize.get() - 1; t++) {
-				contenders[t] = resources.getRandomInt(resources.populationSize());
+				contenders[t] = getResources().getRandomInt(getResources().populationSize());
 			}
-			if (report.get()) resources.reportln("[ES] Selected contenders: " + Arrays.toString(contenders));
+			if (report.get()) getResources().reportln("[ES] Selected contenders: " + Arrays.toString(contenders));
 			Arrays.sort(contenders);
-			if (report.get()) resources.reportln("[ES] Chr " + contenders[contenders.length - 1] + " wins the tournament, copying and mutating...");
+			if (report.get()) getResources().reportln("[ES] Chr " + contenders[contenders.length - 1] + " wins the tournament, copying and mutating...");
 			// create a copy of the selected chromosome and mutate it
-			newPopulation[i] = new Chromosome(population.getChromosome(contenders[contenders.length - 1]));
-			mutator.mutate(newPopulation[i], resources);
+			newPopulation[i] = new Chromosome(population.get(contenders[contenders.length - 1]));
+			mutator.mutate(newPopulation[i]);
 		}
-		if (report.get()) resources.reportln("[ES] Tournaments are finished, copying new chromosomes into population");
+		if (report.get()) getResources().reportln("[ES] Tournaments are finished, copying new chromosomes into population");
 		// newPopulation has been generated, copy into the population
-		for (int c = 0; c < resources.populationSize(); c++) {
-			population.getChromosome(c).copyGenes(newPopulation[c]);
+		for (int c = 0; c < getResources().populationSize(); c++) {
+			population.get(c).copyGenes(newPopulation[c]);
 		}
 		
-		if (report.get()) resources.reportln("[ES] Generation is complete");
+		if (report.get()) getResources().reportln("[ES] Generation is complete");
 	}
 }
diff --git a/src/jcgp/backend/modules/mutator/FixedPointMutator.java b/src/jcgp/backend/modules/mutator/FixedPointMutator.java
index 5d40c57..1efdd2f 100644
--- a/src/jcgp/backend/modules/mutator/FixedPointMutator.java
+++ b/src/jcgp/backend/modules/mutator/FixedPointMutator.java
@@ -25,7 +25,7 @@ public class FixedPointMutator extends PointMutator {
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public FixedPointMutator(final Resources resources) {
-		super();
+		super(resources);
 		genesMutated = new IntegerParameter(5, "Genes mutated", false, false) {
 			@Override
 			public void validate(Number newValue) {
diff --git a/src/jcgp/backend/modules/mutator/Mutator.java b/src/jcgp/backend/modules/mutator/Mutator.java
index 02fd70a..56692ef 100644
--- a/src/jcgp/backend/modules/mutator/Mutator.java
+++ b/src/jcgp/backend/modules/mutator/Mutator.java
@@ -25,14 +25,22 @@ import jcgp.backend.resources.Resources;
  *
  */
 public abstract class Mutator extends Module {
+	
+	/**
+	 * For internal use only, initialises the resources field.
+	 * 
+	 * @param resources the experiment's resources.
+	 */
+	protected Mutator(Resources resources) {
+		super(resources);
+	}
 
 	/**
 	 * Applies mutations to the specified chromosome according
 	 * to the parameter values.
 	 * 
 	 * @param chromosome the chromosome to mutate.
-	 * @param resources parameters and utilities for optional reference.
 	 */
-	public abstract void mutate(Chromosome chromosome, Resources resources);
+	public abstract void mutate(Chromosome chromosome);
 	
 }
diff --git a/src/jcgp/backend/modules/mutator/PercentPointMutator.java b/src/jcgp/backend/modules/mutator/PercentPointMutator.java
index 31a7739..015edf4 100644
--- a/src/jcgp/backend/modules/mutator/PercentPointMutator.java
+++ b/src/jcgp/backend/modules/mutator/PercentPointMutator.java
@@ -24,12 +24,12 @@ public class PercentPointMutator extends PointMutator {
 	private DoubleParameter mutationRate;
 
 	/**
-	 * Creates a new instance of PointMutator. 
+	 * Creates a new instance of PercentPointMutator. 
 	 * 
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public PercentPointMutator(final Resources resources) {
-		super();
+		super(resources);
 		mutationRate = new DoubleParameter(10, "Percent mutation", false, false) {
 			@Override
 			public void validate(Number newValue) {
diff --git a/src/jcgp/backend/modules/mutator/PointMutator.java b/src/jcgp/backend/modules/mutator/PointMutator.java
index 0223a37..9e421c2 100644
--- a/src/jcgp/backend/modules/mutator/PointMutator.java
+++ b/src/jcgp/backend/modules/mutator/PointMutator.java
@@ -24,48 +24,57 @@ public abstract class PointMutator extends Mutator {
 
 	protected IntegerParameter genesMutated;
 	protected BooleanParameter report;
+	
+	/**
+	 * For internal use only, initialises the resources field.
+	 * 
+	 * @param resources the experiment's resources.
+	 */
+	protected PointMutator(Resources resources) {
+		super(resources);
+	}
 
 	@Override
-	public void mutate(Chromosome chromosome, Resources resources) {
-		if (report.get()) resources.reportln("[Mutator] Number of mutations to be performed: " + genesMutated.get());
+	public void mutate(Chromosome chromosome) {
+		if (report.get()) getResources().reportln("[Mutator] Number of mutations to be performed: " + genesMutated.get());
 		
 		// for however many genes must be mutated
 		for (int i = 0; i < genesMutated.get(); i++) {
 			
 			MutableElement m = chromosome.getRandomMutableElement();
 			
-			if (report.get()) resources.report("[Mutator] Mutation " + i + " selected " + m + ", ");
+			if (report.get()) getResources().report("[Mutator] Mutation " + i + " selected " + m + ", ");
 			
 			// outputs and nodes are mutated differently
 			if (m instanceof Output) {
-				if (report.get()) resources.report("changed source from " + ((Output) m).getSource() + " ");
+				if (report.get()) getResources().report("changed source from " + ((Output) m).getSource() + " ");
 				
 				// outputs are easy, simply set to a different random connection, any will do
 				m.setConnection(0, chromosome.getRandomConnection());
 				
-				if (report.get()) resources.reportln("to " + ((Output) m).getSource());
+				if (report.get()) getResources().reportln("to " + ((Output) m).getSource());
 			} else if (m instanceof Node) {
 				/* nodes are more complicated, first we must decide whether to mutate the function
 				 * or a connection
 				 * we do this by generating a random int between 0 and 1 + arity
 				 */
-				int geneType = resources.getRandomInt(1 + resources.arity());
+				int geneType = getResources().getRandomInt(1 + getResources().arity());
 				
 				// if the int is less than 1, mutate function, else mutate connections 
 				if (geneType < 1) {
-					if (report.get()) resources.report("changed function from " + ((Node) m).getFunction() + " ");
+					if (report.get()) getResources().report("changed function from " + ((Node) m).getFunction() + " ");
 					
-					((Node) m).setFunction(resources.getRandomFunction());
+					((Node) m).setFunction(getResources().getRandomFunction());
 					
-					if (report.get()) resources.reportln("to " + ((Node) m).getFunction());
+					if (report.get()) getResources().reportln("to " + ((Node) m).getFunction());
 				} else {
 					// if we decided to mutate connection, subtract 1 from geneType so it fits into the arity range
 					geneType -= 1;
-					if (report.get()) resources.report("changed connection " + geneType + " from " + ((Node) m).getConnection(geneType) + " ");
+					if (report.get()) getResources().report("changed connection " + geneType + " from " + ((Node) m).getConnection(geneType) + " ");
 					
 					m.setConnection(geneType, chromosome.getRandomConnection(((Node) m).getColumn()));
 					
-					if (report.get()) resources.reportln("to " + ((Node) m).getConnection(geneType));
+					if (report.get()) getResources().reportln("to " + ((Node) m).getConnection(geneType));
 				}
 			}
 		}
diff --git a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java
index c65fc22..9273558 100644
--- a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java
+++ b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java
@@ -25,17 +25,14 @@ public class ProbabilisticMutator extends Mutator {
 
 	private DoubleParameter mutationProbability;
 	private BooleanParameter report;
-	
-	private Resources resources;
-	
+		
 	/**
 	 * Creates a new instance of ProbabilisticMutator. 
 	 * 
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public ProbabilisticMutator(Resources resources) {
-		super();
-		this.resources = resources;
+		super(resources);
 		
 		mutationProbability = new DoubleParameter(10, "Mutation probability", false, false) {
 			@Override
@@ -56,53 +53,53 @@ public class ProbabilisticMutator extends Mutator {
 	}
 
 	@Override
-	public void mutate(Chromosome chromosome, Resources resources) {
-		if (report.get()) resources.reportln("[Mutator] Starting mutations");
+	public void mutate(Chromosome chromosome) {
+		if (report.get()) getResources().reportln("[Mutator] Starting mutations");
 		
 		// go through nodes - [rows][columns]
-		for (int r = 0; r < resources.rows(); r++) {
-			for (int c = 0; c < resources.columns(); c++) {
+		for (int r = 0; r < getResources().rows(); r++) {
+			for (int c = 0; c < getResources().columns(); c++) {
 				// go through all connections
-				for (int a = 0; a < resources.arity(); a++) {
+				for (int a = 0; a < getResources().arity(); a++) {
 					if (mutateGene()) {
 						Node n = chromosome.getNode(r, c);
 						
-						if (report.get()) resources.report("[Mutator] Mutating " + n +
+						if (report.get()) getResources().report("[Mutator] Mutating " + n +
 								", changed connection " + a + " from " + n.getConnection(a) + " ");
 						
 						n.setConnection(a, chromosome.getRandomConnection(c));
 						
-						if (report.get()) resources.reportln("to " + n.getConnection(a));
+						if (report.get()) getResources().reportln("to " + n.getConnection(a));
 						
 					}
 				}
 				// deal with node function next
 				if (mutateGene()) {
 					Node n = chromosome.getNode(r, c);
-					if (report.get()) resources.report("[Mutator] Mutating " + n +
+					if (report.get()) getResources().report("[Mutator] Mutating " + n +
 							", changed function from " + n.getFunction());
 					
-					n.setFunction(resources.getRandomFunction());
+					n.setFunction(getResources().getRandomFunction());
 					
-					if (report.get()) resources.reportln(" to " + n.getFunction());
+					if (report.get()) getResources().reportln(" to " + n.getFunction());
 				}
 			}
 		}
 		// finally, mutate outputs
-		for (int o = 0; o < resources.outputs(); o++) {
+		for (int o = 0; o < getResources().outputs(); o++) {
 			if (mutateGene()) {
 				Output out = chromosome.getOutput(o);
 				
-				if (report.get()) resources.report("[Mutator] Mutating " + out +
+				if (report.get()) getResources().report("[Mutator] Mutating " + out +
 						", changed source from " + out.getSource());
 				
 				out.setConnection(0, chromosome.getRandomConnection());
 				
-				if (report.get()) resources.reportln("to " + out.getSource());
+				if (report.get()) getResources().reportln("to " + out.getSource());
 			}
 		}
 		
-		if (report.get()) resources.reportln("[Mutator] Mutation finished ");
+		if (report.get()) getResources().reportln("[Mutator] Mutation finished ");
 
 	}
 	
@@ -115,6 +112,6 @@ public class ProbabilisticMutator extends Mutator {
 	 * @return true if a mutation should be performed, false if otherwise.
 	 */
 	private boolean mutateGene() {
-		return resources.getRandomDouble(100) < mutationProbability.get();
+		return getResources().getRandomDouble(100) < mutationProbability.get();
 	}
 }
diff --git a/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
index 6654928..0071ed5 100644
--- a/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
+++ b/src/jcgp/backend/modules/problem/DigitalCircuitProblem.java
@@ -2,7 +2,6 @@ package jcgp.backend.modules.problem;
 
 import jcgp.backend.function.DigitalCircuitFunctions;
 import jcgp.backend.function.UnsignedInteger;
-import jcgp.backend.population.Chromosome;
 import jcgp.backend.population.Population;
 import jcgp.backend.resources.Resources;
 
@@ -18,7 +17,7 @@ import jcgp.backend.resources.Resources;
  *
  */
 public class DigitalCircuitProblem extends TestCaseProblem<UnsignedInteger> {
-	
+
 	/**
 	 * Construct a new instance of DigitalCircuitProblem.
 	 * 
@@ -30,43 +29,38 @@ public class DigitalCircuitProblem extends TestCaseProblem<UnsignedInteger> {
 		setName("Digital circuit");
 		setFileExtension(".plu");
 	}
-	
+
 	@Override
 	public void evaluate(Population population, Resources resources) {
 		// for every chromosome in the population
 		for (int i = 0; i < resources.populationSize(); i++) {
 			// assume an initial fitness of 0
 			int fitness = 0;
-			
+
 			// iterate over every test case
 			for (int t = 0; t < testCases.size(); t++) {
-				population.getChromosome(i).setInputs((Object[]) testCases.get(t).getInputs());
+				population.get(i).setInputs((Object[]) testCases.get(t).getInputs());
 				// check each output
 				for (int o = 0; o < resources.outputs(); o++) {
-					Integer output = ((UnsignedInteger) population.getChromosome(i).getOutput(o).calculate()).get();
+					Integer output = ((UnsignedInteger) population.get(i).getOutput(o).calculate()).get();
 					Integer matches = ~(output ^ testCases.get(t).getOutput(o).get());
 					// check only the relevant bits
 					int bits = (int) Math.pow(2.0, (double) resources.inputs());
 					for (int b = 0; b < bits; b++) {
-						if (((matches >>> b) & 1) == 1) {
-							fitness++;
-						}
+						fitness += (matches >>> b) & 1;
 					}
 				}
 			}
-			
+
 			// assign the resulting fitness to the respective individual
-			population.getChromosome(i).setFitness(fitness);
+			population.get(i).setFitness(fitness);
 		}
-		
-		// sort population
-		population.sortAscending();
 	}
-	
+
 	@Override
 	protected double getMaxFitness() {
 		// calculate the fitness by looking at inputs, not number of test cases
-		double maxFitness = Math.pow(2.0, (double) resources.inputs()) * resources.outputs();
+		double maxFitness = Math.pow(2.0, (double) getResources().inputs()) * getResources().outputs();
 		return maxFitness;
 	}
 
@@ -81,24 +75,30 @@ public class DigitalCircuitProblem extends TestCaseProblem<UnsignedInteger> {
 		for (int o = 0; o < outputCases.length; o++) {
 			outputCases[o] = new UnsignedInteger(outputs[o]);
 		}
-		
+
 		return new TestCase<UnsignedInteger>(inputCases, outputCases);
 	}
-	
+
 	@Override
-	public boolean isPerfectSolution(Chromosome fittest) {
+	public int perfectSolutionFound(Population population) {
 		// higher fitness is better
-		return fittest.getFitness() >= maxFitness.get();
+		for (int i = 0; i < getResources().populationSize(); i++) {
+			if (population.get(i).getFitness() >= maxFitness.get()) {
+				return i;
+			}
+		}
+		return -1;
 	}
 
 	@Override
-	public boolean isImprovement(Chromosome fittest) {
+	public int hasImprovement(Population population) {
 		// higher fitness is better
-		if (fittest.getFitness() > bestFitness.get()) {
-			bestFitness.set(fittest.getFitness());
-			return true;
-		} else {
-			return false;
+		for (int i = 0; i < getResources().populationSize(); i++) {
+			if (population.get(i).getFitness() > bestFitness.get()) {
+				bestFitness.set(population.get(i).getFitness());
+				return i;
+			}
 		}
+		return -1;
 	}
 }
diff --git a/src/jcgp/backend/modules/problem/Problem.java b/src/jcgp/backend/modules/problem/Problem.java
index 721b9b3..5f194b5 100644
--- a/src/jcgp/backend/modules/problem/Problem.java
+++ b/src/jcgp/backend/modules/problem/Problem.java
@@ -6,23 +6,21 @@ import jcgp.backend.function.FunctionSet;
 import jcgp.backend.modules.Module;
 import jcgp.backend.parameters.DoubleParameter;
 import jcgp.backend.parameters.monitors.DoubleMonitor;
-import jcgp.backend.population.Chromosome;
 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 
+ * Defines the general behaviour of a CGP problem. The primary function of {@code Problem} 
  * is to evaluate a population and assign a fitness value to each chromosome. 
  * <br>
- * By convention, the population should be sorted into ascending order of fitness. The
- * reason for this is because high fitness is not necessarily better - some problem types
- * might treat 0 as the best fitness. In order for the evolutionary strategy to be able to
- * pick chromosomes by fitness, the safest way is to sort them such that the last chromosome
- * is the fittest.
+ * Problems are free to define whether better fitness means a higher or lower fitness value.
+ * In some problem types, it is more convenient to treat fitness 0 as the best possible value.
+ * This can be done by changing the fitness orientation to {@code BestFitness.HIGH} or {@code BestFitness.LOW} as appropriate.
+ * Fitness orientation is set to high by default.
  * <br><br>
- * When extending this class, the constructor should call a couple methods in order to
- * properly construct the problem type: {@code setFunctionSet()} and {@code setFileExtension()},
+ * When extending this class, the constructor should call a few methods in order to
+ * properly construct the problem type: {@code setFunctionSet()}, {@code setFileExtension()} and {@code setFitnessOrientation()},
  * with the respective arguments. As with all subclasses of {@code Module}, {@code setName()} and
  * {@code registerParameters()} should be used where appropriate as well.
  * <br><br>
@@ -41,12 +39,18 @@ public abstract class Problem extends Module {
 	private FunctionSet functionSet;
 	private String fileExtension = ".*";
 	
+	private BestFitness fitnessOrientation = BestFitness.HIGH;
+	
 	protected DoubleParameter maxFitness, bestFitness;
 	
 	/**
 	 * Initialises the two problem-wide parameters, maxFitness and bestFitness.
+	 *
+	 * @param resources a reference to the experiment's resources.
 	 */
-	public Problem() {
+	public Problem(Resources resources) {
+		super(resources);
+		
 		maxFitness = new DoubleMonitor(0, "Max fitness");
 		bestFitness = new DoubleMonitor(0, "Best fitness");
 		registerParameters(maxFitness, bestFitness);
@@ -73,29 +77,26 @@ public abstract class Problem extends Module {
 	public abstract void evaluate(Population population, Resources resources);
 	
 	/**
-	 * Used to assert whether a given chromosome is a perfect solution
+	 * Used to assert whether a given population contains a perfect solution
 	 * to the problem. It is up to the problem to define what qualifies
 	 * a perfect solution, as some problems (subject ones such as music and
 	 * art evolution, for example) might not have perfect solutions at all.
-	 * <br><br>
-	 * Note that if this method returns true, the experiment will move on
-	 * to the next run, or finish if no more runs are left.
 	 * 
-	 * @param candidate the potentially perfect chromosome.
-	 * @return true if the argument is a perfect solution.
+	 * @param population the population to search through for a perfect chromosome.
+	 * @return the perfect solution index, if one exits, -1 if no perfect solution was found.
 	 */
-	public abstract boolean isPerfectSolution(Chromosome candidate);
+	public abstract int perfectSolutionFound(Population population);
 	
 	/**
-	 * Used to assert whether a given chromosome is an improvement over 
+	 * Used to assert whether a given population has a chromosome that is an improvement over 
 	 * the current best chromosome. A typical implementation of this method
 	 * will simply compare chromosome fitness values, though the problem type
 	 * is free to implement this in any way.
 	 * 
-	 * @param candidate the potentially fitter chromosome.
-	 * @return true if the argument is fitter than the currently fittest chromosome.
+	 * @param population the population potentially containing a fitter chromosome.
+	 * @return the index of the first chromosome in the population that is an improvement, -1 if none is found.
 	 */
-	public abstract boolean isImprovement(Chromosome candidate);
+	public abstract int hasImprovement(Population population);
 	
 	/**
 	 * Parses the specified file and uses the parsed data to
@@ -148,6 +149,20 @@ public abstract class Problem extends Module {
 		return fileExtension;
 	}
 	
+	/**
+	 * @param newOrientation the new fitness orientation to set.
+	 */
+	protected void setFitnessOrientation(BestFitness newOrientation) {
+		this.fitnessOrientation = newOrientation;
+	}
+	
+	/**
+	 * @return the fitness orientation of this particular problem.
+	 */
+	public BestFitness getFitnessOrientation() {
+		return fitnessOrientation;
+	}
+	
 	/**
 	 * @return the current best fitness, in other words, the fitness
 	 * value of the fittest chromosome in the current generation.
diff --git a/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java b/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java
index 04e9fe8..24c61d6 100644
--- a/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java
+++ b/src/jcgp/backend/modules/problem/SymbolicRegressionProblem.java
@@ -4,7 +4,6 @@ import jcgp.backend.function.SymbolicRegressionFunctions;
 import jcgp.backend.parameters.BooleanParameter;
 import jcgp.backend.parameters.DoubleParameter;
 import jcgp.backend.parameters.ParameterStatus;
-import jcgp.backend.population.Chromosome;
 import jcgp.backend.population.Population;
 import jcgp.backend.resources.Resources;
 
@@ -20,12 +19,12 @@ import jcgp.backend.resources.Resources;
  * <li>Error threshold: the maximum difference allowed between an
  * evolved output and the equivalent output from the problem data.
  * Outputs within the error threshold will be considered correct.
- * This is only used if HITS is enabled.</li>
+ * This is only used if hits is enabled.</li>
  * <li>Perfection threshold: if the fitness is calculated without
- * using the HITS method, it is a decimal value. A solution is
+ * using the hits method, it is a decimal value. A solution is
  * considered perfect when the difference between its fitness and
  * the maximum possible fitness is within the perfection threshold.</li>
- * <li>HITS-based fitness: increment the fitness by 1 whenever the
+ * <li>Hits-based fitness: increment the fitness by 1 whenever the
  * chromosome output is within the error threshold.</li></ul>
  * 
  * 
@@ -79,7 +78,7 @@ public class SymbolicRegressionProblem extends TestCaseProblem<Double> {
 			}
 		};
 		
-		hitsBasedFitness = new BooleanParameter(true, "HITS-based fitness");
+		hitsBasedFitness = new BooleanParameter(false, "Hits-based fitness");
 		
 		registerParameters(errorThreshold, perfectionThreshold, hitsBasedFitness);
 	}
@@ -87,15 +86,15 @@ public class SymbolicRegressionProblem extends TestCaseProblem<Double> {
 	@Override
 	public void evaluate(Population population, Resources resources) {
 		// for every chromosome in the population
-		for (int i = 0; i < resources.populationSize(); i++) {
+		for (int i = 0; i < getResources().populationSize(); i++) {
 			// assume an initial fitness of 0
 			double fitness = 0;
 			// for each test case
 			for (int t = 0; t < testCases.size(); t++) {
-				population.getChromosome(i).setInputs((Object[]) testCases.get(t).getInputs());
+				population.get(i).setInputs((Object[]) testCases.get(t).getInputs());
 				// check each output
-				for (int o = 0; o < resources.outputs(); o++) {
-					Double cgpValue = (Double) population.getChromosome(i).getOutput(o).calculate();
+				for (int o = 0; o < getResources().outputs(); o++) {
+					Double cgpValue = (Double) population.get(i).getOutput(o).calculate();
 					Double dataValue = testCases.get(t).getOutput(o);
 					if (hitsBasedFitness.get()) {
 						if (Math.abs(cgpValue - dataValue) <= errorThreshold.get()) {
@@ -107,11 +106,8 @@ public class SymbolicRegressionProblem extends TestCaseProblem<Double> {
 				}
 			}
 			// assign the resulting fitness to the respective individual
-			population.getChromosome(i).setFitness(fitness);
+			population.get(i).setFitness(fitness);
 		}
-		
-		// sort population
-		population.sortAscending();
 	}
 	
 	@Override
@@ -130,19 +126,27 @@ public class SymbolicRegressionProblem extends TestCaseProblem<Double> {
 	}
 
 	@Override
-	public boolean isPerfectSolution(Chromosome fittest) {
+	public int perfectSolutionFound(Population population) {
 		// higher fitness is better
-		return fittest.getFitness() >= maxFitness.get() - perfectionThreshold.get();
+		for (int i = 0; i < getResources().populationSize(); i++) {
+			if (population.get(i).getFitness() >= maxFitness.get() - perfectionThreshold.get()) {
+				return i;
+			}
+		}
+		return -1;
 	}
 	
 	@Override
-	public boolean isImprovement(Chromosome fittest) {
+	public int hasImprovement(Population population) {
 		// higher fitness is better
-		if (fittest.getFitness() > bestFitness.get()) {
-			bestFitness.set(fittest.getFitness());
-			return true;
-		} else {
-			return false;
+		for (int i = 0; i < getResources().populationSize(); i++) {
+			System.out.println("checking for improvement");
+			if (population.get(i).getFitness() > bestFitness.get()) {
+				System.out.println("found a better chr, " + i);
+				bestFitness.set(population.get(i).getFitness());
+				return i;
+			}
 		}
+		return -1;
 	}
 }
diff --git a/src/jcgp/backend/modules/problem/TestCaseProblem.java b/src/jcgp/backend/modules/problem/TestCaseProblem.java
index c11fab4..69c078d 100644
--- a/src/jcgp/backend/modules/problem/TestCaseProblem.java
+++ b/src/jcgp/backend/modules/problem/TestCaseProblem.java
@@ -30,7 +30,7 @@ public abstract class TestCaseProblem<T> extends Problem {
 	 * contains arrays of inputs and outputs and associated getters.
 	 * 
 	 * @author Eduardo Pedroni
-	 * @param <U>
+	 * @param <U> the data type of the test case.
 	 */
 	public static class TestCase<U> {
 		private U[] inputs;
@@ -80,7 +80,6 @@ public abstract class TestCaseProblem<T> extends Problem {
 	}
 	
 	protected ObservableList<TestCase<T>> testCases;
-	protected Resources resources;
 	
 	/**
 	 * Creates a new TestCaseProblem object.
@@ -88,8 +87,7 @@ public abstract class TestCaseProblem<T> extends Problem {
 	 * @param resources a reference to the experiment's resources.
 	 */
 	public TestCaseProblem(Resources resources) {
-		super();
-		this.resources = resources;
+		super(resources);
 		testCases = FXCollections.observableArrayList();
 	}
 	
@@ -139,12 +137,12 @@ public abstract class TestCaseProblem<T> extends Problem {
 	public final void addTestCase(String[] inputs, String[] outputs) {
 		TestCase<T> testCase = parseTestCase(inputs, outputs);
 		
-		if (testCase.getInputs().length != resources.inputs()) {
+		if (testCase.getInputs().length != getResources().inputs()) {
 			throw new IllegalArgumentException("Received test case with " + testCase.getInputs().length + 
-					" inputs but need exactly " + resources.inputs());
-		} else if (testCase.getOutputs().length != resources.outputs()) {
+					" inputs but need exactly " + getResources().inputs());
+		} else if (testCase.getOutputs().length != getResources().outputs()) {
 			throw new IllegalArgumentException("Received test case with " + testCase.getOutputs().length + 
-					" outputs but need exactly " + resources.outputs());
+					" outputs but need exactly " + getResources().outputs());
 		} else {
 			this.testCases.add(testCase);
 			maxFitness.set(getMaxFitness());
diff --git a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java b/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java
deleted file mode 100644
index 94417ae..0000000
--- a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package jcgp.backend.modules.problem;
-
-import java.io.File;
-
-import jcgp.backend.function.TravellingSalesmanFunctions;
-import jcgp.backend.population.Chromosome;
-import jcgp.backend.population.Population;
-import jcgp.backend.resources.ModifiableResources;
-import jcgp.backend.resources.Resources;
-
-/**
- * Travelling salesman problem
- * <br><br>
- * Using this problem type, travelling salesman tours can be evolved.
- * {@code parseData()} must be used to load the desired city
- * coordinates in the standard .tsp format. 
- * 
- * @see TravellingSalesmanFunctions
- * @author Eduardo Pedroni
- *
- */
-public class TravellingSalesmanProblem extends Problem {
-	
-	/**
-	 * Construct a new instance of TravellingSalesmanProblem.
-	 * 
-	 * @param resources a reference to the experiment's resources.
-	 */
-	public TravellingSalesmanProblem(Resources resources) {
-		setFunctionSet(new TravellingSalesmanFunctions());
-		setName("Travelling salesman");
-		setFileExtension(".tsp");
-	}
-
-	@Override
-	public void evaluate(Population population, Resources resources) {
-		// TODO Auto-generated method stub
-	}
-
-	@Override
-	public boolean isPerfectSolution(Chromosome fittest) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	@Override
-	public void parseProblemData(File file, ModifiableResources resources) {
-		// TODO Auto-generated method stub
-	}
-
-	@Override
-	public boolean isImprovement(Chromosome fittest) {
-		// TODO Auto-generated method stub
-		return false;
-	}
-}
-- 
cgit v1.2.3