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