I'm a beginner and I am trying to find the minimum cut of a graph using Kruskal's algorithm in Java.
I have gotten to where I can read the input and create vertexCount^2 number of MST's with random weights for the edges. All I have left to do is figure out from my MST how many cuts are required to separate S and V-S. This will allow me to choose the minimum out of the vertexCount^2 number of choices.
I think I understand correctly that I am supposed to ignore the last edge of the MST to get S and V-S. But I'm lost on how to figure out how many edges are connecting S and V-S.
So my question is: 1) Is vertexCount^2 random MST's enough to be confident that it will contain the minimum-cut? 2) How can I find how many edges are connecting S and V-S?
PS. This is a snippet form my code:
// create weighted edge graph from input.txt
int vertexCount, edgeCount;
Edge edgeTemp;
vertexCount = s.nextInt();
edgeCount = s.nextInt();
EdgeWeightedGraph G = new EdgeWeightedGraph(vertexCount, edgeCount);
for (int j = 0; j < edgeCount; j++) {
edgeTemp = new Edge(s.nextInt(), s.nextInt(), new Random().nextInt(edgeCount));
G.addEdge(edgeTemp);
}
// create kruskal's mst from graph G
for (int j = 0; j < vertexCount*vertexCount; j++) {
KruskalMST mst = new KruskalMST(G);
for (Edge e : mst.edges()) {
System.out.println(e);
}
System.out.println(NEWLINE);
if (j != vertexCount*vertexCount - 2)
G.randomizeWeight(edgeCount);
}
PSS. In case this is relevant, I looked at the code from http://algs4.cs.princeton.edu/43mst/ when writing my code.
When getting the MST from the graph, I used Kruskal's algorithm. That means I must have used union and find methods.
Each vertex is its own parent in the beginning. When getting the union of distinct components from the graph, I assign the combining components (including singletons) to have a single parent. So by the time I'm left with S and V-S, all the vertices of each component will have the same parent!
Therefore, I go back to my EdgeWeightedGraph and iterate all the edges in the graph (not the MST!). When I find an edge whose two vertices have different parents, that means that the edge connects component S and V-S. I count++ every time I see an edge like this.
This gives me the total number of cuts needed in the graph!
Related
I'm a student in computing sciences in Paris. In mathematics this year we have to use the K-means algorithm to solve a problem (the Clustered Capacited Vehicle Routing Problem applied to the resupplying of self-service bicycles' stations). Here is my algorithm :
public void run() {
boolean hasConverged = false;
List<Integer> nearestClusters = null;
//A list used to check if the nearestClusters list has evolved
//If it isn't the case, the algorithm is finish
List<Integer> previousList = new ArrayList<Integer>();
//Random initialization of the clusters' centroids
for (int i = 0; i < clustersNumber; ++i) {
clusters.add(ClusterGenerator.Generate(stationsList,colorList.get(i) ,latMin, latMax, lngMin, lngMax));
}
while (!hasConverged) {
if (nearestClusters != null) {
previousList.clear();
previousList.addAll(nearestClusters);
}
nearestClusters= new ArrayList<Integer>();
//Each point is connected to it nearest cluster
for (int j = 0; j < stationsList.size(); ++j) {
nearestClusters.add(getIndexOfTheNearestCluster(stationsList.get(j)));
}
//We move the clusters centroids to the center of the points they are connected to
for (int k = 0; k < clusters.size(); ++k) {
clusters.get(k).setCentre(stationsCenters(getStationsOfCluster(clusters.get(k), nearestClusters)));
}
if (!nearestClusters.isEmpty() && previousList.equals(nearestClusters))
hasConverged = true;
}
}
Yet, I wanted to show the result of my algorithm with the clusters formed and I found this work on the Internet : https://github.com/ertugrulozcan/K-Means-Simulation
I imported in my project the class ClusterGenerator which creates clusters along with random elements, the class Item, the class Graphic (I didn't touch anything there) and the class MainWindow which initiates all the graphic elements.
I did not manage to display the plots and there are no errors in Eclipse that could give me any clue.
Can someone please explain to me where is the problem ?
Thanks
The problem was that my algorithm was generating clusters for the stations but I did not configure the class Graphic (which I understood later was very important for the display) to render correctly my points. Since, I used latitude and longitude as coordinates for my station, I had to put these coordinates to scale for the window. Here is how I did that (using cross multiplications) : I calculate the "gap" between two units in the graph and added an adjustment because I don't start at zero.
double gapX = (this.getWidth() - 2 * edgeSpace) / (topX-bottomX+1);
int adjustmentX =(int) (-bottomX*gapX);
(getWidth() gives the actual width of the panel where is the graph, edgespace is the padding space between the graph and the edge of the panel, topX is the maximum value of a coordinate and bottomX the minimum value)
it's my first time with CGAL, some of you may argue why do I have to learn CGAL from something like that, but it's a new project that I must do (and... yes, I must use CGAL and Java combined) :/ Long story short... I only have:
Two double arrays, representing x and y coordinates of my vertices. Let's call them double[] x, y;.
Both arrays have S random values.
Two vertices, u and w are connected if distance(x[u], y[u], x[w], y[w]) < CONSTANT (ofc. I do distanceSquared(x[u], y[u], x[w], y[w]) < CONSTANT_SQUARED, so I avoid to call sqrt()).
x and y are filled randomly with values from 0 to UPPER_LIMIT, no other infos are given.
Question, do x and y describes a connected graph?
Right now I have two algoritms:
Algorithm 1:
Build adjacency list (Arraylist<Integer>[] adjLists;) for each vertex (only upper triangular matrix explored). Complexity O(|V|^2) (V = vertices set).
Recursive graph exploration, vertex marking and counting, if visited vertex equals S my graph have only one connected component, my graph is connected. Complexity O(|E|) (E = edges set).
Algorithm 2:
private static boolean algorithmGraph(double[] x, double[] y) {
int unchecked, inside = 0, current = 0;
double switchVar;
while (current <= inside && inside != S - 1) {
unchecked = inside + 1;
while (unchecked < S) {
if ((x[current] - x[unchecked]) * (x[current] - x[unchecked]) + (y[current] - y[unchecked]) * (y[current] - y[unchecked]) <= CONSTANT_SQUARED) {
inside++;
// switch x coordinates | unchecked <-> inside
switchVar = x[unchecked];
x[unchecked] = x[inside];
x[inside] = switchVar;
// switch y coordinates | unchecked <-> inside
switchVar = y[unchecked];
y[unchecked] = y[inside];
y[inside] = switchVar;
}
unchecked++;
}
current++;
}
return inside == S - 1;
}
Funny thing the second one is slower, I do not use data structures, the code is iterative and in-place but the heavy use of switch makes it slow as hell.
The problem spec changed and now I must do it with CGAL and Java, I'll read the whole "https://github.com/CGAL/cgal-swig-bindings" to learn how to use CGAL within Java.... but I'd like some help about this specific instance of CGAL code... Are there faster algorithms already implemented in CGAL?
Thank you for your times guys! Happy coding!
I believe that, without a method of spatial indexing, the best performance you are going to achieve in the worst-case-scenario (all connected) is going to be O(n*(n-1)/2).
If you can afford to build a spatial index (have enough memory to pay for the boost in speed), you may consider R-tree and variants - insertion is O(n) searching is O(log2(n)): this will get your "outlier detection by examining distances" approach for a cost of of O(n*log2(n)) in the worst-case-scenario.
A notable result
I'm trying to implement the min-cut Karger's algorithm in Java. For this, I created a Graph class which stores a SortedMap, with an integer index as key and a Vertex object as value, and an ArrayList of Edge objects. Edges stores the index of its incident vertices. Than I merge the vertices of some random edge until the number of vertices reach 2. I repeat this steps a safe number of times. Curiously, in my output I get 2x the number of crossing edges. I mean, if the right answer is 10, after execute n times the algorithm (for n sufficient large), the min of these execution results is 20, what makes me believe the implementation is almost correct.
This is the relevant part of code:
void mergeVertex(int iV, int iW) {
for (int i = 0; i < edges.size(); i++) {
Edge e = edges.get(i);
if (e.contains(iW)) {
if (e.contains(iV)) {
edges.remove(i);
i--;
} else {
e.replace(iW, iV);
}
}
}
vertices.remove(iW);
}
public int kargerContraction(){
Graph copy = new Graph(this);
Random r = new Random();
while(copy.getVertices().size() > 2){
int i = r.nextInt(copy.getEdges().size());
Edge e = copy.getEdges().get(i);
copy.mergeVertex(e.getVertices()[0], e.getVertices()[1]);
}
return copy.getEdges().size()/2;
}
Actually the problem was much more simple than I thought. While reading the .txt which contains the graph data, I was counting twice each edge, so logically the minCut returned was 2 times the right minCut.
I'm so confused by graphs and adjacency matrices. I'm doing an assignment for a class where I have a text file of nodes and a text file of edges and I have to read each of them and make them a graph onto which I can then perform operations such as determining if the graph is connected, finding a minimal spanning tree, traversals and finding paths. I've never worked with graphs before though, and I'm really confused by the whole thing, and I was wondering if someone could help explain some of this to me.
Firstly, do I build a graph on its own (with node and edges classes perhaps?) and then construct an adjacency matrix from that? Or is the adjacency matrix itself the graph?
And then I'm confused on how to implement the adjacent matrix into the program. The nodes are names things like "ND5" and "NR7" and so I would have to set and read the edges of [ND5][NR7] but I'm not sure how to set up a 2d array like that with strings for the outside and numbers on the inside.
I've been searching all over the internet and read through the whole chapter on graphs in my textbook, and I'm really not understanding just the first basic steps of getting this graph set up. I'd really appreciate the help. Thanks.
Firstly, do I build a graph on its own (with node and edges classes perhaps?) and then construct an adjacency matrix from that? Or is the adjacency matrix itself the graph?
There is no way anyone can answer that question for sure without actually reading the instructions for your assignment. However, unless the assignment specifically mentions Node and Edge classes or something, my guess is that you're just supposed to use the adjacency matrix to represent your graph.
And then I'm confused on how to implement the adjacent matrix into the program. The nodes are names things like "ND5" and "NR7" and so I would have to set and read the edges of [ND5][NR7] but I'm not sure how to set up a 2d array like that with strings for the outside and numbers on the inside.
I can totally understand your confusion here. What you actually want to do is create a bijection (a one-to-one relationship) between your node names and the indices of your matrix. For example, if you have n nodes in your graph, then you need an n×n matrix (i.e. new boolean[n][n]), and each of your nodes would correspond to a single integer in the range 0 until n (not inclusive of n).
I'm not sure what data structures you've covered in your class so far, but the easiest way to do this would probably be to use a Map<String, Integer>, which would let you look up a name like "ND5" and get back an integer (the index).
Another nice alternative might be to use an array. You could put all your node names into an array, sort it with Arrays.sort, and then once it's sorted you can use Arrays.binarySearch to find the index of a particular node name in that array. I think this solution is actually better than using a Map because it lets you do the lookups both ways. You use Arrays.binarySearch to do name-to-index lookups, and you just index into the array to do an index-to-name lookup.
Example: Let's say we have this graph:
Given that graph, here's some sample code of how you could do this: (warning! it's untested)
import java.util.Arrays;
// Add all your node names to an array
String[] nameLookup = new String[4];
nameLookup[0] = "A";
nameLookup[1] = "B";
nameLookup[2] = "C";
nameLookup[3] = "D";
// Our array is already properly sorted,
// but yours might not be, so you should sort it.
// (if it's not sorted then binarySearch won't work)
Arrays.sort(nameLookup);
// I'm assuming your edges are unweighted, so I use boolean.
// If you have weighted edges you should use int or double.
// true => connected, false => not connected
// (entries in boolean arrays default to false)
boolean[][] matrix = new boolean[4];
for (int i=0; i<matrix.length; i++) matrix[i] = new boolean[4];
// I don't want to call Arrays.binarySearch every time I want an index,
// so I'm going to cache the indices here in some named variables.
int nodeA = Arrays.binarySearch(nameLookup, "A");
int nodeB = Arrays.binarySearch(nameLookup, "B");
int nodeC = Arrays.binarySearch(nameLookup, "C");
int nodeD = Arrays.binarySearch(nameLookup, "D");
// I'm assuming your edges are undirected.
// If the edges are directed then the entries needn't be semmetric.
// A is connected to B
matrix[nodeA][nodeB] = true;
matrix[nodeB][nodeA] = true;
// A is connected to D
matrix[nodeA][nodeD] = true;
matrix[nodeD][nodeA] = true;
// B is connected to D
matrix[nodeB][nodeD] = true;
matrix[nodeD][nodeB] = true;
// C is connected to D
matrix[nodeC][nodeD] = true;
matrix[nodeD][nodeC] = true;
// Check if node X is connected to node Y
int nodeX = Arrays.binarySearch(nameLookup, stringNameOfX);
int nodeY = Arrays.binarySearch(nameLookup, stringNameOfY);
if (matrix[nodeX][nodeY]) { /* They're connected */ }
// Print all of node Z's neighbors' names
int nodeZ = Arrays.binarySearch(nameLookup, stringNameOfZ);
for (int i=0; i<matrix.length; i++) {
if (matrix[nodeZ][i]) {
System.out.println(nameLookup[nodeZ] + " is connected to " + nameLookup[i]);
}
}
I'm trying to find the set of vertices that minimizes their distance to other vertices on a weighted graph. Based on a cursory wikipedia search, I think that this is called the Jordan Center. What are some good algorithms for finding it?
Right now, my plan is to get a list of the weight for each branch emanating from a given vertex. The vertices whose weights have the smallest relative difference will be the central ones. Any other ideas?
I'm using Java, but helpful answers don't necessarily need to be Java specific.
I woluld first use Dijkstra algorithm (it has to be run for each verticle) for computng shortest distances between all pairs of verticles - there are also some more efficient algorithms for that like Floyd-Warshall. Then for each verticle V you have to find Vm - the largest distance to any other verticles amongs the data retuirned form Dijkstra algorithm. Then, the verticles with the smallest Vm are the one in the graph center. Pseudocode:
int n = number of verticles;
int[][] D = RunDijkstraOrWarshall()
// D[a,b] = length of shortest path from a to b
int[] Vm = new int[n];
for(int i=0; i<n i++)
{
Vm[i] = 0
for(int j=0; j<n; j++)
{
if (Vm[i] < D[i,j]) Vm[i] = D[i,j];
}
}
minVm = int.Max;
for(int i=0; i<n ;i++)
{
if (minVm < Vm[i]) minVm = Vm[i];
}
for(int i=0; i<n ;i++)
{
if (Vm[i] == minVm)
{
// graph center contans i
}
}
Three algorithms for graph center problem are presented in this MSc thesis: A distributed algorithm for the graph center problem.
Starting from JGraphT version 1.1.0, you can simply use the method GraphMeasurer.getGraphCenter(). The underlying code uses a shortest path method. The user can choose which method to use, depending on some characteristics of the graph (e.g. sparse/dense/...).