| /*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 |
| |