#include	"BSprivate.h"

/*+ BSfnd_clique - Find and number the cliques

    Input Parameters:
.   A - The sparse matrix
.   size_limit - the limit on the number of rows in the clique
.   weight - the weight (in rows) of each node in the graph
.   procinfo - the usual processor info

    Returns:
    a numbering of the nodes in which if two nodes have the same
    number, then they are in the same clique

    Notes:
    This only finds cliques local to a processor

+*/
BSnumbering	*BSfnd_clique(BSspmat *A, int size_limit, int *weight,
				BSprocinfo *procinfo)
{
	int	n;
	BSsprow	**rows;
	BSnumbering	*numbering;
	int	*used;
	int	i, j, k, l;
	int	cur_num;
	BSsprow *cur_row;
	BSsprow *neighbor_row;
	int	neighbor;
	int	connected, found;
	int	*list, list_len;
	int	cur_weight;

	n = A->num_rows;
	rows = A->rows;
	numbering = BSalloc_numbering(n); CHKERRN(0);

	if (procinfo->single) {
		for	(i=0;i<n;i++) numbering->numbers[i] = i;
		return(numbering);
	}

	MY_MALLOCN(used,(int *),sizeof(int)*n,1);
	for	(i=0;i<n;i++) used[i] = FALSE;

	cur_num = 0;

	/* go over every node in my partition */
	for	(i=0;i<n;i++) {
		/* if node is already numbered then skip it */
		if (used[i]) continue;

		/* examine nodes that this node is connected to 
		   to check if that node is identical, do not examine
		   nodes that are not in my partition
		*/
		numbering->numbers[i] = cur_num;
		used[i] = TRUE;
		cur_row = rows[i];
		MY_MALLOCN(list,(int *),sizeof(int)*cur_row->length,2+i);
		list_len = 0;
		cur_weight = weight[i];
		for (j=0;j<cur_row->length;j++) {
			/* don't look at myself */
			if (j == cur_row->diag_ind) continue;
			/* if over my limit, then stop looking */
			if (cur_weight >= size_limit) break;
			/* if neighbor is in my partition */
			(*A->map->fglobal2local)(1,&(cur_row->col[j]),
				&neighbor,procinfo,A->map); CHKERRN(0);
			if (neighbor >= 0) {
				/* continue if the neighbor is already numbered */
				if (used[neighbor]) continue;

				neighbor_row = rows[neighbor];
				/* if neighbor is connected to everyone in current clique */
				connected = TRUE;
				for (k=0;k<list_len;k++) {
					found = FALSE;
					for (l=0;l<neighbor_row->length;l++) {
						if (list[k] == neighbor_row->col[l]) {
							found = TRUE;
							break;
						}
					}
					if (!found) {
						connected = FALSE;
						break;
					}
				}
				if ((connected) && 
					((cur_weight + weight[neighbor]) <= size_limit)) {
					cur_weight += weight[neighbor];
					list[list_len] = cur_row->col[j];
					list_len++;
					numbering->numbers[neighbor] = cur_num;
					used[neighbor] = TRUE;
				}
			}
		}
		MY_FREEN(list);
		cur_num++;
	}

	MY_FREEN(used);
	return(numbering);
}


syntax highlighted by Code2HTML, v. 0.9.1