public float shortestPath(Position source, Position target) throws IllegalArgumentException, IllegalStateException, PositionsNotConnectedException {
		// Check whether the Positions exist.
		if (!nodes.containsKey(source) || !nodes.containsKey(target)) {
			throw new IllegalArgumentException();
		}
		
		// Add a temporary starting Node.
		Node s = graph.addNode();
		for (Map.Entry<Vehicle, Node> entry : nodes.get(source).entrySet()) {
			Vehicle v = entry.getKey();
			Node n = entry.getValue();
			graph.addEdge(s, n, v.getCost());
		}
		
		// Add the temporary end Node.
		Map<Node, Edge> edges = new HashMap<Node, Edge>();
		Node t = graph.addNode();
		for (Node x : nodes.get(target).values()) {
			Edge e = graph.addEdge(x, t, 0);
			edges.put(x, e);
		}
		
		// Find the shortest path.
		Route route;
		try {
			route = graph.shortestPath(s, t);
		} catch (NodesNotConnectedException e) {
			throw new PositionsNotConnectedException();
		}
		
		// Remove the temporary end Nodes.
		for (Map.Entry<Node, Edge> entry : edges.entrySet()) {
		    entry.getKey().removeEdge(entry.getValue());
		}
		
		// Remove the temporary starting and end Nodes.
		List<Node> nodes = route.getNodes();
		nodes.remove(0);
		nodes.remove(nodes.size() - 1);
		
		// Save the route for future use.
		lastRoute = new ArrayList<Position>();
		for (Node n : nodes) {
			if (!(n.getData() instanceof Position)) {
				throw new IllegalStateException();
			}
			
			// Add the Position to the list. Invert, because the Route starts with the target.
			Position p = (Position)n.getData();
			lastRoute.add(0, p);
		}
		
		return route.getDistance();
	}