diff --git a/framework/pom.xml b/framework/pom.xml
index 51ecd7bd..a41db17f 100644
--- a/framework/pom.xml
+++ b/framework/pom.xml
@@ -26,6 +26,16 @@
watchmaker-framework
+
+
+
+ jfree
+ jfreechart
+ 1.0.0
+
+
+
+
org.uncommons.maths
@@ -43,8 +53,8 @@
6.2.1test
-
-
+
+
src/java/mainsrc/java/test
diff --git a/framework/src/java/main/org/uncommons/watchmaker/framework/AbstractEvolutionEngine.java b/framework/src/java/main/org/uncommons/watchmaker/framework/AbstractEvolutionEngine.java
index 486f10dd..6d5131e8 100644
--- a/framework/src/java/main/org/uncommons/watchmaker/framework/AbstractEvolutionEngine.java
+++ b/framework/src/java/main/org/uncommons/watchmaker/framework/AbstractEvolutionEngine.java
@@ -35,17 +35,17 @@
public abstract class AbstractEvolutionEngine implements EvolutionEngine
{
// A single multi-threaded worker is shared among multiple evolution engine instances.
- private static FitnessEvaluationWorker concurrentWorker = null;
+ protected static FitnessEvaluationWorker concurrentWorker = null;
- private final Set> observers = new CopyOnWriteArraySet>();
+ protected final Set> observers = new CopyOnWriteArraySet>();
- private final Random rng;
- private final CandidateFactory candidateFactory;
- private final FitnessEvaluator super T> fitnessEvaluator;
+ protected final Random rng;
+ protected final CandidateFactory candidateFactory;
+ protected final FitnessEvaluator super T> fitnessEvaluator;
- private volatile boolean singleThreaded = false;
+ protected volatile boolean singleThreaded = false;
- private List satisfiedTerminationConditions;
+ protected List satisfiedTerminationConditions;
/**
@@ -166,7 +166,7 @@ public List> evolvePopulation(int populationSize,
return evaluatedPopulation;
}
-
+
/**
* This method performs a single step/iteration of the evolutionary process.
* @param evaluatedPopulation The population at the beginning of the process.
@@ -303,7 +303,7 @@ public void removeEvolutionObserver(EvolutionObserver super T> observer)
* Send the population data to all registered observers.
* @param data Information about the current state of the population.
*/
- private void notifyPopulationChange(PopulationData data)
+ protected void notifyPopulationChange(PopulationData data)
{
for (EvolutionObserver super T> observer : observers)
{
@@ -330,7 +330,7 @@ public void setSingleThreaded(boolean singleThreaded)
/**
* Lazily create the multi-threaded worker for fitness evaluations.
*/
- private static synchronized FitnessEvaluationWorker getSharedWorker()
+ protected static synchronized FitnessEvaluationWorker getSharedWorker()
{
if (concurrentWorker == null)
{
diff --git a/framework/src/java/main/org/uncommons/watchmaker/framework/CompetitionEngine.java b/framework/src/java/main/org/uncommons/watchmaker/framework/CompetitionEngine.java
new file mode 100644
index 00000000..495c0337
--- /dev/null
+++ b/framework/src/java/main/org/uncommons/watchmaker/framework/CompetitionEngine.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2016 Fabrizio
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
+ * express or implied. See the License for the specific language
+ * governing permissions and limitations under the License.
+ */
+
+package org.uncommons.watchmaker.framework;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Subclassing of one Watchmaker's class to add the capability to run a game
+ * before applying evolution rules and population change.
+ *
+ * @param Type of object to evolve
+ */
+public abstract class CompetitionEngine extends GenerationalEvolutionEngine {
+
+ public CompetitionEngine(CandidateFactory candidateFactory,
+ EvolutionaryOperator evolutionScheme,
+ FitnessEvaluator super T> fitnessEvaluator,
+ SelectionStrategy super T> selectionStrategy, Random rng) {
+ super(candidateFactory, evolutionScheme, fitnessEvaluator, selectionStrategy, rng);
+ }
+
+ @Override
+ public List> evolvePopulation(int populationSize,
+ int eliteCount,
+ Collection seedCandidates,
+ TerminationCondition... conditions) {
+ if( eliteCount < 0 || eliteCount >= populationSize ) {
+ throw new IllegalArgumentException("Elite count must be non-negative and less than population size.");
+ }
+
+ if( conditions.length == 0 ) {
+ throw new IllegalArgumentException("At least one TerminationCondition must be specified.");
+ }
+
+ satisfiedTerminationConditions = null;
+
+ int currentGenerationIndex = 0;
+ long startTime = System.currentTimeMillis();
+
+ List population = candidateFactory.generateInitialPopulation( populationSize, seedCandidates, rng );
+
+ // The competition is first run here
+ population = runCompetition(population);
+ // Check that there are still individuals after the population
+ if( population.size() <= 1 ) {
+ throw new IllegalArgumentException("The population after the competition is too small");
+ }
+
+ // Calculate the fitness scores for each member of the initial population.
+ List> evaluatedPopulation = evaluatePopulation( population );
+
+ EvolutionUtils.sortEvaluatedPopulation(
+ evaluatedPopulation,
+ fitnessEvaluator.isNatural()
+ );
+
+ PopulationData data = EvolutionUtils.getPopulationData(
+ evaluatedPopulation,
+ fitnessEvaluator.isNatural(),
+ eliteCount,
+ currentGenerationIndex,
+ startTime
+ );
+
+ // Notify observers of the state of the population.
+ notifyPopulationChange( data );
+
+ List satisfiedConditions = EvolutionUtils.shouldContinue( data, conditions );
+ while( satisfiedConditions == null ) {
+ ++currentGenerationIndex;
+
+ evaluatedPopulation = nextEvolutionStep( evaluatedPopulation, eliteCount, rng );
+
+ // Competition is run again
+ evaluatedPopulation = runCompetitionInternal( evaluatedPopulation );
+ if( population.size() <= 1 ) {
+ throw new IllegalArgumentException("The population after the competition is too small");
+ }
+
+ EvolutionUtils.sortEvaluatedPopulation(
+ evaluatedPopulation,
+ fitnessEvaluator.isNatural()
+ );
+
+ data = EvolutionUtils.getPopulationData(
+ evaluatedPopulation,
+ fitnessEvaluator.isNatural(),
+ eliteCount,
+ currentGenerationIndex,
+ startTime
+ );
+
+ // Notify observers of the state of the population.
+ notifyPopulationChange(data);
+
+ satisfiedConditions = EvolutionUtils.shouldContinue(data, conditions);
+ }
+
+ this.satisfiedTerminationConditions = satisfiedConditions;
+
+ return evaluatedPopulation;
+ }
+
+ private List> runCompetitionInternal(List> population) {
+ List work = new ArrayList<>(population.size());
+
+ for( EvaluatedCandidate candidate : population ) {
+ work.add(candidate.getCandidate());
+ }
+
+ work = runCompetition( work );
+
+ return this.evaluatePopulation( work );
+ }
+
+ /**
+ * This method runs the competition between the individuals of the population
+ *
+ * @param population The population of individuals
+ * @return The population of individuals after the competition
+ */
+ protected abstract List runCompetition( List population );
+}
diff --git a/framework/src/java/main/org/uncommons/watchmaker/framework/GenerationalEvolutionEngine.java b/framework/src/java/main/org/uncommons/watchmaker/framework/GenerationalEvolutionEngine.java
index 3e43915f..fe43179f 100644
--- a/framework/src/java/main/org/uncommons/watchmaker/framework/GenerationalEvolutionEngine.java
+++ b/framework/src/java/main/org/uncommons/watchmaker/framework/GenerationalEvolutionEngine.java
@@ -44,9 +44,9 @@
*/
public class GenerationalEvolutionEngine extends AbstractEvolutionEngine
{
- private final EvolutionaryOperator evolutionScheme;
- private final FitnessEvaluator super T> fitnessEvaluator;
- private final SelectionStrategy super T> selectionStrategy;
+ protected final EvolutionaryOperator evolutionScheme;
+ protected final FitnessEvaluator super T> fitnessEvaluator;
+ protected final SelectionStrategy super T> selectionStrategy;
/**
* Creates a new evolution engine by specifying the various components required by
@@ -101,7 +101,7 @@ public GenerationalEvolutionEngine(CandidateFactory candidateFactory,
/**
- * {@inheritDoc}
+ * {@inheritDoc}
*/
@Override
protected List> nextEvolutionStep(List> evaluatedPopulation,
diff --git a/pom.xml b/pom.xml
index 6698f38b..1f4ee105 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
watchmakerWatchmaker Framework - Root Projecthttp://watchmaker.uncommons.org
-
+
Apache License, Version 2.0
@@ -21,13 +21,13 @@
repo
-
+
https://github.com/dwdyer/watchmakerscm:git://github.com/dwdyer/watchmaker.gitscm:git:ssh://git@github.com:dwdyer/watchmaker.git
-
+
dwdyer
@@ -57,8 +57,8 @@
maven-compiler-plugin2.3.2
- 1.6
- 1.6
+ 1.7
+ 1.7${project.build.sourceEncoding}