// 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.clique; import graphtea.graph.graph.GraphModel; import graphtea.graph.graph.SubGraph; import graphtea.graph.graph.Vertex; import graphtea.platform.lang.CommandAttitude; import graphtea.plugins.reports.extension.GraphReportExtension; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.stream.Collectors; /** * @author Ali Rostami */ @CommandAttitude(name = "mst_prim", abbreviation = "_max_c") public class MaxCliqueExtension implements GraphReportExtension { public String getName() { return "Maximal Cliques"; } public String getDescription() { return "Maximal Cliques"; } public Object calculate(GraphModel g) { Vector<SubGraph> ret = new Vector<>(); MaxCliqueAlg mca = new MaxCliqueAlg(g); Cliques mcs = mca.allMaxCliques(); for(Vector<Vertex> ss : mcs) { SubGraph sg = new SubGraph(g); sg.vertices.addAll(ss); ret.add(sg); } return ret; } @Override public String getCategory() { // TODO Auto-generated method stub return "General"; } } /** * * Bron-Kerbosch clique detection algorithm * * Samudrala R.,Moult J.:A Graph-theoretic Algorithm for * comparative Modeling of Protein Structure; J.Mol. Biol. (1998); vol 279; pp. * 287-302 */ class MaxCliqueAlg { public MaxCliqueAlg(GraphModel g) { this.g = g; } public Cliques allMaxCliques() { maxCliques = new Cliques(); List<Vertex> likelyC = new ArrayList<>(); List<Vertex> searchC = new ArrayList<>(); List<Vertex> found = new ArrayList<>(); for(Vertex v : g) {searchC.add(v);} cliques(likelyC, searchC, found); return maxCliques; } public Cliques GreatestOne() { allMaxCliques(); int maximum = 0; Cliques greatest = new Cliques(); for (Vector<Vertex> clique : maxCliques) { if (maximum < clique.size()) { maximum = clique.size(); } } for (Vector<Vertex> clique : maxCliques) { if (maximum == clique.size()) { greatest.add(clique); } } return greatest; } private void cliques( List<Vertex> likelyC, List<Vertex> C, List<Vertex> F) { List<Vertex> candidates_array = new ArrayList<>(C); if (!allEdgesSeen(C, F)) { for (Vertex candidate : candidates_array) { List<Vertex> new_candidates = new ArrayList<>(); List<Vertex> new_already_found = new ArrayList<>(); likelyC.add(candidate); C.remove(candidate); new_candidates.addAll(C.stream().filter(new_candidate -> g.isEdge(candidate, new_candidate)).collect(Collectors.toList())); new_already_found.addAll(F.stream().filter(new_found -> g.isEdge(candidate, new_found)).collect(Collectors.toList())); if (new_candidates.isEmpty() && new_already_found.isEmpty()) { maxCliques.add(new Vector<>(likelyC)); } else { cliques( likelyC, new_candidates, new_already_found); } F.add(candidate); likelyC.remove(candidate); } } } private boolean allEdgesSeen(List<Vertex> candidates, List<Vertex> already_found) { boolean end = false; int numOfEdges; for (Vertex found : already_found) { numOfEdges = 0; for (Vertex candidate : candidates) { if (g.isEdge(found, candidate)) { numOfEdges++; } } if (numOfEdges == candidates.size()) { end = true; } } return end; } private final GraphModel g; private Cliques maxCliques; } class Cliques extends Vector<Vector<Vertex>> {}