/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: SimulatedAnnealing.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 com.sun.electric.tool.placement.PlacementFrame.PlacementNode;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* Class for running simulated annealing.
* The parallelization concept is: parallel evaluation of multiple moves
* This concept relies on the fact that the number of threads corresponds to the
* number of physical cores.
* Thread pools are used to accelerate thread construction.
*/
public class SimulatedAnnealing
{
/**
* Helper class to find candidate solutions in parallel.
* When a solution has been accepted, the solutions of all other threads are
* thrown away because they were relative to the previous reference placement.
*/
class Annealer implements Runnable
{
DeltaIndividual dIndi;
Random rand;
double p;
public Annealer (Random rand)
{
dIndi = new DeltaIndividual(ref, rand);
this.rand = rand;
}
public void setProgress(double p)
{
this.p = p;
dIndi.setProgress(p);
}
public void run()
{
dIndi.reboot(rand);
}
}
Annealer[] annealers;
private Random rand;
private long evolutionStepTime;
double p;
int numThreads;
ExecutorService threadExecutor;
Reference ref;
/**
* Constructor of the simulated annealing class.
* @param nodesToPlace
* @param allNetworks
* @param evoStepTime Run for this time and then return to the loop in GeneticPlacer
* @param numThreads Number of threads
* @param ref The reference placement (nodesToPlace wrapper)
*/
SimulatedAnnealing(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks,
long evoStepTime, int numThreads, Reference ref)
{
this.ref = ref;
rand = new Random();
evolutionStepTime = evoStepTime;
this.numThreads = numThreads;
p = 0.0;
Random[] rands = new Random[numThreads];
annealers = new Annealer[numThreads];
for(int i = 0; i < numThreads; i++)
{
rands[i] = new Random();
annealers[i] = new Annealer(rands[i]);
}
threadExecutor = Executors.newFixedThreadPool(numThreads);
}
public void setProgress(double p)
{
this.p = p;
ref.setProgress(p);
for(Annealer a : annealers) a.setProgress(p);
}
public void go()
{
Future[] futures = new Future[numThreads];
long t = System.currentTimeMillis();
double r;
double bDiff;
while((System.currentTimeMillis()-t) < evolutionStepTime)
{
for(int i = 0; i < numThreads; i++)
{
futures[i] = threadExecutor.submit(annealers[i]);
}
for(int i = 0; i < numThreads; i++)
{
try {
futures[i].get(); // wait for each thread to complete execution
} catch(Exception e) { }
}
// once the first annealer's candidate is accepted, the other annealer's
// candidates are discarded.
for(Annealer a : annealers)
{
bDiff = a.dIndi.getBadness()-ref.getBadness();
r = Math.abs(rand.nextGaussian()*(0.9-p));
if(bDiff < 0.0 || r > bDiff*0.005)
{
//if(bDiff > 0.0 && r > bDiff*0.005) System.out.println("step backward");
ref.update(a.dIndi);
// The other annealer's results are now not usable any more so we throw them away
break;
}
}
}
}
}