--- /dev/null
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+// By downloading, copying, installing or using the software you agree to this license.
+// If you do not agree to this license, do not download, install,
+// copy or use the software.
+//
+//
+// Intel License Agreement
+// For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistribution's of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+//
+// * Redistribution's in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// * The name of Intel Corporation may not be used to endorse or promote products
+// derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_cvaux.h"
+
+#if 0
+
+#include <float.h>
+#include <limits.h>
+#include <stdio.h>
+
+
+#include "_cvutils.h"
+#include "_cvwrap.h"
+
+/*typedef struct CvCliqueFinder
+{
+ CvGraph* graph;
+ int** adj_matr;
+ int N; //graph size
+
+ // stacks, counters etc/
+ int k; //stack size
+ int* current_comp;
+ int** All;
+
+ int* ne;
+ int* ce;
+ int* fixp; //node with minimal disconnections
+ int* nod;
+ int* s; //for selected candidate
+ int status;
+ int best_score;
+
+} CvCliqueFinder;
+*/
+
+#define GO 1
+#define BACK 2
+#define PEREBOR 3
+#define NEXT PEREBOR
+#define END 4
+
+
+#define CV_GET_ADJ_VTX( vertex, edge ) \
+( \
+ assert(edge->vtx[0]==vertex||edge->vtx[1] == vertex ), \
+ (edge->vtx[0] == vertex)?edge->vtx[1]:edge->vtx[0] \
+)
+
+
+#define NUMBER( v ) ((v)->flags >> 1 )
+
+void _MarkNodes( CvGraph* graph )
+{
+ //set number of vertices to their flags
+ for( int i = 0; i < graph->total; i++ )
+ {
+ CvGraphVtx* ver = cvGetGraphVtx( graph, i );
+ if( ver )
+ {
+ ver->flags = i<<1;
+ }
+ }
+}
+
+void _FillAdjMatrix( CvGraph* graph, int** connected, int reverse )
+{
+ //assume all vertices are marked
+ for( int i = 0; i < graph->total; i++ )
+ {
+ for( int j = 0; j < graph->total; j++ )
+ {
+ connected[i][j] = 0|reverse;
+ }
+ //memset( connected[i], 0, sizeof(int)*graph->total );
+ CvGraphVtx* ver = cvGetGraphVtx( graph, i );
+ if( ver )
+ {
+ connected[i][i] = 1;
+ for( CvGraphEdge* e = ver->first; e ; e = CV_NEXT_GRAPH_EDGE( e, ver ) )
+ {
+ CvGraphVtx* v = CV_GET_ADJ_VTX( ver, e );
+ connected[i][NUMBER(v)] = 1^reverse;
+ }
+ }
+ }
+}
+
+
+void cvStartFindCliques( CvGraph* graph, CvCliqueFinder* finder, int reverse, int weighted, int weighted_edges )
+{
+ int i;
+
+ if (weighted)
+ {
+ finder->weighted = 1;
+ finder->best_weight = 0;
+ finder->vertex_weights = (float*)malloc( sizeof(float)*(graph->total+1));
+ finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
+ finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
+
+ finder->cur_weight[0] = 0;
+ finder->cand_weight[0] = 0;
+ for( i = 0 ; i < graph->total; i++ )
+ {
+ CvGraphWeightedVtx* ver = (CvGraphWeightedVtx*)cvGetGraphVtx( graph, i );
+ assert(ver);
+ assert(ver->weight>=0);
+ finder->vertex_weights[i] = ver->weight;
+ finder->cand_weight[0] += ver->weight;
+ }
+ }
+ else finder->weighted = 0;
+
+ if (weighted_edges)
+ {
+ finder->weighted_edges = 1;
+ //finder->best_weight = 0;
+ finder->edge_weights = (float*)malloc( sizeof(float)*(graph->total)*(graph->total));
+ //finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
+ //finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
+
+ //finder->cur_weight[0] = 0;
+ //finder->cand_weight[0] = 0;
+ memset( finder->edge_weights, 0, sizeof(float)*(graph->total)*(graph->total) );
+ for( i = 0 ; i < graph->total; i++ )
+ {
+ CvGraphVtx* ver1 = cvGetGraphVtx( graph, i );
+ if(!ver1) continue;
+ for( int j = i ; j < graph->total; j++ )
+ {
+ CvGraphVtx* ver2 = cvGetGraphVtx( graph, j );
+ if(!ver2) continue;
+ CvGraphEdge* edge = cvFindGraphEdgeByPtr( graph, ver1, ver2 );
+ if( edge )
+ {
+ assert( ((CvGraphWeightedEdge*)edge)->weight >= 0 );
+ finder->edge_weights[ i * graph->total + j ] =
+ finder->edge_weights[ j * graph->total + i ] = ((CvGraphWeightedEdge*)edge)->weight;
+ }
+ }
+ }
+ }
+ else finder->weighted_edges = 0;
+
+
+ //int* Compsub; //current component (vertex stack)
+ finder->k = 0; //counter of steps
+ int N = finder->N = graph->total;
+ finder->current_comp = new int[N];
+ finder->All = new int*[N];
+ for( i = 0 ; i < finder->N; i++ )
+ {
+ finder->All[i] = new int[N];
+ }
+
+ finder->ne = new int[N+1];
+ finder->ce = new int[N+1];
+ finder->fixp = new int[N+1]; //node with minimal disconnections
+ finder->nod = new int[N+1];
+ finder->s = new int[N+1]; //for selected candidate
+
+ //form adj matrix
+ finder->adj_matr = new int*[N]; //assume filled with 0
+ for( i = 0 ; i < N; i++ )
+ {
+ finder->adj_matr[i] = new int[N];
+ }
+
+ //set number to vertices
+ _MarkNodes( graph );
+ _FillAdjMatrix( graph, finder->adj_matr, reverse );
+
+ //init all arrays
+ int k = finder->k = 0; //stack size
+ memset( finder->All[k], 0, sizeof(int) * N );
+ for( i = 0; i < N; i++ ) finder->All[k][i] = i;
+ finder->ne[0] = 0;
+ finder->ce[0] = N;
+
+ finder->status = GO;
+ finder->best_score = 0;
+
+}
+
+void cvEndFindCliques( CvCliqueFinder* finder )
+{
+ int i;
+
+ //int* Compsub; //current component (vertex stack)
+ delete finder->current_comp;
+ for( i = 0 ; i < finder->N; i++ )
+ {
+ delete finder->All[i];
+ }
+ delete finder->All;
+
+ delete finder->ne;
+ delete finder->ce;
+ delete finder->fixp; //node with minimal disconnections
+ delete finder->nod;
+ delete finder->s; //for selected candidate
+
+ //delete adj matrix
+ for( i = 0 ; i < finder->N; i++ )
+ {
+ delete finder->adj_matr[i];
+ }
+ delete finder->adj_matr;
+
+ if(finder->weighted)
+ {
+ free(finder->vertex_weights);
+ free(finder->cur_weight);
+ free(finder->cand_weight);
+ }
+ if(finder->weighted_edges)
+ {
+ free(finder->edge_weights);
+ }
+}
+
+int cvFindNextMaximalClique( CvCliqueFinder* finder )
+{
+ int** connected = finder->adj_matr;
+// int N = finder->N; //graph size
+
+ // stacks, counters etc/
+ int k = finder->k; //stack size
+ int* Compsub = finder->current_comp;
+ int** All = finder->All;
+
+ int* ne = finder->ne;
+ int* ce = finder->ce;
+ int* fixp = finder->fixp; //node with minimal disconnections
+ int* nod = finder->nod;
+ int* s = finder->s; //for selected candidate
+
+ //START
+ while( k >= 0)
+ {
+ int* old = All[k];
+ switch(finder->status)
+ {
+ case GO://Forward step
+ /* we have all sets and will choose fixed point */
+ {
+ //check potential size of clique
+ if( (!finder->weighted) && (k + ce[k] - ne[k] < finder->best_score) )
+ {
+ finder->status = BACK;
+ break;
+ }
+ //check potential weight
+ if( finder->weighted && !finder->weighted_edges &&
+ finder->cur_weight[k] + finder->cand_weight[k] < finder->best_weight )
+ {
+ finder->status = BACK;
+ break;
+ }
+
+ int minnod = ce[k];
+ nod[k] = 0;
+
+ //for every vertex of All determine counter value and choose minimum
+ for( int i = 0; i < ce[k] && minnod != 0; i++)
+ {
+ int p = old[i]; //current point
+ int count = 0; //counter
+ int pos = 0;
+
+ /* Count disconnections with candidates */
+ for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
+ {
+ if ( !connected[p][old[j]] )
+ {
+ count++;
+ /* Save position of potential candidate */
+ pos = j;
+ }
+ }
+
+ /* Test new minimum */
+ if (count < minnod)
+ {
+ fixp[k] = p; //set current point as fixed
+ minnod = count; //new value for minnod
+ if (i < ne[k]) //if current fixed point belongs to 'not'
+ {
+ s[k] = pos; //s - selected candidate
+ }
+ else
+ {
+ s[k] = i; //selected candidate is fixed point itself
+ /* preincr */
+ nod[k] = 1; //nod is aux variable, 1 means fixp == s
+ }
+ }
+ }//for
+
+ nod[k] = minnod + nod[k];
+ finder->status = NEXT;//go to backtrackcycle
+ }
+ break;
+ case NEXT:
+ //here we will look for candidate to translate into not
+ //s[k] now contains index of choosen candidate
+ {
+ int* new_ = All[k+1];
+ if( nod[k] != 0 )
+ {
+ //swap selected and first candidate
+ int i, p = old[s[k]];
+ old[s[k]] = old[ne[k]];
+ int sel = old[ne[k]] = p;
+
+ int newne = 0;
+ //fill new set 'not'
+ for ( i = 0; i < ne[k]; i++)
+ {
+ if (connected[sel][old[i]])
+ {
+ new_[newne] = old[i];
+ newne++;
+
+ }
+ }
+ //fill new set 'candidate'
+ int newce = newne;
+ i++;//skip selected candidate
+
+ float candweight = 0;
+
+ for (; i < ce[k]; i++)
+ {
+ if (connected[sel][old[i]])
+ {
+ new_[newce] = old[i];
+
+ if( finder->weighted )
+ candweight += finder->vertex_weights[old[i]];
+
+ newce++;
+ }
+ }
+
+ nod[k]--;
+
+ //add selected to stack
+ Compsub[k] = sel;
+
+ k++;
+ assert( k <= finder->N );
+ if( finder->weighted )
+ {
+ //update weights of current clique and candidates
+ finder->cur_weight[k] = finder->cur_weight[k-1] + finder->vertex_weights[sel];
+ finder->cand_weight[k] = candweight;
+ }
+ if( finder->weighted_edges )
+ {
+ //update total weight by edge weights
+ float added = 0;
+ for( int ind = 0; ind < k-1; ind++ )
+ {
+ added += finder->edge_weights[ Compsub[ind] * finder->N + sel ];
+ }
+ finder->cur_weight[k] += added;
+ }
+
+ //check if 'not' and 'cand' are both empty
+ if( newce == 0 )
+ {
+ finder->best_score = MAX(finder->best_score, k );
+
+ if( finder->weighted )
+ finder->best_weight = MAX( finder->best_weight, finder->cur_weight[k] );
+ /*FILE* file = fopen("cliques.txt", "a" );
+
+ for (int t=0; t<k; t++)
+ {
+ fprintf(file, "%d ", Compsub[t]);
+ }
+ fprintf(file, "\n");
+
+ fclose(file);
+ */
+
+ //output new clique//************************
+ finder->status = BACK;
+ finder->k = k;
+
+ return CLIQUE_FOUND;
+
+ }
+ else //check nonempty set of candidates
+ if( newne < newce )
+ {
+ //go further
+ ne[k] = newne;
+ ce[k] = newce;
+ finder->status = GO;
+ break;
+ }
+
+ }
+ else
+ finder->status = BACK;
+
+ }
+ break;
+
+ case BACK:
+ {
+ //decrease stack
+ k--;
+ old = All[k];
+ if( k < 0 ) break;
+
+ //add to not
+ ne[k]++;
+
+ if( nod[k] > 0 )
+ {
+ //select next candidate
+ for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
+ {
+ if( !connected[fixp[k]][old[s[k]]])
+ break;
+ }
+ assert( s[k] < ce[k] );
+ finder->status = NEXT;
+ }
+ else
+ finder->status = BACK;
+
+ }
+ break;
+ case END: assert(0);
+
+ }
+ }//end while
+
+ finder->status = END;
+ return CLIQUE_END;
+}
+
+
+
+
+void cvBronKerbosch( CvGraph* graph )
+{
+ int* Compsub; //current component (vertex stack)
+ int k = 0; //counter of steps
+ int N = graph->total;
+ int i;
+ Compsub = new int[N];
+ int** All = new int*[N];
+ for( i = 0 ; i < N; i++ )
+ {
+ All[i] = new int[N];
+ }
+
+ int* ne = new int[N];
+ int* ce = new int[N];
+ int* fixp = new int[N]; //node with minimal disconnections
+ int* nod = new int[N];
+ int* s = new int[N]; //for selected candidate
+
+ //form adj matrix
+ int** connected = new int*[N]; //assume filled with 0
+ for( i = 0 ; i < N; i++ )
+ {
+ connected[i] = new int[N];
+ }
+
+
+
+ //set number to vertices
+ _MarkNodes( graph );
+ _FillAdjMatrix( graph, connected, 0 );
+
+ //init all arrays
+ k = 0; //stack size
+ memset( All[k], 0, sizeof(int) * N );
+ for( i = 0; i < N; i++ ) All[k][i] = i;
+ ne[0] = 0;
+ ce[0] = N;
+
+ int status = GO;
+ int best_score = 0;
+
+ //START
+ while( k >= 0)
+ {
+ int* old = All[k];
+ switch(status)
+ {
+ case GO://Forward step
+ /* we have all sets and will choose fixed point */
+ {
+
+ if( k + ce[k] - ne[k] < best_score )
+ {
+ status = BACK;
+ break;
+ }
+
+ int minnod = ce[k];
+ nod[k] = 0;
+
+ //for every vertex of All determine counter value and choose minimum
+ for( int i = 0; i < ce[k] && minnod != 0; i++)
+ {
+ int p = old[i]; //current point
+ int count = 0; //counter
+ int pos = 0;
+
+ /* Count disconnections with candidates */
+ for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
+ {
+ if ( !connected[p][old[j]] )
+ {
+ count++;
+ /* Save position of potential candidate */
+ pos = j;
+ }
+ }
+
+ /* Test new minimum */
+ if (count < minnod)
+ {
+ fixp[k] = p; //set current point as fixed
+ minnod = count; //new value for minnod
+ if (i < ne[k]) //if current fixed point belongs to 'not'
+ {
+ s[k] = pos; //s - selected candidate
+ }
+ else
+ {
+ s[k] = i; //selected candidate is fixed point itself
+ /* preincr */
+ nod[k] = 1; //nod is aux variable, 1 means fixp == s
+ }
+ }
+ }//for
+
+ nod[k] = minnod + nod[k];
+ status = NEXT;//go to backtrackcycle
+ }
+ break;
+ case NEXT:
+ //here we will look for candidate to translate into not
+ //s[k] now contains index of choosen candidate
+ {
+ int* new_ = All[k+1];
+ if( nod[k] != 0 )
+ {
+ //swap selected and first candidate
+ int p = old[s[k]];
+ old[s[k]] = old[ne[k]];
+ int sel = old[ne[k]] = p;
+
+ int newne = 0;
+ //fill new set 'not'
+ for ( i = 0; i < ne[k]; i++)
+ {
+ if (connected[sel][old[i]])
+ {
+ new_[newne] = old[i];
+ newne++;
+
+ }
+ }
+ //fill new set 'candidate'
+ int newce = newne;
+ i++;//skip selected candidate
+ for (; i < ce[k]; i++)
+ {
+ if (connected[sel][old[i]])
+ {
+ new_[newce] = old[i];
+ newce++;
+ }
+ }
+
+ nod[k]--;
+
+ //add selected to stack
+ Compsub[k] = sel;
+ k++;
+
+ //check if 'not' and 'cand' are both empty
+ if( newce == 0 )
+ {
+ best_score = MAX(best_score, k );
+
+ FILE* file = fopen("cliques.txt", "a" );
+
+ for (int t=0; t<k; t++)
+ {
+ fprintf(file, "%d ", Compsub[t]);
+ }
+ fprintf(file, "\n");
+
+ fclose(file);
+
+ /*for( int t = 0; t < k; t++ )
+ {
+ printf("%d ", Compsub[t] );
+ }
+ printf("\n"); */
+
+ //printf("found %d\n", k);
+
+ //output new clique//************************
+ status = BACK;
+ }
+ else //check nonempty set of candidates
+ if( newne < newce )
+ {
+ //go further
+ ne[k] = newne;
+ ce[k] = newce;
+ status = GO;
+ break;
+ }
+
+ }
+ else
+ status = BACK;
+
+ }
+ break;
+
+ case BACK:
+ {
+ //decrease stack
+ k--;
+ old = All[k];
+ if( k < 0 ) break;
+
+ //add to not
+ ne[k]++;
+
+ if( nod[k] > 0 )
+ {
+ //select next candidate
+ for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
+ {
+ if( !connected[fixp[k]][old[s[k]]])
+ break;
+ }
+ assert( s[k] < ce[k] );
+ status = NEXT;
+ }
+ else
+ status = BACK;
+
+ }
+ break;
+
+
+ }
+ }//end while
+
+}//end cvBronKerbosch
+
+#endif
+