![JAR search and dependency download from the Maven repository](/logo.png)
de.tsl2.nano.vnet.routing.AbstractRoutingAStar Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tsl2.nano.vnet Show documentation
Show all versions of tsl2.nano.vnet Show documentation
TSL2 Framework VirtualNetwork (Generic parallelized Network-Mechanism providing implementations for: NeuronalNetwork, Routing, Workflow)
The newest version!
/*
* File: $HeadURL$
* Id : $Id$
*
* created by: Thomas Schneider, Thomas Schneider
* created on: Nov 25, 2012
*
* Copyright: (c) Thomas Schneider 2012, all rights reserved
*/
package de.tsl2.nano.vnet.routing;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Set;
import de.tsl2.nano.core.messaging.IListener;
import de.tsl2.nano.core.util.Util;
import de.tsl2.nano.structure.Cover;
import de.tsl2.nano.structure.IConnection;
import de.tsl2.nano.structure.INode;
import de.tsl2.nano.vnet.Connection;
import de.tsl2.nano.vnet.ILocatable;
import de.tsl2.nano.vnet.Link;
import de.tsl2.nano.vnet.Node;
import de.tsl2.nano.vnet.Notification;
/**
* Implementation of A*-Algorithm like http://de.wikipedia.org/wiki/A*-Algorithmus.
*
* Using the vnet with its {@link Node}s and {@link Connection}s, a new created route will have new created nodes with
* back-connections (weight is negative).
*
* to change the 'weight' behavior (e.g. to categorize specific roads) overwrite the {@link #g(Connection)} method.
*
* TODO: use ThreadingEventController to do parallel networking.
*
* @param type of {@link Node} content (=core)
* @param connection descriptor (on simple weighted connections, it would be Float)
* @author Thomas Schneider, Thomas Schneider
* @version $Revision$
*/
public abstract class AbstractRoutingAStar & ILocatable & Serializable & Comparable, D extends Comparable> {
/**
* this priority queue holds all connections to be inspected. the priority is defined by the calculated minimal
* distance to the destination. we use a weighted connection - a connection of a real node-connection to use the
* float-number as calculated distance.
*/
PriorityQueue, Float>> openlist = new PriorityQueue, Float>>();
/** closedlist - see description of {@link #openlist} */
Set> closedlist = new HashSet>();
/**
* route
*
* @param start
* @param destination
* @return
*/
public Connection route(Node start, Node destination) {
Connection currentConnection, route;
// Initialisierung der Open List, die Closed List ist noch leer
// (die Priorität bzw. der f Wert des Startknotens ist unerheblich)
log("starting at: " + start);
route = new Connection(start, null);
openlist.add(new Link, Float>(route, 0f));
// diese Schleife wird durchlaufen bis entweder
// - die optimale Lösung gefunden wurde oder
// - feststeht, dass keine Lösung existiert
do {
// Knoten mit dem geringsten f Wert aus der Open List entfernen
currentConnection = openlist.poll().getContent();
// Wurde das Ziel gefunden?
if (currentConnection.getDestination().equals(destination)) {
log("route finished: " + start + currentConnection);
return currentConnection;
}
// Wenn das Ziel noch nicht gefunden wurde: Nachfolgeknoten
// des aktuellen Knotens auf die Open List setzen
log("checking connection " + currentConnection);
expandNode(currentConnection, destination);
// der aktuelle Knoten ist nun abschließend untersucht
closedlist.add(currentConnection);
} while (!openlist.isEmpty());
// die Open List ist leer, es existiert kein Pfad zum Ziel
return null;
}
/**
*
* überprüft alle Nachfolgeknoten und fügt sie der Open List hinzu, wenn entweder
* - expandNode
* - der Nachfolgeknoten zum ersten Mal gefunden wird oder
* - ein besserer Weg zu diesem Knoten gefunden wird
*
*
* @param currentNode node to evaluate
* @param destination
*/
void expandNode(Connection currentConnection, Node destination) {
// distance f
float f, g, tentative_g;
List> nextConnections =
(List>) Util.untyped(currentConnection.getDestination().getConnections());
Node successor;
for (Connection con : nextConnections) {
successor = con.getDestination();
log_("\t--> " + successor);
// wenn der Nachfolgeknoten bereits auf der Closed List ist - tue nichts
if (closedlist.contains(con)) {
continue;
}
// g Wert für den neuen Weg berechnen: g Wert des Vorgängers plus
// die Kosten der gerade benutzten Kante
g = g(con);
tentative_g = g(currentConnection) + g;
log_("\t g + c = " + tentative_g);
// wenn der Nachfolgeknoten bereits auf der Open List ist,
// aber der neue Weg nicht besser ist als der alte - tue nichts
if (openlist.contains(new Link(con, g)) && tentative_g >= g) {
continue;
}
// Vorgängerzeiger setzen und g Wert merken
// f Wert des Knotens in der Open List aktualisieren
// bzw. Knoten mit f Wert in die Open List einfügen
f = tentative_g + h(successor, destination);
log("\t f = " + f);
// if (openlist.contains(successor)) {
// openlist.decreaseKey(successor, f);
// } else {
// openlist.add(successor, f);
// }
Connection next = connect(currentConnection.getDestination(), con.getDestination(), tentative_g);
Link, Float> weightedConnection = new Link, Float>(next, f);
// openlist.remove(weightedConnection);
openlist.add(weightedConnection);
}
}
public Collection> navigate(INode start,
IConnection route,
List> currentTrack) {
if (currentTrack == null) {
currentTrack = new LinkedList>();
}
currentTrack.add(route);
List> connections = route.getDestination().getConnections();
//filter the backward connections
IConnection c = null, con;
for (Iterator> iterator = connections.iterator(); iterator.hasNext();) {
con = iterator.next();
if (isTrack(con)) {
c = con;
removeTrackMarker(c);
break;
}
}
if (c == null) {
Collections.reverse(currentTrack);
return currentTrack;
}
return navigate(route.getDestination(), c, currentTrack);
}
/** to identify a track */
protected abstract boolean isTrack(IConnection con);
/** remove the track marker. see {@link #getTrackMarker()}. optional, may do nothing.... */
protected abstract void removeTrackMarker(IConnection connection);
/**
* successor.connectTo(currentNode, -tentative_g);
*
* @param successor
* @param currentNode
* @param f
*/
protected abstract Connection connect(Node successor, Node currentNode, float f);
/**
* direct distance to destination
*
* @param successor current evaluation node
* @param destination destination
* @return distance
*/
protected float h(Node successor, Node destination) {
return successor.compareTo(destination);
}
/**
* edge length (weight) of given connection
*
* @param con connection
* @return connection length
*/
protected float g(Connection con) {
return con.length();
}
protected void log_(String msg) {
System.out.print(msg);
}
protected void log(String msg) {
System.out.println(msg);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy