多线程技术模拟并行计算之一:查找极大独立集(Find the Maximal Independent Set)

来源:互联网 发布:后台数据怎么传到前台 编辑:程序博客网 时间:2024/05/29 17:28

1.极大独立集的概念:




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 100int 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 -lpthreadrun:./sequential_MISclean: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 100int 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 emptyelse 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 differentcontinue;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 Sprintf("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 -lpthreadrun:./parallel_MISclean:rm parallel_MIS

4.运行结果:

以下展示的只是其中的一种可能性:


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









原创粉丝点击