Related
I am working on an implementation of Dijkstra's Algorithm to retrieve the shortest path between interconnected nodes on a network of routes. I have the implementation working. It returns all the shortest paths to all the nodes when I pass the start node into the algorithm.
My question:
How does one go about retrieving all possible paths from Node A to, say, Node G or even all possible paths from Node A and back to Node A?
Finding all possible paths is a hard problem, since there are exponential number of simple paths. Even finding the kth shortest path [or longest path] are NP-Hard.
One possible solution to find all paths [or all paths up to a certain length] from s to t is BFS, without keeping a visited set, or for the weighted version - you might want to use uniform cost search
Note that also in every graph which has cycles [it is not a DAG] there might be infinite number of paths between s to t.
I've implemented a version where it basically finds all possible paths from one node to the other, but it doesn't count any possible 'cycles' (the graph I'm using is cyclical). So basically, no one node will appear twice within the same path. And if the graph were acyclical, then I suppose you could say it seems to find all the possible paths between the two nodes. It seems to be working just fine, and for my graph size of ~150, it runs almost instantly on my machine, though I'm sure the running time must be something like exponential and so it'll start to get slow quickly as the graph gets bigger.
Here is some Java code that demonstrates what I'd implemented. I'm sure there must be more efficient or elegant ways to do it as well.
Stack connectionPath = new Stack();
List<Stack> connectionPaths = new ArrayList<>();
// Push to connectionsPath the object that would be passed as the parameter 'node' into the method below
void findAllPaths(Object node, Object targetNode) {
for (Object nextNode : nextNodes(node)) {
if (nextNode.equals(targetNode)) {
Stack temp = new Stack();
for (Object node1 : connectionPath)
temp.add(node1);
connectionPaths.add(temp);
} else if (!connectionPath.contains(nextNode)) {
connectionPath.push(nextNode);
findAllPaths(nextNode, targetNode);
connectionPath.pop();
}
}
}
I'm gonna give you a (somewhat small) version (although comprehensible, I think) of a scientific proof that you cannot do this under a feasible amount of time.
What I'm gonna prove is that the time complexity to enumerate all simple paths between two selected and distinct nodes (say, s and t) in an arbitrary graph G is not polynomial. Notice that, as we only care about the amount of paths between these nodes, the edge costs are unimportant.
Sure that, if the graph has some well selected properties, this can be easy. I'm considering the general case though.
Suppose that we have a polynomial algorithm that lists all simple paths between s and t.
If G is connected, the list is nonempty. If G is not and s and t are in different components, it's really easy to list all paths between them, because there are none! If they are in the same component, we can pretend that the whole graph consists only of that component. So let's assume G is indeed connected.
The number of listed paths must then be polynomial, otherwise the algorithm couldn't return me them all. If it enumerates all of them, it must give me the longest one, so it is in there. Having the list of paths, a simple procedure may be applied to point me which is this longest path.
We can show (although I can't think of a cohesive way to say it) that this longest path has to traverse all vertices of G. Thus, we have just found a Hamiltonian Path with a polynomial procedure! But this is a well known NP-hard problem.
We can then conclude that this polynomial algorithm we thought we had is very unlikely to exist, unless P = NP.
The following functions (modified BFS with a recursive path-finding function between two nodes) will do the job for an acyclic graph:
from collections import defaultdict
# modified BFS
def find_all_parents(G, s):
Q = [s]
parents = defaultdict(set)
while len(Q) != 0:
v = Q[0]
Q.pop(0)
for w in G.get(v, []):
parents[w].add(v)
Q.append(w)
return parents
# recursive path-finding function (assumes that there exists a path in G from a to b)
def find_all_paths(parents, a, b):
return [a] if a == b else [y + b for x in list(parents[b]) for y in find_all_paths(parents, a, x)]
For example, with the following graph (DAG) G given by
G = {'A':['B','C'], 'B':['D'], 'C':['D', 'F'], 'D':['E', 'F'], 'E':['F']}
if we want to find all paths between the nodes 'A' and 'F' (using the above-defined functions as find_all_paths(find_all_parents(G, 'A'), 'A', 'F')), it will return the following paths:
Here is an algorithm finding and printing all paths from s to t using modification of DFS. Also dynamic programming can be used to find the count of all possible paths. The pseudo code will look like this:
AllPaths(G(V,E),s,t)
C[1...n] //array of integers for storing path count from 's' to i
TopologicallySort(G(V,E)) //here suppose 's' is at i0 and 't' is at i1 index
for i<-0 to n
if i<i0
C[i]<-0 //there is no path from vertex ordered on the left from 's' after the topological sort
if i==i0
C[i]<-1
for j<-0 to Adj(i)
C[i]<- C[i]+C[j]
return C[i1]
If you actually care about ordering your paths from shortest path to longest path then it would be far better to use a modified A* or Dijkstra Algorithm. With a slight modification the algorithm will return as many of the possible paths as you want in order of shortest path first. So if what you really want are all possible paths ordered from shortest to longest then this is the way to go.
If you want an A* based implementation capable of returning all paths ordered from the shortest to the longest, the following will accomplish that. It has several advantages. First off it is efficient at sorting from shortest to longest. Also it computes each additional path only when needed, so if you stop early because you dont need every single path you save some processing time. It also reuses data for subsequent paths each time it calculates the next path so it is more efficient. Finally if you find some desired path you can abort early saving some computation time. Overall this should be the most efficient algorithm if you care about sorting by path length.
import java.util.*;
public class AstarSearch {
private final Map<Integer, Set<Neighbor>> adjacency;
private final int destination;
private final NavigableSet<Step> pending = new TreeSet<>();
public AstarSearch(Map<Integer, Set<Neighbor>> adjacency, int source, int destination) {
this.adjacency = adjacency;
this.destination = destination;
this.pending.add(new Step(source, null, 0));
}
public List<Integer> nextShortestPath() {
Step current = this.pending.pollFirst();
while( current != null) {
if( current.getId() == this.destination )
return current.generatePath();
for (Neighbor neighbor : this.adjacency.get(current.id)) {
if(!current.seen(neighbor.getId())) {
final Step nextStep = new Step(neighbor.getId(), current, current.cost + neighbor.cost + predictCost(neighbor.id, this.destination));
this.pending.add(nextStep);
}
}
current = this.pending.pollFirst();
}
return null;
}
protected int predictCost(int source, int destination) {
return 0; //Behaves identical to Dijkstra's algorithm, override to make it A*
}
private static class Step implements Comparable<Step> {
final int id;
final Step parent;
final int cost;
public Step(int id, Step parent, int cost) {
this.id = id;
this.parent = parent;
this.cost = cost;
}
public int getId() {
return id;
}
public Step getParent() {
return parent;
}
public int getCost() {
return cost;
}
public boolean seen(int node) {
if(this.id == node)
return true;
else if(parent == null)
return false;
else
return this.parent.seen(node);
}
public List<Integer> generatePath() {
final List<Integer> path;
if(this.parent != null)
path = this.parent.generatePath();
else
path = new ArrayList<>();
path.add(this.id);
return path;
}
#Override
public int compareTo(Step step) {
if(step == null)
return 1;
if( this.cost != step.cost)
return Integer.compare(this.cost, step.cost);
if( this.id != step.id )
return Integer.compare(this.id, step.id);
if( this.parent != null )
this.parent.compareTo(step.parent);
if(step.parent == null)
return 0;
return -1;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Step step = (Step) o;
return id == step.id &&
cost == step.cost &&
Objects.equals(parent, step.parent);
}
#Override
public int hashCode() {
return Objects.hash(id, parent, cost);
}
}
/*******************************************************
* Everything below here just sets up your adjacency *
* It will just be helpful for you to be able to test *
* It isnt part of the actual A* search algorithm *
********************************************************/
private static class Neighbor {
final int id;
final int cost;
public Neighbor(int id, int cost) {
this.id = id;
this.cost = cost;
}
public int getId() {
return id;
}
public int getCost() {
return cost;
}
}
public static void main(String[] args) {
final Map<Integer, Set<Neighbor>> adjacency = createAdjacency();
final AstarSearch search = new AstarSearch(adjacency, 1, 4);
System.out.println("printing all paths from shortest to longest...");
List<Integer> path = search.nextShortestPath();
while(path != null) {
System.out.println(path);
path = search.nextShortestPath();
}
}
private static Map<Integer, Set<Neighbor>> createAdjacency() {
final Map<Integer, Set<Neighbor>> adjacency = new HashMap<>();
//This sets up the adjacencies. In this case all adjacencies have a cost of 1, but they dont need to.
addAdjacency(adjacency, 1,2,1,5,1); //{1 | 2,5}
addAdjacency(adjacency, 2,1,1,3,1,4,1,5,1); //{2 | 1,3,4,5}
addAdjacency(adjacency, 3,2,1,5,1); //{3 | 2,5}
addAdjacency(adjacency, 4,2,1); //{4 | 2}
addAdjacency(adjacency, 5,1,1,2,1,3,1); //{5 | 1,2,3}
return Collections.unmodifiableMap(adjacency);
}
private static void addAdjacency(Map<Integer, Set<Neighbor>> adjacency, int source, Integer... dests) {
if( dests.length % 2 != 0)
throw new IllegalArgumentException("dests must have an equal number of arguments, each pair is the id and cost for that traversal");
final Set<Neighbor> destinations = new HashSet<>();
for(int i = 0; i < dests.length; i+=2)
destinations.add(new Neighbor(dests[i], dests[i+1]));
adjacency.put(source, Collections.unmodifiableSet(destinations));
}
}
The output from the above code is the following:
[1, 2, 4]
[1, 5, 2, 4]
[1, 5, 3, 2, 4]
Notice that each time you call nextShortestPath() it generates the next shortest path for you on demand. It only calculates the extra steps needed and doesnt traverse any old paths twice. Moreover if you decide you dont need all the paths and end execution early you've saved yourself considerable computation time. You only compute up to the number of paths you need and no more.
Finally it should be noted that the A* and Dijkstra algorithms do have some minor limitations, though I dont think it would effect you. Namely it will not work right on a graph that has negative weights.
Here is a link to JDoodle where you can run the code yourself in the browser and see it working. You can also change around the graph to show it works on other graphs as well: http://jdoodle.com/a/ukx
find_paths[s, t, d, k]
This question is now a bit old... but I'll throw my hat into the ring.
I personally find an algorithm of the form find_paths[s, t, d, k] useful, where:
s is the starting node
t is the target node
d is the maximum depth to search
k is the number of paths to find
Using your programming language's form of infinity for d and k will give you all paths§.
§ obviously if you are using a directed graph and you want all undirected paths between s and t you will have to run this both ways:
find_paths[s, t, d, k] <join> find_paths[t, s, d, k]
Helper Function
I personally like recursion, although it can difficult some times, anyway first lets define our helper function:
def find_paths_recursion(graph, current, goal, current_depth, max_depth, num_paths, current_path, paths_found)
current_path.append(current)
if current_depth > max_depth:
return
if current == goal:
if len(paths_found) <= number_of_paths_to_find:
paths_found.append(copy(current_path))
current_path.pop()
return
else:
for successor in graph[current]:
self.find_paths_recursion(graph, successor, goal, current_depth + 1, max_depth, num_paths, current_path, paths_found)
current_path.pop()
Main Function
With that out of the way, the core function is trivial:
def find_paths[s, t, d, k]:
paths_found = [] # PASSING THIS BY REFERENCE
find_paths_recursion(s, t, 0, d, k, [], paths_found)
First, lets notice a few thing:
the above pseudo-code is a mash-up of languages - but most strongly resembling python (since I was just coding in it). A strict copy-paste will not work.
[] is an uninitialized list, replace this with the equivalent for your programming language of choice
paths_found is passed by reference. It is clear that the recursion function doesn't return anything. Handle this appropriately.
here graph is assuming some form of hashed structure. There are a plethora of ways to implement a graph. Either way, graph[vertex] gets you a list of adjacent vertices in a directed graph - adjust accordingly.
this assumes you have pre-processed to remove "buckles" (self-loops), cycles and multi-edges
You usually don't want to, because there is an exponential number of them in nontrivial graphs; if you really want to get all (simple) paths, or all (simple) cycles, you just find one (by walking the graph), then backtrack to another.
I think what you want is some form of the Ford–Fulkerson algorithm which is based on BFS. Its used to calculate the max flow of a network, by finding all augmenting paths between two nodes.
http://en.wikipedia.org/wiki/Ford%E2%80%93Fulkerson_algorithm
There's a nice article which may answer your question /only it prints the paths instead of collecting them/.
Please note that you can experiment with the C++/Python samples in the online IDE.
http://www.geeksforgeeks.org/find-paths-given-source-destination/
I suppose you want to find 'simple' paths (a path is simple if no node appears in it more than once, except maybe the 1st and the last one).
Since the problem is NP-hard, you might want to do a variant of depth-first search.
Basically, generate all possible paths from A and check whether they end up in G.
In my case, I want to create a binary tree by taking the depth as the input.
For example, if I do tree.create(3), there will generate a binary tree when the depth of the deepest left is three, which means there will be 2^3 - 1 nodes in the tree and the value of all of them will be 0. The index will be 0 - 6 accorndingly.
class Tree<T> {
int depth;
int index;
T value;
public Tree(int index,T value) {
this.index = index;
this.value = value;
}
public static <K> Tree<K> create(int depth){
if(depth >= 1) {
//return a tree with the inputting depth,
//but I don't know how to do in this step
return new Tree(...?)
}
}
}
Which part of knowledge shall I use to achieve this in Java? Thanks!
Usually when working with a binary tree data structure you need to write recursive methods. When writing a recursive method, you need to write a condition that terminates the recursion. In your case, the recursion will end if we have reached the desired depth. In order to determine if we have reached the desired depth, we need to know what that desired depth is and what the current depth is. I will assume that the depth of the root node in the binary tree is zero. This means that for a maximum depth of 3 (as in the example in your question), the deepest level will be level 2. If we have not reached the desired depth, then I need to add a left and a right child node and then call the same method on each of those children and make sure that the depth of the child nodes is one greater than the depth of the parent. So my recursive method needs three parameters:
a node to (possibly) add child nodes to
the current depth
the maximum depth
Note that I don't need to handle the value (or data) that each node contains because you state, in your question, that each node will have the same value. Hence I can simply copy the value from the parent node to each of its children.
Here is a complete example. Note that when I tested it, a depth greater than 25 causes an OutOfMemoryError because there is a limit on how many recursive method invocations can be done.
import java.util.ArrayList;
import java.util.List;
public class BinTree<T> {
BinTreeNode<T> root;
public static <T> BinTree<T> create(int depth, T val) {
if (depth > 0) {
BinTree<T> theTree = new BinTree<>();
theTree.root = new BinTreeNode<>(val);
theTree.addLevel(theTree.root, 0, depth);
return theTree;
}
else {
throw new IllegalArgumentException("Invalid depth: " + depth);
}
}
public void getAllElements(BinTreeNode<T> aNode, List<T> list) {
if (aNode == null) {
return;
}
else {
getAllElements(aNode.left, list);
list.add(aNode.genericObject);
getAllElements(aNode.right, list);
}
}
private void addLevel(BinTreeNode<T> theNode, int level, int deepest) {
if (level == deepest - 1) {
return;
}
theNode.left = new BinTreeNode<>(theNode.genericObject);
theNode.right = new BinTreeNode<>(theNode.genericObject);
addLevel(theNode.left, level + 1, deepest);
addLevel(theNode.right, level + 1, deepest);
}
public static void main(String[] args) {
BinTree<String> aTree = BinTree.create(3, "George"); // max depth = 25
List<String> list = new ArrayList<>();
aTree.getAllElements(aTree.root, list);
System.out.println(list.size());
}
}
class BinTreeNode<T> {
BinTreeNode<T> left, right;
T genericObject;
public BinTreeNode(T obj) {
genericObject = obj;
}
}
Note that I added method getAllElements as a test to see whether the correct number of nodes were created.
This information is related to what type of tree. In other words, you should recognize that this information The peak of the pyramid(Max Heap), or binary search tree or a combination of both or none of them do not.
Input format is as follows:
(94,RR) (17,L) (36,RL) (51,R) (20,) (76,RRR) ()
Input format each node in the tree for a given pair. The first value represents the amount of Node and the second value represents the root path that must be navigated to get to this node. Node Has no way represents the root of the tree. With this information you should be able to type Identify the tree.
For example, the tree is as follows:
(94,RR) (17,L) (36,RL) (51,R) (20,) (76,RRR) ()
tree for this string
this tree is not a maximum pyramid(max Heap),not a binary search tree and not a combination of there.
Entrance :
At the entrance you get a string that information is relevant to a tree. Each tree
With the statement (s) end. Entry Exit program ends.
Output:
You are one of the following phrases in your printed output.
1.BST: If the input tree is a binary search tree.
2.MaxHeap: If the tree is the maximum pyramid entrance.
3.BST MaxHeap: If the combined input of binary search tree and the pyramid is the maximum.
4.Nothing: If there is none of the above.
**Sample Input:**
(94,RR) (17,L) (36,RL) (51,R) (20,) (76,RRR) ()
(94,) (59,LL) (61,RR) (53,LR) (79,L) (77,R) (15,RL) ()
(72,) (44,LR) (15,L) (2,LL) ()
Exit
**Sample Output:**
Nothing
MaxHeap
BST
Now I cant implementation tree for this question.please help.
Thank you.
Let us represent your data in an array. We can construct a binary tree from that array by using the formula 2*i for the left child of node i and 2*i+1 for the right child of node i. I am also assuming you have your own basic BST ready.
1. How to determine if the given tree is a BST: Sort the input by the size of the String representing the positions of the tree. Your data can be stored in a class called Pair which stores an integer representing the value and a string representing the position relative to the root. We can then sort it. Here's how you can implement the class and the array which stores it:
class Pair
{
int val;
String pos;
Pair(int val, String pos)
{
this.val=val;
this.pos=pos;
}
}
Now in the main method or wherever, you can start building your tree array
int n;
//Take n which is number of nodes here
Pair[] input=new Pair[n];
for(int i=0;i<n;i++)
{
input[i]=new Pair(*input value*, *input Position*);
}
Arrays.sort(input, new Comparator<Book>() //Sorts by the distance from start node
{
#Override
public int compare(Pair p1, Pair p2)
{
return p1.pos.length()-p2.pos.length();
}
});
Now, simply create a recursive method in your BST called Insert(Node curr, int value, String where, int tillWhere)'. I am assuming again, that your BST has aNode` class which stores the data, as well as left and right child references.
class Node //The node for the BSt should look something like this
{
Node left, right;
int data;
Node(Node left, Node right, int data)
{
this.left=left;
this.right=right;
this.data=data;
}
}
<br>
//Method for inserting into the BST
void Insert(Node curr, int value, String where, int tillWhere)
{
if(curr==null)
curr=new Node(value);
else
{
if(where.charAt(tillWhere)=='L')
Insert(curr.left, value, where, tillWhere+1);
else
Insert(curr.right, value, where, tillWhere+1);
}
}
Now, simply perform an In-order traversal of the BST and store the results in the array Inorder. After that if the data is in sorted order, It will be a BST.
ArrayList<Integer> inOrder=new ArrayList<Integer>();
//Method
void Inorder(Node curr)
{
if(curr!=null)
{
if(curr.left!=null)
Inorder(curr.left);
inOrder.add(curr.data); //Appending to list
if(curr.right!=null)
Inorder(curr.right);
}
}
//Now after method call:
boolean isBST(ArrayList<Integer> inOrder)
{
for(int i=1;i<=inOrder.size();i++)
if(inOrder.get(i)<inOrder.get(i-1)) //Not possible in BST
return false;
return true
}
How to determine if given tree is a Heap: Simply satisfy the property that the parent is >= it's children. We can write a simple recursive solution for that like this:
boolean isHeap(int[] arr, int i, int n)// array storing the tree, initial postion , size
{
if (i > (n - 2)/2) //Root
return true;
// If an internal node and is greater than its children, and
// same is recursively true for the children
if (arr[i] >= arr[2*i + 1] && arr[i] >= arr[2*i + 2] &&
isHeap(arr, 2*i + 1, n) && isHeap(arr, 2*i + 2, n))
return true;
return false;
}
You can work out all the 4 conditions in your question from the data I have given you above. I hope this helped!
I am currently working on an implementation of the A* Algorithm with irregular distances between two nodes. The graph containing the nodes is a directed and weighted graph. Every node is connected to at least one other node, there may also be symmetrical connections with different distances. A node is nothing more than a label and doesn't contain any special information
What I need is a heuristic to determine the shortest path from any node A to another node B as accurate as possible. I tried to use a heuristic that returns the distance to the nearest neighbor of a node, but of course that wasn't as effective as no heuristic at all (= Dijkstra).
My implementation of the A* Algorithm consists mainly of 2 classes, the class for the algorithm itself (AStar) and one for the nodes (Node). The code is heavily based on the Wikipedia pseudocode.
Source code of AStar.java
public class AStar {
private AStar() {}
private static Node[] reconstructPath(Map<Node, Node> paths, Node current) {
List<Node> path = new ArrayList<Node>();
path.add(0, current);
while (paths.containsKey(current)) {
current = paths.get(current);
path.add(0, current);
}
return path.toArray(new Node[0]);
}
public static Node[] calculate(Node start, Node target, IHeuristic heuristic) {
List<Node> closed = new ArrayList<Node>();
PriorityQueue<Node> open = new PriorityQueue<Node>();
Map<Node, Double> g_score = new HashMap<Node, Double>();
Map<Node, Double> f_score = new HashMap<Node, Double>();
Map<Node, Node> paths = new HashMap<Node, Node>();
g_score.put(start, 0d);
f_score.put(start, g_score.get(start) + heuristic.estimateDistance(start, target));
open.set(start, f_score.get(start));
while (!open.isEmpty()) {
Node current = null;
// find the node with lowest f_score value
double min_f_score = Double.POSITIVE_INFINITY;
for (Entry<Node, Double> entry : f_score.entrySet()) {
if (!closed.contains(entry.getKey()) && entry.getValue() < min_f_score) {
min_f_score = entry.getValue();
current = entry.getKey();
}
}
if (current.equals(target)) return reconstructPath(paths, target);
open.remove(current);
closed.add(current);
for (Node neighbor : current.getAdjacentNodes()) {
if (closed.contains(neighbor)) {
continue;
}
double tentative_g_score = g_score.get(current) + current.getDistance(neighbor);
if (!open.contains(neighbor) || tentative_g_score < g_score.get(neighbor)) {
paths.put(neighbor, current);
g_score.put(neighbor, tentative_g_score);
f_score.put(neighbor, g_score.get(neighbor) + heuristic.estimateDistance(neighbor, target));
if (!open.contains(neighbor)) {
open.set(neighbor, f_score.get(neighbor));
}
}
}
}
throw new RuntimeException("no path between " + start + " and " + target);
}
}
Source code of Node.java
public class Node {
private Map<Node, Double> distances = new HashMap<Node, Double>();
public final String name;
public Node(String name) {
this.name = name;
}
public Set<Node> getAdjacentNodes() {
return Collections.unmodifiableSet(distances.keySet());
}
public double getDistance(Node node) {
return distances.get(node);
}
public void setDistance(Node node, double distance) {
distances.put(node, distance);
}
#Override
public String toString() {
return (name == null ? "Node#" + Integer.toHexString(hashCode()) : name);
}
}
Source code of PriorityQueue.java
public class PriorityQueue<T> {
transient ArrayList<PriorityEntry<T>> elements = null;
private static final int DEFAULT_SIZE = 10;
public PriorityQueue() {
elements = new ArrayList<PriorityEntry<T>>(DEFAULT_SIZE);
}
public PriorityQueue(int initialCapacity) {
elements = new ArrayList<PriorityEntry<T>>(initialCapacity);
}
public boolean push(T element, double priority) {
PriorityEntry<T> entry = new PriorityEntry<T>(element, priority);
if (elements.contains(entry)) return false;
elements.add(entry);
elements.sort(null);
return true;
}
public void set(T element, double priority) {
PriorityEntry<T> entry = new PriorityEntry<T>(element, priority);
int index = elements.indexOf(entry);
if (index >= 0) {
elements.get(index).setPriority(priority);
} else {
elements.add(entry);
}
elements.sort(null);
}
public T peek() {
return size() <= 0 ? null : elements.get(0).getValue();
}
public T pop() {
return size() <= 0 ? null : elements.remove(0).getValue();
}
public boolean remove(T element) {
return elements.remove(new PriorityEntry<T>(element, 0));
}
public int size() {
return elements.size();
}
public boolean isEmpty() {
return elements.isEmpty();
}
public boolean contains(T element) {
return elements.contains(new PriorityEntry<T>(element, 0));
}
private class PriorityEntry<E> implements Comparable<PriorityEntry<? extends T>> {
private final E value;
private double priority = Double.MIN_VALUE;
public PriorityEntry(E value, double priority) {
this.value = value;
this.priority = priority;
}
public E getValue() {
return value;
}
public double getPriority() {
return priority;
}
public void setPriority(double priority) {
this.priority = priority;
}
#Override
#SuppressWarnings("unchecked")
public boolean equals(Object o) {
if (!(o instanceof PriorityEntry)) return false;
PriorityEntry<?> entry = (PriorityEntry<?>) o;
return value.equals(entry);
}
#Override
public int compareTo(PriorityEntry<? extends T> entry) {
return (int) (getPriority() - entry.getPriority());
}
}
}
Before trying to define a heuristic function for your problem, consider that in many cases, using a poor (or incorrect) estimation of the cost to the goal is as self-defeating as not using an heuristic at all.
In the case of a graph with weighted arcs, you need to consider if there is some information in the nodes which can lead to obtain the heuristic values (for example, if your nodes are cities, a good estimation can be the lenght of the straight line between them; or if your nodes are arrays, a similarity measurement between them). If your nodes are only labels and there is no information that you can use to obtain your heuristic values, maybe the best solution is not using a heuristic at all. This is not the worst scenario for most problems of this type. It is better to use a Dijkstra search (which is the same of A* but using heuristic=0), letting the algorithm expand the nodes based on the cost from the start, than using a bad heuristic which is not consistent, because in this situation you might be expanding unncecesary nodes that seem to be promising based on a bad estimation of the cost to the goal.
I don't know how big are your graphs, but for most problems there is not a significant difference in computation time between using a heuristic and don't using it at all. Specially in the case of a bad heuristic.
I can see that you have your own implementation of A*. I recommend you to take a look of an heuristic search library like Hipster. This library allows you to define your graph and test different search algorithms to know the best one that fits your problem. Some code examples describe exactly your case: seach in weighted directed graphs. It might be useful for your problem.
I hope my answer helps. Regards,
Without going into other possible problems I would like to point out the main problem - you lack the plane. In case of shortest distance problem between cities, you have
node - city
weight - numerical value describing cost to get from city a to city b
plane - describes environment ex: city position (in your square grid)
From plane you can extrapolate meaningful heuristic. For example you can make assumption from city position like city with lowest arithmetical distance should be looked first.
If you do not have a plane you do not have any means to predict a meaningful heuristic. A* will still work, but it hardly differs from exhaustive search. You can create plane from the weight, but it .
Ex:
Iterate over weights and find the weight quantiles 20/60/20 - now you have a relative plane
- good weight threshold (lowest 20%)
- average weight threshold (middle 60%)
- bad weight threshold (highest 20%)
With priority queue your algorithm would pick good moves, then average and finally bad ones.
If you want you can have more then 3 segments.
Just as a reminder: A* returns good enough result fast. Using exhaustive search you can find the best solution, but it would become exponentially slower if problem size grows.
To add to #kiheru comment above. Your solution will only be as good as the heuristic provided.
If the following line and the heuristic.estimate, has too narrow of a scope. The algorithm will quickly reach a local minimum. Alternatively, if the heuristic isn't admissible the algorithm will result in either no solution or an incorrect random solution.
f_score.put(start, g_score.get(start) + heuristic.estimateDistance(start, target));
Take a close look at your heuristic and confirm it's admissible. If it is admissible, it may need to be improved in order to provide a more accurate estimate.
In the case of your node class it seems to have an X and Y if these represent the node's position in a 2D space maybe you could use a heuristic based on the straight line distance between the nodes calculated from the X and Y values.
I am trying to build a graph based on a linked list, where I build the linked list of nodes, and each node points to a linked list of edges. I build the graph based on an input file.
My input file will be on the following scheme:
Number of Nodes in graph
SourceNode1 EndNode1
SourceNode2 EndNode2
....
For example:
4 //Number of nodes
1 2 //An edge between 1 and 2
1 3 //An edge between 1 and 3
2 4 //An edge between 2 and 4
An assumption is that the nodes in the graph will numbered 1 through the number of nodes and that no node will have more than 1 "parent" (though a node might have more than 1 "child").
My problem is trying to build the linked list containing the nodes. Each node has 3 fields: the edges coming from that node, the node value (1, 2, 3, etc.), and the next node (because is a linked list of nodes). I attempt to parse in the number of nodes, create a first node manually, and attach the rest of the nodes in an in an iterative fashion.
Note: The parent field is for some external analysis unrelated to this question. You can ignore it.
Node class:
public class Node {
private Edge firstEdge;
private Node parent;
private Node nextNode;
private int element;
//Constructor
public Node() {
parent = null;
firstEdge = null;
nextNode = null;
}
//Accsessor and Modifier Methods
public void setElement(int e) {element = e;}
public Node getNextNode() {return nextNode;}
public Edge getFirstEdge() {return firstEdge;}
public void setFirstEdge(Edge a) {firstEdge = a;}
public void setNextNode(Node a) {nextNode = a;}
public int getElement() {return element;}
public Node getParent() {return parent;}
public void setParent(Node p) {parent = p;}
//Checks for a non-null parent
public boolean hasParent() { return parent == null; }
//checks iff node has next edge
public boolean hasFirstEdge() { return firstEdge == null; }
//checks if a node has a next node
public boolean hasNextNode() { return nextNode == null; }
}
Edge class:
public class Edge {
//Instance Variables
private Node nextNode;
private Edge nextEdge;
//Constructor
public Edge() {
nextNode = null;
nextEdge = null;
}
//Accsessor and Modifier Methods
public void setNextNode(Node a) {nextNode = a;}
public void setNextEdge(Edge a) {nextEdge = a;}
public Node getNextNode() {return nextNode;}
public Edge getNextEdge() {return nextEdge;}
public boolean hasNextEdge() {
return nextEdge == null;
}
}
Driver class:
import java.util.Scanner;
import java.io.*;
public class Driver {
public static void main(String[] args)throws FileNotFoundException{
//Get text file for building the graph
Scanner console = new Scanner(System.in);
System.out.print("Please enter the text file name: ");
String fileName = console.nextLine();
Scanner in = new Scanner(new File(fileName));
//in contains the file reading scanner
int numNodes = in.nextInt(); //first line of the text file
Node first = new Node(); //first is head of the list
first.setElement(1);
int i = 2; //counter
//Build the nodes list; I get problems in this loop
while (i <= numNodes) {
Node head = new Node(); //Tracker node
head = first; //head is the first node of the list
/*Loop to end of the list*/
while(head.hasNextNode()) {
//Null check; without it, I get NullPointerExceptions.
//If it is not needed, or there is a better way, please inform me.
if (head.getNextNode() == null) {
break;
}
head = head.getNextNode(); //get to the end of the ilst
}
//Next node to add
Node newNode = new Node();
newNode.setElement(i); //Because of the 1, 2, 3 nature of the graph
head.setNextNode(newNode); //Set the last element as the next node
i++;
}
//Manually check if graph is made (check if the nodes are linked correctly)
System.out.println("First elem (expect 1): " + first.getElement());
System.out.println("Second elem (expect 2): " + first.getNextNode().getElement()); //It prints 4 here for some reason
System.out.println("Third elem (expect 3): " + first.getNextNode().getNextNode().getElement()); //Getting a NullPointerException
System.out.println("Fourth elem (expect 4): " + first.getNextNode().getNextNode().getNextNode().getElement());
System.out.println("Expecting null: " + first.getNextNode().getNextNode().getNextNode().getNextNode().getElement());
}
When I'm checking if the graph is built, I get problems. I am manually checking it (for this small graph, its possible), and simply print out the first node and the value of the subsequent nodes. I am expecting 1, 2, 3, 4, and null (for the element past 4, because it does not exist). The first node is fine, it prints 1. Calling first.getNextNode().getElement() prints 4, for some odd reason. And calling the node after that gives a NullPointerException. Could someone help me solve this problem?
Note: I haven't added the edges yet. I am just trying to get the core of the linked list of nodes built.
This is my first post on stack overflow. I apologize if it is vague, ambigous, overly detailed, lacking in information, or is a duplicate question. I could not find the answer anywhere else. All input is welcome and appreciated.
Much of your naming is very confusing and is in serious need of clarifying refactorization. Edge's nextNode should be called destinationNode or something along those lines to make it clear you are dereferencing from an Edge object instead of from another Node.
Now, let's delve into the actual implementation.
Node head = new Node(); //Tracker node
head = first; //head is the first node of the list
What's going on here? It looks like you set your local variable head to be a brand new Node; that's great. Except the very next line, you discard it and set it to the value of your first variable.
Then you traverse all the way to the end of the list with a while loop, then create another new Node (this one you actually use). (Normally if you wanted to add something to the end of the list you should be utilizing a doubly linked list, or should at least have pointers to both the first and the last elements... i.e., first always stays the same, but when you add a new node you simply say newNode = new Node(); last.nextNode = newNode; last = newNode; and then configure the new element from there. The way you are doing it, it's taking O(N^2) time to construct a singly-linked list with N elements, hardly ideal.
I also have some preferential criticism about the construction of your minor classes... if you are allowing values to be freely get and set to any value with public setters and getters without taking any action whatsoever when they change, you get the exact same functionality from simply marking those fields public and doing away with the getters and setters entirely. If you have any plans to add more functionality in the future it's fine the way it is, but if they are just going to be dumb linked list elements whose actual uses are implemented elsewhere then you are better off treating the class more like a struct.
Here's a good way to build a singly-linked Node list the way you're looking to:
int numNodes = in.nextInt(); //first line of the text file
// sentinel value indicating the beginning of the list
Node header = new Node();
header.setElement(-1);
// last node in the list
Node last = first;
// this loop constructs a singly linked ring from the header
for (int i = 1; i <= numNodes; i++) {
Node newNode = new Node();
newNode.setElement(i);
newNode.setNextNode(header);
last.setNextNode(newNode);
last = newNode;
}
// do your debug outputs here
// for instance, this loop always outputs every node in the list:
for (Node n = header.getNextNode(); n != header; n = n.getNextNode()) {
System.out.println("Node " + n.getElement());
}
Note that the use of header as a sentinel value guarantees that for any Node that's already been built, getNextNode() will never return null.
Again, all this code can be made much more readable by making the fields in your Node and Edge classes public and scrapping the getters and setters. header.getNextNode().getNextNode().getNextNode() can become header.nextNode.nextNode.element and so forth.
Stage 2
Now that that's out of the way, we have the question of how useful this type of structure will actually be for your application. My biggest concern in looking at this is the fact that, when applying edges between nodes on your graph, you will need to access arbitrarily indexed Nodes to attach edges to them... and while every Node already knows what its element index is, getting the Nth node takes N steps because your entire set of nodes is in a linked list.
Remember, the main advantage of using a linked list is the ability to remove arbitrary elements in O(1) time as you step through the list. If you are only building a list and aren't going to ever remove anything from it, arrays are often faster -- especially if you ever need to access arbitrary elements.
What if you don't need to guarantee they're in any particular order or access them by their index, but you need to be able to add, access-by-ID, and remove them very quickly for larger data sets? HashSet may be the thing for you! What if you still need to be able to access them all in the order they were added? LinkedHashSet is your best friend. With this, you could easily even give the nodes names that are strings with no real slowdown.
As for the edges, I feel you are already doing fine: it's probably best to implement the outgoing edges for each Node in a singly linked list, assuming you will rarely be removing edges or will have a small number of edges per node and will always access them all together. To add a new edge, simply say newEdge = new Edge(); newEdge.nextEdge = firstEdge; firstEdge = newEdge; and you're done, having added the new edge to the beginning of the list. (Singly linked lists are easiest to use as stacks rather than queues.)
For extra fancy-points, implement Iterable<Edge> with your Node class and make a little Iterator class so you can use extended-for to visit every edge and make your life even easier!
As #Widdershins says, the terms used makes the algorithm hard to understand.
I would recommend two things in order to refactor your code:
Review the terminology (maybe this helps: http://en.wikipedia.org/wiki/Glossary_of_graph_theory). I know that it sounds like a silly recommendation, but using proper terms will help you a lot to review the object model.
Use a better representation. In your code a Node fills multiple roles, which makes the code hard to follow.
A good representation will depend a lot of the kind of problems that you try to resolve. For example an Adjacency List, or a Matrix are useful to apply some algorithms of graph theory.
But if you only want to exercise with an object oriented design, is useful to start with the basics.
Take the definition of a Graph in mathematics: G = (V, E)... a graph is a pair of a set of nodes and a set of edges between those nodes, and translate it to code:
(the example uses fields for brevity)
class DirectedGraph {
final Set<Node> nodes = new HashSet<Node>();
final Set<Edge> edges = new HashSet<Edge>();
}
Now you need to extend this definition. You can do it step by step. I did the same to end with this representation:
class DirectedGraph {
final Set<Node> nodes = new HashSet<Node>();
final Set<Edge> edges = new HashSet<Edge>();
public Node addNode(Object value) {
Node newNode = new Node(value);
nodes.add(newNode);
return newNode;
}
public Edge addEdge(Node src, Node dst) {
Edge newEdge = new Edge(src, dst);
edges.add(newEdge);
return newEdge;
}
private assertValidNode(Node n) {
if (n.graph != this)
throw new IllegalArgumentException("Node " + n + " not part of the graph");
}
public Set<Node> successorsOf(Node n) {
assertValidNode(n);
Set<Node> result = new HashSet<Node>();
for (Edge e : edges) {
if (e.src == n) { result.add(e.dst); }
}
return result;
}
class Node {
final graph = DirectedGraph.this;
final Object value;
Node(Object v) {
this.value = v;
}
public String toString() { return value.toString(); }
public Set<Node> successors() {
return graph.successorsOf(this);
}
// useful shortcut
public Node connectTo(Node... nodes) {
for (Node dst : nodes) {
graph.addEdge(this, dst);
}
return this;
}
}
class Edge {
final graph = DirectedGraph.this;
final Node src; final Node dst;
Edge(Node src, Node dst) {
graph.assertValidNode(src);
graph.assertValidNode(dst);
this.src = src; this.dst = dst;
}
public String toString() { return src.toString() + " -> " + dst.toString(); }
}
}
DirectedGraph g = new DirectedGraph();
DirectedGraph.Node one = g.addNode(1);
DirectedGraph.Node two = g.addNode(2);
DirectedGraph.Node three = g.addNode(3);
DirectedGraph.Node four = g.addNode(4);
one.connectTo(two, three)
two.connectTo(four);
System.out.println(g.edges);
System.out.println(one.successors());
System.out.println(two.successors());
This strategy of representing the domain model in a "1 to 1" mapping, always helped me to "discover" the object model. Then you can improve the implementation for your specific needs (i.e. the running time of successorsOf can be improved by using an adjacency list).
Note that in this representation a Node and an Edge can only exist as a part of a graph. This restriction is not deduced directly from the math representation... but helps to maintain the constraints of a proper graph.
Note You can extract the inner-classes by constructing the Node and Edge with a parent graph reference.