All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.alg.BronKerboschCliqueFinder Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
/*
 * (C) Copyright 2005-2017, by Ewgenij Proschak and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * This program and the accompanying materials are dual-licensed under
 * either
 *
 * (a) the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation, or (at your option) any
 * later version.
 *
 * or (per the licensee's choosing)
 *
 * (b) the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation.
 */
package org.jgrapht.alg;

import java.util.*;

import org.jgrapht.*;

/**
 * This class implements Bron-Kerbosch clique detection algorithm as it is described in [Samudrala
 * R.,Moult J.:A Graph-theoretic Algorithm for comparative Modeling of Protein Structure; J.Mol.
 * Biol. (1998); vol 279; pp. 287-302]
 * 
 * @param  the graph vertex type
 * @param  the graph edge type
 *
 * @author Ewgenij Proschak
 */
public class BronKerboschCliqueFinder
{
    private final Graph graph;

    private Collection> cliques;

    /**
     * Creates a new clique finder.
     *
     * @param graph the graph in which cliques are to be found; graph must be simple
     */
    public BronKerboschCliqueFinder(Graph graph)
    {
        this.graph = graph;
    }

    /**
     * Finds all maximal cliques of the graph. A clique is maximal if it is impossible to enlarge it
     * by adding another vertex from the graph. Note that a maximal clique is not necessarily the
     * biggest clique in the graph.
     *
     * @return Collection of cliques (each of which is represented as a Set of vertices)
     */
    public Collection> getAllMaximalCliques()
    {
        // TODO jvs 26-July-2005: assert that graph is simple

        cliques = new ArrayList<>();
        List potential_clique = new ArrayList<>();
        List candidates = new ArrayList<>();
        List already_found = new ArrayList<>();
        candidates.addAll(graph.vertexSet());
        findCliques(potential_clique, candidates, already_found);
        return cliques;
    }

    /**
     * Finds the biggest maximal cliques of the graph.
     *
     * @return Collection of cliques (each of which is represented as a Set of vertices)
     */
    public Collection> getBiggestMaximalCliques()
    {
        // first, find all cliques
        getAllMaximalCliques();

        int maximum = 0;
        Collection> biggest_cliques = new ArrayList<>();
        for (Set clique : cliques) {
            if (maximum < clique.size()) {
                maximum = clique.size();
            }
        }
        for (Set clique : cliques) {
            if (maximum == clique.size()) {
                biggest_cliques.add(clique);
            }
        }
        return biggest_cliques;
    }

    private void findCliques(List potential_clique, List candidates, List already_found)
    {
        List candidates_array = new ArrayList<>(candidates);
        if (!end(candidates, already_found)) {
            // for each candidate_node in candidates do
            for (V candidate : candidates_array) {
                List new_candidates = new ArrayList<>();
                List new_already_found = new ArrayList<>();

                // move candidate node to potential_clique
                potential_clique.add(candidate);
                candidates.remove(candidate);

                // create new_candidates by removing nodes in candidates not
                // connected to candidate node
                for (V new_candidate : candidates) {
                    if (graph.containsEdge(candidate, new_candidate)) {
                        new_candidates.add(new_candidate);
                    } // of if
                } // of for

                // create new_already_found by removing nodes in already_found
                // not connected to candidate node
                for (V new_found : already_found) {
                    if (graph.containsEdge(candidate, new_found)) {
                        new_already_found.add(new_found);
                    } // of if
                } // of for

                // if new_candidates and new_already_found are empty
                if (new_candidates.isEmpty() && new_already_found.isEmpty()) {
                    // potential_clique is maximal_clique
                    cliques.add(new HashSet<>(potential_clique));
                } // of if
                else {
                    // recursive call
                    findCliques(potential_clique, new_candidates, new_already_found);
                } // of else

                // move candidate_node from potential_clique to already_found;
                already_found.add(candidate);
                potential_clique.remove(candidate);
            } // of for
        } // of if
    }

    private boolean end(List candidates, List already_found)
    {
        // if a node in already_found is connected to all nodes in candidates
        boolean end = false;
        int edgecounter;
        for (V found : already_found) {
            edgecounter = 0;
            for (V candidate : candidates) {
                if (graph.containsEdge(found, candidate)) {
                    edgecounter++;
                } // of if
            } // of for
            if (edgecounter == candidates.size()) {
                end = true;
            }
        } // of for
        return end;
    }
}

// End BronKerboschCliqueFinder.java




© 2015 - 2024 Weber Informatics LLC | Privacy Policy