【Educoder离散数学实训】关系基础

题有点多,能聊的不多。有些题还是比较有价值的

就单独说几个题,代码放在最后。所有函数都改成自己写的了,没准比答案给的好读一点?

T1 求给定集合的对角线关系(diagonal relation)

我觉得如果卡住的话,第一关会是一个大坎。
因为我们并不知道他到底在说啥,于是我们选择输出一下看一看。
首先,我们在__init__函数里输入

print(type(sets), type(rel))

我们发现,他俩都是setsetset
紧接着,我们对于relrelrel内部的元素输出,想看一看序偶的存在形式是什么。
我们输入

for x in rel :print(type(rel))

发现,序偶是以元组的形式存储的。
那么就好办了,我们就可以按照自己的理解写好这个函数。
写完了看到注释,代表IAI_AIA​的RelationRelationRelation对象,其实说的就是返回一个类的实例回去。
或者在调试的时候发现,给出的报错中含有:

print(Relation(sets[i], EmptySet).diagonalRelation() == Relation(sets[i], rels[i]))

我们也可以发现,返回的就是一个类的实例而已。

T3 关系的幂运算

这个题是递归做的,需要判断掉指数是000和−1-1−1的情况,分别返回转置和IAI_AIA​

T14 关系的传递闭包

这个题我想简单聊两句(估计没人看
首先,我们抽象出来一个数学模型:
有nnn个城市,如果<x,y>∈R<x,y>\in R<x,y>∈R则代表xxx和yyy有一条路可达,这条路需要走一天。
那么RRR的关系矩阵MMM代表什么呢?代表的是,如果Mi,jM_{i,j}Mi,j​是111代表的是iii可以走111天到jjj
问题来了,R2R^2R2代表什么呢?其实通过关系的合成我们可以明白,如果R2R^2R2得到的关系矩阵M′M'M′,其中若Mi,j′M'_{i,j}Mi,j′​代表的是iii走222天可以到jjj
同理,RkR^kRk就是走kkk天罢了。
那这时,我们就可以发现,其实R∪R2∪R3...R\cup R^2\cup R^3...R∪R2∪R3...只需要计算到Rn−1R^{n-1}Rn−1即可。因为一个城市如果真的能到另一个城市,最多只需要走n−1n-1n−1天,就是把其他n−2n-2n−2个城市都经历一遍。这是容易理解的。再多的RRR的幂次也就可以很容易的证明是无效贡献的。

T15 利用Warshall算法求传递闭包

这个题其实就是floydfloydfloyd。
本质上讲,就是一种以O(n3)O(n^3)O(n3)的时间复杂度求任意两点最短路的算法。
其基于的理论是最短路的两点,途径的任意两点之间都是最短路,这是显然的。
至于floydfloydfloyd算法的正确性可以用数学归纳法进行证明,这里不过多赘述了。
这个题其实是floydfloydfloyd的一种特殊应用,也就是求传递闭包。
明白了求最短路,传递闭包其实就是路径大小变成是否可达而已。

T17 计算等价类

这个题有更快的一种数据结构,叫并查集。感兴趣可以自行查询。
这里的做法非常的平凡,建立一个visitedvisitedvisited数组,表示这个元素有没有进别的等价类里面。如果没有的话,就遍历整个setsetset找到他的所有等价类,并将他们的visitedvisitedvisited全部设置成TrueTrueTrue即可。

其余的题没有聊的必要了,都是书上的定义而已,简单的代码复现。
代码:

import functoolsclass Relation(object):def __init__(self, sets, rel):#rel为sets上的二元关系assert not(len(sets)==0 and len(rel) > 0) #不允许sets为空而rel不为空assert sets.issuperset(set([x[0] for x in rel]) | set([x[1] for x in rel])) #不允许rel中出现非sets中的元素self.rel = relself.sets = setsdef __str__(self):relstr = '{}'setstr = '{}'if len(self.rel) > 0:relstr = str(self.rel)if len(self.sets) > 0:setstr = str(self.sets)return 'Relation: ' + relstr + ' on Set: ' + setstrdef __eq__(self, other):#判断两个Relation对象是否相等,关系及集合都要相等return self.sets == other.sets and self.rel == other.reldef diagonalRelation(self):#返回代表IA的Relation对象n = len(self.sets)ret = set()for x in self.sets :ret.add((x, x))return Relation(self.sets, ret)def __mul__(self, other):assert self.sets == other.sets#实现两个关系的合成,即self*other表示other合成self。请注意是先看other的序偶#返回合成的结果,为一个Relation对象ret = set()for x in other.rel :for y in self.rel :if x[1] == y[0] :ret.add((x[0], y[1]))return Relation(self.sets, ret)def __pow__(self, power, modulo=None):assert power >= -1# 实现同一关系的多次合成,重载**运算符,即self*self*self=self**3# 在每个分支中返回对应的结果,结果是一个Relation对象if power == -1 :ret = set()for x in self.rel :ret.add((x[1], x[0]))return Relation(self.sets, ret)elif power == 0 :return self.diagonalRelation()else :return self * self ** (power - 1)def __add__(self, other):assert self.sets == other.sets#实现两个关系的并运算,重载+运算符,即self+other表示self并other#请注意,是Relation对象rel成员的并返回结果为一个Relation对象ret = set()for x in self.rel :ret.add(x)for y in other.rel :ret.add(y)return Relation(self.sets, ret)def toMatrix(self):#将序偶集合形式的关系转换为矩阵。#为保证矩阵的唯一性,需对self.sets中的元素先排序matrix = []elems = sorted(list(self.sets))line = [0]*len(self.sets)for elem in elems:#实现转换为矩阵的功能line = [0] * len(self.sets)for x in self.rel :if x[0] == elem :line[elems.index(x[1])] = 1matrix.append(line)return matrixdef isReflexive(self):#判断self是否为自反关系,是则返回True,否则返回Falsefor x in self.sets :if not (x, x) in self.rel :return Falsereturn Truedef isIrreflexive(self):# 判断self是否为反自反关系,是则返回True,否则返回Falsefor x in self.sets :if (x, x) in self.rel :return Falsereturn True def isSymmetric(self):# 判断self是否为对称关系,是则返回True,否则返回Falsefor x in self.rel :if not (x[1], x[0]) in self.rel :return False return True  def isAsymmetric(self):# 判断self是否为非对称关系,是则返回True,否则返回Falsefor x in self.rel :if (x[1], x[0]) in self.rel :return Falsereturn Truedef isAntiSymmetric(self):# 判断self是否为反对称关系,是则返回True,否则返回Falsefor x in self.rel :if x[0] != x[1] and (x[1], x[0]) in self.rel :return Falsereturn Truedef isTransitive(self):# 判断self是否为传递关系,是则返回True,否则返回Falsefor x in self.rel :for y in self.rel :if x[1] == y[0] and not (x[0], y[1]) in self.rel :return Falsereturn Truedef reflexiveClosure(self):#求self的自反闭包,注意使用前面已经重载过的运算符#返回一个Relation对象,为self的自反闭包ret = self.rel.copy()for x in self.sets :ret.add((x, x))return Relation(self.sets, ret)def symmetricClosure(self):# 求self的对称闭包,注意使用前面已经重载过的运算符# 返回一个Relation对象,为self的对称闭包ret = self.rel.copy()for x in self.rel :ret.add((x[1], x[0]))return Relation(self.sets, ret)def transitiveClosure(self):closure = self# 求self的传递闭包,注意使用前面已经重载过的运算符# 该方法实现的算法:严格按照传递闭包计算公式求传递闭包n = len(self.sets)for i in range(2, n) :closure = closure + self ** ireturn closuredef transitiveClosure3(self):#该方法利用Roy-Warshall计算传递闭包#现将关系转换为矩阵,再调用__warshall函数m = self.toMatrix()return self.__warshall(m)def __warshall(self, a):assert (len(row) == len(a) for row in a)n = len(a)#请在下面编程实现Roy-Warshall求传递闭包的算法#参数a:为一个关系矩阵for k in range(n) :for i in range(n) :for j in range(n) :a[i][j] |= a[i][k] & a[k][j]return adef isEquivalenceRelation(rel):#该函数对给定的Relation对象rel,判断其是否为等价关系#是则返回True,否则返回Falsereturn rel.isReflexive() & rel.isSymmetric() & rel.isTransitive()def createPartition(rel):#对给定的Relation对象rel,求其决定的rel.sets上的划分#如果rel不是等价关系,返回空集if not isEquivalenceRelation(rel):print("The given relation is not an Equivalence Relation")return set([])#如rel是等价关系,请编程实现求划分的程序partition = set([])n = len(rel.sets)L = list(rel.sets)visited = [0] * nfor i in range(n) :mdl = set()mdl.add(L[i])if not visited[i] :visited[i] = 1for j in range(n) :if (L[i], L[j]) in rel.rel :mdl.add(L[j])visited[j] = 1partition.add(frozenset(mdl))return partitiondef createEquivalenceRelation(partition, A):#对给定的集合A,以及A上的一个划分partition#生成由该划分决定的等价关系assert functools.reduce(lambda x, y: x.union(y), partition) == Aret = set()for S in partition :for x in S :for y in S :ret.add((x, y))return Relation(A, ret)def isPartialOrder(rel):# 该函数对给定的Relation对象rel,判断其是否为半序关系#是则返回True,否则返回False。return rel.isReflexive() & rel.isAntiSymmetric() & rel.isTransitive()def isQuasiOrder(rel):# 该函数对给定的Relation对象rel,判断其是否为拟序关系# 是则返回True,否则返回False。return rel.isIrreflexive() & rel.isAntiSymmetric() & rel.isTransitive()def isLinearOrder(rel):# 该函数对给定的Relation对象rel,判断其是否为全序关系if not isPartialOrder(rel):return Falseelse:S = rel.setsfor x in S :for y in S :if not (x, y) in rel.rel and not (y, x) in rel.rel :return Falsereturn Truedef join(rel1, rel2):#对给定的关系rel1和rel2assert rel1.sets == rel2.sets#首先得到二者的矩阵M1 = rel1.toMatrix()M2 = rel2.toMatrix()m = len(M1)n = mM = []#实现关系矩阵的join运算,结果存于M中for i in range(n) :mdl = []for j in range(n) :mdl.append(M1[i][j] | M2[i][j])M.append(mdl)return Mdef meet(rel1, rel2):# 对给定的关系rel1和rel2assert rel1.sets == rel2.sets# 首先得到二者的矩阵M1 = rel1.toMatrix()M2 = rel2.toMatrix()m = len(M1)n = mM = []# 实现关系矩阵的meet运算,结果存于M中for i in range(n) :mdl = []for j in range(n) :mdl.append(M1[i][j] & M2[i][j])M.append(mdl)return Mdef booleanProduct(rel1, rel2):# 对给定的关系rel1和rel2assert rel1.sets == rel2.sets# 首先得到二者的矩阵M1 = rel1.toMatrix()M2 = rel2.toMatrix()m = len(M1)n = mM = []#**********  Begin  **********## 实现关系矩阵的布尔乘积运算,结果存于M中for i in range(n) :mdl = []for j in range(n) :tmp = 0for k in range(n) :tmp |= M1[i][k] & M2[k][j]mdl.append(tmp)M.append(mdl)#**********  End  **********#return M

【Educoder离散数学实训】关系基础相关推荐

  1. 【Educoder离散数学实训】生成真值表

    [Educoder离散数学实训]生成真值表 这个相当于是class的一个实际应用,体现出来了一点Python中类的强大 总体说一下想干啥:我们想用PythonPythonPython做一个真值表,对于 ...

  2. Educoder离散数学实训【自然推理系统】答案

    [使用说明] 1.本文主要供分享思路.答疑使用,请勿白一味嫖照搬. 2.本文95%以上为作者本人独立思考的过程,关闭编程平台右侧tab转换后,答案直接复制粘贴,将部分空格转化为tab即可过关. 3.允 ...

  3. 【头歌educoder】离散数学实训参考-第二章-关系-part1-关系基础

    目录 第一关:求给定集合的对角线关系(Diagonal Relation) 第二关:关系的合成 第三关:关系的幂运算 第四关:关系的并运算 第五关:转换成关系矩阵 第六关:自反关系的判断 第七关:反自 ...

  4. python基础实训_python基础实践(三)

    -*-列表是新手可直接使用的最强大的python功能之一,它融合了众多重要的编程概念.-*- # -*- coding:utf-8 -*- # Author:sweeping-monk Questio ...

  5. 计算机试题新编实训,计算机基础与实训 练习题

    计算机一级考试模拟试题 第三章 Word练习题 一.单项选择题 01.中文Word编辑软件的运行环境是______. A)DOS B)WPS C)Windows D)高级语言 02.段落的标记是在输入 ...

  6. 数据结构与算法--头歌(educoder)实训作业题目及答案

    目录 Java 数据结构之图 第1关:图的表示 第2关:深度优先搜索 第3关:广度优先搜索 第4关:单源最短路径 Java 数据结构之排序 第1关:选择排序 第2关:插入排序 第3关:归并排序 第4关 ...

  7. 计算机实训应用,计算机应用基础及实训

    <计算机应用基础及实训>是2008年科学出版社出版的图书,作者是方风波.田岭.该书覆盖了计算机初学者所需掌握的所有知识和操作技能,既适合中等职业学校计算机类专业及相关专业使用,也可作为专业 ...

  8. 计算机基础实训计划,《计算机基础》课实训计划.doc

    <计算机基础>课实训计划,计算机基础授课计划,大学计算机基础实训,计算机基础实训教程,计算机基础实训心得,计算机基础实训总结,计算机基础实训,计算机基础实训大纲,计算机基础实训教案,实训课 ...

  9. c#程序设计实训报告心得体会_关于实训的心得体会4篇

    关于实训的心得体会4篇 心得体会是指将学习的东西运用到实践中去,通过实践反思学习内容并记录下来的文字.有关实训的心得体会,欢迎大家一起来借鉴一下! 实训的心得体会(一): 透过这两周的实训,我们学会了 ...

最新文章

  1. 编码 data:text/html;c,关于 Data URI Scheme -- data:image/jpg;base64
  2. spring如何解决循环依赖
  3. debian下编译安装poco
  4. python使用ORM之如何调用多对多关系
  5. 在VC中使用MATLAB C++函数库
  6. java conterller_java后台controller能否直接接收list
  7. redhat怎样修改语言_硕士博士个人陈述(PS)辅导及修改服务带你极速前进!
  8. 政治经济学第一-三章脉络图
  9. HOHO 拿了個小嘉獎 Happy一下 可惜過年可能被留下...痛苦
  10. k8s升级从1.13到1.16教程与采坑解决办法
  11. 湘潭比赛有感---铩羽之行
  12. linux ora -03113,ORA-03113解决方法
  13. java.net.UnknownServiceException: CLEARTEXT communication to xxxxx not permitted by network secur...
  14. Linux Capability探索试验
  15. Tilera吴晓东:2013年要做成三百多个核
  16. 计算机美术教学应用,浅谈计算机在美术教学中的应用
  17. Belief propagation
  18. 如何将word一键导入PPT并对内容格式批量修改
  19. ACCESS年月日时分秒格式化语句
  20. SSL 域名证书 安装指引

热门文章

  1. 【ES6】阮一峰ES6学习之Module的语法
  2. SpringBoot的查询操作
  3. [裴礼文数学分析中的典型问题与方法习题参考解答]4.5.10
  4. Axure原型创建折线、柱状等图形,引用echarts
  5. QCC3040---蓝牙名称修改
  6. SaaSBase:微宏科技是什么?
  7. python:实现IIR 滤波器算法(附完整源码)
  8. 安卓开发--连接到聚合网,获取JSON数据并解析(踩了好多好多坑)
  9. js 金钱格式化(money)
  10. 碰到国内外虚拟机无法识别usb加密狗或者银行U盾问题,大家请进入!!!