Skip to content

Instantly share code, notes, and snippets.

@TomTasche
Last active December 17, 2015 02:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TomTasche/5534850 to your computer and use it in GitHub Desktop.
Save TomTasche/5534850 to your computer and use it in GitHub Desktop.
EinStern is a mixture of routing algorithms like depth-first and dijkstra. it is able to find a path between "things" - points without any distance or similar between each other. Blog post about it: http://blog.tomtasche.at/2013/05/routing-things-and-stuff.html
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* some kind of depth-first and dijkstra mixture. this little code snippet is
* able to find a path between "things" - points without any distance or similar
* between each other
*
* @author Thomas Taschauer
*
*/
public abstract class EinStern {
/**
* @return all the Things which should be considered for routing
*/
public abstract Thing[] getAllTheThings();
/**
* @return the Thing we want to start routing from
*/
public abstract Thing getStart();
/**
* @return the Thing we want to route to
*/
public abstract Thing getDestination();
/*
* maps the names of a thing to its connected Things.
*/
private Map<String, List<Thing>> graph;
/*
* prevents endless-loops by remembering all previously visited / inspected
* / "closed" Things. we won't inspect closed Things a second time.
*/
private List<String> closedThings;
/*
* holds the shortest path currently known to the algorithm. whenever we
* find a shorter one we replace this with the shorter one.
*/
private List<Thing> currentShortestKnownPath;
public EinStern() {
buildGraph();
Thing fromThing = getStart();
Thing toThing = getDestination();
closedThings = new LinkedList<String>();
currentShortestKnownPath = new LinkedList<Thing>();
// remembers the path we were "walking" so far. if we get stuck, we go
// back step by step until there is a new possible path to walk on
List<Thing> currentPath = new LinkedList<Thing>();
discover(currentPath, fromThing.getName(), toThing.getName());
// this is the path you're looking for. congratulations!
List<Thing> shortestPath = currentShortestKnownPath;
System.out.println("shortest path takes " + shortestPath.size()
+ " hops");
}
private void buildGraph() {
Thing[] things = getAllTheThings();
graph = new HashMap<String, List<Thing>>();
for (Thing thing : things) {
String name = thing.getName();
List<Thing> connectedThings = graph.get(name);
if (connectedThings == null) {
connectedThings = new LinkedList<Thing>();
graph.put(name, connectedThings);
}
connectedThings.add(thing);
}
// now you can get all the Things connected to a Thing only by its name
}
private void discover(List<Thing> currentPath, String fromThing,
String toThing) {
// we're now inspecting this Thing, so we close it because we don't want
// to inspect it another time later on
closedThings.add(fromThing);
List<Thing> things = graph.get(fromThing);
for (Thing thing : things) {
String toDevice = thing.getName();
if (toThing.equals(toDevice)) {
currentPath.add(thing);
System.out.println("found path with " + currentPath.size()
+ " hops");
if (currentShortestKnownPath.isEmpty()
|| currentPath.size() < currentShortestKnownPath.size()) {
currentShortestKnownPath.clear();
currentShortestKnownPath.addAll(currentPath);
}
} else {
String newFrom = thing.getName();
if (!closedThings.contains(newFrom)) {
currentPath.add(thing);
discover(currentPath, newFrom, toThing);
currentPath.remove(thing);
}
}
}
}
/**
* this is by far not the best object for representing a point in a graph,
* but it's approximately what i had to deal with when creating this. using
* this class there can be multiple instances of the class representing just
* a single Thing (one instance represents the Thing and the connection to
* Thing-A, another instance might represent the same Thing but the
* connection to Thing-B, etc).
*
* if you can, you should use a class which is able to represent a Thing and
* *all* its connections to other Things. this would save you from the
* buildGraph()-method too.
*
*/
public class Thing {
String name;
Thing connectedTo;
public String getName() {
return name;
}
public Thing getConnectedTo() {
return connectedTo;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment