/* * Copyright (c) 2005-2011 KOM - Multimedia Communications Lab * * This file is part of PeerfactSim.KOM. * * PeerfactSim.KOM 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 * any later version. * * PeerfactSim.KOM 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 PeerfactSim.KOM. If not, see . * */ package de.tud.kom.p2psim.impl.network.gnp.topology; import java.util.ArrayList; import de.tudarmstadt.maki.simonstrator.api.Randoms; import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location; /** * This class implements a NetPosition for a GNP-Based calculation of round trip * times. Therefore it includes methods for error estimation and methods for * positioning by a downhill simplex algorithm in the GnpSpace class * * @author Gerald Klunker * @version 0.1, 09.01.2008 * */ public class GnpPosition implements Location, Comparable { private static final long serialVersionUID = -1103996725403557900L; private double[] gnpCoordinates; private GnpSpace gnpRef; private Host hostRef; private double error = -1.0; /** * * @param gnpCoordinates * coordinate array for new position */ public GnpPosition(double[] gnpCoordinates) { super(); this.gnpCoordinates = gnpCoordinates; } /** * Object will be initialized with a random position. Position must be * random according to the downhill simplex * * @param noOfDimensions * number of dimensions * @param hostRef * related Host object * @param gnpRef * related GnpSpace object */ public GnpPosition(int noOfDimensions, Host hostRef, GnpSpace gnpRef) { super(); gnpCoordinates = new double[noOfDimensions]; this.hostRef = hostRef; this.gnpRef = gnpRef; for (int c = 0; c < gnpCoordinates.length; c++) gnpCoordinates[c] = Randoms.getRandom(GnpPosition.class) .nextDouble(); } /** * * @param dimension * @param maxDiversity */ public void diversify(double[][] dimension, double maxDiversity) { for (int c = 0; c < this.gnpCoordinates.length; c++) { double rand = (2 * maxDiversity * Math.random()) - maxDiversity; gnpCoordinates[c] = gnpCoordinates[c] + (rand * dimension[c][2]); } error = -1.0; } /** * reposition * * @param pos * position in the coordinate array * @param value * new value at position pos */ public void setGnpCoordinates(int pos, double value) { gnpCoordinates[pos] = value; error = -1.0; } /** * * @return the related GnpSpace object */ private GnpSpace getGnpRef() { return gnpRef; } /** * * @return the related Host object */ public Host getHostRef() { return hostRef; } /** * * @return number of dimensions */ public int getNoOfDimensions() { return gnpCoordinates.length; } /** * * @param pos * position in the coordinate array * @return value at position pos */ public double getGnpCoordinates(int pos) { return gnpCoordinates[pos]; } /** * Calculates the sum of all errors according to the downhill simplex * operator. * * @return error */ public double getDownhillSimplexError() { if (error < 0.0) { error = 0.0; for (int c = 0; c < getGnpRef().getNumberOfMonitors(); c++) { error += getDownhillSimplexError(getGnpRef() .getMonitorPosition(c)); } } return error; } /** * Calculates the error to a monitor according to the downhill simplex * operator * * @param monitor * @return error */ public double getDownhillSimplexError(GnpPosition monitor) { double calculatedDistance = this.distanceTo(monitor); double measuredDistance = this.getMeasuredRtt(monitor); if (Double.compare(measuredDistance, Double.NaN) == 0) return 0.0; double error = Math.pow((calculatedDistance - measuredDistance) / calculatedDistance, 2); return error; } /** * Calculates an error, that indicates the deviation of the measured vs. the * calculated rtt. * * @param monitor * @return error value */ public double getDirectionalRelativError(GnpPosition monitor) { double calculatedDistance = this.distanceTo(monitor); double measuredDistance = this.getMeasuredRtt(monitor); if (Double.compare(measuredDistance, Double.NaN) == 0) return Double.NaN; double error = (calculatedDistance - measuredDistance) / Math.min(calculatedDistance, measuredDistance); return error; } /** * Method must be overwrite to sort different GnpPositions in order of their * quality. * * Is needed for the positioning with the downhill simplex * */ public int compareTo(GnpPosition arg0) { double val1 = this.getDownhillSimplexError(); double val2 = arg0.getDownhillSimplexError(); if (val1 < val2) return -1; if (val1 > val2) return 1; else return 0; } /** * * @return Comma-separated list of coordinates */ public String getCoordinateString() { if (gnpCoordinates.length == 0) { return ""; } else { String result = String.valueOf(gnpCoordinates[0]); for (int c = 1; c < gnpCoordinates.length; c++) result = result + "," + gnpCoordinates[c]; return result; } } /** * * @param monitor * @return measured rtt to monitor, nan if no rtt was measured */ public double getMeasuredRtt(GnpPosition monitor) { return this.getHostRef().getRtt(monitor.getHostRef()); } /** * @return euclidean distance */ public double getDistance(Location point) { GnpPosition coord = (GnpPosition) point; double distance = 0.0; for (int c = 0; c < gnpCoordinates.length; c++) distance += Math.pow( gnpCoordinates[c] - coord.getGnpCoordinates(c), 2); return Math.sqrt(distance); } @Override public int getTransmissionSize() { return 16; // 2 * double } /** * Static method generates a new GnpPosition according to the downhill * simplex operator * * @param solution * @param moveToSolution * @param moveFactor * @return new position */ public static GnpPosition getMovedSolution(GnpPosition solution, GnpPosition moveToSolution, double moveFactor) { GnpPosition returnValue = new GnpPosition(solution.getNoOfDimensions(), solution.getHostRef(), solution.getGnpRef()); for (int c = 0; c < solution.getNoOfDimensions(); c++) { double newCoord = (moveToSolution.getGnpCoordinates(c) - solution .getGnpCoordinates(c)) * moveFactor + solution.getGnpCoordinates(c); returnValue.setGnpCoordinates(c, newCoord); } return returnValue; } /** * Static method generates a new GnpPosition according to the downhill * simplex operator * * @param solution * @param moveToSolution * @param moveFactor * @return new position */ public static GnpPosition getCenterSolution(ArrayList solutions) { GnpPosition returnValue = new GnpPosition(solutions.get(0) .getNoOfDimensions(), solutions.get(0).getHostRef(), solutions .get(0).getGnpRef()); for (int d = 0; d < solutions.size(); d++) { for (int c = 0; c < solutions.get(0).getNoOfDimensions(); c++) { returnValue.setGnpCoordinates(c, returnValue .getGnpCoordinates(c) + solutions.get(d).getGnpCoordinates(c)); } } for (int c = 0; c < returnValue.getNoOfDimensions(); c++) { returnValue.setGnpCoordinates(c, returnValue.getGnpCoordinates(c) / solutions.size()); } return returnValue; } public GnpPosition clone() { return new GnpPosition(gnpCoordinates); } @Override public float bearingTo(Location dest) { throw new AssertionError( "bearingTo is not defined for this Position-Type"); } @Override public double distanceTo(Location dest) { return getDistance(dest); } @Override public long getAgeOfLocation() { throw new UnsupportedOperationException(); } @Override public double getLatitudeOrY() { throw new UnsupportedOperationException(); } @Override public double getLongitudeOrX() { throw new UnsupportedOperationException(); } @Override public void set(Location l) { throw new UnsupportedOperationException(); } }