離散數學實驗——關係及操作
阿新 • • 發佈:2020-11-16
3.1實驗目的
關係是集合論中的一個十分重要的概念,關係性質的判定是集合論中的重要內容。通過該組實驗,更加深刻地理解關係的概念和性質,並掌握關係性質的判定及關係的閉包的求法。
3.2實驗內容
1、鍵盤輸入集合A中的所有元素,並輸入關係R中的所有序偶對,建立關係R的關係矩陣;
2、判斷關係所具有的性質;
3、求關係R的逆關係,及關係的合成運算;
4、求關係R的r(R)、s(R)、t(R)。(注意關係的傳遞閉包採用Warshall演算法)。
5、判斷關係R是否為等價關係,若是等價關係,則求出其所有等價類;
6、選做:求集合A上的等價關係數
3.3主要演算法思想
1、鍵盤輸入集合A中的所有元素,並輸入關係R中的所有序偶對,建立關係R的關係矩陣;
①用字串ListA儲存集合A中所有元素,每個字元就是一個元素
②然後用List_Relation儲存關係R。
③然後定義一個方法建立關係R的關係矩陣。
2、判斷關係所具有的性質
關係性質的充要條件:
設R為A上的關係, 則
(1)
R在A上自反當且僅當 IA⊆R
(2) R在A上反自反當且僅當 R∩IA=Ø
(3)
R在A上對稱當且僅當 R=R-1
(4) R在A上反對稱當且僅當 R∩R-1⊆IA
(5)
R在A上傳遞當且僅當 R°R⊆R
判斷自反性:
///判斷自反性 ///List_Relation是自反性說明 List_Relation包含集合A的恆等關係 ///所以利用迴圈判斷每個元素 bool ReflexivityJudge(int** R) { for (int i = 0; i < ListA.length(); i++) if (R[i][i] == 0) return false; return true; }
判斷反自反性:
///判斷反自反性 ///R在A上反自反當且僅當 R∩IA=空集 ///意思就是沒有一個環 bool InverserReflexivityJudge(int** R) { int n = ListA.length(); for (int i = 0; i < n; i++) { if (R[i][i] == 1) return false; } return true; }
判斷對稱性:
///判斷對稱性 ///List_Relation滿足對稱性,則說明它的關係矩陣一定是對稱矩陣 bool SymmetryJudge(int** R) { for (int i = 0; i < ListA.length(); i++) for (int j = 0; j < i; j++)if (R[i][j] != R[j][i])return false; return true; }
判斷反對稱性:
///判斷反對稱性 /// R在A上反對稱當且僅當 (R∩R的逆)包含於IA /// bool InverseSymmtryJudge(int** R) { for (int i = 0; i < ListA.length(); i++) for (int j = 0; j < i; j++)if (R[i][j] == 1 && (R[i][j] == R[j][i]) && (i != j))return false; return true; }
判斷傳遞性:
/// 判斷傳遞性 /// R在A上傳遞當且僅當 (R·R)包含於R bool TransitivityJudge(int** R) { int n = ListA.length(); InitMatrix(S); Synthetise(R);//求R合成R,傳R進去,修改的是S for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (S[i][j] > R[i][j]) return false; } } return true; }
3.4源程式及測試結果
3.5完整程式碼
#include <iostream> #include <string> using namespace std; string ListA;//定義全域性集合 string List_Relation,List_InverseRelation;//定義全域性集合的關係和逆關係 int** R_Matrix,**R_InverseMatrix;//R_matrix為List_Relation的關係矩陣,R_InverseMatrix為逆關係矩陣, int** S;//R合成R後的關係矩陣 char** EC;//等價關係R的等價類 //返回字元在集合中的下標 int Get_Index(string List, char ch) { int i; for (i = 0; i < List.length(); i++)if (List[i] == ch)return i; } //初始化矩陣 void InitMatrix(int**& M) { int n = ListA.length(); //動態建立二維陣列 M = new int* [n]; for (int i = 0; i < n; i++) M[i] = new int[n]; //先將矩陣全置為0 for (int i = 0; i < n; i++) for (int j = 0; j < n; j++)M[i][j] = 0; } //輸入關係並建立關係矩陣 void CreateRelation() { int x, y;//定義矩陣中的位置y代表行數,x代表列數 //輸入關係有序偶對 請按照{<1,2>,<2,3>}輸入 cout << "注:請按照{<1,2>,<2,3>}這種格式輸入" << endl; cout << "請輸入集合A上的關係R="; cin >> List_Relation; int n = List_Relation.length(); InitMatrix(R_Matrix);//初始化矩陣 for (int i = 2; i < n; i+=6) { y = Get_Index(ListA,List_Relation[i]); x = Get_Index(ListA, List_Relation[i + 2]); R_Matrix[y][x] = 1; } } //根據List_Relation得到它的逆關係List_InverseRelation和逆矩陣 void GetInverseRelation() { int n= ListA.length(); List_InverseRelation = List_Relation; InitMatrix(R_InverseMatrix); R_InverseMatrix = R_Matrix; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (R_Matrix[i][j] != 0) R_InverseMatrix[j][i] = R_Matrix[i][j]; } } for (int i = 2; i < n; i += 6) { char temp; temp = List_InverseRelation[i]; List_InverseRelation[i] = List_InverseRelation[i + 2]; List_InverseRelation[i + 2] = temp; } } //關係合成(只能自己合成自己) //S是合成後的關係矩陣 void Synthetise(int **R) { int n = ListA.length(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (R[i][j] == 1) { for (int k = 0; k < n; k++) { if (R[k][i] == 1) S[k][j] = 1; } } } } } //生成R合成R後的關係字串 string GetSynthetiseStr(){ int n = ListA.length(); string SynthetiseStr;//R合成R後的關係字串 SynthetiseStr = "{"; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (S[i][j] == 1) { SynthetiseStr = SynthetiseStr + "<" + ListA[i] + "," + ListA[j] + ">,"; } } } SynthetiseStr.erase(SynthetiseStr.length() - 1, 1); SynthetiseStr += '}'; return SynthetiseStr; } //輸出矩陣 void MatrixOut(int **M) { int n = ListA.length(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << M[i][j] << " "; } cout << endl; } } #pragma region 關係的判斷 ///判斷自反性 ///List_Relation是自反性說明 List_Relation包含集合A的恆等關係 ///所以利用迴圈判斷每個元素 bool ReflexivityJudge(int** R) { for (int i = 0; i < ListA.length(); i++) if (R[i][i] == 0) return false; return true; } ///判斷反自反性 ///R在A上反自反當且僅當 R∩IA=空集 ///意思就是沒有一個環 bool InverserReflexivityJudge(int** R) { int n = ListA.length(); for (int i = 0; i < n; i++) { if (R[i][i] == 1) return false; } return true; } ///判斷對稱性 ///List_Relation滿足對稱性,則說明它的關係矩陣一定是對稱矩陣 bool SymmetryJudge(int** R) { for (int i = 0; i < ListA.length(); i++) for (int j = 0; j < i; j++)if (R[i][j] != R[j][i])return false; return true; } ///判斷反對稱性 /// R在A上反對稱當且僅當 (R∩R的逆)包含於IA /// bool InverseSymmtryJudge(int** R) { for (int i = 0; i < ListA.length(); i++) for (int j = 0; j < i; j++)if (R[i][j] == 1 && (R[i][j] == R[j][i]) && (i != j))return false; return true; } /// 判斷傳遞性 /// R在A上傳遞當且僅當 (R·R)包含於R bool TransitivityJudge(int** R) { int n = ListA.length(); InitMatrix(S); Synthetise(R);//求R合成R,傳R進去,修改的是S for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (S[i][j] > R[i][j]) return false; } } return true; } #pragma endregion #pragma region 求關係的閉包 ///自反閉包 相當於是求R和恆等關係的並集 直接把矩陣對角線的值置為1就行了 /// r(R)=R∪R^0 /// R^0=I(A) void ReflexivityClosure() { string ReflexivityStr;//用來儲存自反閉包的集合字串 int n = ListA.length(); //int** R;//自反閉包關係矩陣 //R = new int* [n]; //for (int i = 0; i < n; i++)R[i] = new int[n]; //R = R_Matrix; ReflexivityStr = "{"; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) { cout << "1 "; ReflexivityStr = ReflexivityStr + "<" + ListA[i] + "," + ListA[j] + ">,"; continue; } else cout << R_Matrix[i][j] << " "; if (R_Matrix[i][j] == 1) {//矩陣中為1的才有關係,則要儲存在集合字串中 ReflexivityStr = ReflexivityStr + "<" + ListA[i] + "," + ListA[j] + ">,"; } } cout << endl; } ReflexivityStr.erase(ReflexivityStr.length()-1,1); ReflexivityStr += '}'; cout << "r(R)="<<ReflexivityStr; } ///對稱閉包 /// 如果有<x,y>且沒有<y,x> 則新增<y,x>到集合中 /// s(R)=R∪R^-1 void SymmtryClosure() { string SymmtryStr;//用來儲存對稱閉包的集合字串 int n = ListA.length(); int** R;//對稱閉包關係矩陣 R = new int* [n]; for (int i = 0; i < n; i++)R[i] = new int[n]; for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) R[i][j] = R_Matrix[i][j]; SymmtryStr = "{"; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { //關係中如果有<x,y>且沒有<y,x> 則新增<y,x>到集合中 if (R[i][j] == 1 && R[j][i] != 1) { R[j][i] = 1; } } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << R[i][j] << " "; if (R[i][j] == 1) { SymmtryStr = SymmtryStr + "<" + ListA[i] + "," + ListA[j] + ">,"; } } cout << endl; } SymmtryStr.erase(SymmtryStr.length() - 1, 1); SymmtryStr += '}'; cout << "s(R)=" << SymmtryStr; } ///傳遞閉包(採用Warshall演算法) /// t(R)=R∪R^2∪R^3∪… void TransitivityClosure() { string TransitivityStr;//用來儲存對稱閉包的集合字串 int n = ListA.length(); int** R;//對稱閉包關係矩陣 R = new int* [n]; for (int i = 0; i < n; i++)R[i] = new int[n]; for (int i = 0; i < n; i++) for(int j=0;j<n;j++) R[i][j] = R_Matrix[i][j]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (R[j][i]==1) { for (int k = 0; k < n; k++) { R[j][k] = R[j][k] | R[i][k];//邏輯加 } } } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { cout << R[i][j] << " "; if (R[i][j] == 1) { TransitivityStr = TransitivityStr + "<" + ListA[i] + "," + ListA[j] + ">,"; } } cout << endl; } TransitivityStr.erase(TransitivityStr.length() - 1, 1); TransitivityStr += '}'; cout << "t(R)=" << TransitivityStr; } #pragma endregion ///判斷關係R是否為等價關係 /// 如果R同時滿足自反、對稱、傳遞則是等價 bool EqualJudge(int **R) { if (ReflexivityJudge(R_Matrix) && SymmetryJudge(R_Matrix) && TransitivityJudge(R_Matrix)) return true; else return false; } /// 求出所有等價類 /// 如果<x,y>∈R,則說明x,y在同一個等價類 /// 例如:等價關係R={<1,2><2,1><1,3><3,1><2,3><3,2><4,5><5,4>}∪IA /// 則等價類有兩個{1,2,3},{4,5} void GetEqualClass(int **R) { int n = ListA.length(); string A = ListA; EC = new char*[n];//最大的等價類個數就是元素個數 int Num=0;//等價類個數 int ip; for (int i = 0; i < n; i++) { if (A[i]) { ip = 0; EC[Num] = new char[n]; EC[Num][ip++] = A[i]; for (int j = i + 1; j < n; j++) { if (A[i] && R[i][j]) { EC[Num][ip++] = A[j]; A[j] = 0; } } EC[Num][ip] = '\0'; Num++; } } cout << "等價類有" << Num << "個,分別是"; for (int i = 0; i < Num; i++) { cout << "{"; for (int j = 0; j < strlen(EC[i]); j++) { if (j == strlen(EC[i]) - 1) cout << EC[i][j]; else cout << EC[i][j] << ","; } cout << "} "; } } /// 求出等價關係數 /// 算等價關係數相當於是算有多少種組合,又因為集合A的等價關係與劃分個數是一一對應的,因此求其劃分個數即可 /// 在有n個元素的集合裡面,有1個元素的劃分、2個元素的劃分.....到n個元素的劃分 /// 最後再把所有劃分的個數加起來 /// 等價關係數=S(n,1)+S(n,2)+.....+S(n,n) void GetEqualClassNum() { int allNum=0; int n = ListA.length(); for (int i = 1; i <= n; i++) allNum += Stirling(n, i); cout << "集合A的等價關係有" << allNum << "個;"; } //建立集合 void ListCreat() { while (true) { cout << "請輸入集合A的的元素:"; cin >> ListA; bool flag; for (int j = 0; j < ListA.length(); j++) { flag = true; for (int k = j + 1; k < ListA.length(); k++) { if (ListA[j] == ListA[k]) { flag = false; break; } } if (!flag) break; } if (!flag) { cout << "集合中不允許存在相同元素!,請重新輸入!" << endl;; } else { break; } } } void main() { //1、鍵盤輸入集合A中的所有元素,並輸入關係R中的所有序偶對,建立關係R的關係矩陣 cout << "1、鍵盤輸入集合A中的所有元素,並輸入關係R中的所有序偶對,建立關係R的關係矩陣;" << endl; ListCreat(); CreateRelation(); cout << "關係R的關係矩陣:" << endl; MatrixOut(R_Matrix); //2、判斷關係所具有的性質 cout << endl << "2、判斷關係所具有的性質" << endl; cout << "關係R:" << endl; cout << "*****************\n"; if (ReflexivityJudge(R_Matrix)) cout << "具有自反性\t*" << endl; if(InverserReflexivityJudge(R_Matrix)) cout << "具有反自反性\t*" << endl; if (SymmetryJudge(R_Matrix)) cout << "具有對稱性\t*" << endl; if (InverseSymmtryJudge(R_Matrix)) cout << "具有反對稱性\t*" << endl; if (TransitivityJudge(R_Matrix)) cout << "具有傳遞性\t*" << endl; cout << "*****************\n"; //3、求關係R的逆關係,及關係的合成運算; cout << endl << "3、求關係R的逆關係,及關係的合成運算" << endl; GetInverseRelation(); cout << "關係R的逆關係=" << List_InverseRelation << endl; cout << "關係R的逆關係矩陣:" << endl; MatrixOut(R_InverseMatrix); cout << "R·R(R合成R)後的關係=" << GetSynthetiseStr() << endl; cout << "R·R(R合成R)後的關係矩陣:" << endl; MatrixOut(S); //4、求關係R的r(R)、s(R)、t(R) cout << endl << "4、求關係R的r(R)、s(R)、t(R)" << endl; cout << "自反閉包矩陣:" << endl; ReflexivityClosure(); cout << endl; cout << "對稱閉包矩陣:" << endl; SymmtryClosure(); cout << endl; cout << "傳遞閉包矩陣:" << endl; TransitivityClosure(); cout << endl; //5、判斷關係R是否為等價關係,若是等價關係,則求出其所有等價類 cout <<endl<< "5、判斷關係R是否為等價關係,若是等價關係,則求出其所有等價類" << endl; cout << "關係R"; if (EqualJudge(R_Matrix)) { cout << "是等價關係\n"; GetEqualClass(R_Matrix); } else cout << "不是等價關係"; cout << endl; }