Last active
September 21, 2015 19:02
-
-
Save dhadka/559be932acc55b1ada6b to your computer and use it in GitHub Desktop.
Temporary fix to a bug in the island model example, where TimSort throws an exception indicating the comparator's contract is violated
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Comparator; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
import java.util.Properties; | |
import java.util.concurrent.Semaphore; | |
import org.apache.commons.math3.random.MersenneTwister; | |
import org.apache.commons.math3.random.RandomAdaptor; | |
import org.apache.commons.math3.random.SynchronizedRandomGenerator; | |
import org.moeaframework.algorithm.NSGAII; | |
import org.moeaframework.algorithm.PeriodicAction; | |
import org.moeaframework.algorithm.PeriodicAction.FrequencyType; | |
import org.moeaframework.core.NondominatedPopulation; | |
import org.moeaframework.core.NondominatedSortingPopulation; | |
import org.moeaframework.core.PRNG; | |
import org.moeaframework.core.Population; | |
import org.moeaframework.core.Problem; | |
import org.moeaframework.core.Solution; | |
import org.moeaframework.core.comparator.ChainedComparator; | |
import org.moeaframework.core.comparator.CrowdingComparator; | |
import org.moeaframework.core.comparator.ParetoDominanceComparator; | |
import org.moeaframework.core.operator.RandomInitialization; | |
import org.moeaframework.core.operator.TournamentSelection; | |
import org.moeaframework.core.spi.OperatorFactory; | |
import org.moeaframework.core.spi.ProblemFactory; | |
public class IslandModel { | |
public static void main(String[] args) { | |
final int numberOfIslands = 4; | |
final int maxEvaluations = 1000000; | |
final int migrationFrequency = 10000; | |
final Problem problem = ProblemFactory.getInstance().getProblem("DTLZ2_2"); | |
final Map<Thread, NSGAII> islands = new HashMap<Thread, NSGAII>(); | |
// this semaphore is used to synchronize locking to prevent deadlocks | |
final Semaphore semaphore = new Semaphore(1); | |
// need to use a synchronized random number generator instead of the | |
// default | |
PRNG.setRandom(new RandomAdaptor( | |
new SynchronizedRandomGenerator( | |
new MersenneTwister()))); | |
for (int i = 0; i < numberOfIslands; i++) { | |
// create an instance of NSGAII for each island | |
final NSGAII nsgaii = new NSGAII( | |
problem, | |
new SynchronizedPopulation(), | |
null, | |
new TournamentSelection(2, | |
new ChainedComparator( | |
new ParetoDominanceComparator(), | |
new CrowdingComparator())), | |
OperatorFactory.getInstance().getVariation( | |
null, | |
new Properties(), | |
problem), | |
new RandomInitialization(problem, 100)); | |
// create a periodic action for handling migration events | |
final PeriodicAction migration = new PeriodicAction(nsgaii, | |
migrationFrequency, | |
FrequencyType.EVALUATIONS) { | |
@Override | |
public void doAction() { | |
try { | |
Thread thisThread = Thread.currentThread(); | |
for (Thread otherThread : islands.keySet()) { | |
if (otherThread != thisThread) { | |
semaphore.acquire(); | |
NondominatedSortingPopulation oldIsland = | |
(NondominatedSortingPopulation)islands.get(thisThread).getPopulation(); | |
NondominatedSortingPopulation newIsland = | |
(NondominatedSortingPopulation)islands.get(otherThread).getPopulation(); | |
synchronized (oldIsland) { | |
synchronized (newIsland) { | |
int emigrant = PRNG.nextInt(oldIsland.size()); | |
newIsland.add(oldIsland.get(emigrant).copy()); | |
newIsland.truncate(newIsland.size()-1); | |
System.out.println("Sent solution " + | |
emigrant + " from " + | |
Thread.currentThread().getName() + | |
" to " + otherThread.getName()); | |
} | |
} | |
semaphore.release(); | |
} | |
} | |
} catch (InterruptedException e) { | |
// ignore | |
} | |
} | |
}; | |
// create the thread for running each island concurrently | |
Thread thread = new Thread() { | |
public void run() { | |
while (migration.getNumberOfEvaluations() < maxEvaluations) { | |
migration.step(); | |
} | |
} | |
}; | |
islands.put(thread, nsgaii); | |
} | |
// start the threads | |
for (Thread thread : islands.keySet()) { | |
thread.start(); | |
} | |
// wait for the threads to finish and aggregate the result | |
NondominatedPopulation result = new NondominatedPopulation(); | |
for (Thread thread : islands.keySet()) { | |
try { | |
thread.join(); | |
result.addAll(islands.get(thread).getResult()); | |
} catch (InterruptedException e) { | |
System.out.println("Thread " + thread.getId() + " was interrupted!"); | |
} | |
} | |
System.out.println(result.size()); | |
} | |
// synchronized version of the NondominatedSortingPopulation | |
public static class SynchronizedPopulation extends NondominatedSortingPopulation { | |
@Override | |
public boolean add(Solution solution) { | |
synchronized (this) { | |
return super.add(solution); | |
} | |
} | |
@Override | |
public void replace(int index, Solution solution) { | |
synchronized (this) { | |
super.replace(index, solution); | |
} | |
} | |
@Override | |
public Solution get(int index) { | |
synchronized (this) { | |
return super.get(index); | |
} | |
} | |
@Override | |
public void remove(int index) { | |
synchronized (this) { | |
super.remove(index); | |
} | |
} | |
@Override | |
public boolean remove(Solution solution) { | |
synchronized (this) { | |
return super.remove(solution); | |
} | |
} | |
@Override | |
public void clear() { | |
synchronized (this) { | |
super.clear(); | |
} | |
} | |
@Override | |
public Iterator<Solution> iterator() { | |
synchronized (this) { | |
return super.iterator(); | |
} | |
} | |
@Override | |
public void sort(Comparator<? super Solution> comparator) { | |
synchronized (this) { | |
super.sort(comparator); | |
} | |
} | |
@Override | |
public void truncate(int size, Comparator<? super Solution> comparator) { | |
synchronized (this) { | |
super.truncate(size, comparator); | |
} | |
} | |
@Override | |
public void truncate(int size) { | |
synchronized (this) { | |
super.truncate(size); | |
} | |
} | |
@Override | |
public void prune(int size) { | |
synchronized (this) { | |
super.prune(size); | |
} | |
} | |
@Override | |
public void update() { | |
synchronized (this) { | |
super.update(); | |
} | |
} | |
@Override | |
public int indexOf(Solution solution) { | |
synchronized (this) { | |
return super.indexOf(solution); | |
} | |
} | |
@Override | |
public boolean addAll(Iterable<? extends Solution> iterable) { | |
synchronized (this) { | |
return super.addAll(iterable); | |
} | |
} | |
@Override | |
public <T extends Solution> boolean addAll(T[] solutions) { | |
synchronized (this) { | |
return super.addAll(solutions); | |
} | |
} | |
@Override | |
public boolean contains(Solution solution) { | |
synchronized (this) { | |
return super.contains(solution); | |
} | |
} | |
@Override | |
public boolean containsAll(Iterable<? extends Solution> iterable) { | |
synchronized (this) { | |
return super.containsAll(iterable); | |
} | |
} | |
@Override | |
public <T extends Solution> boolean containsAll(T[] solutions) { | |
synchronized (this) { | |
return super.containsAll(solutions); | |
} | |
} | |
@Override | |
public boolean isEmpty() { | |
synchronized (this) { | |
return super.isEmpty(); | |
} | |
} | |
@Override | |
public boolean removeAll(Iterable<? extends Solution> iterable) { | |
synchronized (this) { | |
return super.removeAll(iterable); | |
} | |
} | |
@Override | |
public <T extends Solution> boolean removeAll(T[] solutions) { | |
synchronized (this) { | |
return super.removeAll(solutions); | |
} | |
} | |
@Override | |
public int size() { | |
synchronized (this) { | |
return super.size(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment