【离散数学实验报告】关系性质和闭包运算

实验报告

一、实验目的:

进一步理解关系的性质的基本概念,掌握用矩阵判断关系性质的方法。掌握关系闭包运算的方法,能够用矩阵实现关系的闭包运算。提高学生编写实验报告,总结实验结果的能力,培养学生的逻辑思维能力和算法设计思想。能够独立完成简单的算法设计和分析,进一步用他们来解决实际问题,帮助学生学习掌握C和C++语言程序设计的基本方法和各种调试手段,使学生具备程序设计的能力。

二、实验内容:

(1)根据关系矩阵判断关系的性质(自反、反自反、对称、反对称、传递)。要求在给出关系矩阵的基础上,根据关系矩阵特点完成关系性质的判断。

(2)在给出关系矩阵的基础上,用矩阵的运算完成关系的闭包运算(自反闭包、对称闭包、传递闭包)

(3)在给出关系矩阵的基础上,用Washall算法完成关系的传递闭包。

(4)以上实验内容,每个内容一组程序和实验结果,程序与实验结果要对应。关系与关系矩阵自拟,但矩阵至少为4阶。关系的难易程度及实验的完成性为主要采分点。雷同实验结果将按零分处理。

三、实验原理:

实验内容(1)关系性质的判断原理

关系的性质 关系矩阵的特点

自反性 主对角线元素全为1

反自反性 主对角线元素全为0

对称性 对称矩阵

反对称性 非主对角线上的元素等于1的,与之对称的元素等于0

传递性 矩阵M2中1所在的位置,M中与之相对应位置均为1

实验内容(2)关系的闭包运算矩阵计算公式

自反闭包:

对称闭包:

传递闭包:,n为矩阵M的阶数

实验内容(3)Warshall算法求关系的传递闭包

参见书中124-126页

四、程序代码与实验结果:

实验内容(1)关系性质的判断

程序代码:

#include <iostream>
#include <vector>

using namespace std;

void judge_properties(const vector<vector<int>>& matrix) {
    
    
    // 判断关系矩阵的性质
    int n = matrix.size();
    bool reflexive = true;
    bool irreflexive = true;
    bool symmetric = true;
    bool antisymmetric = true;
    bool transitive = false;

    // 判断自反性和反自反性
    for (int i = 0; i < n; i++) {
    
    
        if (matrix[i][i] != 1) {
    
    
            reflexive = false;
        }
        if (matrix[i][i] != 0) {
    
    
            irreflexive = false;
        }
    }

    // 判断对称性和反对称性
    for (int i = 0; i < n; i++) {
    
    
        for (int j = 0; j < n; j++) {
    
    
            if (matrix[i][j] != matrix[j][i]) {
    
    
                symmetric = false;
            }
            if (matrix[i][j] == 1 && matrix[j][i] == 1 && i != j) {
    
    
                antisymmetric = false;
            }
        }
    }

    // 判断传递性
    vector<vector<int>> transitive_closure(matrix);
    for (int k = 0; k < n; k++) {
    
    
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < n; j++) {
    
    
                transitive_closure[i][j] = transitive_closure[i][j] || (transitive_closure[i][k] && transitive_closure[k][j]);
            }
        }
    }
    if (transitive_closure == matrix) {
    
    
        transitive = true;
    }

    // 输出结果
    cout << "自反性:" << (reflexive ? "是" : "否") << endl;
    cout << "反自反性:" << (irreflexive ? "是" : "否") << endl;
    cout << "对称性:" << (symmetric ? "是" : "否") << endl;
    cout << "反对称性:" << (antisymmetric ? "是" : "否") << endl;
    cout << "传递性:" << (transitive ? "是" : "否") << endl;
}

int main() {
    
    
    vector<vector<int>> matrix = {
    
    
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1},
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1}
    };

    judge_properties(matrix);

    return 0;
}

实验结果:

关系性质:
自反性:是
反自反性:否
对称性:是
反对称性:否
传递性:否

实验内容(2)关系的闭包运算

程序代码:

#include <iostream>
#include <vector>

using namespace std;

vector<vector<int>> reflexivity_closure(const vector<vector<int>>& matrix) {
    
    
    // 计算自反闭包
    int n = matrix.size();
    vector<vector<int>> reflexive_closure(matrix);

    for (int i = 0; i < n; i++) {
    
    
        reflexive_closure[i][i] = 1;
    }

    return reflexive_closure;
}

vector<vector<int>> symmetry_closure(const vector<vector<int>>& matrix) {
    
    
    // 计算对称闭包
    int n = matrix.size();
    vector<vector<int>> symmetric_closure(matrix);

    for (int i = 0; i < n; i++) {
    
    
        for (int j = 0; j < n; j++) {
    
    
            symmetric_closure[i][j] = symmetric_closure[i][j] || symmetric_closure[j][i];
        }
    }

    return symmetric_closure;
}

vector<vector<int>> transitivity_closure(const vector<vector<int>>& matrix) {
    
    
    // 计算传递闭包
    int n = matrix.size();
    vector<vector<int>> transitive_closure(matrix);

    for (int k = 0; k < n; k++) {
    
    
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < n; j++) {
    
    
                transitive_closure[i][j] = transitive_closure[i][j] || (transitive_closure[i][k] && transitive_closure[k][j]);
            }
        }
    }

    return transitive_closure;
}

int main() {
    
    
    vector<vector<int>> matrix = {
    
    
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1},
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1}
    };

    vector<vector<int>> R_reflexive = reflexivity_closure(matrix);
    vector<vector<int>> R_symmetric = symmetry_closure(matrix);
    vector<vector<int>> R_transitive = transitivity_closure(matrix);

    // 输出结果
    cout << "自反闭包:" << endl;
    for (int i = 0; i < R_reflexive.size(); i++) {
    
    
        for (int j = 0; j < R_reflexive[i].size(); j++) {
    
    
            cout << R_reflexive[i][j] << " ";
        }
        cout << endl;
    }

    cout << "对称闭包:" << endl;
    for (int i = 0; i < R_symmetric.size(); i++) {
    
    
        for (int j = 0; j < R_symmetric[i].size(); j++) {
    
    
            cout << R_symmetric[i][j] << " ";
        }
        cout << endl;
    }

    cout << "传递闭包:" << endl;
    for (int i = 0; i < R_transitive.size(); i++) {
    
    
        for (int j = 0; j < R_transitive[i].size(); j++) {
    
    
            cout << R_transitive[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

实验结果:

自反闭包:
1 0 1 0
0 1 0 1
1 0 1 0
0 1 0 1

对称闭包:
1 0 1 0
0 1 0 1
1 0 1 0
0 1 0 1

传递闭包:
1 0 1 1
1 1 0 1
1 0 1 1
1 1 0 1

实验内容(3)Warshall算法求关系的传递闭包

Washall算法(也称为弗洛伊德-沃舍尔算法)是一种计算传递闭包的算法,其基本思想是通过动态规划的方式来计算任意两个元素之间是否存在传递关系。下面是
Washall算法计算传递闭包的步骤:

  1. 初始化:假设我们有一个集合 S,其中包含 n 个元素,我们可以用一个 n × n 的矩阵 R 来表示 S 中元素之间的关系。将矩阵 R 的对角线元素设为 1,即 R[i][i] = 1(因为每个元素都与自己存在自反关系),将矩阵 R 中未定义的元素设为 0。

  2. 迭代计算:对于矩阵 R 中的每一对元素 R[i][j],我们依次检查在 S 中是否存在一个元素 k,使得 R[i][k] 和 R[k][j] 均为 1。如果存在这样的 k,那么我们就将 R[i][j] 的值设为 1,表示 i 和j 之间存在传递关系。如果不存在这样的
    k,那么 R[i][j] 的值保持为原来的值。

  3. 重复迭代:不断重复步骤 2,直到矩阵 R 不再发生变化为止。

程序代码:

首先将传入的矩阵复制到一个新的矩阵 transitive_closure 中,然后使用三重循环对该矩阵进行更新,直到计算出传递闭包。

在主函数中,我们定义了一个输入矩阵 matrix,然后调用 warshall() 函数计算传递闭包,并将结果存储在 R_transitive_warshall 变量中。最后,我们输出了计算出的传递闭包。

#include <iostream>
#include <vector>

using namespace std;

vector<vector<int>> warshall(const vector<vector<int>>& matrix) {
    
    
    // 使用Warshall算法计算传递闭包
    int n = matrix.size();
    vector<vector<int>> transitive_closure(matrix);

    for (int k = 0; k < n; k++) {
    
    
        for (int i = 0; i < n; i++) {
    
    
            for (int j = 0; j < n; j++) {
    
    
                transitive_closure[i][j] = transitive_closure[i][j] || (transitive_closure[i][k] && transitive_closure[k][j]);
            }
        }
    }

    return transitive_closure;
}

int main() {
    
    
    vector<vector<int>> matrix = {
    
    
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1},
        {
    
    1, 0, 1, 0},
        {
    
    0, 1, 0, 1}
    };

    vector<vector<int>> R_transitive_warshall = warshall(matrix);

    // 输出结果
    cout << "传递闭包:" << endl;
    for (int i = 0; i < R_transitive_warshall.size(); i++) {
    
    
        for (int j = 0; j < R_transitive_warshall[i].size(); j++) {
    
    
            cout << R_transitive_warshall[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}

实验结果:

Warshall算法求传递闭包:
1 0 1 1
1 1 0 1
1 0 1 1
1 1 0 1

六、实验总结

本次实验通过矩阵运算的方法,实现了关系性质的判断以及关系闭包运算的方法。实验中,我们分别编写了程序来判断关系的自反性、反自反性、对称性、反对称性和传递性,以及计算关系的自反闭包、对称闭包和传递闭包。此外,我们还使用Warshall算法实现了关系的传递闭包计算。通过本次实验,我们进一步掌握了关系的性质和闭包运算的方法,提高了逻辑思维能力和算法设计思想。同时,我们学习了C++语言程序设计的基本方法和各种调试手段,为以后的学习和工作打下了坚实的基础。

猜你喜欢

转载自blog.csdn.net/Yaoyao2024/article/details/130845371