Change (same) variables of multiple objects quickly - java

I have an implementation of depth-first search for a directed graph with same size edges. This search changes the state of the nodes in my graph. So if I want to do a new search all nodes have to be reset to default.
My implementation:
public void resetGraph() {
ListItem temp = nodes.getHead();
while(temp != null){
DiGraphNode node = temp.key;
node.visitorState = VISITORS.NONE; //Set all nodes their initial state
node.sumOfDistances = 0;
temp = temp.next;
}
}
=> This takes some time for a large graph
Is there a way to do this more time efficient ?
Maybe someting like:
DiGraphNode.someStaticMethod(0);

As your structure stands at the moment there is little you can do - you must visit every node to reset it so you are stuck with an O(n) algorithm.
One possible solution that may improve performance a little would be to keep track of all of your visitorState and sumOfDistances fields in an array. You could then use a int nodeID (generated at node construction time perhaps) to access the state and sum. The benefit of this tweak would be to allow you to use Arrays.fill which may make use of cpu-specific block-set instructions.
You will not be able to change the order of the algorithm but you might find some speed-up this way.

Related

How to make my path-finding algorithm not go in reverse?

My path-finding method is given two objects containing an id, name, x/y coordinates, and path stored in an Array List. The path data is the id of each object that it can directly connect to. The objective is to call my method recursively until it finds its goal using the shortest distance, and when it reaches the end it returns true.
The problem:
If the distance to the node that you came from is shorter than the other nodes in the current nodes path, then it will cause an infinite loop bouncing back and forth between the two nodes. I have struggled with this problem for several hours and could be over thinking it. Any advice or suggestions will be greatly appreciated!
The Algorithm:
while (!pathfound) {
current = findPath(current, end);
}
public static Place findPath(Place curPlace, Place endPlace) {
ArrayList<Integer> path = curPlace.path;
int id;
double lastdist = 999;
double distance;
Place bestPlace = null;
for (int i = 0; i < path.size(); i++) {
id = curPlace.path.get(i);
distance = distance(getPlace(id), curPlace)
+ distance(getPlace(id), endPlace);
if (distance < lastdist) {
bestPlace = getPlace(id);
}
lastdist = distance;
}
if (result.length() == 0) {
result += bestPlace.name;
} else {
result += ", " + bestPlace.name;
}
System.out.println("CURCITY: " + bestPlace.id);
System.out.println(result);
System.out.println(lastdist);
if (bestPlace == endPlace) {
pathfound = true;
}
return bestPlace;
}
You can ignore result, it is for keeping up with the nodes that are passed through. If there are any other details you would like to know, please ask.
If it is acceptable to modify Place you can add a boolean "visited" flag. Reset them all to false prior to running the algorithm; set to true when you visit and false when you leave (don't forget to unset them on the way out of the recursion - if you do this properly you can even avoid having to explicitly reset the flags before starting). Skip nodes where the flag is true.
A more short-sighted option is to pass the last visited Place as a parameter to the function, and skip that one. This will not prevent larger loops but may be entirely appropriate for your situation and is the simplest to implement.
Both of the above are O(1) with minimal overhead. If you cannot modify Place you could store a Set of visited places (remove them from the set on the way out of recursion), and skip places that are already in that set. Depending on your performance requirements, if you use a HashSet you will want to come up with an appropriate hashing function.
Along those lines, at the expense of more memory, if your ID numbers are unique and cover a reasonably sized finite range, a boolean[] indexed by ID number is a constant time alternative to a set here (it is essentially the "visited" flag option with the flags stored externally).
Using a recursive approach to path finding algorithm can be quite tricky, as you always need some kind of global information to evaluate, which one of two paths is more suitable. While following a single path, you can never be sure, if it is the right one. Even if you always follow the nearest node, it doesn't have to be the right path. This is called best-first search strategy and although it is not the best, it can be made to work, but you have to make sure to try other paths as well, because you can't pull it off by simply always sticking to the closest node.
If you want to do a path finding algorithm, you will need to keep track of all the nodes, that you have already explored exhaustively and therefore will never need to visit again. This can be done either explicitly, by storing the list of visited nodes in a structure of some kind, or you can be smarter about it and enforce this by good design of policy for selecting a new node to be visited.
In other words, if you keep track of the nodes to be visited along with the distances to each node (priority queue) and you always make sure to visit the nearest not-yet-visited node, you will never revisit the same nodes again, without having to explicitly enforce it, such as in A* algorithm, or Dijkstra.

how to extract a sample from KNeighborhoodFilter

I am building a bipartite network generator and I am using the code in How to filter the result of KNeighborhoodFilter? and it works perfectly when my network is small (5000 nodes).
Now I am working with a network with 60.000 nodes and 250.000 links. To speed up things, I am wondering if it is possible to just take a random sample of nodes when extracting the 2-dist neighbors of a node, say just 50% of 2-dist neighbors...
I really have no clue on how to achieve this, nor if it is possible without hacking the KNeighborhoodFilter class itself (I know I won't be able to do that...).
Right now I take the result and just pick a random sample, but I don't know if I am on the right path:
Predicate<Node> onlyUsers = new Predicate<Node>() {
#Override
public boolean apply(Node node) {
return node.getName().startsWith("u");
}
};
// find neighbors of nodes with degree i
Filter<Node, Edge> filter = new KNeighborhoodFilter<Node, Edge>(u, 2, KNeighborhoodFilter.EdgeType.IN_OUT);
// retrieve everything at distance 2 from node u
List<Node> twoDistNei = Lists.newArrayList(filter.transform(zpa).getVertices());
// sample the collection
List<Node> sampledUsers = Lists.newArrayList();
for (int i = 0; i < 2000; i++) {
sampledUsers.add(twoDistNei.get(context.getRNG().nextInt(twoDistNei.size())));
}
Set<Node> sampledNodesHashed = Sets.newHashSet(sampledNodes);
Set<Node> twoDistUsers = Sets.newHashSet(Collections2.filter(sampledNodesHashed, onlyUsers));
My goal is to make this code run faster. Thank you very much for your time.
Best regards,
Simone
If you want to go faster, here are a couple of possible approaches. They both involve some hacking. :)
(1) Modify KNeighborhoodFilter to give you a version in which you traverse edges with some probability p.
A generalization of this is in which you specify a probability for each hop, i.e., use one probability for the first hop, one for the second hop, etc.
A further generalization would use separate probabilities for each edge, possibly based on some property of the nodes/edges involved (e.g., maybe you want to follow edges more or less often if the target has high degree).
Note that this solution involves giving some serious consideration to what kind of random sampling is appropriate in your case. If what you really want is a uniform random sampling of the nodes that would have been in the full result, then you basically need to generate the full result and then filter it.
This is probably the easiest solution; it wouldn't involve much work at all, really.
(2) Create a modified version of KNeighborhoodFilter that divides the work up among different processors. You're probably running this on a machine with > 1 core, so you could create multiple threads and let Java allocate them to different machines; if you really want to speed this up (and you have an appropriate setup) then you could farm it out to different machines, MapReduce-style.

Traverse a graph, but only n levels deep

I have a graph which is essentially an ArrayList of Nodes, each of which stores their neighbors.
public class Node {
ArrayList<Node> neighbors;
String data;
public Node() {
data = null;
neighbors = new ArrayList<Node>();
}
}
I print out every path in this graph, but only do it n-levels deep. How should I go about coding this?
Or, if I should store this differently, feel free to let me know. But more importantly I want to know how to print out every path n-levels deep.
Just do a depth-limited traversal of the graph. This is just like depth-first search, except in the recursive step, you also add a variable called depth which is incremented every time you go down a depth. Then simply stop recursing once you've hit the desired depth.
Add an extra variable called visited in every node.
Do a breadth first search using a Queue and use the visited to prevent from forming a loop.
Do it for length n.

Converting a Breadth First Search to Depth first Search in Java

its been a long time since I touched Java so this may seem like an odd question. Currently have this Breadth First Search code I found here on StackOverflow, I have it modified on my end but I'll post the original code here.
public List<Node> getDirections(Node start, Node finish){
List<Node> directions = new LinkedList<Node>();
Queue<Node> q = new LinkedList<Node>();
Node current = start;
q.add(current);
while(!q.isEmpty()){
current = q.remove();
directions.add(current);
if (current.equals(finish)){
break;
}else{
for(Node node : current.getOutNodes()){
if(!q.contains(node)){
q.add(node);
}
}
}
}
if (!current.equals(finish)){
System.out.println("can't reach destination");
}
return directions;
}
I'm aware of other depth first search algorithms out there, but I was also told its possible to convert breadth first search to depth first search easily, and I would understand it better if it was done to this code instead of 2 totally different codes.
How can I change this to be a Depth First Search?
The main difference between Depth first and Breadth fist is the order in which you explore the nodes in your "frontier" (the list of nodes you're yet to explore).
If you add the outgoing nodes from your current node to the end of that list, you'll be testing every possibility in a "level" (for simplification purposes, imagine this as a tree), before going to the next level, so you have a Breadth first search.
If, on the other hand, you explore the newly added nodes (the outgoing nodes from your current position), before the nodes you've added earlier (that belong in the "upper" levels of the tree), then you'll be exploring the depth of the tree first.
In terms of data structures, you want a Stack instead of a Queue, but I think the explanation may come in handy.
You'd have to replace q.add(node) (which adds at the end of a list) with q.add(0, node) (to add at the beginning). Basically, use a stack instead of a queue.
Obviously you'd have to use the List interface instead of the Queue one to access the LinkedList.
Deque<Node> q = new LinkedList<Node>();
and use pop and push instead of remove and add
basically remove from the same side you added (normal remove and add are LIFO queue base ops) depth first uses a FIFO stack
and the other search algorithms are essentially the same but use different types of queues (eager search uses a easiest next step for example)
Replace Queue and LinkedList with Stack, add with push, and remove with pop

Graph Tour with Uniform Cost Search in Java

I'm new to this site, so hopefully you guys don't mind helping a nub.
Anyway, I've been asked to write code to find the shortest cost of a graph tour on a particular graph, whose details are read in from file. The graph is shown below:
http://img339.imageshack.us/img339/8907/graphr.jpg
This is for an Artificial Intelligence class, so I'm expected to use a decent enough search method (brute force has been allowed, but not for full marks).
I've been reading, and I think that what I'm looking for is an A* search with constant heuristic value, which I believe is a uniform cost search. I'm having trouble wrapping my head around how to apply this in Java.
Basically, here's what I have:
Vertex class -
ArrayList<Edge> adjacencies;
String name;
int costToThis;
Edge class -
final Vertex target;
public final int weight;
Now at the moment, I'm struggling to work out how to apply the uniform cost notion to my desired goal path. Basically I have to start on a particular node, visit all other nodes, and end on that same node, with the lowest cost.
As I understand it, I could use a PriorityQueue to store all of my travelled paths, but I can't wrap my head around how I show the goal state as the starting node with all other nodes visited.
Here's what I have so far, which is pretty far off the mark:
public static void visitNode(Vertex vertex) {
ArrayList<Edge> firstEdges = vertex.getAdjacencies();
for(Edge e : firstEdges) {
e.target.costToThis = e.weight + vertex.costToThis;
queue.add(e.target);
}
Vertex next = queue.remove();
visitNode(next);
}
Initially this takes the starting node, then recursively visits the first node in the PriorityQueue (the path with the next lowest cost).
My problem is basically, how do I stop my program from following a path specified in the queue if that path is at the goal state? The queue currently stores Vertex objects, but in my mind this isn't going to work as I can't store whether other vertices have been visited inside a Vertex object.
Help is much appreciated!
Josh
EDIT: I should mention that paths previously visited may be visited again. In the case I provided this isn't beneficial, but there may be a case where visiting a node previously visited to get to another node would lead to a shorter path (I think). So I can't just do it based on nodes already visited (this was my first thought too)
Two comments:
1) When you set costToThis of a vertex, you override the existing value, and this affects all paths in the queue, since the vertex is shared by many paths. I would not store the costToThis as a part of Vertex. Instead, I would have defined a Path class that contains the total cost of the path plus a list of nodes composing it.
2) I am not sure if I understood correctly your problem with the goal state. However, the way I would add partial paths to the queue is as follows: if the path has a length<N-1, a return to any visited node is illegal. When length=N-1, the only option is returning to the starting node. You can add visitedSet to your Path class (as a HashSet), so that you can check efficiently whether a given node has been visited or not.
I hope this helps...

Categories

Resources