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

这篇具有很好参考价值的文章主要介绍了【Educoder离散数学实训】关系基础。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

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

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

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

我们发现,他俩都是 s e t set set
紧接着,我们对于 r e l rel rel内部的元素输出,想看一看序偶的存在形式是什么。
我们输入

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

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

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

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

T3 关系的幂运算

这个题是递归做的,需要判断掉指数是 0 0 0 − 1 -1 1的情况,分别返回转置和 I A I_A IA

T14 关系的传递闭包

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

T15 利用Warshall算法求传递闭包

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

T17 计算等价类

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

其余的题没有聊的必要了,都是书上的定义而已,简单的代码复现。
代码:文章来源地址https://www.toymoban.com/news/detail-731306.html

import functools

class 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 = rel
        self.sets = sets

    def __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: ' + setstr

    def __eq__(self, other):
        #判断两个Relation对象是否相等,关系及集合都要相等
        return self.sets == other.sets and self.rel == other.rel

    def 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])] = 1
            matrix.append(line)
        return matrix

    def isReflexive(self):
        #判断self是否为自反关系,是则返回True,否则返回False
        for x in self.sets :
            if not (x, x) in self.rel :
                return False
        return True

    def isIrreflexive(self):
        # 判断self是否为反自反关系,是则返回True,否则返回False
        for x in self.sets :
            if (x, x) in self.rel :
                return False
        return True 
        
    def isSymmetric(self):
        # 判断self是否为对称关系,是则返回True,否则返回False
        for x in self.rel :
            if not (x[1], x[0]) in self.rel :
                return False 
        return True  

    def isAsymmetric(self):
        # 判断self是否为非对称关系,是则返回True,否则返回False
        for x in self.rel :
            if (x[1], x[0]) in self.rel :
                return False
        return True
        
    def isAntiSymmetric(self):
        # 判断self是否为反对称关系,是则返回True,否则返回False
        for x in self.rel :
            if x[0] != x[1] and (x[1], x[0]) in self.rel :
                return False
        return True

    def isTransitive(self):
        # 判断self是否为传递关系,是则返回True,否则返回False
        for x in self.rel :
            for y in self.rel :
                if x[1] == y[0] and not (x[0], y[1]) in self.rel :
                    return False
        return True

    def 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 ** i
        return closure

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

def isEquivalenceRelation(rel):
    #该函数对给定的Relation对象rel,判断其是否为等价关系
    #是则返回True,否则返回False
    return 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] * n
    for i in range(n) :
        mdl = set()
        mdl.add(L[i])
        if not visited[i] :
            visited[i] = 1
            for j in range(n) :
                if (L[i], L[j]) in rel.rel :
                    mdl.add(L[j])
                    visited[j] = 1
            partition.add(frozenset(mdl))
    return partition
        
def createEquivalenceRelation(partition, A):
    #对给定的集合A,以及A上的一个划分partition
    #生成由该划分决定的等价关系
    assert functools.reduce(lambda x, y: x.union(y), partition) == A
    ret = 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 False
    else:
        S = rel.sets
        for x in S :
            for y in S :
                if not (x, y) in rel.rel and not (y, x) in rel.rel :
                    return False
        return True

def join(rel1, rel2):
    #对给定的关系rel1和rel2
    assert rel1.sets == rel2.sets
    #首先得到二者的矩阵
    M1 = rel1.toMatrix()
    M2 = rel2.toMatrix()

    m = len(M1)
    n = m
    M = []
    #实现关系矩阵的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 M

def meet(rel1, rel2):
    # 对给定的关系rel1和rel2
    assert rel1.sets == rel2.sets

    # 首先得到二者的矩阵
    M1 = rel1.toMatrix()
    M2 = rel2.toMatrix()

    m = len(M1)
    n = m
    M = []
    # 实现关系矩阵的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 M

def booleanProduct(rel1, rel2):
    # 对给定的关系rel1和rel2
    assert rel1.sets == rel2.sets

    # 首先得到二者的矩阵
    M1 = rel1.toMatrix()
    M2 = rel2.toMatrix()

    m = len(M1)
    n = m
    M = []
    #**********  Begin  **********#
    # 实现关系矩阵的布尔乘积运算,结果存于M中
    for i in range(n) :
        mdl = []
        for j in range(n) :
            tmp = 0
            for k in range(n) :
                tmp |= M1[i][k] & M2[k][j]
            mdl.append(tmp)
        M.append(mdl)

    #**********  End  **********#
    return M

到了这里,关于【Educoder离散数学实训】关系基础的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CSS--头歌(educoder)实训作业题目及答案

    目录 CSS——基础知识 第1关: 初识CSS:丰富多彩的网页样式 第2关: CSS样式引入方式 CSS——基础选择器 第1关: CSS 元素选择器 第2关: CSS 类选择器 第3关: CSS id选择器 CSS——文本与字体样式 第1关: 字体颜色、类型与大小 第2关: 字体粗细与风格 第3关: 文本装饰与文本布局 CSS——

    2024年04月15日
    浏览(117)
  • JavaScript下部分--头歌(educoder)实训作业题目及答案

    目录  JSON 第1关: JSON对象 第2关: JSON数组 第3关: JSON字符串 Math、日期和异常处理 第1关: Math类 第2关: Date类 第3关: JavaScript错误 HTML DOM——文档元素的操作(一) 第1关: 通过id获取文档元素 第2关: 通过类名获取文档元素 第3关: 通过标签名获取文档元素 第4关: html5中获取元素的

    2023年04月26日
    浏览(40)
  • JavaScript上部分--头歌(educoder)实训作业题目及答案

      目录 JS简介 第1关: JavaScript基础入门 第2关: JavaScript 与 HTML 第3关: JavaScript 变量 JS 数据类型 第1关: JavaScript 数据类型介绍 第2关: JavaScript 数据类型转换 JS运算符 第1关: 算术运算符 第2关: 比较和逻辑运算符 第3关: 条件和赋值运算符 第4关: 运算符的优先级和结合性 JS对象 第

    2024年02月08日
    浏览(33)
  • JavaScript上部分--头歌(educoder)实训作业题目及答案 JS简介

      目录 JS简介 第1关: JavaScript基础入门 第2关: JavaScript 与 HTML 第3关: JavaScript 变量 JS 数据类型 第1关: JavaScript 数据类型介绍 第2关: JavaScript 数据类型转换 JS运算符 第1关: 算术运算符 第2关: 比较和逻辑运算符 第3关: 条件和赋值运算符 第4关: 运算符的优先级和结合性 JS对象 第

    2023年04月22日
    浏览(132)
  • 头歌(educoder)实训作业题目及答案分享 ——1-4 Java入门 - 分支结构

    📜个人简介 :  作者简介:大家好,我是Passenger.n✌️  支持一下:点赞👍+收藏🌟+留言📪 📣 系列专栏:java基础🍁 ✉️格言:花有重开日,人无再少年!🌞 万事开头难,既然迈开了这一步,那就坚持走下去! 这是我的第一篇博客,希望萌新看了有收获,大佬看了给指

    2024年02月06日
    浏览(95)
  • 头歌(educoder)实训作业题目及答案分享 ——1-7 Java入门-分支与循环练习

    📜个人简介 :  作者简介:大家好,我是Passenger.n✌️  支持一下:点赞👍+收藏🌟+留言📪 📣 系列专栏:java基础🍁 ✉️格言:花有重开日,人无再少年!🌞 万事开头难,既然迈开了这一步,那就坚持走下去! 这是我的第一篇博客,希望萌新看了有收获,大佬看了给指

    2024年02月04日
    浏览(71)
  • 头歌(educoder)实训作业题目及答案分享 ——1-3 Java入门 - 运算符和表达式

    📜个人简介 :  作者简介:大家好,我是Passenger.n  支持一下:点赞👍+收藏🌟+留言📪 📣 系列专栏:java基础🍁 ✉️格言:花有重开日,人无再少年!🌞 万事开头难,既然迈开了这一步,那就坚持走下去! 这是我新的一篇博客,希望萌新看了有收获,大佬看了给指路😝

    2024年02月07日
    浏览(104)
  • 获取头歌实训参考答案(EduCoder)

    头歌EduCoder平台实训答案在此,里面搜集了一些答案,可以查查有没有想看的。 https://edaser.github.io/ 一定 不要直接复制答案 ,建议还是自己做,实在不会做的,参考看完后要独立完成。 在这里可以查询一些实训的答案,后台的数据库记录了几百个实训关卡的答案,实现的方

    2024年02月11日
    浏览(38)
  • 头歌实训-离散数学-图论!

    5阶无向完全图的边数为:10 设图 G 有 n 个结点, m 条边,且 G 中每个结点的度数不是 k ,就是 k+1 ,则 G 中度数为 k 的节点数是: n(k+1)-2m 若一个图有5个顶点,8条边,则该图所有顶点的度数和为多少?16 他让输出关联矩阵和邻接矩阵这不简单么? 我是直接摆烂了 输出个球呀

    2024年02月04日
    浏览(68)
  • 头歌实践教学平台答案(Java实训作业答案)

    搜集整理了一份最新最全的头歌(EduCoder)Java实训作业答案,分享给大家.(EduCoder)是信息技术类实践教学平台。(EduCoder)涵盖了计算机、大数据、云计算、人工智能、软件工程、物联网等专业课程。超60000个实训案例,建立学、练、评、测一体化实验环境。这份是头歌实践教学平

    2023年04月11日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包