[Educoder Discrete Mathematics Training] Beziehungsgrundlagen

[Educoder Discrete Mathematics Training] Beziehungsgrundlagen

Es gibt viele Fragen und nicht viel Gesprächsstoff. Manche Fragen sind sehr wertvoll

Besprechen Sie einfach separat ein paar Fragen und fügen Sie den Code am Ende ein. Alle Funktionen wurden so geändert, dass sie von mir selbst geschrieben werden können. Vielleicht ist es einfacher zu lesen als die Antwort?

T1 findet die Diagonalbeziehung der gegebenen Menge (Diagonalbeziehung)

Ich denke, wenn du nicht weiterkommst, wird das erste Level eine große Hürde sein.
Da wir nicht wissen, wovon er spricht, entscheiden wir uns, es auszugeben und einen Blick darauf zu werfen.
Zuerst geben wir die Funktion __init__ ein

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

Wir haben festgestellt, dass beide eingestellt sindset
紧 Haftung, wir werden kaufen r e l rel rel interne Elementausgabe, ich möchte sehen, welche Existenzform das Sequenzpaar hat.
Wir betreten

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

hat festgestellt, dass das Sequenzpaar in Form eines Tupels gespeichert ist.
Dann wird es einfach sein, wir können diese Funktion nach unserem eigenen Verständnis schreiben.
Nach dem Schreiben sehen Sie die Kommentare, das heißt I A I_A ICHA R e l a t i o n Relation Relat ion Objekt bedeutet eigentlich die Rückgabe einer Instanz einer Klasse.
Oder beim Debuggen stellen Sie möglicherweise fest, dass die Fehlermeldung Folgendes enthält:

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

Wir können auch feststellen, dass das, was zurückgegeben wird, nur eine Instanz einer Klasse ist.

Potenzierung der T3-Beziehung

Diese Frage wird rekursiv gestellt. Es muss ermittelt werden, dass der Exponent 0 0 ist0Summe − 1 -1 1s Umstände, Trennung und Rückkehr I A I_A ICHA

Transitiver Abschluss der T14-Beziehung

Ich möchte kurz auf diese Frage eingehen (ich denke, niemand wird sie lesen
Zuerst abstrahieren wir ein mathematisches Modell:
Ja n n n Städte, wenn < x , y > ∈ R <x,y>\in R <x,Und>∈RVertreter x x xSumme y y yEs gibt eine Straße, die erreicht werden kann. Für diese Straße braucht man einen Tag.
Dann R R Beziehungsmatrix von R M M Wofür steht M? Es stellt dar, dass wenn M i , j M_{i,j} Mi,jRichtig 1 1 1Repräsentative Idee i i i可以走 1 1 1Himmlische Ankunft j j j
问题到了, R 2 R^2 RWofür steht 2? Tatsächlich können wir durch die Synthese von Beziehungen verstehen, dass wenn R 2 R^2 R2Die erhaltene Beziehungsmatrix M ′ M' M,Dieser mittlere Junge M i , j ′ M'_{i,j} Mi,jRepräsentative Idee i i irun 2 2 2天可以到 j j j
同理, R k R^k RkShukuresu k k Es sind nur kTage.
Zu diesem Zeitpunkt können wir tatsächlich feststellen, dass R ∪ R 2 ∪ R 3 . . . R\cup R^2\cup R^ 3. .. RR2R3...Nur Bedarfsberechnung erreicht R n − 1 R^{n-1 } Rn1 ist genug. Denn wenn man wirklich von einer Stadt in eine andere Stadt gelangen kann, muss man höchstens n − 1 n-1 N1Himmel, es lohnt sich n − 2 n-2 NErleben Sie alle 2 Städte. Das ist leicht zu verstehen. Mehr R R Die Potenz von R lässt sich leicht als ungültiger Beitrag erweisen.

T15 Verwenden Sie den Warshall-Algorithmus, um einen transitiven Abschluss zu finden

Diese Frage ist eigentlich f l o y d floyd floyd.
Darüber hinaus ist es eine Art O ( n 3 ) O(n^3) O(nEin Algorithmus zum Finden des kürzesten Pfades zwischen zwei beliebigen Punkten mit der zeitlichen Komplexität von 3).
Die Theorie, auf der es basiert, sind die zwei Punkte des kürzesten Weges. Es ist offensichtlich, dass zwei beliebige Punkte auf dem Weg der kürzeste Weg sind.
Wie für f l o y d floyd floydDie Korrektheit des Algorithmus Der Beweis mittels mathematischer Induktion wird hier nicht weiter ausgeführt.
Diese Frage ist eigentlich f l o y d floyd Eine spezielle Anwendung von floyd , das heißt, eine transitive Schließung anzustreben.
Um den kürzesten Pfad zu finden, ist die transitive Schließung eigentlich nur eine Änderung der Pfadgröße, um festzustellen, ob er erreichbar ist.

T17 Compute-Äquivalenzklasse

Diese Frage hat eine schnellere Datenstruktur namens Union Search. Bei Interesse können Sie selbst nachfragen.
Der Ansatz hier ist sehr gewöhnlich. Erstellen Sie einen v i s i t e d besuchte visit Das Array ed gibt an, ob dieses Element in andere Äquivalenzklassen eingetreten ist. Wenn nicht, durchlaufen Sie die gesamte s e t-Menge setFinden Sie alle seine Äquivalenzklassen und vergleichen Sie deren besuchte Besuche set a>visit edAlle konfigurieren Wahr Wahr True即可.

Über den Rest der Fragen muss nicht gesprochen werden. Sie sind lediglich Definitionen im Buch und können mit einfachen Codes reproduziert werden.
Code:

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

Guess you like

Origin blog.csdn.net/JZYshuraK/article/details/126624903