// 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;
import graphtea.graph.graph.Vertex;
import graphtea.library.BaseEdge;
import graphtea.library.BaseGraph;
import graphtea.library.BaseVertex;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Iterator;
/**
* generates all partitionings of the given graph with t or less partitions
* which in each partition does not have any edges
*
* @author Azin Azadi
*/
public class Partitioner {
public BaseVertex[] vertices;
private int[][] edgeArray;
public int[] color;
private BaseGraph g;
public Partitioner(final BaseGraph g) {
this.g = g;
edgeArray = g.getEdgeArray();
vertices = g.getVertexArray();
}
public boolean findAllSubsets(SubSetListener listener) {
color = new int[vertices.length];
ArrayDeque<BaseVertex> v = new ArrayDeque<>();
Collections.addAll(v, g.getVertexArray());
return findAllSubsetsRecursively(1, listener, v, new ArrayDeque<>(), new ArrayDeque<>());
}
public int findMaxIndSet(boolean putFirstVertexInSet) {
color = new int[vertices.length];
v = new ArrayDeque<>();
set = new boolean[g.getVerticesCount()];
int i = 0;
for (BaseVertex baseVertx : g.getVertexArray()) {
v.add(baseVertx);
set[i++] = false;
}
maxSet = Integer.MIN_VALUE;
curSet = 0;
if (putFirstVertexInSet) {
curSet = 1;
set[0] = true;
v.remove(vertices[0]);
for (int ii : edgeArray[0]) {
v.remove(vertices[ii]);
}
}
V = new Vertex[v.size()];
N = v.size();
v.toArray(V);
ID = new int[vertices.length];
for (i = 0; i < vertices.length; i++) {
ID[i] = vertices[i].getId();
}
mark = new boolean[vertices.length];
found = 0;
findMaxIndSetsRecursively(0);
return maxSet;
}
boolean set[];
boolean mark[];
// boolean markbck[];
Vertex[] V;
int ID[];
int N;
ArrayDeque<BaseVertex> v;
int maxSet = Integer.MIN_VALUE;
int curSet;
// int curRejectedFromSet;
// int minRejectedFromSet;
int found = 0;
int iter = 0;
int i;
private void findMaxIndSetsRecursively(int iv) {
while (iv < N && mark[iv]) {
iv++;
}
iter++;
if (curSet + (N - iv) < maxSet) {
return;
}
if (iv >= N) {
if (curSet > maxSet) {
maxSet = curSet;
found++;
}
return;
}
int vid = V[iv].getId();
//set and backup marks
int[] nv = edgeArray[vid];
int ss = nv.length;
boolean markbck[] = new boolean[ss];
for (i = 0; i < ss; i++) {
markbck[i] = mark[nv[i]];
mark[nv[i]] = true;
}
//put vid in set
int iiv = iv + 1;
while (iiv < N && mark[iiv]) {
iiv++;
}
set[vid] = true;
curSet++;
//////////////////////////////////
findMaxIndSetsRecursively(iiv);
//////////////////////////////////
curSet--;
set[vid] = false;
for (i = 0; i < ss; i++) {
mark[nv[i]] = markbck[i];
}
//BackTrak on complement
iiv = iv + 1;
while (iiv < N && mark[iiv]) {
iiv++;
}
//////////////////////////////////
findMaxIndSetsRecursively(iiv);
//////////////////////////////////
}
public boolean findAllPartitionings(final int t, final ColoringListener listener) {
color = new int[vertices.length];
ArrayDeque<BaseVertex> v = new ArrayDeque<>();
Collections.addAll(v, g.getVertexArray());
return findAllPartitioningsRecursively(t, t1 -> checkColoring(g) && listener.coloringFound(t1), v);
}
public boolean findAllPartitioningsRecursively(final int tt, final ColoringListener listener, final ArrayDeque<BaseVertex> v) {
if (tt == 0 || v.size() == 0) {
return listener.coloringFound(tt);
}
BaseVertex fv = v.removeFirst();
color[fv.getId()] = tt;
ArrayDeque<BaseVertex> compl = new ArrayDeque<>();
if (findAllSubsetsRecursively(tt, (t, complement, set1) -> findAllPartitioningsRecursively(tt - 1, listener, complement)
, v, new ArrayDeque<>(), compl)) return true;
color[fv.getId()] = 0;
v.addFirst(fv);
return false;
}
private boolean findAllSubsetsRecursively(final int t, SubSetListener listener, ArrayDeque<BaseVertex> v, ArrayDeque<BaseVertex> set, ArrayDeque<BaseVertex> complement) {
if (t == 0 || v.size() == 0) {
//all colorings of valid and checked before except the remaining vertices which all have color 0
for (BaseVertex baseVertex : v) {
for (int i : edgeArray[baseVertex.getId()])
if (color[i] == 0)
return false;
}
//so it is a valid partitioning (coloring)
return listener.subsetFound(t, complement, set);
}
BaseVertex baseVertex = v.removeFirst();
boolean canColoredT = true;
for (int i : edgeArray[baseVertex.getId()]) {
if (color[i] == t) {
canColoredT = false;
break;
}
}
if (canColoredT) {
color[baseVertex.getId()] = t;
set.add(baseVertex);
if (findAllSubsetsRecursively(t, listener, v, set, complement)) return true;
set.remove(baseVertex);
}
color[baseVertex.getId()] = 0;
complement.add(baseVertex);
if (findAllSubsetsRecursively(t, listener, v, set, complement)) return true;
complement.remove(baseVertex);
v.addFirst(baseVertex);
return false;
}
/**
* @param g The given graph
* @return true if the coloring of g is a valid vertex coloring
*/
public boolean checkColoring(BaseGraph g) {
Iterator<BaseEdge> ie = g.edgeIterator();
while (ie.hasNext()) {
BaseEdge e = ie.next();
if (color[e.source.getId()] == color[e.target.getId()]) {
return false;
}
}
return true;
}
}