/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: GeneticPlacer.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 com.sun.electric.tool.placement.genetic2.metrics.DeltaBBMetric; import java.util.List; import java.util.Random; /** * Genetic algorithm for placement. */ public class GeneticPlacer { // private static final int MAX_INDIVIDUALS = 200; // for islands (deprecated) private static final int INDIVIDUALS = 1000; // population size for UnifiedPopulation private static int EVOLUTION_STEPS; // maximum runtime of the placement algorithm in seconds public int maxRuntime; // number of threads public int numThreads; // if false: NO system.out.println statements public boolean printDebugInformation; long startTime; UnifiedPopulation population = null; Reference ref; public String getAlgorithmName() { return "team4Genetic"; } public UnifiedPopulation getPopulation() { return population; } GeneticPlacer(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks, int runtime, int threads, boolean debug) { maxRuntime = runtime*1000; EVOLUTION_STEPS = maxRuntime/10000; numThreads = threads; printDebugInformation = debug; startTime = System.currentTimeMillis(); Random rand = new Random(System.currentTimeMillis()); DeltaBBMetric.init(nodesToPlace, allNetworks); ref = new Reference(nodesToPlace, allNetworks, rand); DeltaBBMetric.setRef(ref); ref.calculateRefNetLength(); // initialize population DeltaIndividual[] indis = new DeltaIndividual[INDIVIDUALS]; for(int i = 0; i < INDIVIDUALS; i++) { indis[i] = new DeltaIndividual(ref, rand); } population = new UnifiedPopulation(nodesToPlace, allNetworks, indis, maxRuntime/EVOLUTION_STEPS, numThreads, rand); } private void placeUnified(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks, long partTime) { long localStartTime = System.currentTimeMillis(); if(printDebugInformation) { System.out.println("Starting genetic algorithm...\n" + "Total running time is " + maxRuntime/1000 + " seconds (~" +maxRuntime/60000+ " minutes).\n" + "There will be " + EVOLUTION_STEPS + " text messages while running,\n" + "each will tell you the current round number and champion badness:"); } int round = 0; long t = 0; long localT = 0; DeltaIndividual champion; ref.calculateFirstTime(); while(t < partTime) { population.setProgress(((double)localT)/(double)(partTime-(localStartTime-startTime))); population.evolveLocalMT(numThreads); // this is where the evolution happens! champion = (DeltaIndividual)population.getChampion(); if(printDebugInformation) { System.out.println("Round " + round + " of " + EVOLUTION_STEPS + " | champion badness: " + population.getChampion().getBadness()); System.out.println("champion overlap: " + champion.getBadnessComponents()[1]); System.out.println("champion netlength: " + champion.getBadnessComponents()[0]); } ref.update(champion); if(round%4==0) { // adapt the grid to the changed placement ref.createGrid(); } if(printDebugInformation) { System.out.println("ref overlap: " + ref.getBadnessComponents()[1]); System.out.println("ref netlength: " + ref.getBadnessComponents()[0]); System.out.println(); } population.reboot(); round++; t = (System.currentTimeMillis()-startTime); localT = (System.currentTimeMillis()-localStartTime); } // find the champion champion = (DeltaIndividual)population.getChampion(); // write champion placement to nodesToPlace ref.update(champion); ref.calculateFirstTime(); if(printDebugInformation) { System.out.println("final ref net length: " + ref.getBadnessComponents()[0]); System.out.println("final ref overlap: " + ref.getBadnessComponents()[1]); System.out.println("final ref naiveOverlap: " + ref.getNaiveOverlap()); System.out.println("final net length (bb): " + DeltaBBMetric.compute()); //System.out.println("final evolverSteps: " + population.getEvolverSteps()); } } private void placeAnnealing(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks, long partTime) { long localStartTime = System.currentTimeMillis(); SimulatedAnnealing annealing = new SimulatedAnnealing(nodesToPlace, allNetworks, maxRuntime/EVOLUTION_STEPS, numThreads, ref); if(printDebugInformation) { System.out.println("Starting simulated annealing...\n" + "Total running time is " + maxRuntime/1000 + " seconds (~" +maxRuntime/60000+ " minutes).\n" + "There will be " + EVOLUTION_STEPS + " text messages while running,\n" + "each will tell you the current round number and champion badness:"); } int round = 0; long t = 0; long localT = 0; ref.calculateFirstTime(); while(t < partTime) { annealing.setProgress(((double)localT)/(double)(partTime-(localStartTime-startTime))); annealing.go(); if(printDebugInformation) { System.out.println("Round " + round + " of " + EVOLUTION_STEPS); System.out.println("ref netlength: " + ref.getBadnessComponents()[0]); System.out.println("ref overlap: " + ref.getBadnessComponents()[1]); } if(round%4==0) { // adapt the grid to the changed placement ref.createGrid(); } // annealing.reboot(); round++; t = (System.currentTimeMillis()-startTime); localT = (System.currentTimeMillis()-localStartTime); } if(printDebugInformation) { System.out.println("final ref net length: " + ref.getBadnessComponents()[0]); System.out.println("final ref overlap: " + ref.getBadnessComponents()[1]); System.out.println("final ref naiveOverlap: " + ref.getNaiveOverlap()); System.out.println("final net length (bb): " + DeltaBBMetric.compute()); //System.out.println("final evolverSteps: " + population.getEvolverSteps()); } } // /** // * This function is deprecated, use placeUnified or placeAnnealing instead. // * It is only provided for comparison and can be deleted at any time // */ // private void placeIslands(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks) // { // BBMetric m_bb = new BBMetric(nodesToPlace, allNetworks); // // // create root random number generator // Random rand = new Random(System.currentTimeMillis()); // // // create one random number generator per thread // int[] seeds = new int[numThreads]; // Random[] rands = new Random[numThreads]; // // for(int i=0; i<numThreads; i++) // { // seeds[i] = rand.nextInt(); // rands[i] = new Random(seeds[i]); // } // // // // initialize populations (one per thread) // Population<ClassicIndividual>[] populations = new Population[numThreads]; // Thread[] threads = new Thread[numThreads]; // // // for(int i=0; i<numThreads; i++) { // // ClassicIndividual[] indis = new ClassicIndividual[MAX_INDIVIDUALS/numThreads]; // for(int n = 0; n < MAX_INDIVIDUALS/numThreads; n++) // indis[n] = new ClassicIndividual(ref, rand); // // populations[i] = // new Population<ClassicIndividual>(nodesToPlace, // allNetworks, // indis, // (long)(maxRuntime/EVOLUTION_STEPS), // Gesamtzeit geteilt durch Evolutionsschritte // rands[i]); // } // // if(printDebugInformation) // { // System.out.println("Starting genetic algorithm...\n" // + "Total running time is " + maxRuntime/1000 + " seconds (~" +maxRuntime/60000+ " minutes).\n" // + "There will be " + EVOLUTION_STEPS + " text messages while running,\n" // + "each will tell you the current round number and champion badness:"); // } // // // periodically start threads and exchange champions between populations // int round = 0; // long t = 0; // // while(t < maxRuntime) // { // for(int i=0; i<numThreads; i++) // { // populations[i].setProgress(((double)t)/((double)maxRuntime)); // threads[i] = new Thread(populations[i]); // threads[i].start(); // } // // // wait until all populations have completed some rounds of evolution // for(int i=0; i<numThreads; i++) // { // try { // threads[i].join(); // } catch (InterruptedException e) { e.printStackTrace(); } // } // // if(printDebugInformation) // { // System.out.println("(" + round + ") : " // + populations[0].getChampion().getBadness()); // } // // // // exchange champions so the populations can cooperate // for(int i=0; i<numThreads; i++) // { // //if(rand.nextDouble() > 0.5) // { // populations[i].insert(populations[(i+1)%numThreads].getChampion()); // //populations[i].insert(populations[(i+1)%numThreads].getRandomOne()); // } // } // // // write champion placement to nodesToPlace // population.getChampion().writeToPlacement(nodesToPlace); // population.reEvaluateAll(); // // round++; // t = (System.currentTimeMillis()-startTime); // } // // // find the best champion of all populations // Individual champion = populations[0].getChampion(); // // for(int p=1; p<numThreads; p++) // { // Individual challenger = populations[p].getChampion(); // if(challenger.getBadness() < champion.getBadness()) // { // champion = challenger; // } // } // // // write champion placement to nodesToPlace // population.getChampion().writeToPlacement(nodesToPlace); // if(printDebugInformation) // { // System.out.println("final champion badness: " + champion.getBadness()); // System.out.println("final champion overlap: " + champion.calculateOverlap()); // System.out.println("final champion semiperimeter length: " + champion.getSemiperimeterLength()); // System.out.println("final champion bounding box area: " + champion.getBoundingBoxArea()); // // System.out.println("final net length (bb): " + m_bb.compute()); // } // } /** * Method to run the genetic algorithm to find a good placement. * @param nodesToPlace a list of all nodes that are to be placed. * @param allNetworks a list of all networks that connect the nodes. */ protected void runPlacement(List<PlacementNode> nodesToPlace, List<PlacementNetwork> allNetworks) { // For a runtime of less than 20 seconds, do only simulated annealing if(maxRuntime >= 19900) placeUnified(nodesToPlace, allNetworks, maxRuntime/2); placeAnnealing(nodesToPlace, allNetworks, maxRuntime); //placeIslands(nodesToPlace, allNetworks); // deprecated } }