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

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









评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值