We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Weighted graph Kruskal, next step help
Page Index Toggle Pages: 1
Weighted graph Kruskal, next step help (Read 1656 times)
Weighted graph Kruskal, next step help
Mar 14th, 2009, 3:12pm
 
Hi

I was reading Robert Sedgewick´s "Algorithms in Java" and stumbled on the part about Graphs. I have never done much in this area and decided to try and implement some simple Prim, Kruskal and maybe Dijkstra.

The examples in the book are near to impossible to follow as Robert takes every effort to only use one letter variable and array names plus he implements his own small environment for algorithms, which I can't get a hold on... shame on You Robert!

Well, the very abstract steps in the Kruskal algorithm sounds simple at first:
Quote:
Kruskal'’s algorithm works as follows: Take a graph with 'n' vertices, keep adding the shortest (least cost) edge, while avoiding the creation of cycles, until (n - 1) edges have been added. (NOTE: Sometimes two or more edges may have the same cost. The order in which the edges are chosen, in this case, does not matter. Different MSTs may result, but they will all have the same total cost, which will always be the minimum cost)


I made a weighted graph, composed by an ArrayList of n random points (Vertex(x, y), then I made an ArrayList with every possible edge, this is an Edge object containing start Vertex, end Vertex and weight (distance).
Now I sorted that ArrayList with respect to weight, ascending.

Ok, already and now what? The definition states that I start out by taking the Edges with the smallest weights, *that does not create a cycle* and add these to my minimum spanning tree until I added n-1 edges.

The part about not creating a cycle is what Im having a hard time realizing:

Code:

ArrayList vertices, edges;
int numOfVertex = 100;

void setup()
{
size(600, 500);
background(0);
stroke(255, 255, 255, 45);
strokeWeight(2);
fill(255, 255, 255, 100);
vertices = new ArrayList();
edges = new ArrayList();

for(int i = 0; i < numOfVertex; i++)
{
vertices.add(new Vertex(random(width), random(height))); //add the random vertices
Vertex v = (Vertex) vertices.get(i);
ellipse(v.x, v.y, 4, 4); //draw it to the screen
}
buildEdges();
drawEdges();
}

void buildEdges()
{
int currentVertex = 0;
while(currentVertex < numOfVertex) //first measure n weights, then n-1 weights and so on.
{
for(int i = currentVertex; i < numOfVertex-1; i++)
{
edges.add(new Edge((Vertex)vertices.get(currentVertex), (Vertex)vertices.get(i+1)));
}
currentVertex++;
}
Collections.sort(edges); //sort the edges so edges with smaller weights are first
}

void drawEdges()
{
for(int i = 0; i < numOfVertex; i++) //draw edges
{
Edge e = (Edge)edges.get(i);
line(e.start.x, e.start.y, e.end.x, e.end.y);
}
}

Code:

class Edge implements Comparable{
//Edges consists of a start Vertex, end Vertex and a weight
public Vertex start;
public Vertex end;
public float weight;

Edge(Vertex s, Vertex e)
{
start = s;
end = e;
weight = dist(s.x, s.y, e.x, e.y);
}

public int compareTo(Object edge) //overrides compareTo so I can use Collections to sort the edges
{
Edge n = (Edge) edge;
float w1 = weight;
float w2 = n.getWeight();
return w1 == w2 ? 0 : (w1 > w2 ? 1 : -1);
}

public float getWeight()
{
return weight;
}
}



Code:

class Vertex{
//Could use PVector, but this does just fine
public float x;
public float y;

Vertex(float _x, float _y)
{
x = _x;
y = _y;
}
}


Any help is appreciated :)
Re: Weighted graph Kruskal, next step help
Reply #1 - Mar 14th, 2009, 4:23pm
 
not creating a cycle is simply a case of not revisiting a node you're already been to during your traversal. just keep a hashset (or map) containing the nodes you've already been to (you may already have one) and check it before adding the new node.
Re: Weighted graph Kruskal, next step help
Reply #2 - Mar 14th, 2009, 4:53pm
 
Hi koogs

Thanks, I am still a bit hazy on the actual implementation.
I have the list of vertices and a list of edges, containing the vertices.
Maybe my graph is put together the wrong way, since I can't really see how to traverse it.
a
The Edge list is every possible edge between the vertices, hmm should I map the data in a different way...w
Re: Weighted graph Kruskal, next step help
Reply #3 - Mar 15th, 2009, 3:17pm
 
Hi

Im still stuck in the implementation part. Every source of info I find is either extremely abstract and described with "regular words" and small pictures or extremely weighted towards code and does not show the graph or the format of it.

I make my own graph from random points in the sketch, so the program is just meant to 1: draw n random points  2: build a weighted graph from these points 3: construct the minimum spanning tree, using the distance as the weight.
The minimum spanning tree would in this case, I guess, be an array of Edges that make up the tree.

So I don't know how to structure the graph to get to the next step.
The approach I took is just a strictly "OOP" way of solving it. Make a Vertex class consisting of the x, y and an id (V1, V2, V3....Vn) then I combine every two Vertices into an Edge object. Edge(startVertex, endVertex) and now all I need is easily accessible, but I can't figure out what to do with it...

When writing(overriding the toString) out my graph, the Edges objects, I have this:
Quote:
V0-V3(87.40597)
V1-V4(138.25545)
V0-V1(297.51062)
V0-V4(308.27765)
V0-V2(313.21295)
V2-V4(333.14572)
V1-V3(355.55353)
V2-V3(386.82214)
V3-V4(387.57074)
V1-V2(436.22794)


This means, from the top, "V0 is connected to V3 and the distance between them is (87.40597 pixels)" the graph is sorted with the smallest distances first.

So I guess I have all the info I need to build a Prim, Kruskal or Dijkstra algorithm to find the minimum spanning tree.

I just can't get my head around the flow of constructing the tree from the graph without producing cycles or having to traverse the graph a lot more then n-1 times :/

Pseudo code, kick in the groin, angry yelling or napkin blueprints.... anything is welcome.
Thanks.
Re: Weighted graph Kruskal, next step help
Reply #4 - Mar 15th, 2009, 8:41pm
 
i had a very clear dijkstra page somewhere which stepped through the algorithm. can't find it now though, have a paper copy somewhere but my flat is a tip...

this, though, is useful. quite a clear description and an applet that you can step through:

http://students.ceid.upatras.gr/~papagel/project/kruskal.htm

although the trees aspect of it i haven't worked out yet (my code is currently about half complete compared to yours).
Re: Weighted graph Kruskal, next step help
Reply #5 - Mar 15th, 2009, 9:07pm
 
Hi koogs

Thanks for the link, I think I actually went there yesterday evening, but I have visited so many algorithm sites the last couple of days that I actually think I saw Skynet at least one time:)

I have been playing around with it the last hour or so and I am currently trying out an approach that I think will work, then afterwards I will have to see how many more steps my try needs compared to the Kruskal/Prims.

I did a small pseudo code that I am implementing, just to get my head around it:
Quote:
Three vertices, V1, V2, V3
//These are 3 random points and their distance to each other
//is the weight of the graph

First build all possible edges:
V1-V2
V1-V3
V2-V3
//not the redundant ones, like V2-V1, V3-V1
//now sort them according to distance
//all good :)
//make MST array for holding the map

buildMST
{
try first edges:
V1-V2
if(MST contain an edge with V1 or V2 as the endpoint)
test if Vx-V1 and Vx-V3 exists;
will create cycle, remove edge and break
else
add edge to MST and remove edge from edgeArray;
//the reason I remove it from edges is that I
//loop through edge each time to test for edges
//and by making it smaller each time I reduce that
//time
try second edge;
}

when edges.size() - 1 edges have been added to the MST the map is complete.


If it works I will post it and we can compare notes :)
Re: Weighted graph Kruskal, next step help
Reply #6 - Mar 16th, 2009, 11:49pm
 
ick, anything indented over 6 spaces deep gets mangled so i won't paste the code here but...

http://www.koogy.clara.co.uk/Kruskal/

most of the logic is in the mousePressed() which handles adding nodes to trees and most of the useful information is printed to stdout when you click but you don't get to see this in the applet. but the results look convincing enough.
Re: Weighted graph Kruskal, next step help
Reply #7 - Mar 17th, 2009, 2:15pm
 
Hi koogs

This is just great, the trick was the "tree" variable in the Vertex/node objects and the "connected" boolean in the Edge objects. That did the trick, I was moving towards matrix, x-dimensional array or a hashMap, but just letting each node/edge hold this info makes it way more simple:)

So I implemented your "engine" in my version and played around with it.
I will post it on my blog (which actually is just hotel waiting for me to install wordpress, hope it is up before thursday) I will comment it a bit and see if I can write up an ActionScript3 version of it to see how it handles in terms of speed.

Thanks again :)
Re: Weighted graph Kruskal, next step help
Reply #8 - Mar 17th, 2009, 4:34pm
 
well, i rewrote it a bit in my head in the bath this morning and figured it'd be neater with a few changes

maybe move all the connecting stuff to the Edge class, pass it current tree number and have it return a boolean (added vs ignored) so you know when to increment the master count of connected edges (that said, the 'joining different trees' loop is a bit ugly in an oop sense, i think)

it might be cleaner (more readable) to change the comparison order:

Code:

if (n0.tree == n1.tree) {
// same
if (n0 == -1) {
// add both to new tree
} else {
// same tree - do nothing
}
} else {
// different
if (n0.tree == -1) {
// add node 0 to node 1 tree
} else if (n1.tree == -1) {
// add node 1 to node 0 tree
} else {
// merge trees
}
}


am sure there's some simplification that can be done there, it's the only gnarly bit of code. there are 6 cases but am sure a lot of them have a lot in common.

and add some stuff to show an edge being considered and rejected as it looks like it's done nothing when you click sometimes.

oh, and use your comparator over mine - mine's a bit slapdash.
Re: Weighted graph Kruskal, next step help
Reply #9 - Mar 17th, 2009, 4:51pm
 
Hi

Yeah I also have an idea that code should look "pretty", but I have seen the implementation the Algorithms in Java book, and it is not pretty.

I would like for the sketch to just be run, then display all edges and then, in a tempo your eye can keep up with, draw the MST.

About the test inside the Edge object, Im generally against it, the Edge should only know about the nodes, and the nodes should not know about anything.

I did spread our code out over an "Main", "Edge" "Vertex" "GraphBuilder" and "ProcessMST" class, so I can play around with a way to "animate" the progress and also I would like to make a "ProcessShortestPath" "ProcessDirected" and so on later on. It is just easier if the algorithm it self is incapsulated in a class that takes an object from the GraphBuilder as an input.

I'll just zip the sketch folder for you, till the blog comes up.
http://ors.dk/processing/KruskalsAlgorithm/

It looks pretty cool with all the edges draw in thin white and the path in red.
http://ors.dk/processing/900nodes.png

My MacBook Air makes processing go "To many recursive steps" at around 1000 nodes :)
Re: Weighted graph Kruskal, next step help
Reply #10 - Mar 17th, 2009, 5:19pm
 
http://ors.dk/processing/applet/

Here was the applet, with a ver. 0.5 animation
Re: Weighted graph Kruskal, next step help
Reply #11 - Mar 17th, 2009, 7:21pm
 
nice.

but needs some indication that it is still working - i often see it get to a point where 90% of the nodes are attached and then it just appears to sit there. i know it's probably testing 100s of edges already in the same tree and it'll connect the last few nodes when it gets to them but it often looks like it's finished before it has.

(either that or there's a bug!)

> MacBook Air

there's your problem 8)
Re: Weighted graph Kruskal, next step help
Reply #12 - Mar 17th, 2009, 10:08pm
 
ah, ok, it's the drawing that makes it look like the last of the nodes aren't being connected - it takes a while for the red line to appear but the drawing stops before it has a chance. i guess that's why it's version 0.5 8)
Re: Weighted graph Kruskal, next step help
Reply #13 - Mar 18th, 2009, 8:34am
 
Exactly why it is 0.5 Smiley

The red lines have an alpha of something < 10 and it is only because they get drawn on top of each other every time a new one is added that you can see them. The last one only gets drawn once, cause then I stop calling the redraw function.

I only posted it because it looked a bit funny, working on a draw class to do the real drawing in a more elegant way.

P.s. My criteria is always that a sketch must run on my MacBook before I test it elsewhere, so I sometimes get really surprised to see how fast it runs on a "real" computer:)
Re: Weighted graph Kruskal, next step help
Reply #14 - Apr 1st, 2009, 9:04am
 
Hi koogs, if you are out there:)

I was just writing up a small graph post on my brand new blog and would like to acknowledge you for the help on the Kruskal algorithm.

Do you have a website or similar I could mention?

You could drop a line at "hi (at) rickigregersen.com" and maybe take a peek at the blog (the domain above).
I have not done any proof reading yet and my English needs dusting:)
Page Index Toggle Pages: 1