Bron Kerbosch Algorithm In C++ - C++ Programming Tutorial
C++ Course / STL Algorithm / Bron Kerbosch Algorithm In C++

Bron Kerbosch Algorithm In C++

BLUF: Mastering Bron Kerbosch Algorithm In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Bron Kerbosch Algorithm In C++

C++ is renowned for its efficiency. Learn how Bron Kerbosch Algorithm In C++ enables low-level control and high-performance computing in the tutorial below.

The computational procedure is commonly known as the Bron-Kerbosch algorithm, which was introduced by Coenraad Bron and Joep Kerbosch in 1973. This technique utilizes a backtracking approach to explore all clusters within a network to identify the largest cluster that cannot be merged with adjacent vertices. The algorithm functions by removing potential vertices that do not satisfy the clique condition and incrementally constructing cliques one vertex at a time. Due to its straightforward nature and efficient performance, especially in scenarios involving sparse graphs, this algorithm remains pertinent in contemporary applications and continues to be utilized today.

When considering the size, the maximum Clique of a specific graph is referred to as the largest clique size, distinct from a maximal clique. In contrast, the Bron-Kerbosch algorithm aims to identify all 'maximal cliques', which are cliques that cannot be expanded by adding a vertex without violating the clique definition. While determining the largest Clique in a network is an NP-hard problem, finding the maximal Clique is relatively simpler, even though it may not represent the largest Clique within the network.

The Bron-Kerbosch technique proves valuable in scenarios where the goal is to pinpoint communities or clusters of closely interconnected nodes, rather than solely focusing on identifying the largest one. This distinction is particularly important in various applications. For example, in social networks, a tight-knit group of friends or colleagues can be depicted by a maximal clique. Determining the cliques to which they all belong can unveil the underlying structure of the network. This concept is also applicable in bioinformatics, specifically in protein-protein interaction networks, where cliques represent functional sets of proteins collaborating to achieve a common task.

When the algorithm runs recursively, it operates on three sets:

  • R: The Clique that is being formed now.
  • P: The group was made up of nodes that possess the ability to enlarge the Clique.
  • X: are the vertices that, to prevent duplicates, are not included in the present Clique.

At each step of the algorithm, a vertex is selected from set P and connected to set R. Subsequently, sets P and X are updated one after the other with only the adjacent vertices of the newly added vertex to expand the Clique. The maximal clique, labeled as R, is revealed only when none of the elements are present in either P or X. This condition is then documented. The process systematically transfers each vertex in P to X as they become ineligible.

Adaptability stands out as a significant characteristic of the Bron-Kerbosch algorithm. A well-recognized strategy for improving the fundamental framework of an algorithm is the implementation of 'pivoting'. Within the Bron-Kerbosch approach, the selection of a 'pivot' vertex plays a crucial role in managing the recursive calls. In this process, vertices belonging to set P, but not linked to the pivot, are scrutinized by opting for a vertex from either set P or set X. This approach effectively reduces the necessity for excessive recursive calls, yet guarantees the preservation of essential cliques within dense networks.

The fundamental yet powerful essence of the Bron-Kerbosch algorithm must be complemented by thoughtful consideration of challenges specific to C++ implementation, such as memory handling, iterative methodology, and accurate graph representation. Key approaches to illustrating graphs within this algorithm in C++ involve the utilization of adjacency matrices or adjacency lists. Proficiency in efficiently navigating the adjacent vertices of each node is a crucial advantage of the data structures utilized for the iterative adjustment of sets P and X.

In cases where the graph is relatively sparse, the preference is often given to using an adjacency list. This approach proves to be more efficient in real-world scenarios as it necessitates the validation of fewer vertices at each iteration. Conversely, adjacency matrices offer constant-time accessibility, enabling swift verification of connections between any pair of vertices. This makes them particularly effective in dense graphs where the majority of vertices are interconnected.

Within image processing, maximal cliques serve to represent clusters of pixels or regions that exhibit specific similarities, such as color, texture, or intensity. The Bron-Kerbosch algorithm can be utilized for identifying these cliques, aiding in tasks like image segmentation, which involves dividing the image into meaningful sections.

When identifying objects within images, diagrams are frequently created to illustrate the connections among different characteristics of objects, like edges, corners, or patterns. The clusters within these diagrams signify sets of characteristics that are closely linked and may correspond to identifiable objects or forms present in the image.

Considering the management of memory usage and the impact of nested loops is crucial when implementing the Bron-Kerbosch algorithm in C++. Proper implementation of this algorithm can lead to significant memory usage, especially in large networks with numerous vertices and edges. To address challenges related to high recursion levels and excessive memory utilization, it is essential to control the depth of recursion and efficiently handle memory allocation.

The stored advantages of the Bron-Kerbosch algorithm maintain its ongoing significance for current requirements. Despite newer algorithms emerging for specific tasks, the Bron-Kerbosch algorithm remains widely employed in various industries and academic fields. Its superior efficiency in handling sparse graphs makes it a preferred option for real-world uses such as processing biological data, analyzing social networks, and managing telecommunication networks.

In this article, we will explore the Bron-Kerbosch algorithm extensively, diving into its C++ implementation, potential enhancements to improve its performance, and its significance in addressing practical challenges. The Bron-Kerbosch approach provides a reliable framework for identifying cliques in complex networks, serving as a valuable tool for developers and computer science learners seeking efficient solutions for graph-related problems.

Key Concepts of the Bron-Kerbosch Algorithm

The Bron-Kerbosch algorithm employs recursive backtracking to identify all maximal cliques within an undirected graph. These maximal cliques represent connected subgraphs where additional vertices cannot be included without disrupting connectivity. Unlike a maximum clique, which is determined by vertex count and represents the largest possible clique, the output of the Bron-Kerbosch algorithm consists of maximal cliques that are locally complete but may not be the largest overall.

Understanding a handful of fundamental algorithms can provide insight into key concepts within the field.

1. Graphs with Cliques

Graph theory describes a clique as a group of vertices in a graph where each pair of vertices is connected by an edge. A maximum clique is the largest possible clique where no additional adjacent vertices can be added without exceeding its size. On the other hand, a maximal clique is a clique that cannot be expanded further, even though it may not be the largest clique in the graph.

The Bron-Kerbosch algorithm is designed to identify every single maximal clique within a graph. This involves identifying all potential cliques that meet the maximal criteria, rather than focusing on finding the largest clique. While there may be numerous contenders for the largest clique, the algorithm is focused on identifying cliques that are maximal. This functionality is especially valuable in various scenarios, such as identifying functional clusters in biological networks or tightly-knit groups within social networks.

2. The Recursive Backtracking Approach

Recursive backtracking is employed in conjunction with the Bron-Kerbosch algorithm to construct the Clique. The fundamental strategy involves gradually assembling the Clique by sequentially introducing one vertex at a time and evaluating the potential for extending the existing Clique. Once all avenues for further enlargement have been exhausted, the Clique is deemed to be at its maximum capacity.

At every iteration of recursion, the algorithm employs three sets to manage the process of constructing cliques at the present stage:

The vertices within the existing Clique being built are stored in the set, R (Current Clique), which starts off empty.

  • P (Candidates): This collection includes all the possible candidates for membership in the current Clique, initially encompassing every vertex in the graph. Throughout the algorithm's advancement, vertices from set P are gradually eliminated.
  • X: These vertices have already undergone processing and are not part of the current Clique under review. Consequently, they are disregarded at the current recursion level as they must have been explored in a previous recursion stage.

At every iteration, a single vertex from set P gets selected and moved to set R. Following the addition of this vertex to the current Clique, the procedure adjusts sets P and X so that solely the neighbors of the added vertex remain in each set, adhering to the clique criteria. The set R qualifies as a maximal clique when, during any recursion step, both sets P and X become empty, indicating no further vertices can be included.

It subsequently reverses its process and initiates extracting vertices from P to X in a manner that guarantees the exploration of all potential maximal cliques.

3. Change in Direction to Optimize

Pivoting stands out as a crucial addition to the fundamental Bron-Kerbosch algorithm, serving the purpose of minimizing the volume of recursive function calls. Within dense graphs, this approach enables the algorithm to avoid traversing unnecessary paths, thereby cutting down on the quantity of recursive iterations.

In the Bron-Kerbosch algorithm featuring pivoting, a single vertex known as the pivot is selected from either set P or set X. Consequently, the recursive calls are restricted by the process to vertices within set P that are not connected to the pivot. This enhancement significantly enhances the efficiency of the algorithm, particularly in scenarios where the graph is densely populated, and there are numerous cliques that need to be evaluated during the search process. Additionally, it aids in partially restricting the exploration area.

By choosing a suitable pivot with strong connections, the algorithm can skip evaluating certain branches that are already determined not to result in a larger clique. This optimization leads to a decrease in both the computational time required and the total recursive function calls made.

4. Graph Example

The selection of how the graph is represented directly impacts the performance of the Bron-Kerbosch algorithm. Graphs are commonly depicted using either a collection of edges or through an adjacency matrix.

An Adjacency Matrix is essentially a 2D array where each element at position (i, j) represents the presence or absence of an edge between vertices i and j, denoted by 0 or 1 respectively. While this representation offers constant-time edge lookups, it consumes O(n²) space, which may be inefficient for large or sparse graphs. In Protein-Protein Interaction (PPI) networks, cliques often signify functional modules, clusters of proteins collaborating to execute specific tasks. For instance, proteins participating in a shared metabolic pathway or regulatory mechanism might form a clique. By employing the Bron-Kerbosch algorithm on these networks, scientists can pinpoint such modules, gaining valuable insights into the underlying biological mechanisms.

Discovering cliques in PPI networks, genetic networks, or metabolic pathways is a valuable capability for bioinformaticians, enabling them to map out biological interactions and functions effectively. The Bron-Kerbosch algorithm stands out for its proficiency in identifying all maximal cliques, facilitating a thorough investigation of potential functional modules.

The format of an adjacency list is more compact, particularly suitable for graphs with few connections. It comprises a list of neighboring vertices for each vertex. While it doesn't facilitate instant edge retrieval, it enables swift traversal of a vertex's adjacent nodes.

For dense graphs, when considering the use case and graph size, the Adjacency matrix is a suitable choice when implementing the Bron-Kerbosch Algorithm. Conversely, for sparse graphs, the Adjacency list is generally preferred.

5. Time Complexity

The time complexity of the Bron-Kerbosch algorithm is significant, as it scales with the count of maximal cliques within the graph. In the worst-case scenario, the algorithm examines all possible vertex subsets, resulting in a time complexity of O(3^(n/3)), where 'n' signifies the number of vertices present. Nevertheless, the algorithm demonstrates superior performance in numerous practical scenarios, excelling notably with sparse graphs.

By integrating pivoting, the algorithm significantly reduces the number of recursive calls, making it highly efficient in the majority of scenarios. While this enhancement does improve performance, its effectiveness is still contingent upon the specific graph structure and the quantity of maximal cliques present in real-world scenarios.

One of the robust and versatile algorithms used to discover maximal cliques in undirected graphs is the Bron-Kerbosch algorithm. Its effectiveness is attributed to the utilization of recursive backtracking and pivoting functionalities, which contribute to its efficiency especially with sparse datasets. A solid grasp of key concepts related to the Bron-Kerbosch algorithm, including the principles of cliques, recursion, and optimization strategies like pivoting, is crucial for effectively implementing and applying the algorithm in real-world applications such as life sciences, web analytics, and social network analysis.

Pseudocode of Bron-Kerbosch Algorithm

The fundamental pseudocode for the Bron-Kerbosch algorithm lacking any pivoting technique is outlined below:

Example

BronKerbosch(R, P, X):
    if P and X are both empty:
        report R as a maximal clique
    for each vertex v in P:
        BronKerbosch(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v))
        P = P \ {v}
        X = X ⋃ {v}

Here, N(v) represents the collection of adjacent vertices to vertex v.

C++ Implementation of the Bron-Kerbosch Algorithm

Now, we will explore the process of incorporating the Bron-Kerbosch algorithm in C++.

C++ Implementation without Pivoting

Example

#include <iostream>
#include <vector>
#include <set>

using namespace std;

//Function to find maximal cliques
void BronKerbosch(set<int> R, set<int> P, set<int> X, const vector<set<int>> &graph) {
    if (P.empty() && X.empty()) {
        // Base case: both P and X are empty, R is a maximal clique
        cout << "Maximal clique: ";
        for (int v : R)
            cout << v << " ";
        cout << endl;
        return;
    }

    // Iterate through all vertices in P
    set<int> P_copy = P;
    for (int v : P_copy) {
        set<int> newR = R;
        newR.insert(v);

        set<int> newP;
        set<int> newX;

        // Neighbors of v
        const set<int> &neighbors = graph[v];

        // Update P and X with neighbors of v
        for (int u : P)
            if (neighbors.count(u))
                newP.insert(u);

        for (int u : X)
            if (neighbors.count(u))
                newX.insert(u);

        // Recursive call
        BronKerbosch(newR, newP, newX, graph);

        // Move vertex v from P to X
        P.erase(v);
        X.insert(v);
    }
}

int main() {
    // Example graph represented as an adjacency list
    vector<set<int>> graph = {
        {1, 2},     // Vertex 0 is connected to vertices 1, 2
        {0, 2},     // Vertex 1 is connected to vertices 0, 2
        {0, 1},     // Vertex 2 is connected to vertices 0, 1
        {4},        // Vertex 3 is connected to vertex 4
        {3}         // Vertex 4 is connected to vertex 3
    };

    // Initialize R, P, and X
    set<int> R;
    set<int> P = {0, 1, 2, 3, 4};
    set<int> X;

    // Run the Bron-Kerbosch algorithm
    BronKerbosch(R, P, X, graph);

    return 0;
}

Output:

Output

Maximal clique: 0 1 2 
Maximal Clique: 3 4

Explanation of Code:

  • Graph Representation: We represent the graph using an adjacency list, where each vertex has a set of its neighbors.
  • BronKerbosch Function: This Function takes three sets (R, P, X) and the graph as input and recursively explores all maximal cliques.
  • Base Case: If both P and X are empty, the current set R represents a maximal clique.
  • Recursive Exploration: For each vertex in P, we recursively explore potential cliques by adding the vertex to R and updating P and X with their neighbours.

This result displays the largest cliques present in the graph.

Optimizations: Bron-Kerbosch with Pivoting

A crucial enhancement for the Bron-Kerbosch algorithm involves implementing pivoting, a technique that decreases the frequency of recursive function calls. The concept revolves around choosing a pivot vertex from the union of sets P and X, focusing solely on vertices in set P that do not share an edge with the pivot. This strategy minimizes the number of vertices that require examination. In the context of wireless networks, cliques symbolize clusters of devices that can all directly communicate with one another. Recognizing these cliques empowers network administrators to fine-tune resource distribution, such as bandwidth allocation or channel assignment, to promote efficient communication throughout the network.

Pseudocode with Pivoting

Example

BronKerboschPivot(R, P, X):
    if P and X are both empty:
        report R as a maximal clique
    Choose a pivot vertex u from P ⋃ X
    for each vertex v in P \ N(u):
        BronKerboschPivot(R ⋃ {v}, P ⋂ N(v), X ⋂ N(v))
        P = P \ {v}
        X = X ⋃ {v}

C++ Implementation with Pivoting

Example

#include <iostream>
#include <vector>
#include <set>

using namespace std;

//Function to find maximal cliques with pivoting
void BronKerboschPivot(set<int> R, set<int> P, set<int> X, const vector<set<int>> &graph) {
    if (P.empty() && X.empty()) {
        // Base case: both P and X are empty, R is a maximal clique
        cout << "Maximal clique: ";
        for (int v : R)
            cout << v << " ";
        cout << endl;
        return;
    }

    // Choose a pivot vertex from P ⋃ X
    int pivot = -1;
    if (!P.empty()) pivot = *P.begin();
    else if (!X.empty()) pivot = *X.begin();

    // Iterate through vertices in P \ N(pivot)
    set<int> non_neighbors;
    for (int v : P)
        if (!graph[pivot].count(v))
            non_neighbors.insert(v);

    for (int v : non_neighbors) {
        set<int> newR = R;
        newR.insert(v);

        set<int> newP, newX;
        const set<int> &neighbors = graph[v];

        for (int u : P)
            if (neighbors.count(u))
                newP.insert(u);

        for (int u : X)
            if (neighbors.count(u))
                newX.insert(u);

        // Recursive call
        BronKerboschPivot(newR, newP, newX, graph);

        // Move vertex v from P to X
        P.erase(v);
        X.insert(v);
    }
}

int main() {
    // Example graph represented as an adjacency list
    vector<set<int>> graph = {
        {1, 2},     // Vertex 0 is connected to vertices 1, 2
        {0, 2},     // Vertex 1 is connected to vertices 0, 2
        {0, 1},     // Vertex 2 is connected to vertices 0, 1
        {4},        // Vertex 3 is connected to vertex 4
        {3}         // Vertex 4 is connected to vertex 3
    };

    // Initialize R, P, and X
    set<int> R;
    set<int> P = {0, 1, 2, 3, 4};
    set<int> X;

    // Run the Bron-Kerbosch algorithm with pivoting
    BronKerboschPivot(R, P, X, graph);

    return 0;
}

Output:

Output

Maximal clique: 0 1 2 
Maximal Clique: 3 4

Time Complexity

The efficiency of the Bron-Kerbosch algorithm is tied to the count of maximal cliques within the graph. In the most unfavorable scenario, the algorithm examines each vertex and edge of the graph, resulting in a time complexity of approximately O(3^(n/3)) for any given graph, where n represents the quantity of vertices. Nevertheless, incorporating pivoting typically leads to significantly enhanced performance, particularly when dealing with graphs that are not densely populated.

The Bron-Kerbosch Algorithm's Applications

As a fundamental method employed to discover maximal cliques in an undirected graph, the Bron-Kerbosch algorithm is extensively applied within the realm of graph theory. While it may not be highly beneficial in certain scenarios, its main purpose lies in identifying cliques. Initially developed across diverse disciplines such as biology and social networks, the Bron-Kerbosch technique finds significant utility. Below, we outline the key uses of the Bron-Kerbosch approach and examine its application in tackling intricate challenges across different scientific fields.

1. Social Networks: Recognizing Groups

Surprisingly, one of the most well-known applications of this algorithm is Social network analysis. It can be noted that both online and offline social networks are depicted as graphs with people depicted as vertices and relationships such as friendship, communication, or cooperation as edges. Social networks explain the dynamics of people's relations, and in order to discover a group or several concrete groupings in such networks, it is necessary to identify groups of individuals most interconnected with one another.

  • Clique Detection: In a social network, a clique is a group of persons, and their interconnectivity is like that of a completely connected sub-graph. Such groups often represent close-knit groups of people, friends, teams or communities. The Bron-Kerbosch algorithm is useful in discovering all the M nodes, which can loosely be termed communities, which are intrinsically incapable of increasing in size through the addition of new members.
  • Identification of Influencers: On social media platforms, Facebook , Instagram, Twitter, etc, influencers can be identified by their betweenness in a group or by interacting with many groups. The Bron-Kerbosch technique helps in finding clustering coefficients around such people and shows that they exercise influence in different parts of the given network.
  • Collaborative Networks: The method is applied in order to identify organizations that cooperate on different levels, including academic, business or in entertainment industry. For instance, maximal cliques are used to identify research groups in the co-authorship network in which nodes reflect authors and edges denote co-authored articles.

In addition to facilitating the exploration of communities, social network analysis also advances comprehension of how information propagates within these networks. Recognizing cliques is crucial for deciphering the dynamics of gossip dissemination, marketing campaigns, and viral content spread.

2. Network Biology

Hence, the process of identifying cliques within a graph is a valuable method used in bioinformatics to gain insights into biological occurrences. For example, graphs representing Protein-Protein Interactions (PPI) Networks depict individual proteins as nodes and their interactions as edges. Understanding these relationships is crucial for unraveling the mechanisms of cells and biological functions.

  • Functional Units: Clusters within PPI networks often correspond to functional units, comprising cohesive groups of proteins collaborating to carry out specific functions. For instance, proteins within the same regulatory network or metabolic pathways tend to aggregate and form cliques. Researchers can pinpoint these units by employing the Bron-Kerbosch algorithm on the networks, aiding in the comprehension of the biological systems at play.
  • Identification of Drug Targets: In the context of targeting proteins to manipulate or inhibit disease processes, scientists concentrate on ailments like cancer and identify proteins that, when targeted, can disrupt harmful biological activities. Patterns within PPI networks can reveal densely interconnected protein complexes participating in vital disease-related pathways. Developing drugs that interfere with proteins within these cliques could potentially be a promising strategy.

In this scenario, clusters within genetic interaction networks may indicate groups of genes that share a common genetic pathway or are governed by similar regulatory mechanisms. This aids in comprehending gene expression patterns and identifying genes associated with specific phenotypes or medical conditions.

In specific, the process of clique mining has offered bioinformaticians an efficient method to determine the positional relationship between proteins or genes within metabolic pathways, genetic networks, or PPI networks. The essential functional units known as functional modules have been extensively examined using the Bron-Kerbosch algorithm, which proves to be highly efficient by successfully recognizing all maximal cliques.

3. Computational Chemistry: Further understanding of the structure of molecules.

The Bron-Kerbosch algorithm is widely used in computational chemistry for the determination of chemical subgraphs with specific features. In chemical graphs, nodes are usually used to depict atoms; on the other hand, edges are used in the depiction of chemical bonds between atoms. Such graphs are amenable to clique analysis, which is pertinent to studies of chemical interactions and structures.

  • Chemical Substructures: In a chemical graph, maximal cliques can be imposed as substructures which can be considered as combinations in which all the atoms are tied to each of the others in the Clique. The subgraphs that are wholly contained and connected are termed specific chemical structures, such as rings or more complicated molecular connectors. They could look for all the maximal cliques in the graph for chemists to discover these substructures and get a feel of the molecule's chemical nature.
  • Drug Design and Pharmacophores: Pharmacophore is defined as the core structural element of a drug that is essential in the management of the drug-target interaction during drug development. Knowing the chemical structure, researchers can identify the necessary bonds that define the biological activity of the molecule and, utilizing the maximal clique detection algorithm, find these bonds in possible therapeutic compounds. Some of these interactions are precontact found in part by the Bron-Kerbosch algorithm, which searches for these dense substructures in the molecular graph.
  • Crystal Structures: Besides, in materials science, the algorithm can be applied to analyze the crystal structures. In crystal formations, atoms are organized in a predictable manner and locating cliques within the formations yields details on the stability, conductivity, and/or other properties of the material.
  • 4. Machine learning for image recognition

The Bron-Kerbosch approach is utilized for picture data clustering or identification of strongly connected substructures in fields such as pattern recognition and computer vision. It is possible to depict images and patterns as graphs where nodes could be pixels, features or objects and edge into account spatial relations or proximity.

  • Image Segmentation: In image processing, maximum cliques can be defined for groups of pixels or regions that are composed of similar characteristics such as color, texture or intensity. As to the tasks such as image segmentation to divide an image into meaningful parts, the cliques can be found out using the Bron-Kerbosch technique.
  • Object Recognition: To find out the objects and their features in a particular picture, one may create graphs illustrating the existing links between attributes, for example, edges, corners or textures. Closely related features that make up many parts of these graphs can be linked to cliques, which often refer to more recognizable objects or forms within the image.
  • Scene Understanding: The goal of scene understanding achieved also by the algorithm is to comprehend how objects are laid in a scene. When it comes to contextually linked objects, the idea for researchers is to recognize maximal cliques in the map of objects' relations.
  • 5. Networks for Telecommunication

In networking, cliques represent nodes or devices interconnected directly in a network. Bayesian networks enhance data transmission efficiency, whereas the Bron-Kerbosch algorithm optimizes network resource utilization.

  • Network Optimization: In wireless networks, cliques refer to clusters of devices within each other's communication range. These clusters highlight potential communication challenges within the network, which can be addressed by network administrators through resource allocation management, such as channel bandwidth distribution.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience