1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
42 #include "precomp.hpp"
54 /*typedef struct CvCliqueFinder
60 // stacks, counters etc/
67 int* fixp; //node with minimal disconnections
69 int* s; //for selected candidate
83 #define CV_GET_ADJ_VTX( vertex, edge ) \
85 assert(edge->vtx[0]==vertex||edge->vtx[1] == vertex ), \
86 (edge->vtx[0] == vertex)?edge->vtx[1]:edge->vtx[0] \
90 #define NUMBER( v ) ((v)->flags >> 1 )
92 void _MarkNodes( CvGraph* graph )
94 //set number of vertices to their flags
95 for( int i = 0; i < graph->total; i++ )
97 CvGraphVtx* ver = cvGetGraphVtx( graph, i );
105 void _FillAdjMatrix( CvGraph* graph, int** connected, int reverse )
107 //assume all vertices are marked
108 for( int i = 0; i < graph->total; i++ )
110 for( int j = 0; j < graph->total; j++ )
112 connected[i][j] = 0|reverse;
114 //memset( connected[i], 0, sizeof(int)*graph->total );
115 CvGraphVtx* ver = cvGetGraphVtx( graph, i );
119 for( CvGraphEdge* e = ver->first; e ; e = CV_NEXT_GRAPH_EDGE( e, ver ) )
121 CvGraphVtx* v = CV_GET_ADJ_VTX( ver, e );
122 connected[i][NUMBER(v)] = 1^reverse;
129 void cvStartFindCliques( CvGraph* graph, CvCliqueFinder* finder, int reverse, int weighted, int weighted_edges )
135 finder->weighted = 1;
136 finder->best_weight = 0;
137 finder->vertex_weights = (float*)malloc( sizeof(float)*(graph->total+1));
138 finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
139 finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
141 finder->cur_weight[0] = 0;
142 finder->cand_weight[0] = 0;
143 for( i = 0 ; i < graph->total; i++ )
145 CvGraphWeightedVtx* ver = (CvGraphWeightedVtx*)cvGetGraphVtx( graph, i );
147 assert(ver->weight>=0);
148 finder->vertex_weights[i] = ver->weight;
149 finder->cand_weight[0] += ver->weight;
152 else finder->weighted = 0;
156 finder->weighted_edges = 1;
157 //finder->best_weight = 0;
158 finder->edge_weights = (float*)malloc( sizeof(float)*(graph->total)*(graph->total));
159 //finder->cur_weight = (float*)malloc( sizeof(float)*(graph->total+1));
160 //finder->cand_weight = (float*)malloc( sizeof(float)*(graph->total+1));
162 //finder->cur_weight[0] = 0;
163 //finder->cand_weight[0] = 0;
164 memset( finder->edge_weights, 0, sizeof(float)*(graph->total)*(graph->total) );
165 for( i = 0 ; i < graph->total; i++ )
167 CvGraphVtx* ver1 = cvGetGraphVtx( graph, i );
169 for( int j = i ; j < graph->total; j++ )
171 CvGraphVtx* ver2 = cvGetGraphVtx( graph, j );
173 CvGraphEdge* edge = cvFindGraphEdgeByPtr( graph, ver1, ver2 );
176 assert( ((CvGraphWeightedEdge*)edge)->weight >= 0 );
177 finder->edge_weights[ i * graph->total + j ] =
178 finder->edge_weights[ j * graph->total + i ] = ((CvGraphWeightedEdge*)edge)->weight;
183 else finder->weighted_edges = 0;
186 //int* Compsub; //current component (vertex stack)
187 finder->k = 0; //counter of steps
188 int N = finder->N = graph->total;
189 finder->current_comp = new int[N];
190 finder->All = new int*[N];
191 for( i = 0 ; i < finder->N; i++ )
193 finder->All[i] = new int[N];
196 finder->ne = new int[N+1];
197 finder->ce = new int[N+1];
198 finder->fixp = new int[N+1]; //node with minimal disconnections
199 finder->nod = new int[N+1];
200 finder->s = new int[N+1]; //for selected candidate
203 finder->adj_matr = new int*[N]; //assume filled with 0
204 for( i = 0 ; i < N; i++ )
206 finder->adj_matr[i] = new int[N];
209 //set number to vertices
211 _FillAdjMatrix( graph, finder->adj_matr, reverse );
214 int k = finder->k = 0; //stack size
215 memset( finder->All[k], 0, sizeof(int) * N );
216 for( i = 0; i < N; i++ ) finder->All[k][i] = i;
221 finder->best_score = 0;
225 void cvEndFindCliques( CvCliqueFinder* finder )
229 //int* Compsub; //current component (vertex stack)
230 delete finder->current_comp;
231 for( i = 0 ; i < finder->N; i++ )
233 delete finder->All[i];
239 delete finder->fixp; //node with minimal disconnections
241 delete finder->s; //for selected candidate
244 for( i = 0 ; i < finder->N; i++ )
246 delete finder->adj_matr[i];
248 delete finder->adj_matr;
252 free(finder->vertex_weights);
253 free(finder->cur_weight);
254 free(finder->cand_weight);
256 if(finder->weighted_edges)
258 free(finder->edge_weights);
262 int cvFindNextMaximalClique( CvCliqueFinder* finder )
264 int** connected = finder->adj_matr;
265 // int N = finder->N; //graph size
267 // stacks, counters etc/
268 int k = finder->k; //stack size
269 int* Compsub = finder->current_comp;
270 int** All = finder->All;
272 int* ne = finder->ne;
273 int* ce = finder->ce;
274 int* fixp = finder->fixp; //node with minimal disconnections
275 int* nod = finder->nod;
276 int* s = finder->s; //for selected candidate
282 switch(finder->status)
284 case GO://Forward step
285 /* we have all sets and will choose fixed point */
287 //check potential size of clique
288 if( (!finder->weighted) && (k + ce[k] - ne[k] < finder->best_score) )
290 finder->status = BACK;
293 //check potential weight
294 if( finder->weighted && !finder->weighted_edges &&
295 finder->cur_weight[k] + finder->cand_weight[k] < finder->best_weight )
297 finder->status = BACK;
304 //for every vertex of All determine counter value and choose minimum
305 for( int i = 0; i < ce[k] && minnod != 0; i++)
307 int p = old[i]; //current point
308 int count = 0; //counter
311 /* Count disconnections with candidates */
312 for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
314 if ( !connected[p][old[j]] )
317 /* Save position of potential candidate */
322 /* Test new minimum */
325 fixp[k] = p; //set current point as fixed
326 minnod = count; //new value for minnod
327 if (i < ne[k]) //if current fixed point belongs to 'not'
329 s[k] = pos; //s - selected candidate
333 s[k] = i; //selected candidate is fixed point itself
335 nod[k] = 1; //nod is aux variable, 1 means fixp == s
340 nod[k] = minnod + nod[k];
341 finder->status = NEXT;//go to backtrackcycle
345 //here we will look for candidate to translate into not
346 //s[k] now contains index of choosen candidate
348 int* new_ = All[k+1];
351 //swap selected and first candidate
352 int i, p = old[s[k]];
353 old[s[k]] = old[ne[k]];
354 int sel = old[ne[k]] = p;
358 for ( i = 0; i < ne[k]; i++)
360 if (connected[sel][old[i]])
362 new_[newne] = old[i];
367 //fill new set 'candidate'
369 i++;//skip selected candidate
371 float candweight = 0;
373 for (; i < ce[k]; i++)
375 if (connected[sel][old[i]])
377 new_[newce] = old[i];
379 if( finder->weighted )
380 candweight += finder->vertex_weights[old[i]];
388 //add selected to stack
392 assert( k <= finder->N );
393 if( finder->weighted )
395 //update weights of current clique and candidates
396 finder->cur_weight[k] = finder->cur_weight[k-1] + finder->vertex_weights[sel];
397 finder->cand_weight[k] = candweight;
399 if( finder->weighted_edges )
401 //update total weight by edge weights
403 for( int ind = 0; ind < k-1; ind++ )
405 added += finder->edge_weights[ Compsub[ind] * finder->N + sel ];
407 finder->cur_weight[k] += added;
410 //check if 'not' and 'cand' are both empty
413 finder->best_score = MAX(finder->best_score, k );
415 if( finder->weighted )
416 finder->best_weight = MAX( finder->best_weight, finder->cur_weight[k] );
417 /*FILE* file = fopen("cliques.txt", "a" );
419 for (int t=0; t<k; t++)
421 fprintf(file, "%d ", Compsub[t]);
428 //output new clique//************************
429 finder->status = BACK;
435 else //check nonempty set of candidates
447 finder->status = BACK;
464 //select next candidate
465 for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
467 if( !connected[fixp[k]][old[s[k]]])
470 assert( s[k] < ce[k] );
471 finder->status = NEXT;
474 finder->status = BACK;
483 finder->status = END;
490 void cvBronKerbosch( CvGraph* graph )
492 int* Compsub; //current component (vertex stack)
493 int k = 0; //counter of steps
494 int N = graph->total;
496 Compsub = new int[N];
497 int** All = new int*[N];
498 for( i = 0 ; i < N; i++ )
503 int* ne = new int[N];
504 int* ce = new int[N];
505 int* fixp = new int[N]; //node with minimal disconnections
506 int* nod = new int[N];
507 int* s = new int[N]; //for selected candidate
510 int** connected = new int*[N]; //assume filled with 0
511 for( i = 0 ; i < N; i++ )
513 connected[i] = new int[N];
518 //set number to vertices
520 _FillAdjMatrix( graph, connected, 0 );
524 memset( All[k], 0, sizeof(int) * N );
525 for( i = 0; i < N; i++ ) All[k][i] = i;
538 case GO://Forward step
539 /* we have all sets and will choose fixed point */
542 if( k + ce[k] - ne[k] < best_score )
551 //for every vertex of All determine counter value and choose minimum
552 for( int i = 0; i < ce[k] && minnod != 0; i++)
554 int p = old[i]; //current point
555 int count = 0; //counter
558 /* Count disconnections with candidates */
559 for (int j = ne[k]; j < ce[k] && (count < minnod); j++)
561 if ( !connected[p][old[j]] )
564 /* Save position of potential candidate */
569 /* Test new minimum */
572 fixp[k] = p; //set current point as fixed
573 minnod = count; //new value for minnod
574 if (i < ne[k]) //if current fixed point belongs to 'not'
576 s[k] = pos; //s - selected candidate
580 s[k] = i; //selected candidate is fixed point itself
582 nod[k] = 1; //nod is aux variable, 1 means fixp == s
587 nod[k] = minnod + nod[k];
588 status = NEXT;//go to backtrackcycle
592 //here we will look for candidate to translate into not
593 //s[k] now contains index of choosen candidate
595 int* new_ = All[k+1];
598 //swap selected and first candidate
600 old[s[k]] = old[ne[k]];
601 int sel = old[ne[k]] = p;
605 for ( i = 0; i < ne[k]; i++)
607 if (connected[sel][old[i]])
609 new_[newne] = old[i];
614 //fill new set 'candidate'
616 i++;//skip selected candidate
617 for (; i < ce[k]; i++)
619 if (connected[sel][old[i]])
621 new_[newce] = old[i];
628 //add selected to stack
632 //check if 'not' and 'cand' are both empty
635 best_score = MAX(best_score, k );
637 FILE* file = fopen("cliques.txt", "a" );
639 for (int t=0; t<k; t++)
641 fprintf(file, "%d ", Compsub[t]);
647 /*for( int t = 0; t < k; t++ )
649 printf("%d ", Compsub[t] );
653 //printf("found %d\n", k);
655 //output new clique//************************
658 else //check nonempty set of candidates
687 //select next candidate
688 for( s[k] = ne[k]; s[k] < ce[k]; s[k]++ )
690 if( !connected[fixp[k]][old[s[k]]])
693 assert( s[k] < ce[k] );
706 }//end cvBronKerbosch