I try to solve a graph problem with a recursive method returning one correct solution but I wonder if it is possible to do so, because changing the state of a graph in one recursion level will change it on other levels since they refer to the same object. Is there any way to solve it?
Here are my code samples:
1) Nodes - here you can see that Nodes are binded creating edges
public class Node{
private int visited;
private int label;
private int order;
private int degree;
private ArrayList <Node> neighbours;
...
}
2) Graph
public class Graph {
private ArrayList <Square> graph;
private int graphSize;
private int numOfVertices;
...
}
3) And the sketch of a method:
public boolean backTracking(int label, int moves, Graph graph){
// something here
if(current.getVisited() != 1){
// current is a next neighbor of a vertex
if(backTracking(current.getLabel(),completedMoves, graph))
return true;
}
return false;
I'm not sure what your "graph problem" is, but if you need to track additional information per level then use a stack (push when going down a level, pop when going up).
If you need to store additional information per node then you can either place it inside Node class, or hold it in a Map. You can also clean entries in the map while backtracking.
Related
Here is the code for the implementation of the Binary Search Tree:
public class BST<T extends Comparable<T>> {
BSTNode<T> root;
public T search(T target)
{
//loop to go through nodes and determine which routes to make
BSTNode<T> tmp = root;
while(tmp != null)
{
//c can have 3 values
//0 = target found
//(negative) = go left, target is smaller
//(positive) = go left, target is greater than current position
int c = target.compareTo(tmp.data);
if(c==0)
{
return tmp.data;
}
else if(c<0)
{
tmp = tmp.left;
}
else
{
tmp = tmp.right;
}
}
return null;
}
/*
* Need a helper method
*/
public T recSearch(T target)
{
return recSearch(target, root);
}
//helper method for recSearch()
private T recSearch(T target, BSTNode<T> root)
{
//Base case
if(root == null)
return null;
int c = target.compareTo(root.data);
if(c == 0)
return root.data;
else if(c<0)
return recSearch(target, root.left);
else
return recSearch(target, root.right);
}
Why do I need the recursive helper method? Why can't I I just use "this.root" to carry out the recursive process that is taking place? Furthermore, if screwing up the root property of the object this method is being called on is a problem, then how is does the helper method prevent this from happening? Does it just create a pointer that is separate from the this.root property, and therefore won't mess up the root property of the object that the method is being called on?
Sorry if the question doesn't seem straight forward, but if anyone can enlighten me on what's exactly going on behind the scenes I would really appreciate it.
The method needs a starting point. It needs to have a non changing Target node and it needs to compare it with some other node to see if they are a match lets call this node current instead of root since it is the current Node the recursive method is evaluating. There really isn't a concise way of doing this when using a recursive method other than using a helper function and passing in both variables (this is the case for many recursive methods). As you said stated if you updated root you would completely alter your tree when going left or right which you wouldn't want to do. The helper function is used because it gives your recursive method a starting point. And it also keeps track of the current node you are working on as you said the method points to the Node object being evaluated but doesn't make any changes. When going left or right it doesn't modify anything it just passes in a reference to the left or right node and continues to do this until the target is found or the base case is hit.
I've currently been learning and programming pathfinding(in Java) using the A* algorithm. A problem I've run into is when multiple entities are trying to pathfind, they both alter the previousNode(the Node that the Node being calculated on came from), messing up the algorithm, and eventually Node A will point to Node B and Node B will point to Node A.
How can I change the algorithm to either
Not use this previousNode system that is littered throughout all of the A * algorithms(that I have seen, that is)
Alter this system to be used concurrently
I am trying to avoid having one entity finish pathfinding, then telling the next entity to pathfinding, and so on. Like doing a wait() - notify() pair in Java.
public Path findPath(int startX, int startY, int goalX, int goalY) {
//Path is basically just a class that contains an ArrayList,
//containing Nodes, which contains the steps to reach a goal.
if(map.getNode(goalX, goalY).isObstacle()) {
return null;
}
map.getNode(startX, startY).setDistanceFromStart(0);
closedList.clear();
openList.clear(); //A List with added getFirst() - gets the first Node in the list
openList.add(map.getNode(startX, startY));
while(openList.size() != 0) {
//Node contains a List that has all of the Nodes around this node, a
//F, G, and H value, and its row(y) and column(x)
Node current = openList.getFirst();
if(current.getX() == goalX && current.getY() == goalY) {
return backtrackPath(current);
}
openList.remove(current);
closedList.add(current);
for(Node neighbor : current.getNeighborList()) {
boolean neighborIsBetter;
//If I've already searched this neighbor/node, don't check it
if(closedList.contains(neighbor)) {
continue;
}
if(!neighbor.isObstacle()) {
float neighborDistanceFromStart = (current.getDistanceFromStart() + map.getDistanceBetween(current, neighbor));
if(!openList.contains(neighbor)) {
openList.add(neighbor);
neighborIsBetter = true;
} else if(neighborDistanceFromStart < current.getDistanceFromStart()) {
neighborIsBetter = true;
} else {
neighborIsBetter = false;
}
if(neighborIsBetter) {
neighbor.setPreviousNode(current);
neighbor.setDistanceFromStart(neighborDistanceFromStart);
neighbor.setHeuristic(getManhattanDistance(neighbor.getX(), neighbor.getY(), goalX, goalY));
}
}
}
}
return null;
}
public Path backtrackPath(Node fromNode) {
Path path = new Path();
while(fromNode.getPreviousNode() != null) {
path.prependWaypoint(fromNode);
fromNode = fromNode.getPreviousNode();
}
return path;
}
I am specifically talking about(within findPath())
if(neighborIsBetter) {
neighbor.setPreviousNode(current); //previousNode is a value in the Node class that points to the Node that it came from
neighbor.setDistanceFromStart(neighborDistanceFromStart);
neighbor.setHeuristic(getManhattanDistance(neighbor.getX(), neighbor.getY(), goalX, goalY));
}
I don't think you can do A* (or any pathfinding algorithm, for that matter) without somehow storing a backpointer for a given path. So that leaves you with two options
Require each agent (Thread, I assume) to create their own copy of the graph to work on. That way each A* call going on won't interfere with one another, as they are working with the fields of the same node on different graphs.
Change your A* code to be able to handle multiple concurrent calls.
Option 1 is fairly self-explanatory and probably the better option. If this is just for you, you should probably just go with that one (instead of trying to make A* fully concurrent on a single graph). This would entail adding map as an input parameter (and requiring that concurrent calls should use a different map instance, either throwing an exception or having unspecified behavior if that doesn't occur). Additionally, you should instantiate closedList and openList as new data structures in each call, rather than share a list.
If that's not to your liking - you really want to fully encapsulate the mutli-call usage into the method itself, I think the simplest way you could do this is require an additional parameter of an id - some unique string that is guaranteed not to be the same as the id of another concurrent call. So the header of A* now looks like:
public Path findPath(final String ID, int startX, int startY, int goalX, int goalY) {
From there, change all of the implementations of each of the settable pathfinding fields in Node to a HashMap with the id as the key. From your code, I'm going to guess that your Node class looks something like this:
public class Node{
//Fields used by the A* call - no problem here
private boolean obstacle;
//Fields *edited* by the A* call
private float distanceFromStart;
private Node previous;
private int heuristic;
//other fields and stuff
public boolean isObstacle(){
return obstacle;
}
public float getDistanceFromStart(){
return distanceFromStart;
}
public void setDistanceFromStart(float f){
distanceFromStart = f;
}
public Node getPrevious(){
return previous;
}
public void setPrevious(Node p){
previous = p;
}
public int getHeuristic(){
return heuristic;
}
public void setHeuristic(int h){
heuristic = h;
}
}
We can edit the edited fields to be able to store many values, by id, as such:
public class Node{
//Fields used by the A* call - no problem here
private boolean obstacle;
//Fields *edited* by the A* call
private HashMap<String,Float> distanceFromStart;
private HashMap<String,Node> previous;
private HashMap<String,Integer> heuristic;
//other fields and stuff
public boolean isObstacle(){
return obstacle;
}
public float getDistanceFromStart(String id){
return distanceFromStart.get(id);
}
public void setDistanceFromStart(String id, float f){
distanceFromStart.put(id, f);
}
public Node getPrevious(String id){
return previous.get(id);
}
public void setPrevious(String id, Node p){
previous.put(id,p);
}
public int getHeuristic(String id){
return heuristic.get(id);
}
public void setHeuristic(String id,int h){
heuristic.put(id,h);
}
}
From there, simply edit your A* method to give the id from the method call to the getters and setters when called for. So long as two concurrent method calls don't have the same id value, they won't interfere with each other. Three things to keep in mind for this to work correctly:
Make sure that every editable field gets this treatment. It won't work if you forget about one. Non-editable fields (fields that don't get altered as a byproduct of running A*) can stay singular.
If you use the the above, you should probably add to the cleanup stage a step of removing all the information for the given ID from the graph, or the nodes' hashmaps will grow larger with each call.
Either way, you still should make openList and closedList new local instances, no matter what concurrent approach you pick. There's nothing to gain from making openList and closedList shared instances, and only bugs can come of it.
List<Node> closedList = new LinkedList<Node>();
List<Node> openList = new LinkedList<Node>();
//Don't have to clear them anymore - they're new lists
openList.add(map.getNode(startX, startY));
I have a method to flatten a Binary search tree. I have two approaches for it:
• Using a variable and passing it around
import java.util.*;
public class BST {
private Node root;
private class Node {
private int val; // associated data
private Node left, right; // left and right subtree
public Node(int val) {
this.val = val;
}
}
public ArrayList<Integer> flattenTree(){
ArrayList<Integer> list = new ArrayList<>();
flattenTree(root, list);
return list;
}
public void flattenTree(Node node, ArrayList<Integer> list)
{
if (node == null)
return;
flattenTree(node.left, list);
list.add(node.val);
flattenTree(node.right, list);
}
public static void main(String[] args) {
BST bst = new BST();
bst.add(5);
bst.add(1);
bst.add(0);
bst.add(3);
System.out.println(bst.flattenTree());
}
}
• Using a class variable:
import java.util.*;
public class BST {
private Node root;
ArrayList<Integer> list = new ArrayList<>();
private class Node {
private int val; // associated data
private Node left, right; // left and right subtree
public Node(int val) {
this.val = val;
}
}
public ArrayList<Integer> flattenTree(){
flattenTree(root);
return list;
}
public void flattenTree(Node node)
{
if (node == null)
return;
flattenTree(node.left);
list.add(node.val);
flattenTree(node.right);
}
public static void main(String[] args) {
BST bst = new BST();
bst.add(5);
bst.add(3);
bst.add(1);
bst.add(0);
bst.add(3);
bst.add(3);
bst.printInorder();
System.out.println(bst.flattenTree());
}
}
In both cases I get:
sgupta$ java BST
[0, 1, 3, 5]
I'm a beginner to java (high school) and wondering what the pros and cons of each approach are.
The only one I can think of is that approach #2 has less messy code by not having to pass the list around.
To add to #caskey's points, I'd like to point out two other major advantages of the first version of the code.
First, the code that accepts an explicit list is harder to use incorrectly. If you call the second version of the code, you need to
make sure no one else is calling the method in a parallel thread,
make sure that the list variable has been initialized,
make sure that the list doesn't already contain anything else, and
remember to read off the list when you're done with it.
If you forget to do any of these, your program will not behave as expected, but you won't get any compiler errors indicating this. This makes the code harder to use correctly and increases the chances that you'll get more bugs in your program.
Second, the first version has an easier description. The first version of the code can be described as "populate the given list with an inorder traversal of the tree." The second version is "appends to the existing contents of the list list an inorder traversal of the tree." It's harder to describe what this second one does, so the burden on the documentation is greater. Plus, it's harder for programmers reading the code for the first time to understand what it does.
Hope this helps!
The disadvantage, in general, to global variables is twofold.
1) you have only one global variable and so two copies of your code can't run at the same time (i.e., multiple threads).
2) The global variable can be modified in other places which your code might not expect.
Your first answer is the better engineered solution.
Good questions to ask:
Does the class have state it needs to hold onto?
If so, what is the state (i.e. the fields)?
Can you avoid state by passing arguments in method calls, which makes for easier to test code.
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 3 years ago.
I get an error whenever I try to create a simple edge from a node.
Basically, I've created two of my own classes called Node and Edge.
The Node class is as follows:
public class Node {
public String ident;
public int numLinks;
public Edge[] neighbours;
public Node (String ident) {
this.ident = ident;
}
public void setNeighbour (Node start, Node end, int cost, int portNum) {
}
}
And my Edge class is as follows:
public class Edge {
Node start;
Node end;
int cost;
int portNum;
public Edge (Node a, Node b, int cost, int portNum) {
this.start = a;
this.end = b;
this.cost = cost;
this.portNum = portNum;
}
}
In my main class, I create two nodes, namely, the start and the end node. The cost and the port number (port number that both these nodes listen to on), I read from a text file and am saving them into an array list named "linkCostList" and "portNumList".
Now, since each start node can have more than one edge (I'm basically creating a graph), I'm calling the setNeighbour() method in the following way:
for (int i = 0; i < startNode.numLinks; i++) {
nextNode = new Node (String name of node I read from text file)
startNode.setNeighbour (startNode, nextNode, linkCostList.get(i), portNumList.get(i));
}
My setNeighbour method is as follows:
public void setNeighbour (Node start, Node end, int cost, int portNum) {
for (int i = 0; i < start.numLinks; i++) {
neighbours[i] = new Edge (start, end, cost, portNum);
}
}
Whenever I compile it, I get an error of the following sort:
Exception in thread "main" java.lang.NullPointerException
at Node.setNeighbour(Node.java: *line number*)
at Start.startlsr(Start.java: *line number*)
at graph.main(lsr.java: *line number*)
}
I understand that this is a null pointer exception, so, somewhere in that loop, I must be doing something wrong. Could anyone please help me figure it out?
Have you initialzed neighbours in your Node class? It looks like the exception is from accessing a null array (neighbours[i]).
Also It looks like the neighbours array will grow/shrink dynamically? In this case, instead of using array, consider using ArrayList so you don't have to grow neighbours yourself.
Further to #Alvin's answer (you haven't initialized neighbours nor allowed for expansion), try this:
public List<Edge> neighbours = new ArrayList<Edge>();
Also make use of java's "foreach":
for (Edge edge : start.neighbours) {
// .. some code
}
Consider renaming "neighbours" to "edges", since they are just that - the edges of the node.
Finally, it seems you have a bug in your logic. It seems too complicated. You may be attempting to keep references of neighbours of neighbours. Consider simply looking stuff up when you need it.
I am fairly new to Java and Jung. I am writing a program where I need to add probabilities on edges of the event occurrence(means probability of the event that data will flow from first node to other). I am a little confuse that will Max-Flow do the trick for me or do I need to use some other option or there is no option to do it within Jung and in that case do I need to write it on my own? Any help in this regard will be appreciated.
regards,
waqas
Do you intend to set the edge weights to represent the probabilities of certain events? The Max-Flow algorithm will use the "capacities" you assign to each edge to find the path of maximum flow from the source vertex to the sink vertex. What exactly are you trying to do here?
I'm not very sure what your final aim is, so I'll try my best to help out.
You can first represent the probabilities by defining a custom Edge and Edge Factory classes. What I did was:
0. Imports:
import org.apache.commons.collections15.Factory;
1. Add in your custom classes. They custom edge class might be something like:
public static class MyEdge {
private int flow;
private int capacity;
private String name;
private int eIndex;
public MyEdge(String name, int eIndex) {
this.name = name;
this.eIndex = eIndex;
}
public int getCapacity() {
return this.capacity;
}
public void setCapacity(int edgeCapacity) {
this.capacity = edgeCapacity;
}
public int getFlow() {
return this.flow;
}
public void setFlow(int edgeFlow) {
this.flow = edgeFlow;
}
public String toString() {
return this.name;
}
}
The custom edge factory is what actually creates your edges each time you draw them on the canvas graphically, it might look like:
public static class MyEdgeFactory implements Factory {
private static int defaultFlow = 0;
private static int defaultCapacity = 0;
private int edgeCount;
private MyEdgeFactory() {
}
public MyEdge create() {
String name = "E" + edgeCount;
MyEdge e = new MyEdge(name, edgeCount);
edgeCount++;
e.setFlow(defaultFlow);
e.setCapacity(defaultCapacity);
return e;
}
}
2. Tell your visualization viewer how to display the edge labels; you'll need to add this in wherever you're creating your graph and VisualizationViewer object (vv):
vv.getRenderContext().setEdgeLabelTransformer(new Transformer() {
public String transform(MyEdge e) {
return (e.toString() + " " + e.getFlow() + "/" + e.getCapacity());
}
});
Now everytime you create an edge, it's label will be of the form "E0 0/0", "E1 0/0" and so on.
I'll be posting detailed tutorials and code on my blog soon so you could watch that space if you're going to be spending significant time on whatever project you're working on.
Look at the way you're calling setEdgeLabelTransformer, you need to pass it a new Transformer(), like I've done in my code snippet numbered 2.
When you pass a new ToStringLabeller(), you're telling the viewer to label using the toString() method of the edge object. You'll need to pass a custom Transformer instead, just correct your code to look like mine and you'll be fine.