So, basically this is what I have so far.
public List<String> cycleSearch(Graph<String,String> g) throws Exception{
List<String> list = null;
Graph<String,String> auxG = g;
for(String aux : g.getVertices()){
String aux2 = aux;
if(g.degree(aux)>1){
if(auxG.removeVertex(aux2)){
for(String d : g.getSuccessors(aux2)){
for(String a : g.getSuccessors(aux)){
if(a!=d){
list = findPath(auxG,d,a);
if(list!=null){
list.add(0,aux);
list.add(aux);
return list;
}
}
}
}
}
}
auxG = g;
}
return null;
}
What the method does is basically to search for a cycle in a hypergraph based on JUNG.
The idea it's to recieve a graph on the parameters and then create a variable (as the same type) to later remove a vertex from it without making any changes on the original graph, just in case a cycle isn't found. That way I can use a method called findPath(,,), once the vertex is removed. The method will 'create' another path without walking through the removed vertex.
My compiler says there is problem right here:
for(String d : g.getSuccessors(aux2))
I've been programming graphs in Java(JUNG) for only 1 month.
HELP
There is a bug in JUNG that this code has turned--getSuccessors() should be returning an empty collection if the graph does not have the vertex, rather than returning null, which is what SetHypergraph's implementation does. Sorry about that. (In general, you can avoid this by wrapping the getSuccessors(x) inside a containsVertex(x) if statement.)
However, the reason why you're encountering this bug is that you're doing at least a couple of things that do not make sense:
(1) you're assigning auxG to g (so they're referencing the same object); this is misleading and not helpful.
Similarly, you're assigning aux2 to aux, which is also misleading.
(2) you're removing aux[2] from auxG and then asking for aux2's successors in auxG. aux2 will not have any successors in auxG once it's removed.
(3) Since aux2 and aux are the same vertex, your innermost loop will also not do anything useful for the same reason; there will be no successors.
You need to rethink your entire algorithm, because this simply is not correct as designed.
Instead of using null to represnt no successors, you could just use an empty list, and thus avoid the NullPointerException. Replace return null; with return new LinkedList<>();.
Related
I have been trying to make simple DFS using object oriented design and by implementing the Iterator class. But DFS does not work as it should.
I have almost tried everything that I could but I was not able to make this work.
Also I couldn't find much relevant info on internet about the type of code I am trying.
I have two interfaces Vertex and Graph.
Following is the code I am trying:
public class GraphIterator implements Iterator<Vertex> {
private Graph g;
private Vertex v;
private Stack<Vertex> stack;
private Set<Vertex> colored;
public GraphIterator(Graph g, Vertex v) {
this.g = g;
this.v = v;
stack = new Stack<>();
colored = new TreeSet<>();
stack.push(v);
colored.add(v);
}
#Override
public boolean hasNext() {
return stack.isEmpty();
}
#Override
public Vertex next() {
Vertex u = stack.pop();
for(Vertex vertex : g.getNeighbours(u)) {
if(vertex != null && !colored.contains(vertex))
stack.add(vertex);
}
return stack.pop();
}
}
This is the code in main() I am trying to test with:
GraphClass g = new GraphClass();
Vertex v = new VertexClass(0);
Vertex w = new VertexClass(1);
g.addVertex(v);
g.addVertex(w);
g.addEdge(v, w);
Iterator<Vertex> it = new GraphIterator(g, v);
System.out.println(v+" vs "+it.next());
System.out.println(it.hasNext());
System.out.println(w+" vs "+it.next());
I know I am doing something wrong with the DFS algorithm but I am not able to quite understand what and where am I going wrong?
I am mostly sure that I am doing something wrong with DFS algorithm, which needs to be implemented using overriden methods from Iterator class. I would also appreciate some tips of how to do so.
I would appreciate if someone could help me in this algorithm.
Possible improvements to the code in question:
In next(), maybe just return u;, instead of return stack.pop();.
Because that would pop 2 elements in a single call to next(), and with the second's neighbor vertices unchecked.
LinkedList might be a better choice than Stack here.
Since there seems has no need for concurrent control.
BTW:
LinkedList is also a stack, it's not thread-safe; while Stack is thread-safe.
(If could post the code in a block, that others can copy & run directly, and see the output, then probably a better answer could be provided.)
I'm having issues with getting an iteration done (and modification) through the Set, which contains Objects. I've tried so many ways of iteration (4), but none of them seem to work and still throw me the Error java.util.ConcurrentModificationException.
[Code is written in Groovy]
private void replaceRock() {
ObjectNodeManager.OBJECTS.each {
System.out.println("Going...");
if(it.getPosition().withinDistance(player.getPosition(), 30)) {
System.out.println("Found...");
Position position = it.getPosition();
ObjectNode newRock = new ObjectNode(439, position, ObjectDirection.NORTH, ObjectType.DEFAULT);
ObjectNodeManager.unregister(it);
ObjectNodeManager.register(newRock);
it.remove();
}
}
}
I've tried synchronization to prevent access from other Threads, but this also didn't work. Please help me, I'm very desperate.
First find them (this will give you basically a list of refs) and then deal with them:
ObjectNodeManager.OBJECTS.findAll {
it.getPosition().withinDistance(player.getPosition(), 30))
}.each{
ObjectNode newRock = new ObjectNode(439, it.position, ObjectDirection.NORTH, ObjectType.DEFAULT)
ObjectNodeManager.unregister(it)
ObjectNodeManager.register(newRock)
it.remove()
}
On a random site note: i'd add a replace method in the ObjectNodeManager to combine unregister, register, remove. Also working with class methods and properties is not the best thing to do (but since it looks like a game...)
The problem is that you are modifying the list of objects while you are looping through the objects.
Try iterating through a copy of the objects instead.
ArrayList<YourType> copy = new ArrayList<YourType>(ObjectNodeManager.OBJECTS);
copy.each(...)
i ran into an issue when trying to print out a list of file dependencies.
About the program:
Scans given *.c files for dependencies, more specifically looks for "#include "%"
Find those files and scans them for their dependencies recursively
All information is stored in a ConcurrentHashMap(key:String value:Linked List of Strings) theTable, where Linked List of Strings contains the list of dependencies.
After processing a certain file, i end up with the following hash table:
If I understand what the map output is saying, there is a cycle ( a #include loop ) in your header files.
i_50.h=[i_35.h, i_28.h, i_45.h, i_44.h, i_46.h],
....
i_35.h=[i_50.h, i_51.h]
That means that your dependencies are a graph and not a DAG. And that in turn means that a simple recursive walk will not work.
By the looks of it, you are attempting to do a graph walk, but for some reason your cycle detection / avoidance is not working, and your algorithm goes into "infinite" recursion.
After looking at the code, I think I can see where the problems are. In the first method, you check that a dependency has already been printed, and then set the entry in the alreadyPrinted map to say it has. But you then proceed to print it irrespective. Then in the second method you are (inexplicably) creating a new alreadyPrinted map each time you recurse to the first method. In other words, the logic of your cycle avoidance is broken.
Rather than fixing your code for you, I'm going to suggest that you go to your favourite "data structures and algorithms" text book and look up "graph traversal" in the index. Alternatively, here's an page I found in some online lecture notes:
http://underpop.online.fr/j/java/algorithims-in-java-1-4/ch05lev1sec8.htm
There's also stuff on graph traversal in Wikipedia, and other places. Google for "java recursive graph traversal", and try and find something that makes sense to you.
The general algorithm is something like this:
traverse(Node node):
traverse_0(node, new Set<Node>())
traverse_0(Node node, Set<Node> visited):
if (visited.contains(node))
return
visited.add(node)
for (Node child: node.children)
traverse_o(child, visited)
The only place where you test if a dependency has already been printed, is the first for loop. You should check in the second for loop too!
for (String d : dependencies) {
if (!alreadyPrinted.containsKey(d)) {
LinkedList<String> key = theTable.get(d);
if (key != null)
output += printDependencies(theTable, key, alreadyPrinted);
}
}
It is fairly easy to see that your algorithm recurses, as soon as some dependency looks like:
item: ...., item, ....
(I hear you say: "that cannot happen, because ...". Yet, the SO shows that either it did happen, or your stack is too small.)
By the way, you maintain the map "already printed", but it is nowhere used? This hints to a flaw in your implementation.
As you are maintaining some state (alreadyPrinted and output) I would recommend moving the state to instance-variabes and to use an object and no class-methods.
The problem was that my Graph traversal had cycles which I was not handling. The working code is provided below.
private static String printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, LinkedList<String> dependencies, ConcurrentHashMap<String, Boolean> alreadyPrinted) {
String output = "";
for (String d : dependencies) {
boolean isPrinted = alreadyPrinted.containsKey(d);
if (!isPrinted) {
output += " " + d;
alreadyPrinted.put(d, true);
}
}
for (String d : dependencies) {
LinkedList<String> key = theTable.get(d);
if (key != null) {
LinkedList<String> unvisited = new LinkedList<String>();
for (String filename : key)
if (!alreadyPrinted.containsKey(filename))
unvisited.add(filename);
if (unvisited != null)
output += printDependencies(theTable, unvisited, alreadyPrinted);
}
}
return output;
}
private static void printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, ConcurrentLinkedQueue<String> toProcess) {
String output = "";
for (String current : toProcess) {
ConcurrentHashMap<String, Boolean> alreadyPrinted = new ConcurrentHashMap<String, Boolean>(); // Keeps track of dependencies already printed
output += current + ":" + printDependencies(theTable, theTable.get(current), alreadyPrinted) + "\n";
}
System.out.println(output);
}
I encountered this issue while working with the Java Collections API. Basically this is a support method for an implementation of Kruskal's algorithm for finding an MST. I created this class for implementing the union/find algorithm.
My question, as I was able to find a work around, is that does anybody know of any reason why the remove method in the "union" method would not work consistently. That is at run time it would remove some elements and not others. For example I implemented this for a task involving cities and it seemed to not like removing some cities. In particular it repeatedly stumbled on a couple of different sets, but always the same ones. I wondered whether it was a object reference issue, i.e. whether I was testing the wrong thing, but I could not get around it.
I know the rest of my work was correct as I was able to replace it with a loop that eliminated the element, and the algorithm executed perfectly. Probably with slightly worse performance, however.
I was wondering whether anybody can see a mistake. Also I should note that I called it from different class, however, the calls were made with elements that were retrieved using the find method. Note that the find method must work well, since simply altering the remove method made the whole thing work, i.e. it was finding and returning the appropriate objects.
Thanks
Oscar
/*
* A constructor for creating a new object of this class.
*/
DisjointSets()
{
underlying = new HashSet<HashSet<String>>();
}
/*
* A method for adding a set to this DisjointSets object
*/
void add(HashSet<String> h)
{
underlying.add(h);
}
/*
* A method for finding an element in this DisjointSet object.
*/
HashSet<String> find(String s)
{
// Check each set in the DisjointSets object
for(HashSet<String> h: underlying)
{
if(h.contains(s))
{
return h;
}
}
return null;
}
/*
* A method for combining to subsets of the DisjointSets
*/
void union(HashSet<String> h1, HashSet<String> h2)
{
System.out.print("CHECK ON DS\n");
System.out.print("*********************\n");
System.out.print("H1 is : { ");
for (HashSet<String> n: underlying)
{
System.out.print("Set is : { ");
for (String h : n)
{
System.out.print(h + " , ");
}
System.out.print("} \n ");
}
// Add the objects of h1 to h2
// DOES NOT WORK CONSISTENTLY
h1.addAll(h2);
underlying.remove(h2);
}
}
And I replaced it with
HashSet<HashSet<String>> temp = new HashSet<HashSet<String>>();
for(HashSet<String> f: underlying)
{
if(f != h2)
{
temp.add(f);
}
}
underlying = temp;
The problem is that when you modify the contents of one of the nested HashSets, you screw up the internals of the outer HashSet (because the hashCode() of the nested HashSet has changed). in order to maintain this collection correctly, whenever you want to modify one of the nested HashSets you must first remove it from the outer HashSet and then re-add it (if necessary).
(you don't really provide enough code to figure out if that's truly the problem, but that's my best guess).
Set<Set<String>> outerSet = new HashSet<String>();
Set<String> innerSet = new HashSet<String>();
innerSet.add("foo");
outerSet.add(innerSet);
// *** BROKEN ***
innerSet.add("bar"); // <- adding element to innerSet changes result of innerSet.hashCode()
outerSet.remove(innerSet); // <- this may or may not work because outerSet is _broken_
// *** BROKEN ***
// *** CORRECT ***
outerSet.remove(innerSet);
innerSet.add("bar");
// now you can put innerSet back in outerSet if necessary
Following up on #jtahlborn's answer, the contract for AbstractSet.hashCode() says
Returns the hash code value for this
set. The hash code of a set is defined
to be the sum of the hash codes of the
elements in the set. This ensures that
s1.equals(s2) implies that
s1.hashCode()==s2.hashCode() for any
two sets s1 and s2, as required by the
general contract of Object.hashCode.
This implementation enumerates over
the set, calling the hashCode method
on each element in the collection, and
adding up the results.
Code to demonstrate #jtahlborn's answer (which is correct)
import java.util.HashSet;
import java.util.Set;
public class TestHashSetHashCode {
public static void main(String[] args)
{
Set<String> strings = new HashSet<String>();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
strings.add("five");
Set<String> test = new HashSet<String>();
System.out.println("Code "+test.hashCode());
for (String s : strings) {
test.add(s);
System.out.println("Code "+test.hashCode());
}
}
}
Outputs
Code 0
Code 115276
Code 3258622
Code 3368804
Code 113708290
Code 116857384
One more reason to add to the list to make use of immutable collections wherever possible.
Am trying to solve a labyrinth by DFS, using adj List to represent the vertices and edges of the graph. In total there are 12 nodes (3 rows[A,B,C] * 4 cols[0,..,3]). My program starts by saving all the vertex labels (A0,..C3), so far so good, then checks the adjacent nodes, also no problems, if movement is possible, it proceeds to create the edge, here its where al goes wrong.
adjList[i].add(vList[j].label);
I used the debugger and found that vList[j].label is not null it contains a correct string (ie. "B1"). The only variables which show null are in adjList[i], which leads me to believe i have implemented it wrongly. this is how i did it.
public class GraphList {
private ArrayList<String>[] adjList;
...
public GraphList(int vertexcount) {
adjList = (ArrayList<String>[]) new ArrayList[vertexCount];
...
}
...
public void addEdge(int i, int j) {
adjList[i].add(vList[j].label); //NULLPOINTEREXCEPTION HERE
}
...
}
I will really appreaciate if anyone can point me on the right track regrading to what its going wrong... Thanks!
You've created the array, but you still need to go through and create the ArrayList objects. As it's written, adjList[i] returns null because nothing has been assigned to it yet.
I see that you created the container but are you sure you populated the list with elements?
Why don't you add assert((adjList[i] != null) && (adjList[j] != null)) to addEdge just to be sure either of them are not null. Run with java -ea ...