/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: Evolver.java
* Written by Team 4: Benedikt Mueller, Richard Fallert
*
* This code has been developed at the Karlsruhe Institute of Technology (KIT), Germany,
* as part of the course "Multicore Programming in Practice: Tools, Models, and Languages".
* Contact instructor: Dr. Victor Pankratius (pankratius@ipd.uka.de)
*
* Copyright (c) 2010 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.placement.genetic2;
import com.sun.electric.tool.placement.PlacementFrame.PlacementNetwork;
import java.util.List;
import java.util.Random;
/**
* Class for running a genetic algorithm in a separate thread.
* Each Evolver iteratively picks individuals from the population, locks them
* and uses them for evolution.
* Different selection methods are implemented here.
*/
public class Evolver implements Runnable
{
List<PlacementNetwork> allNetworks;
private Individual[] indis;
private Random rand;
private long evolutionStepTime;
double p;
long steps;
/**
* Constructor of an Evolver.
* @param indis All the individuals in the whole population.
* @param evolutionStepTime How many milliseconds a single step runs.
* @param evolutionSteps How many steps the evolve-function should iterate.
* @param rand An exclusive random number generator, not to be used by other threads.
*/
Evolver(Individual[] indis, long evolutionStepTime, Random rand)
{
this.indis = indis;
this.evolutionStepTime = evolutionStepTime;
this.rand = rand;
}
/**
* Updates the information of how much of the runtime is already over.
*/
public void setProgress(double p)
{
this.p = p;
}
// /**
// * Local steady-state evolution with diversity bonus.
// */
// private void evoDiverseLocal()
// {
// int comparison;
// comparison = rand.nextInt(indis.length);
// while(!indis[comparison].rwLock.writeLock().tryLock())
// {
// comparison = rand.nextInt(indis.length);
// }
//
// int[] positions = new int[3];
// positions[0] = rand.nextInt(indis.length);
// while(!indis[positions[0]].rwLock.writeLock().tryLock())
// {
// positions[0] = rand.nextInt(indis.length);
// }
//
// for(int i = 1; i < positions.length; i++)
// {
// positions[i] = (positions[0]+(int)(20.0*rand.nextGaussian()))%indis.length;
// if(positions[i] < 0) positions[i] += indis.length;
// while(!indis[positions[i]].rwLock.writeLock().tryLock())
// {
// positions[i] = (positions[0]+(int)(20.0*rand.nextGaussian()))%indis.length;
// if(positions[i] < 0) positions[i] += indis.length;
// }
// }
//
// //double d0 = indis[positions[0]].distance();
// //double d1 = indis[positions[1]].distance();
// //double d2 = indis[positions[2]].distance();
//
// // diversity bonus:
// double d0 = indis[positions[0]].distance(indis[comparison]);
// double d1 = indis[positions[1]].distance(indis[comparison]);
// double d2 = indis[positions[2]].distance(indis[comparison]);
//
// /*
// if(rand.nextInt(100000) == 0)
// {
// System.out.println("d0: " + d0 + " d1: " + d1 + " d2: " + d2);
// }
// */
//
// // overwrite the loser with the crossover of the best two
// if(indis[positions[0]].getBadness()-d0 >= indis[positions[1]].getBadness()-d1 &&
// indis[positions[0]].getBadness()-d0 >= indis[positions[2]].getBadness()-d2)
// {
// indis[positions[0]].deriveFrom(indis[positions[1]], indis[positions[2]], rand);
// }
// else if(indis[positions[1]].getBadness()-d1 >= indis[positions[0]].getBadness()-d0 &&
// indis[positions[1]].getBadness()-d1 >= indis[positions[2]].getBadness()-d2)
// {
// indis[positions[1]].deriveFrom(indis[positions[0]], indis[positions[2]], rand);
// }
// else
// {
// indis[positions[2]].deriveFrom(indis[positions[0]], indis[positions[1]], rand);
// }
//
// for(int i = 0; i < positions.length; i++)
// {
// indis[positions[i]].rwLock.writeLock().unlock();
// }
// indis[comparison].rwLock.writeLock().unlock();
// }
/**
* Local steady-state evolution.
*/
private void evoLocal()
{
int[] positions = new int[3];
positions[0] = rand.nextInt(indis.length);
while(!indis[positions[0]].rwLock.writeLock().tryLock())
{
positions[0] = rand.nextInt(indis.length);
}
for(int i = 1; i < positions.length; i++)
{
positions[i] = (positions[0]+(int)(20.0*rand.nextGaussian()))%indis.length;
if(positions[i] < 0) positions[i] += indis.length;
while(!indis[positions[i]].rwLock.writeLock().tryLock())
{
positions[i] = (positions[0]+(int)(20.0*rand.nextGaussian()))%indis.length;
if(positions[i] < 0) positions[i] += indis.length;
}
}
// overwrite the loser with the crossover of the best two
if(indis[positions[0]].getBadness() >= indis[positions[1]].getBadness() &&
indis[positions[0]].getBadness() >= indis[positions[2]].getBadness())
{
indis[positions[0]].deriveFrom(indis[positions[1]], indis[positions[2]], rand);
}
else if(indis[positions[1]].getBadness() >= indis[positions[0]].getBadness() &&
indis[positions[1]].getBadness() >= indis[positions[2]].getBadness())
{
indis[positions[1]].deriveFrom(indis[positions[0]], indis[positions[2]], rand);
}
else
{
indis[positions[2]].deriveFrom(indis[positions[0]], indis[positions[1]], rand);
}
for(int i = 0; i < positions.length; i++)
{
indis[positions[i]].rwLock.writeLock().unlock();
}
}
/**
* @return The number of evolution steps (generations) the evolver has iterated
*/
public long getSteps()
{
return steps;
}
public void run()
{
long t = System.currentTimeMillis();
while((System.currentTimeMillis()-t) < evolutionStepTime)
{
//evoDiverseLocal();
evoLocal();
steps++;
}
}
}