Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
</parent>
<artifactId>watchmaker-framework</artifactId>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.uncommons.maths</groupId>
Expand All @@ -43,8 +53,8 @@
<version>6.2.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencies>

<build>
<sourceDirectory>src/java/main</sourceDirectory>
<testSourceDirectory>src/java/test</testSourceDirectory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@
public abstract class AbstractEvolutionEngine<T> implements EvolutionEngine<T>
{
// 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<EvolutionObserver<? super T>> observers = new CopyOnWriteArraySet<EvolutionObserver<? super T>>();
protected final Set<EvolutionObserver<? super T>> observers = new CopyOnWriteArraySet<EvolutionObserver<? super T>>();

private final Random rng;
private final CandidateFactory<T> candidateFactory;
private final FitnessEvaluator<? super T> fitnessEvaluator;
protected final Random rng;
protected final CandidateFactory<T> candidateFactory;
protected final FitnessEvaluator<? super T> fitnessEvaluator;

private volatile boolean singleThreaded = false;
protected volatile boolean singleThreaded = false;

private List<TerminationCondition> satisfiedTerminationConditions;
protected List<TerminationCondition> satisfiedTerminationConditions;


/**
Expand Down Expand Up @@ -166,7 +166,7 @@ public List<EvaluatedCandidate<T>> 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.
Expand Down Expand Up @@ -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<T> data)
protected void notifyPopulationChange(PopulationData<T> data)
{
for (EvolutionObserver<? super T> observer : observers)
{
Expand All @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <T> Type of object to evolve
*/
public abstract class CompetitionEngine<T> extends GenerationalEvolutionEngine<T> {

public CompetitionEngine(CandidateFactory<T> candidateFactory,
EvolutionaryOperator<T> evolutionScheme,
FitnessEvaluator<? super T> fitnessEvaluator,
SelectionStrategy<? super T> selectionStrategy, Random rng) {
super(candidateFactory, evolutionScheme, fitnessEvaluator, selectionStrategy, rng);
}

@Override
public List<EvaluatedCandidate<T>> evolvePopulation(int populationSize,
int eliteCount,
Collection<T> 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<T> 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<EvaluatedCandidate<T>> evaluatedPopulation = evaluatePopulation( population );

EvolutionUtils.sortEvaluatedPopulation(
evaluatedPopulation,
fitnessEvaluator.isNatural()
);

PopulationData<T> data = EvolutionUtils.getPopulationData(
evaluatedPopulation,
fitnessEvaluator.isNatural(),
eliteCount,
currentGenerationIndex,
startTime
);

// Notify observers of the state of the population.
notifyPopulationChange( data );

List<TerminationCondition> 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<EvaluatedCandidate<T>> runCompetitionInternal(List<EvaluatedCandidate<T>> population) {
List<T> work = new ArrayList<>(population.size());

for( EvaluatedCandidate<T> 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<T> runCompetition( List<T> population );
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
*/
public class GenerationalEvolutionEngine<T> extends AbstractEvolutionEngine<T>
{
private final EvolutionaryOperator<T> evolutionScheme;
private final FitnessEvaluator<? super T> fitnessEvaluator;
private final SelectionStrategy<? super T> selectionStrategy;
protected final EvolutionaryOperator<T> 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
Expand Down Expand Up @@ -101,7 +101,7 @@ public GenerationalEvolutionEngine(CandidateFactory<T> candidateFactory,


/**
* {@inheritDoc}
* {@inheritDoc}
*/
@Override
protected List<EvaluatedCandidate<T>> nextEvolutionStep(List<EvaluatedCandidate<T>> evaluatedPopulation,
Expand Down
10 changes: 5 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@
<name>watchmaker</name>
<description>Watchmaker Framework - Root Project</description>
<url>http://watchmaker.uncommons.org</url>

<licenses>
<license>
<name>Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
<distribution>repo</distribution>
</license>
</licenses>

<scm>
<url>https://github.com/dwdyer/watchmaker</url>
<connection>scm:git://github.com/dwdyer/watchmaker.git</connection>
<developerConnection>scm:git:ssh://git@github.com:dwdyer/watchmaker.git</developerConnection>
</scm>

<developers>
<developer>
<id>dwdyer</id>
Expand Down Expand Up @@ -57,8 +57,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.7</source>
<target>1.7</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
Expand Down