离散数学实验四 关系闭包计算

一、实验目的
熟悉Warshall算法,掌握求关系的自反闭包、对称闭包和传递闭包的方法。

二、实验内容

定义1  设R是A上的二元关系,R的自反(对称、传递)闭包是关系R1,则

① R1是自反的(对称的、传递的)
② RR1
③对任何自反的(对称的、传递的)关系R2,若RR2,则R1R2。
R的自反、对称和传递闭包分别记为r®、s®和t®。

定理1  令RAA,则

① r®=R∪IA
② s®=R∪R-1
③ t®=R∪R2∪R3…

Warshall算法:设R是n个元素集合上的二元关系,M是R的关系矩阵;

(1)置新矩阵A:=M
(2)置i:=1;
(3)for j=1 to n do
if A[j,i]=1 then do
for k=1 to n do
A[j,k]:=A[j,k]+A[i,k]
(4)i=i+1;
(5) if i<=n then to (3)(6) (7)(8)(9)(10)(11)(12)(13)(14)(15)(16)(17)(18)(19)(20)(21)(22)(23)(24)
else stop

本实验要求从键盘输入一个关系的关系矩阵,计算其自反闭包、对称闭包和传递闭包,计算传递闭包时使用Warshall算法。用C语言或MATLAB实现。

三、实验源程序及结果截图
1.实验源程序:

#include 
#include 

int main() {
     
	int i,j,n;
	//输入关系矩阵,只能输入0或1 ,若输入不为0或1,提示输入错误并结束程序 
	printf("请输入关系矩阵阶数n:\n");
	scanf("%d",&n);
	int a[n][n];
	printf("请输入关系矩阵真值(0或1):\n");
	for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			scanf("%d",&a[i][j]);
		}
	}
	for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			if(a[i][j]!=0&&a[i][j]!=1){
     
				printf("输入错误!");
				return 0;
			}
		}
	}
	//初始化自反闭包、对称闭包和传递闭包的关系矩阵,使之都为刚输入的关系矩阵 
	int zf[n][n], dc[n][n],cd[n][n];
	for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			zf[i][j]=a[i][j];
			dc[i][j]=a[i][j];
			cd[i][j]=a[i][j];
		}
	}
	//求自反闭包(将关系矩阵的主对角线全改为1) 
	for(i=0;i<n;i++){
     
		zf[i][i]=1;
	}
	printf("自反闭包的关系矩阵为:"); 
	for(i=0;i<n;i++){
     
		printf("\n");
		for(j=0;j<n;j++){
     
			printf("%d ",zf[i][j]);
		}
	}
	printf("\n");
	//求对称闭包(保证一个元素真值为1时,关系矩阵中与其对应的元素真值也为1)
	for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			if(dc[i][j]==1){
     
				dc[j][i]=1;
			}
		}
	}
	printf("对称闭包的关系矩阵为:"); 
	for(i=0;i<n;i++){
     
		printf("\n");
		for(j=0;j<n;j++){
     
			printf("%d ",dc[i][j]);
		}
	}
	printf("\n");
	//求传递闭包(利用Warshall算法)
	int k;
	 for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			if(cd[j][i]==1){
     
				for(k=0;k<n;k++){
     
					cd[j][k]=cd[j][k]+cd[i][k];
				}
			}
		}
	}
	//将求出的传递闭包中真值大于1的元素真值改为1 
	for(i=0;i<n;i++){
     
		for(j=0;j<n;j++){
     
			if(cd[i][j]>1){
     
				cd[i][j]=1;
			}
		}
	}
	printf("传递闭包的关系矩阵为:"); 
	for(i=0;i<n;i++){
     
		printf("\n");
		for(j=0;j<n;j++){
     
			printf("%d ",cd[i][j]);
		}
	}
	return 0;
}

2、运行结果:
(1)三阶矩阵
离散数学实验四 关系闭包计算_第1张图片
(2)四阶矩阵
离散数学实验四 关系闭包计算_第2张图片
(3)输入错误
离散数学实验四 关系闭包计算_第3张图片
四、实验的分析与思考

1、实验分析
首先要清楚各个闭包矩阵的性质:自反闭包(将关系矩阵的主对角线全改为1),对称闭包(保证一个元素真值为1时,关系矩阵中与其对应的元素真值也为1),传递闭包(利用Warshall算法)
for(i=0;i for(j=0;j if(cd[j][i]==1){
for(k=0;k cd[j][k]=cd[j][k]+cd[i][k];
}
}
}
}

2、问题与思考
一开始发现求传递闭包时总会出现大于1的数,后来了解到Warshall算法中cd[j][k]+cd[i][k]的含义应该是两者析取,在关系矩阵的输入中,输入的是0或1,因此应该将最后传递闭包中大于1的数改为1。

你可能感兴趣的:(离散数学实验四 关系闭包计算)