Với các hàm min, max và bù đã cho, các phép tốn và các tốn tử trên tập mờ có các tính chất tương tự như trong tập (rõ) kinh điển, cụ thể là [2, 5].
Với mọi tập mờ X, Y, X trên tập nền U ta có các tính chất sau đây:
Tính chất giao hốn X Y = Y X X Y = Y X Tính chất kết hợp (X Y) Z = X (Y Z) (X Y) Z = X (Y Z)
Nhờ tính chất giao hốn và kết hợp ta có thể vận dụng qui tắc sau khi tính tốn các biểu thức tập hợp chỉ chứa các phép hợp hoặc chỉ chứa các phép giao:
Qui tắc
Trong biểu thức tập hợp chỉ chứa các phép hợp (giao) ta
21
Tính chất phân phối
(X Y) Z = (X Z) (Y Z) (X Y) Z = (X Z) (Y Z)
Luật De Morgan
(X Y)’ = X’ Y’ (Bù của hợp bằng giao các bù) (X Y)’ = X’ Y’ (Bù của giao bằng hợp các bù)
Ngoài ra, trật tự (bao hàm) của các tập mờ thỏa các tính chất sau đây:
Tính chất bắc cầu
X Y và Y Z X Z Tính chất tựa bắc cầu
22
CHƯƠNG 2: THIẾT KẾ VÀ CÀI ĐẶT LỚP TẬP MỜ 2.1 Thiết kế hướng đối tượng
Theo tiếp cận hướng đối tượng ta có thể thiết kế và cài đặt một kiểu dữ liệu mới. Luận văn sẽ tập trung thiết kế hai kiểu dữ liệu phục vụ cho các chương trình xử lý các tập mờ là
Kiểu UniSet dùng để quản lí các tập nền. FSet dùng để quản lí các tập mờ
2.2 Thiết kế lớp tập nền UniSet
2.2.1 Các trường dữ liệu
int Size ; char ** Name;
Trường Size ghi nhận kích thước (số phần tử hoặc lực lượng) của tập nền. Trường Name lưu trữ các tên của các phần tử trong tập nền.
Thí dụ,
Với tập nền 4 mơn học, MonHoc = {Toan, Ly, Hoa, Sinh} thì hai trường dữ liệu của tập nền sẽ là: Size = 4; Name[1] = “Toan”; Name[2] = “Ly”; Name[3] = “Hoa”; Name[4] = “Sinh”; 2.2.2 Các phương thức Tạo tử (constructor) Cú pháp UniSet(int size = 0); Ngữ nghĩa
23
Hủy tử (destructor)
Cú pháp
~UniSet();
Ngữ nghĩa
Xóa và thu hồi vùng nhớ đã cấp phát cho tập nền.
Cấp phát vùng chứa tên phần tử của tập nền
Cú pháp
void NewName(int size);
Ngữ nghĩa
Cấp phát vùng nhớ đủ chứa size phần tử cho tập nền. Vùng nhớ này để lưu trữ danh sách (tên) các phần tử của tập nền.
Giải phóng vùng chứa tên phần tử của tập nền
Cú pháp
void DelName(int size);
Ngữ nghĩa
Giải phóng vùng nhớ chứa size phần tử cho tập nền.
Xuất lực lượng của tập nền
Cú pháp
inline int GetSize();
Ngữ nghĩa
Cho ra số phần tử của tập nền.
Phương thức inline là phương thức được cài đặt theo chế độ nhúng mã trực tiếp, nghĩa là không qua cơ chế truyền tham trị. Chế độ này thường giảm được thời gian thực hiện chương trình.
Đặt lại kích thước tập nền
Cú pháp
void Resize(int size = 0);
Ngữ nghĩa
24
Nạp tên một phần tử cho tập nền
Cú pháp
bool SetName(int id, const char * name);
Ngữ nghĩa
Nạp tên cho phần tử thứ id cho tập nền. Mỗi phần tử trong tập nền có tên riêng và được gắn một số thứ tự 1, 2, ...., Size.
Nạp tên nhiều phần tử cho tập nền
Cú pháp
bool void SetNames(int m,...);
Ngữ nghĩa
SetNames cho phép nạp m tên của m phần tử cho tập nền.
C++ có chức năng cài đặt một hàm với danh sách tham biến động theo
nghĩa số lượng tham biến có thể tùy đặt tại mỗi lần gọi hàm. Thí dụ,
MonHoc.SetNames(4, "Toan","Ly", "Hoa", "Sinh");
Nạp 4 tên, lần lượt là "Toan","Ly", "Hoa", "Sinh" cho tập nền MonHoc;
Xuất tên phần tử của tập nền
Cú pháp
char * GetName(int id);
Ngữ nghĩa
Xuất tên của phần tử thứ id của tập nền.
Xuất tập nền: Toán tử <<
Cú pháp
friend ostream & operator <<(ostream & os, UniSet & u);
Ngữ nghĩa
Hiển thị / hoặc ghi tập nền ra file.
<< là phương thức bạn, tức là phương thức ngoại vi, được gá vào lớp UniSet.
25
Thí dụ
Chương trình DemoUniset.cpp thực hiện các thao tác sau đây: 1. Khai báo tập nền u với 3 phần tử.
2. Hiển thị lực lượng của u.
3. Đặt lại lực lượng (kích thước) của u là 5. 4. Hiển thị lại lực lượng của u.
5. Nạp lần lượt 5 phần tử “ca”, “cua”, “tom”, “bo”, “da dieu” vào u. 6. Hiển thị tập nền u.
7. Mở file “Tapnen.dem” rồi ghi tập nền u vào file.
Như vậy, ta thu được tập nền u = {“ca”, “cua”, “tom”, “bo”, “da dieu”}.
/*************************************************** DemoUniset.cpp *************************************************/ #include <iostream> #include <fstream> #include "FSet.h" using namespace std;
UniSet u(5); // Khai bao tap nen u voi 5 phan tu
void TestSet() {
int n = u.GetSize(); // Xuat luc luong cua tap nen u
cout << "\n I. Size of u: " << u.GetSize(); // Nap lan luot 5 phan tu cho tap nen u.SetName(1,"ca");
u.SetName(2,"cua"); u.SetName(3,"tom");
26
u.SetName(4,"bo"); u.SetName(5,"da dieu"); // Hien thi tap nen
cout << "\n Tap nen: " << u;
ofstream f("TapNen.dem"); // Mo file f << u; // Ghi file
f.close(); // dong file }
main(){ TestSet();
// --------------------------
cout << endl << " T H E E N D . "; // cin.get(); return 0;
}
Kết quả thực hiện
27
Nội dung file “Tapnen.dem”
1. ca 2. cua 3. tom 4. bo 5. da dieu 2.3 Thiết kế lớp tập mờ FSet 2.3.1 Đặt vấn đề
Lớp tập mờ Fset được tham chiếu trên lớp tập nền UniSet. Như đã trình bày trong Chương 1: mọi tập mờ được xem là một thể hiện của tập nền với hàm thuộc cho trước.
Khai báo
template <UniSet & U>
Cho biết lớp tập mờ FSet được tham chiếu trên lớp tập nền UniSet U. Trước khi khởi tạo tập mờ cần khởi tạo tập nền vì mọi tập mờ trên tâọ nền U đều được tham chiếu đến tập nền U duy nhất.
2.3.2 Các trường dữ liệu
Lớp tập mờ FSet có một trường dữliệu duy nhất:
int * Val; // membership value
Trường Val chứa độ thuộc của các phần tử trong tập mờ. Val nhận giá trị nguyên trong khoảng 0 (%) đến 100 (%). Giả sử x là tập mờ trên tập nền U, khi đó x[e] sẽ là độ thuộc của các phần tử e U trong x. x[e] = 0 cho biết e không thuộc tập mờ x, ngược lại, x[e] = 100 cho biết e chắc chắn là phần tử của tập mờ x, ngồi ra x[e] có thể nhận một trong các giá trị trong khoảng 0..100.
Một tập mờ được xem là rõ khi và chỉ khi mọi phần tử của nó chỉ nhận đúng
28 2.3.3 Các phương thức Khai báo tập mờ Tạo tử 1 Cú pháp FSet<U> x; Ngữ nghĩa
Khai báo tập mờ x trên tập nền U.
Tạo tử 2
Cú pháp
FSet<U> y(x);
Ngữ nghĩa
Khai báo tập mờ y trên tập nền U và copy nội dung của tập mờ x vào y. Như vậy hai tập mờ x và y chứa nội dung như nhau nhưng được lưu trên hai vùng nhớ khác nhau. Sau lệnh này hai tập mờ x và y được xem là độc lập với nhau theo nghĩa, mọi biến thiên của tập này không ảnh hưởng đến tập kia và ngược lại.
Hủy tử
Cú pháp
~x;
Ngữ nghĩa
Thu hồi vùng nhớ đã cấp phát cho tập mờ x. Tốn tử này tương đương với việc xóa tập mờ x.
Hàm copy và Toán tử copy (gán)
Cú pháp
inline void Copy(const FSet<U> & y); inline void operator =(const FSet<U> & f);
Ngữ nghĩa
Copy nội dung của tập mờ y sang tập mờ chủ thể. Sau khi copy, Hai tập mờ, y và chủ thể có cùng nội dung nhưng được đặt trong hai vùng nhớ khác nhau
29
và được coi là độc lập theo nghĩa mọi sự thay đổi của tập này không ảnh hưởng đến tập khác và ngược lại.
Xuất nội dung của tập mờ
Cú pháp
friend ostream & operator <<(ostream & os, FSet<U> & s);
Ngữ nghĩa
Hiển thị hoặc ghi tập mờ s ra file theo các chi tiết
tên:độ thuộc
cho mỗi phần tử.
Toán tử << là phương thức bạn, tức là phương thức ngoại vi, được gá vào lớp FSset. Thí dụ, cout << x; Hiển thị tập mờ trên màn hình. f << x; Xuất tập mờ ra file mở sẵn f.
Xuất kích thước của tập mờ
Cú pháp
inline int GetSize();
Ngữ nghĩa
Cho ra kích thước của tập mờ, chính là số phần tử của tập nền.
Hiển thị danh sách tên các phần tử của tập mờ
Cú pháp
void ShowName(const char * msg = “”);
Ngữ nghĩa
Hiển thị danh sách tên các phần tử trong tập mờ kèm chú thích msg. Đây cũng chính là danh sách tên các phần tử trong tập nền liên kết với tập mờ.
30
Truy cập phần tử của tập mờ
Cú pháp
int & operator[](int id);
Ngữ nghĩa
Toán tử x[i] truy cập phần tử thứ i trong tập mờ x.
Gán độ thuộc 0 cho toàn tập mờ
Cú pháp
void Reset();
Ngữ nghĩa
Gán độ thuộc 0 cho mọi phần tử của tập mờ.
Gán độ thuộc 0 cho một phần tử của tập mờ
Cú pháp
bool Reset(int id);
Ngữ nghĩa
Gán độ thuộc 0 cho phần tử thứ id của tập mờ.
Nếu id nằm ngoài giới hạn, id < 1 hoặc id > Size, thì phép gán khơng được thực hiện và hàm cho ra giá trị false; ngược lại, hàm cho ra giá trị true.
Gán độ thuộc 100 cho toàn tập mờ
Cú pháp
void Set();
Ngữ nghĩa
Gán độ thuộc 100 cho mọi phần tử của tập mờ.
Gán độ thuộc 100 cho một phần tử của tập mờ
Cú pháp
bool Set(int id);
Ngữ nghĩa
Gán độ thuộc 100 cho phần tử thứ id của tập mờ.
Nếu id nằm ngoài giới hạn, id < 1 hoặc id > Size, thì phép gán khơng được thực hiện và hàm cho ra giá trị false; ngược lại, hàm cho ra giá trị true.
31
Nạp trị
Cú pháp
a) bool Set(int id, int m);
b) inline bool Ins(int id, int m); c) x[id] = m;
d) void Inss(int n,...);
Ngữ nghĩa
a, b) Gán độ thuộc m cho phần tử thứ id của tập mờ chủ thể. Nếu id nằm ngoài giới hạn, id < 1 hoặc id > Size, thì hàm cho ra giá trị false; ngược lại, hàm cho ra giá trị true.
c) Gán độ thuộc m cho phần tử thứ id của tập mờ x. Nếu id nằm ngoài giới hạn, id < 1 hoặc id > Size thì hệ thống báo lỗi và dừng chương trình.
Các hàm a, b và c là tương đương về giá trị.
d) Gán lần lượt n độ thuộc cho n phần tử của tập mờ chủ thể bắt đầu từ phần tử thứ 1 đến phần tử thứ n. Hàm Inss là hàm với danh sách tham biến động, tức là có số lượng tham trị tùy đặt vào thời điểm gọi hàm.
Thí dụ,
x.Inss(4, 100, 60, 30, 50);
sẽ đặt bốn giá trị cho các phần tử của x: Phần tử 1 có độ thuộc: 100;
Phần tử 2 có độ thuộc: 60; Phần tử 3 có độ thuộc: 30; Phần tử 4 có độ thuộc: 50.
Lệnh trên tương đương với dãy 4 lệnh sau đây:
x[1] = 100; x[2] = 60; x[3] = 30; x[4] = 50;
32
Các toán tử cắt theo ngưỡng
CutToFSet
Cú pháp
FSet CutToFSet(int t);
Ngữ nghĩa
CutToFSet(t) cho ra tập mờ được tạo từ tập mờ chủ thể. Các phần tử trong tập mờ chủ thể có độ thuộc dưới t sẽ được chuyển thành các phần tử trong tập mờ kết quả có độ thuộc 0. Các phần tử cịn lại của tập mờ chủ thể (có độ thuộc t) được chuyển qua cho tập mờ kết quả. Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.CutToFSet(int t);
sẽ cho ta tập mờ z = {Z(e) = (X(e) < t) ? 0 : X(e) | e U }
Cut
Cú pháp
Cut(int t);
Ngữ nghĩa
Tương đương với CutToFSet(t) CutToSet
Cú pháp
FSet CutToSet(int t);
Ngữ nghĩa
CutToSet(t) cho ra tập (rõ) được tạo từ tập mờ chủ thể. Các phần tử trong tập mờ chủ thể có độ thuộc dưới t sẽ khơng có trong tập kết quả (nhận độ thuộc 0). Các phần tử còn lại của tập mờ chủ thể (có độ thuộc t) sẽ xuất hiện trong tập kết quả (nhận độ thuộc 100). Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.CutToSet(int t);
sẽ cho ta tập rõ z = {Z(e) = (X(e) < t) ? 0 : 100 | e U } StrongCutToFSet
33
Cú pháp
FSet StrongCutToFSet(int t);
Ngữ nghĩa
Giống CutToFSet nhưng thay phép sánh < bằng phép sánh .
StrongCutToFSet(t) cho ra tập mờ được tạo từ tập mờ chủ thể. Các phần tử trong tập mờ chủ thể có độ thuộc dưới hoặc bằng t sẽ được chuyển thành các phần tử trong tập mờ kết quả có độ thuộc 0. Các phần tử cịn lại của tập mờ chủ thể (có độ thuộc t) được chuyển qua cho tập mờ kết quả. Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.StrongCutToFSet(int t);
sẽ cho ta tập mờ z = {Z(e) = (X(e) t) ? 0 : X(e) | e U } StrongCutToSet
Cú pháp
FSet StrongCutToSet(int t);
Ngữ nghĩa
Giống CutToSet nhưng thay phép sánh < bằng phép sánh .
StrongCutToSet(t) cho ra tập (rõ) được tạo từ tập mờ chủ thể. Các phần tử trong tập mờ chủ thể có độ thuộc dưới hoặc bằng t sẽ khơng có trong tập kết quả (nhận độ thuộc 0). Các phần tử cịn lại của tập mờ chủ thể (có độ thuộc t) sẽ xuất hiện trong tập kết quả (nhận độ thuộc 100). Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.StrongCutToSet(int t);
sẽ cho ta tập rõ z = {Z(e) = (X(e) t) ? 0 : 100 | e U } CutToSet01
Cú pháp
FSet CutToSet01(int t);
Ngữ nghĩa
CutToSet01(t) cho ra tập rõ kinh điển được tạo từ tập mờ chủ thể. Tập rõ kinh điển là tập rõ 0/1 trong đó mỗi phần tử của tập nền hoặc là thuộc (1) hoặc
34
khơng thuộc (0) tập đó. Các phần tử trong tập mờ chủ thể có độ thuộc dưới t sẽ khơng có trong tập kết quả. Các phần tử còn lại của tập mờ chủ thể (có độ thuộc t) sẽ có trong tập kết quả. Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.CutToSet01(int t);
sẽ cho ta tập rõ z = {Z(e) = (X(e) < t) ? 0 : 1 | e U } StrongCutToSet01
Cú pháp
FSet StrongCutToSet01(int t);
Ngữ nghĩa
Giống CutToSet01 nhưng thay phép sánh < bằng phép sánh .
StrongCutToSet01(t) cho ra tập rõ kinh điển được tạo từ tập mờ chủ thể. Các phần tử trong tập mờ chủ thể có độ thuộc dưới hoặc bằng t sẽ khơng có trong tập kết quả. Các phần tử cịn lại của tập mờ chủ thể (có độ thuộc t) sẽ có trong tập kết quả. Cụ thể là, nếu X là tập mờ trên tập nền U thì lời gọi
Z = X.StrongCutToSet01(int t);
sẽ cho ta tập rõ z = {Z(e) = (X(e) t) ? 0 : 1 | e U }
Thí dụ minh họa phép tốn Cut theo ngưỡng
Chương trình AnBa.cpp dưới đây thực hiện các công việc sau: Khởi tạo tập nền MonHoc với 4 môn: Toan, Ly, Hoa, Sinh. Khởi tạo tập mờ An với sở thích các mơn của học sinh An: An = {Toan: 100, Ly: 80, Hoa: 0, Sinh: 50}
Khởi tạo tập mờ Ba với sở thích các mơn của học sinh Ba: Ba = {Toán: 80, Lý: 50, Hóa: 90, Sinh: 60}
Hiển thị hai tập mờ An và Ba. Cắt An và Ba theo ngưỡng t = 60. Hiển thị lại tập mờ Ba.
/************************************************* AnBa.cpp
35
MonHoc = { Toan, Ly, Hoa, Sinh } Tao 2 tap mo
An = {Toan: 100, Ly: 80, Hoa: 0, Sinh: 50} Ba = {Toan: 80, Ly: 50, Hoa: 90, Sinh: 60}
Hien thi An , Ba
Cat theo nguong t = 60 Hien thi lai An, Ba ************************************************/ #include <iostream> #include "FSet.h" using namespace std; UniSet MonHoc(4); void InitUset() { int s = MonHoc.GetSize();
MonHoc.SetNames(s, "Toan","Ly", "Hoa", "Sinh"); }
void AnBa() { InitUset();
FSet<MonHoc> An, Ba; FSet<MonHoc> a, b; int s = MonHoc.GetSize(); // Nap tri mot lan cho An An.Inss(s, 100, 80, 0, 50);
cout << "\n\n So thich cua An: " << An; // Nap tri theo tung phan tu cho Ba Ba[1] = 80;
36
Ba[2] = 50; Ba[3] = 90; Ba[4] = 60;
cout << "\n\n So thich cua Ba: " << Ba; // Cut theo nguong
int t = 60; // nguong
a = An.CutToFSet(t); // Cat An theo nguong t
cout << "\n\n So thich cua An >= " << t << ": " << a; b = Ba.CutToFSet(t); // Cat Ba theo nguong t
cout << "\n\n So thich cua Ba >= " << t << ": " << b; } main(){ AnBa(); // --------------------------