2.查找极大独立集的串行算法:
首先设置集合S为空,遍历所有的顶点v,如果顶点v在S集合中没有邻居,那么就将顶点v加入到集合S中,最终得到的集合S就是MIS(Maximal Independent Set)。
伪代码:
S = empty set; for vertex v = 1 to n { if (v has no neighbor in S) { add v to S } }
sequential_MIS.c:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define MAX 100 int graph[9][9]= { 0,0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0,0, 0,1,0,0,1,0,0,0,0, 0,1,0,0,1,1,0,1,1, 0,1,1,1,0,0,1,0,1, 0,0,0,1,0,0,0,1,0, 0,0,0,0,1,0,0,0,1, 0,0,0,1,0,1,0,0,1, 0,0,0,1,1,0,1,1,0 }; int S[MAX]={-1}; int count = 0; /*to check whether vertex v has neighbor in S*/ int sequential_MIS(int v) { int flag = 0,i,j; for(i=1;i<=8;i++) { if(graph[v][i]==1) //vertex v and i are neighbors { for(j=0;j<count;j++) //search whether vertex i in set S { if( i==S[j] ) { flag = 1; break; }//vertex i is in set S } } if(flag) break; } if(!flag) return 1; else return 0; } int main() { int h,i,j,k,l; for(i=1;i<=8;i++) { if(sequential_MIS(i)) { S[count++]=i; } } /****The maximal independent set**********/ printf("The maximal independent set : "); for(i=0;i<count;i++) printf("%d ",S[i]); printf("\n"); return 0 ; }其中二维数组graph[9][9]是根据第一张图片里的图建立的。
makefile:
target: gcc sequential_MIS.c -o sequential_MIS -lpthread run: ./sequential_MIS clean: rm sequential_MIS
3.查找极大独立集的并行算法(通过多线程进行模拟):
过程如下:
第一步:初始化MIS集合S和顶点集合C:
第二步:给C中的结点附随机值:
第三步:并行处理,直到集合C为空:
parallel_MIS.c:
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #define MAX 100 int graph[9][9]= { 0,0,0,0,0,0,0,0,0, 0,0,1,1,1,0,0,0,0, 0,1,0,0,1,0,0,0,0, 0,1,0,0,1,1,0,1,1, 0,1,1,1,0,0,1,0,1, 0,0,0,1,0,0,0,1,0, 0,0,0,0,1,0,0,0,1, 0,0,0,1,0,1,0,0,1, 0,0,0,1,1,0,1,1,0 }; int S[MAX]={-1}; int countS=0; int C[9]={0,1,2,3,4,5,6,7,8}; int C_num[10]={0}; int temp[10]={0}; int num[100]={0}; pthread_t tids[100]; pthread_mutex_t mutex; int IsNotEmpty(int *array) { int i,flag=0; for(i=1;i<=8;i++) { if(array[i]!=0) { flag = 1; break; } } if(flag) return 1; //array is not empty else return 0; //array is empty } int generate_random_data() { int number; srand((unsigned)time(NULL)); while(num[(number=rand()%97)]!=0)//gaurantee the random numbers are different continue; num[number]=1; return number; } void *fun(void *arg) { int v,i,minimum; v = *(int *)arg; pthread_mutex_lock(&mutex); printf("\n/****mutex enter****/\n"); printf("vertex = %d is now processing\n",v); minimum = 100; for(i=1;i<=8;i++)//min( r(neighbors of v) ) { if(graph[v][i]==1)//vertex i and v are neighbors. { if( C_num[i]<minimum && C[i]!=0 ) minimum = C_num[i]; } } if(C_num[v]<minimum) { S[countS++]=v; //move v from C to S printf("vertex %d is added.\n",v); } printf("/****mutex quit****/\n"); pthread_mutex_unlock(&mutex); pthread_exit(NULL); } void parallel_MIS() { printf("/****************parallel_MIS enter****************/\n"); int h,i,j,k,l,v; int countTids[100]; while(IsNotEmpty(C)) { pthread_mutex_init(&mutex,NULL); memset(num,0,sizeof(num)); memset(C_num,0,sizeof(C_num)); memset(countTids,0,sizeof(countTids)); /***label each vertex in C with a random data***/ for(i=1;i<=8;i++) { if( C[i]!=0 ) C_num[i]=generate_random_data(); } printf("The set C and the random data of each element in C :\n"); for(i=1;i<=8;i++) { printf("C_num[%d] = %d ",i,C_num[i]); printf("C[%d] = %d\n",i,C[i]); } /**for vertex i in C do parallel**/ for( i=1;i<=8;i++ ) { if(C[i]!=0) { int *p; p = (int *)malloc(sizeof(int)); *p = i; pthread_create(&tids[i],NULL,fun,p); countTids[i]=1; } } for( i=1;i<=8;i++ ) if( countTids[i]==1 ) pthread_join(tids[i],NULL); sleep(2); printf("\nthe vertex now in set S are : "); for(i=0;i<countS;i++) { v = S[i]; printf("%d ",v); C[ v ] = 0; for(j=1;j<=8;j++) { if(graph[v][j]==1) C[j]=0;//remove neighbors of v from C } } printf("\n"); } printf("/****************parallel_MIS quit****************/\n"); } int main() { int i ; parallel_MIS(); printf("The final result of MIS : "); for(i=0;i<countS;i++) printf("%d ",S[i]); printf("\n"); return 0 ; }
makefile:
target: gcc parallel_MIS.c -o parallel_MIS -lpthread run: ./parallel_MIS clean: rm parallel_MIS
MIS:{6,2,5};
其他MIS:{2,5,8} {1,8,5} {4,7} {1,5,6}等。
5.总结
a.并行的时候一定要考虑周全,由于多个线程在同时执行,那么一些共用的值会被改变,就像是代码中的C集合。
b.打印调试依旧是一个屡试不爽的办法。
c.线程的标记数组tids[]必须定义为pthread_t类型,如果定义成int类型就会报段错误!
转载请注明文章出处:http://blog.csdn.net/lavorange/article/details/9074255