package uk.ac.rhul.cs.cl1.seeding;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import uk.ac.rhul.cs.graph.BronKerboschMaximalCliqueFinder;
import uk.ac.rhul.cs.graph.Graph;
import uk.ac.rhul.cs.utils.BlockingQueueAdapter;
/**
* Seed generator that returns every maximal clique of a graph as a seed.
*
* Maximal cliques are sought for in a separate thread; a blocking queue is
* used to store the detected cliques. The contents of the queue is produced
* by a {@link BronKerboschMaximalCliqueFinder} and consumed by the user of
* the maximal clique seed generator via its iterator.
*
* @author ntamas
*/
public class MaximalCliqueSeedGenerator extends SeedGenerator {
/**
* Constructs a maximal clique seed generator with no associated graph.
*/
public MaximalCliqueSeedGenerator() {
super();
}
/**
* Constructs a maximal clique seed generator associated to the given graph.
*/
public MaximalCliqueSeedGenerator(Graph graph) {
super(graph);
}
/**
* Returns -1 as we cannot know in advance how many seeds there will be.
*/
public int size() {
return -1;
}
/**
* Returns an iterator that iterates over the maximal cliques of the associated graph
*/
public SeedIterator iterator() {
return new IteratorImpl();
}
class IteratorImpl extends SeedIterator {
/**
* A maximal clique finder we will use
*/
BronKerboschMaximalCliqueFinder cliqueFinder;
/**
* A blocking queue in which the clique finder stores the cliques.
*/
ArrayBlockingQueue<List<Integer>> cliques =
new ArrayBlockingQueue<List<Integer>>(100);
/**
* The thread in which the clique finder runs
*/
Thread cliqueFinderThread = null;
public IteratorImpl() {
cliqueFinder = new BronKerboschMaximalCliqueFinder();
cliqueFinder.setGraph(graph);
cliqueFinderThread = new Thread(new Runnable() {
public void run() {
BlockingQueueAdapter<List<Integer>> cliqueCollection =
new BlockingQueueAdapter<List<Integer>>(cliques);
cliqueFinder.collectMaximalCliques(cliqueCollection);
}
});
cliqueFinderThread.start();
}
public boolean hasNext() {
if (cliques.isEmpty()) {
/* Queue is empty. Is the thread still running? */
return (cliqueFinderThread.isAlive() &&
!cliqueFinderThread.isInterrupted());
}
return true;
}
public Seed next() {
List<Integer> clique;
try {
clique = cliques.take();
} catch (InterruptedException ex) {
return null;
}
int[] members = new int[clique.size()];
int i = 0;
for (int node: clique) {
members[i++] = node;
}
return new Seed(graph, members);
}
}
}