/* -*- tab-width: 4 -*- * * Electric(tm) VLSI Design System * * File: AreaOverlapMetric.java * Written by Team 2: Jan Barth, Iskandar Abudiab * * 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.simulatedAnnealing1.metrics; import com.sun.electric.tool.placement.PlacementFrame.PlacementNode; import com.sun.electric.tool.placement.simulatedAnnealing1.SimulatedAnnealing.PlacementNodePosition; import java.awt.geom.Rectangle2D; import java.util.HashMap; import java.util.List; import java.util.Map; /** Parallel Placement * * Metric to compute the ovelapping areas of the placement nodes. * This metric is incremental, i.e. given a new state it updates the score by only computing * the changes in the ovelapping areas caused by the nodes that were moved or swapped. **/ public class AreaOverlapMetric { private List<PlacementNode> allNodes; private com.sun.electric.tool.placement.simulatedAnnealing1.SimulatedAnnealing.IncrementalState incState; private double currentScore; private Map<PlacementNode, Double> oevrlapScores; /** * Method to create a AreaOverlapMetric object. * @param allNodes a list containing all <code>PlacementNode</code> objects. * @param incrementalState an <code>IncremetntalState</code> object describing the current state. */ public AreaOverlapMetric(List<PlacementNode> allNodes, com.sun.electric.tool.placement.simulatedAnnealing1.SimulatedAnnealing.IncrementalState incrementalState){ this.oevrlapScores = new HashMap<PlacementNode , Double>(allNodes.size()); this.allNodes = allNodes; this.incState = incrementalState; } /** * Initialises this metric. * @param allNodes a list containing all <code>PlacementNode</code> objects. * @return current score, which is the sum of all overlapping areas. */ public double init(List<PlacementNode> allNodes) { currentScore = 0; for (PlacementNode node: allNodes) { oevrlapScores.put(node, new Double(0)); computeOverlapForNode(node); } return currentScore; } /** * Get current score. * @return current score, which is the sum of all overlapping areas. */ public double getCurrentScore() { return currentScore; } /** * Method that computes all overlapping areas caused by the given <code>PlacementNode</code>. * @param theOne <code>PlacementNode</code> object for which the overlapping is to be computed. * @return sum of all overlapping areas caused by this node. */ public double computeOverlapForNode(PlacementNode theOne) { double areaOverlap= 0.0; for (PlacementNode notTheOne: allNodes) { if (theOne == notTheOne) continue; double x1 = theOne.getPlacementX(); double y1 = theOne.getPlacementY(); double w1 = theOne.getWidth(); double h1 = theOne.getHeight(); int angle1 = theOne.getPlacementOrientation().getAngle(); double x2 = notTheOne.getPlacementX(); double y2 = notTheOne.getPlacementY(); double w2 = theOne.getWidth(); double h2 = theOne.getHeight(); int angle2 = notTheOne.getPlacementOrientation().getAngle(); //Check if node was moved or swapped. int originalPlacementNodeIndex = allNodes.indexOf(theOne); if (incState.isNodeChanged(originalPlacementNodeIndex)) { PlacementNodePosition changedNode = incState.getNodeFromState(originalPlacementNodeIndex); x1 = changedNode.getPlacementX(); y1 = changedNode.getPlacementY(); angle1 = changedNode.getPlacementOrientation().getAngle(); } //Get bounding rectangles and compute overlap. Rectangle2D.Double r1 = getRectangleForNode(x1, y1, w1, h1, angle1); Rectangle2D.Double r2 = getRectangleForNode(x2, y2, w2, h2, angle2); areaOverlap += getIntersectionArea(r1, r2); } double oldScore = oevrlapScores.get(theOne).doubleValue(); if (oldScore > 0 && Math.abs(oldScore - areaOverlap) > 0.001) { // System.out.println("Score changed from " + oldScore + " to " + areaOverlap); } oevrlapScores.put(theOne, new Double(areaOverlap)); currentScore = currentScore - oldScore + areaOverlap; return areaOverlap; } /** * Method that creates a bounding <code>Rectangle2D.Double</code> given the nodes placement. * @param x centre's X coordinate. * @param y centre's Y coordinate. * @param w width of the node * @param h height of the node. * @param angle the rotation angle of the node. * @return <code>Rectangle2D.Double</code> object bounding the node. */ private Rectangle2D.Double getRectangleForNode(double x, double y, double w, double h, int angle){ //TODO: Check the correctness of the generated rectangles. switch(angle){ case 0: return new Rectangle2D.Double(x - (w/2), y - (h/2), w, h); case 90: return new Rectangle2D.Double(x - (h/2), y - (w/2), h, w); case 180: return new Rectangle2D.Double(x - (w/2), y - (h/2), w, h); case 270: return new Rectangle2D.Double(x - (h/2), y - (w/2), h, w); default: return new Rectangle2D.Double(x - (w/2), y - (h/2), w, h); } } /** * Method to compute the area overlapped by the two given <code>Rectangle2D.Double</code> objects. * @param r1 the first <code>Rectangle2D.Double</code> object. * @param r2 the second <code>Rectangle2D.Double</code> object * @return returns the area being overlapped by the given rectangles. */ private double getIntersectionArea(Rectangle2D.Double r1, Rectangle2D.Double r2){ double area = 0.0; Rectangle2D overlap = r1.createIntersection(r2); if(!overlap.isEmpty()) area = overlap.getWidth()*overlap.getHeight(); return area; } /** * Updates the metric score. * @param index the index of the node that was moved or swapped. * @return the new metric score. */ public double update(int index) { double BeforeIncUpdate = currentScore; computeOverlapForNode(allNodes.get(index)); double incScore = currentScore; double newScore = currentScore; if (Math.abs(incScore - newScore) > 0.0001) { System.out.println("BeforeIncUpdate=" + BeforeIncUpdate + ", after update: incScore="+ incScore + ", correctScore=" + newScore); } return currentScore; } }