/* -*- mode: C -*- */ /* IGraph library. Copyright (C) 2005 Gabor Csardi MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "igraph.h" #include "memory.h" #include "random.h" void igraph_i_cliques_free_res(igraph_vector_ptr_t *res) { long i, n; n = igraph_vector_ptr_size(res); for (i=0; i(*new_member_storage)[m-1]) { (*new_member_storage)[m++]=v2; n=m; } else { m=n; } } else { m=n; } } } } } /* Calculate how many cliques have we found */ *clique_count = n/size; IGRAPH_FINALLY_CLEAN(1); return 0; } /* Internal function for calculating cliques or independent vertex sets. * They are practically the same except that the complementer of the graph * should be used in the latter case. */ int igraph_i_cliques(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_integer_t min_size, igraph_integer_t max_size, igraph_bool_t independent_vertices) { igraph_integer_t no_of_nodes; igraph_vector_t neis; igraph_real_t *member_storage=0, *new_member_storage, *c1; long int i, j, k, clique_count, old_clique_count; no_of_nodes = igraph_vcount(graph); if (min_size < 0) { min_size = 0; } if (max_size > no_of_nodes || max_size <= 0) { max_size = no_of_nodes; } igraph_vector_ptr_clear(res); IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); igraph_vector_ptr_clear(res); IGRAPH_FINALLY(igraph_i_cliques_free_res, res); /* Will be resized later, if needed. */ member_storage=Calloc(1, igraph_real_t); if (member_storage==0) { IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, member_storage); /* Find all 1-cliques: every vertex will be a clique */ new_member_storage=Calloc(no_of_nodes, igraph_real_t); if (new_member_storage==0) { IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, new_member_storage); for (i=0; i 1; i++) { /* Here new_member_storage contains the cliques found in the previous iteration. Save this into member_storage, might be needed later */ c1=member_storage; member_storage=new_member_storage; new_member_storage=c1; old_clique_count=clique_count; IGRAPH_ALLOW_INTERRUPTION(); /* Calculate the cliques */ IGRAPH_FINALLY_CLEAN(2); IGRAPH_CHECK(igraph_i_find_k_cliques(graph, i, member_storage, &new_member_storage, old_clique_count, &clique_count, &neis, independent_vertices)); IGRAPH_FINALLY(igraph_free, member_storage); IGRAPH_FINALLY(igraph_free, new_member_storage); /* Add the cliques just found to the result if requested */ if (i>=min_size && i<=max_size) { for (j=0, k=0; j * Cliques are fully connected subgraphs of a graph. * * * If you are only interested in the size of the largest clique in the graph, * use \ref igraph_clique_number() instead. * * \param graph The input graph. * \param res Pointer to a pointer vector, the result will be stored * here, ie. \c res will contain pointers to \c igraph_vector_t * objects which contain the indices of vertices involved in a clique. * The pointer vector will be resized if needed but note that the * objects in the pointer vector will not be freed. * \param min_size Integer giving the minimum size of the cliques to be * returned. If negative or zero, no lower bound will be used. * \param max_size Integer giving the maximum size of the cliques to be * returned. If negative or zero, no upper bound will be used. * \return Error code. * * \sa \ref igraph_largest_cliques() and \ref igraph_clique_number(). * * Time complexity: TODO */ int igraph_cliques(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_integer_t min_size, igraph_integer_t max_size) { return igraph_i_cliques(graph, res, min_size, max_size, 0); } int igraph_i_largest_cliques(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_bool_t independent_vertices) { igraph_integer_t no_of_nodes; igraph_vector_t neis; igraph_real_t *member_storage=0, *new_member_storage, *c1; long int i, j, k, clique_count, old_clique_count; no_of_nodes = igraph_vcount(graph); IGRAPH_VECTOR_INIT_FINALLY(&neis, 0); igraph_vector_ptr_clear(res); IGRAPH_FINALLY(igraph_i_cliques_free_res, res); /* Will be resized later, if needed. */ member_storage=Calloc(1, igraph_real_t); if (member_storage==0) { IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, member_storage); new_member_storage=Calloc(no_of_nodes, igraph_real_t); if (new_member_storage==0) { IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, new_member_storage); for (i=0; i 1; i++) { c1=member_storage; member_storage=new_member_storage; new_member_storage=c1; old_clique_count=clique_count; IGRAPH_ALLOW_INTERRUPTION(); /* Calculate the cliques */ IGRAPH_FINALLY_CLEAN(2); IGRAPH_CHECK(igraph_i_find_k_cliques(graph, i, member_storage, &new_member_storage, old_clique_count, &clique_count, &neis, independent_vertices)); IGRAPH_FINALLY(igraph_free, member_storage); IGRAPH_FINALLY(igraph_free, new_member_storage); } /* Where is the result? */ if (clique_count != 0) { c1=new_member_storage; i=no_of_nodes; } else { c1=member_storage; i=i-2; clique_count=old_clique_count; } /* Ok, the result is in c1, there are clique_count cliques and i is the size of the cliques */ for (j=0, k=0; j * A clique is largest (quite intuitively) if there is no other clique * in the graph which contains more vertices. * * * Note that this is not neccessarily the same as a maximal clique, * ie. the largest cliques are always maximal but a maximal clique is * not always largest. * \param graph The input graph. * \param res Pointer to an initialized pointer vector, the result * will be stored here. It will be resized as needed. * \return Error code. * * \sa \ref igraph_cliques(), \ref igraph_maximal_cliques() * * Time complexity: TODO. */ int igraph_largest_cliques(const igraph_t *graph, igraph_vector_ptr_t *res) { return igraph_i_largest_cliques(graph, res, 0); } /** * \function igraph_independent_vertex_sets * Find all independent vertex sets in a graph * * * A vertex set is considered independent if there are no edges between * them. * * * If you are interested in the size of the largest independent vertex set, * use \ref igraph_independence_number() instead. * * \param graph The input graph. * \param res Pointer to a pointer vector, the result will be stored * here, ie. \c res will contain pointers to \c igraph_vector_t * objects which contain the indices of vertices involved in an independent * vertex set. The pointer vector will be resized if needed but note that the * objects in the pointer vector will not be freed. * \param min_size Integer giving the minimum size of the sets to be * returned. If negative or zero, no lower bound will be used. * \param max_size Integer giving the maximum size of the sets to be * returned. If negative or zero, no upper bound will be used. * \return Error code. * * \sa \ref igraph_largest_independent_vertex_sets(), * \ref igraph_independence_number(). * * Time complexity: TODO */ int igraph_independent_vertex_sets(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_integer_t min_size, igraph_integer_t max_size) { return igraph_i_cliques(graph, res, min_size, max_size, 1); } /** * \function igraph_largest_independent_vertex_sets * \brief Finds the largest independent vertex set(s) in a graph. * * * An independent vertex set is largest if there is no other * independent vertex set with more vertices in the graph. * \param graph The input graph. * \param res Pointer to a pointer vector, the result will be stored * here. It will be resized as needed. * \return Error code. * * \sa \ref igraph_independent_vertex_sets(), \ref * igraph_maximal_independent_vertex_sets(). * * Time complexity: TODO */ int igraph_largest_independent_vertex_sets(const igraph_t *graph, igraph_vector_ptr_t *res) { return igraph_i_largest_cliques(graph, res, 1); } typedef struct igraph_i_max_ind_vsets_data_t { igraph_integer_t matrix_size; igraph_i_adjlist_t adj_list; /* Adjacency list of the graph */ igraph_vector_t deg; /* Degrees of individual nodes */ igraph_set_t* buckets; /* Bucket array */ /* The IS value for each node. Still to be explained :) */ igraph_integer_t* IS; igraph_integer_t largest_set_size; /* Size of the largest set encountered */ } igraph_i_max_ind_vsets_data_t; int igraph_i_maximal_independent_vertex_sets_backtrack(const igraph_t *graph, igraph_vector_ptr_t *res, igraph_i_max_ind_vsets_data_t *clqdata, igraph_integer_t level) { long int v1, v2, v3, c, j, k; igraph_vector_t *neis1, *neis2; igraph_bool_t f; igraph_integer_t j1; long int it_state; IGRAPH_ALLOW_INTERRUPTION(); if (level >= clqdata->matrix_size-1) { igraph_vector_t *vec; igraph_integer_t size=0; vec = Calloc(1, igraph_vector_t); if (vec == 0) IGRAPH_ERROR("igraph_i_maximal_independent_vertex_sets failed", IGRAPH_ENOMEM); IGRAPH_VECTOR_INIT_FINALLY(vec, 0); if (res) { for (v1=0; v1matrix_size; v1++) if (clqdata->IS[v1] == 0) { IGRAPH_CHECK(igraph_vector_push_back(vec, v1)); } IGRAPH_CHECK(igraph_vector_ptr_push_back(res, vec)); size=igraph_vector_size(vec); } else { for (v1=0, size=0; v1matrix_size; v1++) if (clqdata->IS[v1] == 0) size++; } if (size>clqdata->largest_set_size) clqdata->largest_set_size=size; IGRAPH_FINALLY_CLEAN(1); } else { v1 = level+1; /* Count the number of vertices with an index less than v1 that have * an IS value of zero */ neis1 = igraph_i_adjlist_get(&clqdata->adj_list, v1); c = 0; j = 0; while (jdeg)[v1] && (v2=VECTOR(*neis1)[j]) <= level) { if (clqdata->IS[v2] == 0) c++; j++; } if (c == 0) { /* If there are no such nodes... */ j = 0; while (jdeg)[v1] && (v2=VECTOR(*neis1)[j]) <= level) { clqdata->IS[v2]++; j++; } IGRAPH_CHECK(igraph_i_maximal_independent_vertex_sets_backtrack(graph,res,clqdata,v1)); j = 0; while (jdeg)[v1] && (v2=VECTOR(*neis1)[j]) <= level) { clqdata->IS[v2]--; j++; } } else { /* If there are such nodes, store the count in the IS value of v1 */ clqdata->IS[v1] = c; IGRAPH_CHECK(igraph_i_maximal_independent_vertex_sets_backtrack(graph,res,clqdata,v1)); clqdata->IS[v1] = 0; f=1; j=0; while (jdeg)[v1] && (v2=VECTOR(*neis1)[j]) <= level) { if (clqdata->IS[v2] == 0) { IGRAPH_CHECK(igraph_set_add(&clqdata->buckets[v1], j)); neis2 = igraph_i_adjlist_get(&clqdata->adj_list, v2); k = 0; while (kdeg)[v2] && (v3=VECTOR(*neis2)[k])<=level) { clqdata->IS[v3]--; if (clqdata->IS[v3] == 0) f=0; k++; } } clqdata->IS[v2]++; j++; } if (f) IGRAPH_CHECK(igraph_i_maximal_independent_vertex_sets_backtrack(graph,res,clqdata,v1)); j=0; while (jdeg)[v1] && (v2=VECTOR(*neis1)[j]) <= level) { clqdata->IS[v2]--; j++; } it_state=0; while (igraph_set_iterate(&clqdata->buckets[v1], &it_state, &j1)) { j=(long)j1; v2=VECTOR(*neis1)[j]; neis2 = igraph_i_adjlist_get(&clqdata->adj_list, v2); k = 0; while (kdeg)[v2] && (v3=VECTOR(*neis2)[k])<=level) { clqdata->IS[v3]++; k++; } } igraph_set_clear(&clqdata->buckets[v1]); } } return 0; } void igraph_i_free_set_array(igraph_set_t* array) { long int i = 0; while (igraph_set_inited(array+i)) { igraph_set_destroy(array+i); i++; } Free(array); } /** * \function igraph_maximal_independent_vertex_sets * \brief Find all maximal independent vertex sets of a graph * * * A maximal independent vertex set is an independent vertex set which * can't be extended any more by adding a new vertex to it. * * * The algorithm used here is based on the following paper: * S. Tsukiyama, M. Ide, H. Ariyoshi and I. Shirawaka. A new algorithm for * generating all the maximal independent sets. SIAM J Computing, * 6:505--517, 1977. * * * The implementation was originally written by Kevin O'Neill and modified * by K M Briggs in the Very Nauty Graph Library. I simply re-wrote it to * use igraph's data structures. * * * If you are interested in the size of the largest independent vertex set, * use \ref igraph_independence_number() instead. * * \param graph The input graph. * \param res Pointer to a pointer vector, the result will be stored * here, ie. \c res will contain pointers to \c igraph_vector_t * objects which contain the indices of vertices involved in an independent * vertex set. The pointer vector will be resized if needed but note that the * objects in the pointer vector will not be freed. * \return Error code. * * \sa \ref igraph_maximal_cliques(), \ref * igraph_independence_number() * * Time complexity: TODO. */ int igraph_maximal_independent_vertex_sets(const igraph_t *graph, igraph_vector_ptr_t *res) { igraph_i_max_ind_vsets_data_t clqdata; long int no_of_nodes = igraph_vcount(graph), i; clqdata.matrix_size=no_of_nodes; IGRAPH_CHECK(igraph_i_adjlist_init(graph, &clqdata.adj_list, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_i_adjlist_destroy, &clqdata.adj_list); clqdata.IS = Calloc(no_of_nodes, igraph_integer_t); if (clqdata.IS == 0) IGRAPH_ERROR("igraph_maximal_independent_vertex_sets failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes); for (i=0; i * The independence number of a graph is the cardinality of the largest * independent vertex set. * * \param graph The input graph. * \param no The independence number will be returned to the \c * igraph_integer_t pointed by this variable. * \return Error code. * * \sa \ref igraph_independent_vertex_sets(). * * Time complexity: TODO. */ int igraph_independence_number(const igraph_t *graph, igraph_integer_t *no) { igraph_i_max_ind_vsets_data_t clqdata; long int no_of_nodes = igraph_vcount(graph), i; clqdata.matrix_size=no_of_nodes; IGRAPH_CHECK(igraph_i_adjlist_init(graph, &clqdata.adj_list, IGRAPH_ALL)); IGRAPH_FINALLY(igraph_i_adjlist_destroy, &clqdata.adj_list); clqdata.IS = Calloc(no_of_nodes, igraph_integer_t); if (clqdata.IS == 0) IGRAPH_ERROR("igraph_independence_number failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes); for (i=0; i * A maximal clique is a clique which * can't be extended any more by adding a new vertex to it. This is actually * implemented by looking for a maximal independent vertex set in the * complementer of the graph. * * * If you are only interested in the size of the largest clique in the graph, * use \ref igraph_clique_number() instead. * * \param graph The input graph. * \param res Pointer to a pointer vector, the result will be stored * here, ie. \c res will contain pointers to \c igraph_vector_t * objects which contain the indices of vertices involved in a clique. * The pointer vector will be resized if needed but note that the * objects in the pointer vector will not be freed. * \return Error code. * * \sa \ref igraph_maximal_independent_vertex_sets(), \ref * igraph_clique_number() * * Time complexity: TODO. */ int igraph_maximal_cliques(const igraph_t *graph, igraph_vector_ptr_t *res) { igraph_i_max_ind_vsets_data_t clqdata; long int no_of_nodes = igraph_vcount(graph), i; clqdata.matrix_size=no_of_nodes; IGRAPH_CHECK(igraph_i_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, 0)); IGRAPH_FINALLY(igraph_i_adjlist_destroy, &clqdata.adj_list); clqdata.IS = Calloc(no_of_nodes, igraph_integer_t); if (clqdata.IS == 0) IGRAPH_ERROR("igraph_maximal_cliques failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes); for (i=0; i * The clique number of a graph is the size of the largest clique. * * \param graph The input graph. * \param no The clique number will be returned to the \c igraph_integer_t * pointed by this variable. * \return Error code. * * \sa \ref igraph_cliques(), \ref igraph_largest_cliques(). * * Time complexity: TODO. */ int igraph_clique_number(const igraph_t *graph, igraph_integer_t *no) { igraph_i_max_ind_vsets_data_t clqdata; long int no_of_nodes = igraph_vcount(graph), i; clqdata.matrix_size=no_of_nodes; IGRAPH_CHECK(igraph_i_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, 0)); IGRAPH_FINALLY(igraph_i_adjlist_destroy, &clqdata.adj_list); clqdata.IS = Calloc(no_of_nodes, igraph_integer_t); if (clqdata.IS == 0) IGRAPH_ERROR("igraph_clique_number failed", IGRAPH_ENOMEM); IGRAPH_FINALLY(igraph_free, clqdata.IS); IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes); for (i=0; i