// GraphTea Project: http://github.com/graphtheorysoftware/GraphTea
// Copyright (C) 2012 Graph Theory Software Foundation: http://GraphTheorySoftware.com
// Copyright (C) 2008 Mathematical Science Department of Sharif University of Technology
// Distributed under the terms of the GNU General Public License (GPL): http://www.gnu.org/licenses/
package graphtea.extensions.reports.connectivity;
import graphtea.graph.graph.GraphModel;
import graphtea.graph.graph.Vertex;
import graphtea.platform.lang.CommandAttitude;
import graphtea.plugins.reports.extension.GraphReportExtension;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
/**
* @author M. Ali Rostami
*/
@CommandAttitude(name = "k_vertex_connectivity", abbreviation = "_kvc")
public class KConnected implements GraphReportExtension {
public Object calculate(GraphModel g) {
return kconn(g);
}
public static int kconn(GraphModel g) {
int pre;
int now = Integer.MIN_VALUE;
boolean preconn, nowconn;
for (Vertex v : g.vertices())
now = Math.max(now, g.getDegree(v));
nowconn = kdisconn(g, now - 1) == null;
do {
preconn = nowconn;
pre = now;
if (preconn) now = pre + 1;
else now = pre - 1;
nowconn = kdisconn(g, now - 1) == null;
} while (!((preconn && !nowconn && pre == now - 1) || (!preconn
&& nowconn && pre == now + 1)));
if (!preconn)
return now;
return pre;
}
public static Vertex[] kdisconn(GraphModel g, int k) {
LinkedList<Integer> remain = new LinkedList<>();
HashSet<Integer> popped = new HashSet<>();
boolean[] done = new boolean[g.numOfVertices()];
specArr karray = new specArr(k, g.numOfVertices());
if (k >= g.numOfVertices())
return g.getVertexArray();
do {
remain.clear();
popped.clear();
Arrays.fill(done, false);
for (int j = 0; j < k; j++)
popped.add(karray.get(j));
for (int j = 0; remain.size() == 0; j++)
if (!popped.contains(j))
remain.add(j);
while (remain.size() > 0) {
Vertex n = g.getVertex(remain.poll());
Integer index;
done[n.getId()] = true;
for (Vertex o : g.getNeighbors(n)) {
index = o.getId();
if (!done[index] && !remain.contains(index)
&& !popped.contains(index))
remain.add(index);
}
}
for (int i = 0; i < done.length; i++)
if (!done[i] && !popped.contains(i)) {
Vertex[] tuple = new Vertex[k];
for (int j = 0; j < k; j++)
tuple[j] = g.getVertex(karray.get(j));
return tuple;
}
} while (karray.next());
return null;
}
private static class specArr extends ArrayList<Integer>{
final int k, n;
public specArr(int k, int n) {
this.k = k;
this.n = n;
for (int i = 0; i < k; i++)
this.add(i);
}
public boolean next() {
int i = k - 1;
while (i >= 0 && this.get(i) >= n - (k - 1 - i))
i--;
if (i >= 0) {
this.set(i,this.get(i)+1);
for (int j = i + 1; j < k; j++)
this.set(j,this.get(j-1)+1);
return true;
}
return false;
}
}
public String getName() {
return "Vertex Connectivity";
}
public String getDescription() {
return "Vertex Connectivity";
}
@Override
public String getCategory() {
return "Connectivity";
}
}