Random contraction algorithm for finding Min Cuts in a graph - algorithm

Okay so here's my algorithm for finding a Cut in a graph (I'm not talking about a min cut here)
Say we're given an adjacency list of a non-directed graph.
Choose any vertice on the graph (let this be denoted by pivot)
Choose any other vertice on the graph (randomly). (denote this by x)
If the two vertices have an edge between them, then remove that edge from the graph. And dump all the vertices that x is connected to, onto pivot. (if not then go back to Step 2.
If any other vertices were connected to x, then change the adjacency list so that now x is replaced by pivot. Ie they're connected to Pivot.
If number of vertices is greater than 2 (go back to step 2)
If equal to 2. Just count number of vertices present in adjacency list of either of the 2 points. This will give the cut
My question is, is this algorithm correct?

That is a nice explanation of Krager's Min-Cut Algorithm for undirected graphs.
I think there might one detail you missed. Or perhaps I just mis-read your description.
You want to remove all self-loops.
For instance, after you remove a vertex and run through your algorithm, Vertex A may now have an edge that goes from Vertex A to Vertex A. This is called a self-loop. And they are generated frequently in process of contracting two vertices. As a first step, you can simply check the whole graph for self-loops, though there are some more sophisticated approaches.
Does that make sense?

I'll only change your randomization.
After choosing first vertex, choose another from his adjacency list. Now you are sure that two vertices have the edge between them. Next step is finding the vertex from adjancecy list.

Agree that you should definitely remove self-loop.
Also another point I want to add is after you randomly choose the first vertice, you don't have to randomly choose another node until you have one that is connected to the first node, you can simply choose from the ones that are connected to the first vertice because you know how many nodes are the first chosen one connects to. So a second random selection within a smaller range. This is just effectively randomly choosing an edge (determined by two nodes/vertices). I have some c# code implementing krager's algorithm you can play around. It's not the most efficient code (especially a more efficient data structure can be used) as I tested it on a 200 nodes graph, for 10000 iterations it takes about 30 seconds to run.
using System;
using System.Collections.Generic;
using System.Linq;
namespace MinCut
{
internal struct Graph
{
public int N { get; private set; }
public readonly List<int> Connections;
public Graph(int n) : this()
{
N = n;
Connections = new List<int>();
}
public override bool Equals(object obj)
{
return Equals((Graph)obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
private bool Equals(Graph g)
{
return N == g.N;
}
}
internal sealed class GraphContraction
{
public static void Run(IList<Graph> graphs, int i)
{
var liveGraphs = graphs.Count;
if (i >= liveGraphs)
{
throw new Exception("Wrong random index generation; index cannot be larger than the number of nodes");
}
var leftV = graphs[i];
var r = new Random();
var index = r.Next(0, leftV.Connections.Count);
var rightV = graphs.Where(x=>x.N == leftV.Connections[index]).Single();
foreach (var v in graphs.Where(x => !x.Equals(leftV) && x.Connections.Contains(leftV.N)))
{
v.Connections.RemoveAll(x => x == leftV.N);
}
foreach (var c in leftV.Connections)
{
if (c != rightV.N)
{
rightV.Connections.Add(c);
int c1 = c;
graphs.Where(x=> x.N == c1).First().Connections.Add(rightV.N);
}
}
graphs.Remove(leftV);
}
}
}

Related

Boost Graph identifying vertices from its created matrix

I have a table of vertices and edges and from this tables i created a Boost graph. each of the vertex edges had its id assign to it while the edges also contains length. now i want to prune the graph by removing nodes. my algorithm is done by creating a matrix of num_vertices. My problem is how to associate my matrix with the boost::vertices that is how do i know which of the matrix column correspond to my vertex in the graph since the matrix has no id. hope i am not thinking too complicated.
void Nodekiller::build_matrix(){
int ndsize=num_vertices(graph);
double matrixtb[ndsize][ndsize];
for(int i=0; i<ndsize;i++){
for (int j=0;j<ndsize; j++){
if(i==j) {matrixtb[i][j]=0;}
else {
matrixtb[i][j]=addEdgeValue(); //if none add random value
}
}
}
}
//i want to to sum each column and then prioritize them based on the values gotten.
so i don't know how to associate the boost::vertices(graph) with the matrix in other to be able to prune the graph.
The question is not very clear. Do I understand right:
You have a boost graph
You create a matrix from that graph?
So a first trivial question (maybe outside of the scope): do you really need two representations of the same graphe? one as a boost::graph, and an other as your matrix?
You can add and remove edges from a boost::graph easily. The easiest representation is the adjacency list: http://www.boost.org/doc/libs/1_55_0/libs/graph/doc/adjacency_list.html
Maybe a starting point could be this answer: adding custom vertices to a boost graph
You can create all your nodes, iterate on every node, and add a vertice only if the two nodes are different. Something like :
boost::graph_traits<Graph>::vertex_iterator vi, vi_end;
boost::tie(vi, vi_end) = boost::vertices(g);
boost::tie(vi2, vi2_end) = boost::vertices(g);
for (; vi != vi_end; ++vi) {
for (; vi2 != vi2_end; ++vi2) {
if(*vi != *vi2) {
boost::add_edge(
edge_t e; bool b;
boost::tie(e,b) = boost::add_edge(u,v,g);
g[e] = addEdgeValue();
}
}
}

Algorithm to find lowest common ancestor in directed acyclic graph?

Imagine a directed acyclic graph as follows, where:
"A" is the root (there is always exactly one root)
each node knows its parent(s)
the node names are arbitrary - nothing can be inferred from them
we know from another source that the nodes were added to the tree in the order A to G (e.g. they are commits in a version control system)
What algorithm could I use to determine the lowest common ancestor (LCA) of two arbitrary nodes, for example, the common ancestor of:
B and E is B
D and F is B
Note:
There is not necessarily a single path to a given node from the root (e.g. "G" has two paths), so you can't simply traverse paths from root to the two nodes and look for the last equal element
I've found LCA algorithms for trees, especially binary trees, but they do not apply here because a node can have multiple parents (i.e. this is not a tree)
Den Roman's link (Archived version) seems promising, but it seemed a little bit complicated to me, so I tried another approach. Here is a simple algorithm I used:
Let say you want to compute LCA(x,y) with x and y two nodes.
Each node must have a value color and count, resp. initialized to white and 0.
Color all ancestors of x as blue (can be done using BFS)
Color all blue ancestors of y as red (BFS again)
For each red node in the graph, increment its parents' count by one
Each red node having a count value set to 0 is a solution.
There can be more than one solution, depending on your graph. For instance, consider this graph:
LCA(4,5) possible solutions are 1 and 2.
Note it still work if you want find the LCA of 3 nodes or more, you just need to add a different color for each of them.
I was looking for a solution to the same problem and I found a solution in the following paper:
http://dx.doi.org/10.1016/j.ipl.2010.02.014
In short, you are not looking for the lowest common ancestor, but for the lowest SINGLE common ancestor, which they define in this paper.
I know it's and old question and pretty good discussion, but since I had some similar problem to solve I came across JGraphT's Lowest Common Ancestor algorithms, thought this might be of help:
NativeLcaFinder
TarjanLowestCommonAncestor
Just some wild thinking. What about using both input nodes as roots, and doing two BFS simultaneously step by step. At a certain step, when there are overlapping in their BLACK sets (recording visited nodes), algorithm stops and the overlapped nodes are their LCA(s). In this way, any other common ancestors will have longer distances than what we have discovered.
Assume that you want to find the ancestors of x and y in a graph.
Maintain an array of vectors- parents (storing parents of each node).
Firstly do a bfs(keep storing parents of each vertex) and find all the ancestors of x (find parents of x and using parents, find all the ancestors of x) and store them in a vector. Also, store the depth of each parent in the vector.
Find the ancestors of y using same method and store them in another vector. Now, you have two vectors storing the ancestors of x and y respectively along with their depth.
LCA would be common ancestor with greatest depth. Depth is defined as longest distance from root(vertex with in_degree=0). Now, we can sort the vectors in decreasing order of their depths and find out the LCA. Using this method, we can even find multiple LCA's (if there).
This link (Archived version) describes how it is done in Mercurial - the basic idea is to find all parents for the specified nodes, group them per distance from the root, then do a search on those groups.
If the graph has cycles then 'ancestor' is loosely defined. Perhaps you mean the ancestor on the tree output of a DFS or BFS? Or perhaps by 'ancestor' you mean the node in the digraph that minimizes the number of hops from E and B?
If you're not worried about complexity, then you could compute an A* (or Dijkstra's shortest path) from every node to both E and B. For the nodes that can reach both E and B, you can find the node that minimizes PathLengthToE + PathLengthToB.
EDIT:
Now that you've clarified a few things, I think I understand what you're looking for.
If you can only go "up" the tree, then I suggest you perform a BFS from E and also a BFS from B. Every node in your graph will have two variables associated with it: hops from B and hops from E. Let both B and E have copies of the list of graph nodes. B's list is sorted by hops from B while E's list is sorted by hops from E.
For each element in B's list, attempt to find it in E's list. Place matches in a third list, sorted by hops from B + hops from E. After you've exhausted B's list, your third sorted list should contain the LCA at its head. This allows for one solution, multiple solutions(arbitrarily chosen among by their BFS ordering for B), or no solution.
I also need exactly same thing , to find LCA in a DAG (directed acyclic graph). LCA problem is related to RMQ (Range Minimum Query Problem).
It is possible to reduce LCA to RMQ and find desired LCA of two arbitrary node from a directed acyclic graph.
I found THIS TUTORIAL detail and good. I am also planing to implement this.
I am proposing O(|V| + |E|) time complexity solution, and i think this approach is correct otherwise please correct me.
Given directed acyclic graph, we need to find LCA of two vertices v and w.
Step1: Find shortest distance of all vertices from root vertex using bfs http://en.wikipedia.org/wiki/Breadth-first_search with time complexity O(|V| + |E|) and also find the parent of each vertices.
Step2: Find the common ancestors of both the vertices by using parent until we reach root vertex Time complexity- 2|v|
Step3: LCA will be that common ancestor which have maximum shortest distance.
So, this is O(|V| + |E|) time complexity algorithm.
Please, correct me if i am wrong or any other suggestions are welcome.
package FB;
import java.util.*;
public class commomAnsectorForGraph {
public static void main(String[] args){
commomAnsectorForGraph com = new commomAnsectorForGraph();
graphNode g = new graphNode('g');
graphNode d = new graphNode('d');
graphNode f = new graphNode('f');
graphNode c = new graphNode('c');
graphNode e = new graphNode('e');
graphNode a = new graphNode('a');
graphNode b = new graphNode('b');
List<graphNode> gc = new ArrayList<>();
gc.add(d);
gc.add(f);
g.children = gc;
List<graphNode> dc = new ArrayList<>();
dc.add(c);
d.children = dc;
List<graphNode> cc = new ArrayList<>();
cc.add(b);
c.children = cc;
List<graphNode> bc = new ArrayList<>();
bc.add(a);
b.children = bc;
List<graphNode> fc = new ArrayList<>();
fc.add(e);
f.children = fc;
List<graphNode> ec = new ArrayList<>();
ec.add(b);
e.children = ec;
List<graphNode> ac = new ArrayList<>();
a.children = ac;
graphNode gn = com.findAncestor(g, c, d);
System.out.println(gn.value);
}
public graphNode findAncestor(graphNode root, graphNode a, graphNode b){
if(root == null) return null;
if(root.value == a.value || root.value == b.value) return root;
List<graphNode> list = root.children;
int count = 0;
List<graphNode> temp = new ArrayList<>();
for(graphNode node : list){
graphNode res = findAncestor(node, a, b);
temp.add(res);
if(res != null) {
count++;
}
}
if(count == 2) return root;
for(graphNode t : temp){
if(t != null) return t;
}
return null;
}
}
class graphNode{
char value;
graphNode parent;
List<graphNode> children;
public graphNode(char value){
this.value = value;
}
}
Everyone.
Try please in Java.
static String recentCommonAncestor(String[] commitHashes, String[][] ancestors, String strID, String strID1)
{
HashSet<String> setOfAncestorsLower = new HashSet<String>();
HashSet<String> setOfAncestorsUpper = new HashSet<String>();
String[] arrPair= {strID, strID1};
Arrays.sort(arrPair);
Comparator<String> comp = new Comparator<String>(){
#Override
public int compare(String s1, String s2) {
return s2.compareTo(s1);
}};
int indexUpper = Arrays.binarySearch(commitHashes, arrPair[0], comp);
int indexLower = Arrays.binarySearch(commitHashes, arrPair[1], comp);
setOfAncestorsLower.addAll(Arrays.asList(ancestors[indexLower]));
setOfAncestorsUpper.addAll(Arrays.asList(ancestors[indexUpper]));
HashSet<String>[] sets = new HashSet[] {setOfAncestorsLower, setOfAncestorsUpper};
for (int i = indexLower + 1; i < commitHashes.length; i++)
{
for (int j = 0; j < 2; j++)
{
if (sets[j].contains(commitHashes[i]))
{
if (i > indexUpper)
if(sets[1 - j].contains(commitHashes[i]))
return commitHashes[i];
sets[j].addAll(Arrays.asList(ancestors[i]));
}
}
}
return null;
}
The idea is very simple. We suppose that commitHashes ordered in downgrade sequence.
We find lowest and upper indexes of strings(hashes-does not mean).
It is clearly that (considering descendant order) the common ancestor can be only after upper index (lower value among hashes).
Then we start enumerating the hashes of commit and build chain of descendent parent chains . For this purpose we have two hashsets are initialised by parents of lowest and upper hash of commit. setOfAncestorsLower, setOfAncestorsUpper. If next hash -commit belongs to any of chains(hashsets),
then if current index is upper than index of lowest hash, then if it is contained in another set (chain) we return the current hash as result. If not, we add its parents (ancestors[i]) to hashset, which traces set of ancestors of set,, where the current element contained. That is the all, basically

Find all the paths forming simple cycles on an undirected graph

I am having some trouble writing an algorithm that returns all the paths forming simple cycles on an undirected graph.
I am considering at first all cycles starting from a vertex A, which would be, for the graph below
A,B,E,G,F
A,B,E,D,F
A,B,C,D,F
A,B,C,D,E,G,F
Additional cycles would be
B,C,D,E
F,D,E,G
but these could be found, for example, by calling the same algorithm again but starting from B and from D, respectively.
The graph is shown below -
My current approach is to build all the possible paths from A by visiting all the neighbors of A, and then the neighbors of the neightbors and so on, while following these rules:
each time that more than one neighbor exist, a fork is found and a new path from A is created and explored.
if any of the created paths visits the original vertex, that path is a cycle.
if any of the created paths visits the same vertex twice (different from A) the path is discarded.
continue until all possible paths have been explored.
I am currently having problems trying to avoid the same cycle being found more than once, and I am trying to solve this by looking if the new neighbor is already part of another existing path so that the two paths combined (if independent) build up a cycle.
My question is: Am I following the correct/better/simpler logic to solve this problem.?
I would appreciate your comments
Based on the answer of #eminsenay to other question, I used the elementaryCycles library developed by Frank Meyer, from web_at_normalisiert_dot_de which implements the algorithms of Johnson.
However, since this library is for directed graphs, I added some routines to:
build the adjacency matrix from a JGraphT undirected graph (needed by Meyer's lib)
filter the results to avoid cycles of length 2
delete repeated cycles, since Meyer's lib is for directed graphs, and each undirected cycle is two directed cycles (one on each direction).
The code is
package test;
import java.util.*;
import org.jgraph.graph.DefaultEdge;
import org.jgrapht.UndirectedGraph;
import org.jgrapht.graph.SimpleGraph;
public class GraphHandling<V> {
private UndirectedGraph<V,DefaultEdge> graph;
private List<V> vertexList;
private boolean adjMatrix[][];
public GraphHandling() {
this.graph = new SimpleGraph<V, DefaultEdge>(DefaultEdge.class);
this.vertexList = new ArrayList<V>();
}
public void addVertex(V vertex) {
this.graph.addVertex(vertex);
this.vertexList.add(vertex);
}
public void addEdge(V vertex1, V vertex2) {
this.graph.addEdge(vertex1, vertex2);
}
public UndirectedGraph<V, DefaultEdge> getGraph() {
return graph;
}
public List<List<V>> getAllCycles() {
this.buildAdjancyMatrix();
#SuppressWarnings("unchecked")
V[] vertexArray = (V[]) this.vertexList.toArray();
ElementaryCyclesSearch ecs = new ElementaryCyclesSearch(this.adjMatrix, vertexArray);
#SuppressWarnings("unchecked")
List<List<V>> cycles0 = ecs.getElementaryCycles();
// remove cycles of size 2
Iterator<List<V>> listIt = cycles0.iterator();
while(listIt.hasNext()) {
List<V> cycle = listIt.next();
if(cycle.size() == 2) {
listIt.remove();
}
}
// remove repeated cycles (two cycles are repeated if they have the same vertex (no matter the order)
List<List<V>> cycles1 = removeRepeatedLists(cycles0);
for(List<V> cycle : cycles1) {
System.out.println(cycle);
}
return cycles1;
}
private void buildAdjancyMatrix() {
Set<DefaultEdge> edges = this.graph.edgeSet();
Integer nVertex = this.vertexList.size();
this.adjMatrix = new boolean[nVertex][nVertex];
for(DefaultEdge edge : edges) {
V v1 = this.graph.getEdgeSource(edge);
V v2 = this.graph.getEdgeTarget(edge);
int i = this.vertexList.indexOf(v1);
int j = this.vertexList.indexOf(v2);
this.adjMatrix[i][j] = true;
this.adjMatrix[j][i] = true;
}
}
/* Here repeated lists are those with the same elements, no matter the order,
* and it is assumed that there are no repeated elements on any of the lists*/
private List<List<V>> removeRepeatedLists(List<List<V>> listOfLists) {
List<List<V>> inputListOfLists = new ArrayList<List<V>>(listOfLists);
List<List<V>> outputListOfLists = new ArrayList<List<V>>();
while(!inputListOfLists.isEmpty()) {
// get the first element
List<V> thisList = inputListOfLists.get(0);
// remove it
inputListOfLists.remove(0);
outputListOfLists.add(thisList);
// look for duplicates
Integer nEl = thisList.size();
Iterator<List<V>> listIt = inputListOfLists.iterator();
while(listIt.hasNext()) {
List<V> remainingList = listIt.next();
if(remainingList.size() == nEl) {
if(remainingList.containsAll(thisList)) {
listIt.remove();
}
}
}
}
return outputListOfLists;
}
}
I'm answering this on the basis that you want to find chordless cycles, but it can be modified to find cycles with chords.
This problem reduces to finding all (inclusion) minimal paths between two vertices s and t.
For all triplets, (v,s,t):
Either v,s,t form a triangle, in which case, output it and continue to next triplet.
Otherwise, remove v and its neighbor except s and t, and enumerate all s-t-paths.
Finding all s-t-paths can be done by dynamic programming.

How to create distinct set from other sets?

While solving the problems on Techgig.com, I got struck with one one of the problem. The problem is like this:
A company organizes two trips for their employees in a year. They want
to know whether all the employees can be sent on the trip or not. The
condition is like, no employee can go on both the trips. Also to
determine which employee can go together the constraint is that the
employees who have worked together in past won't be in the same group.
Examples of the problems:
Suppose the work history is given as follows: {(1,2),(2,3),(3,4)};
then it is possible to accommodate all the four employees in two trips
(one trip consisting of employees 1& 3 and other having employees 2 &
4). Neither of the two employees in the same trip have worked together
in past. Suppose the work history is given as {(1,2),(1,3),(2,3)} then
there is no way possible to have two trips satisfying the company rule
and accommodating all the employees.
Can anyone tell me how to proceed on this problem?
I am using this code for DFS and coloring the vertices.
static boolean DFS(int rootNode) {
Stack<Integer> s = new Stack<Integer>();
s.push(rootNode);
state[rootNode] = true;
color[rootNode] = 1;
while (!s.isEmpty()) {
int u = s.peek();
for (int child = 0; child < numofemployees; child++) {
if (adjmatrix[u][child] == 1) {
if (!state[child]) {
state[child] = true;
s.push(child);
color[child] = color[u] == 1 ? 2 : 1;
break;
} else {
s.pop();
if (color[u] == color[child])
return false;
}
}
}
}
return true;
}
This problem is functionally equivalent to testing if an undirected graph is bipartite. A bipartite graph is a graph for which all of the nodes can be distributed among two sets, and within each set, no node is adjacent to another node.
To solve the problem, take the following steps.
Using the adjacency pairs, construct an undirected graph. This is pretty straightforward: each number represents a node, and for each pair you are given, form a connection between those nodes.
Test the newly generated graph for bipartiteness. This can be achieved in linear time, as described here.
If the graph is bipartite and you've generated the two node sets, the answer to the problem is yes, and each node set, along with its nodes (employees), correspond to one of the two trips.
Excerpt on how to test for bipartiteness:
It is possible to test whether a graph is bipartite, and to return
either a two-coloring (if it is bipartite) or an odd cycle (if it is
not) in linear time, using depth-first search. The main idea is to
assign to each vertex the color that differs from the color of its
parent in the depth-first search tree, assigning colors in a preorder
traversal of the depth-first-search tree. This will necessarily
provide a two-coloring of the spanning tree consisting of the edges
connecting vertices to their parents, but it may not properly color
some of the non-tree edges. In a depth-first search tree, one of the
two endpoints of every non-tree edge is an ancestor of the other
endpoint, and when the depth first search discovers an edge of this
type it should check that these two vertices have different colors. If
they do not, then the path in the tree from ancestor to descendant,
together with the miscolored edge, form an odd cycle, which is
returned from the algorithm together with the result that the graph is
not bipartite. However, if the algorithm terminates without detecting
an odd cycle of this type, then every edge must be properly colored,
and the algorithm returns the coloring together with the result that
the graph is bipartite.
I even used a recursive solution but this one is also passing the same number of cases. Am I leaving any special case handling ?
Below is the recursive solution of the problem:
static void dfs(int v, int curr) {
state[v] = true;
color[v] = curr;
for (int i = 0; i < numofemployees; i++) {
if (adjmatrix[v][i] == 1) {
if (color[i] == curr) {
bipartite = false;
return;
}
if (!state[i])
dfs(i, curr == 1 ? 2 : 1);
}
}
}
I am calling this function from main() as dfs(0,1) where 0 is the starting vertex and 1 is one of the color

Algorithm that will grab all nodes attached to a particular node

I am creating an algorithm that is based on directed graphs. I would like a function that will grab all the nodes that are attached to a particular node.
public List<Node> GetNodesInRange(Graph graph, int Range, Node selected)
{
var result = new List<Node>();
result.Add(selected);
if (Range > 0)
{
foreach (Node neighbour in GetNeighbours(graph, selected))
{
result.AddRange(GetNodesInRange(graph, Range - 1, neighbour));
}
}
return result;
}
private List<Node> GetNeighbours(Graph graph, Node selected)
{
foreach(Node node in graph.node)
{
if (node == selected)
{
GetNodesInRange(node, Range-1, /*don't know what 2 do here*/);
//and confused all the way down
It depends on which kind of implementation you are using for your graph:
edge list: you search all edges that have the specified vertex as first or second parameter to the edge
adjacency list: the list attached to a node is already the list of nodes incident to it
adjacency matrix: you take the column (or row) of the vertex that you chose
You are calling GetNodesInRange inside GetNeighbours and GetNeighbours inside GetNodesInRange and that is creating problem.
Look at the answer by Jack.
And if you post how your Graph,Node and Edge looks like then we will be able to offer more help.

Resources