1: mod! QUEUE(D :: TRIVM) { 2: [Queue]
3: op empty : -> Queue {constr}
4: op _,_ : Queue Elt.D -> Queue {constr l-assoc} -- Các phép toán trên hàng đợi
5: op put : Elt.D Queue -> Queue 6: op get : Queue -> Queue
7: op top : Queue -> EltErr.D 8: op empty? : Queue -> Bool -- Các biến trong CafeOBJ 9: var Q : Queue 10: vars X Y : Elt.D -- Định nghĩa các luật 11: eq put(X,empty) = empty,X . 12: eq put(X,(Q,Y)) = put(X,Q),Y . 13: eq get((Q,X)) = Q . 14: eq top(empty) = (none):EltErr.D . 15: eq top((Q,X)) = X . 16: eq empty?(empty) = true . 17: eq empty?((Q,X)) = false . 18: } Hình 4.4: Đặc tả mô-đun QUEUE.
1: mod! LABEL { 2: [Label]
3: ops rm wt cs : -> Label
4: pred (_=_) : Label Label {comm} . 5: var L : Label 6: eq (L = L) = true . 7: eq (rm = wt) = false . 8: eq (rm = cs) = false . 9: eq (wt = cs) = false . 10: } Hình 4.5: Đặc tả mô-đun LABEL.
Hình 4.6: Đặc tả mô-đun AID định danh các tác tử.
Hình 4.7: Đặc tả mô-đun FID định danh cho chuyến bay.
1: mod* AID {
-- Khai báo 3 kiểu dữ liệu AIdConst là kiểu -- con của kiểu AId, kiểu AId là kiểu con -- của kiểu AIdErr
2: [AIdConst < AId < AIdErr]
3: op none : -> AIdErr -- Khai báo hằng none -- thuộc kiểu AIdErr
4: pred (_=_) : AIdErr AIdErr {comm} 5: var A : AId .
6: eq (A = A) = true . 7: vars AI AJ : AIdConst
8: eq (AI = AJ) = (AI == AJ) . 9: eq (none = A) = false .
1: mod* FID {
2: [FIdConst < FId < FIdErr] 3: op none : -> FIdErr
4: pred (_=_) : FIdErr FIdErr {comm} 5: var F : FId . 6: eq (F = F) = true . 7: vars FI FJ : FIdConst 8: eq (FI = FJ) = (FI == FJ) . 9: eq (none = F) = false . 10: }
4.3. Chứng minh tính đúng đắn của hệ thống
Với việc đặc tả hệ thống như trên, ta cần xây dựng mô-đun INV để kiểm chứng tính đúng đắn cho việc sử dụng chung các chuyến bay của hệ thống hay nói cách khác chính là việc chứng minh xung đột không được phép xảy ra trong quá trình thực thi hệ thống.
1: mod INV{ 2: pr(ATA)
3: pred inv : ATASys FId AId AId -- Tương đương với
-- op inv : ATASys FId AId AId -> Bool . 4: var S : ATASys .
5: vars AI AJ : AId 6: var FI : FId .
7: eq inv(S,FI,AI,AJ) = (((pc(S,FI,AI) = cs) and(pc(S,FI,AJ) = cs)) implies AI = AJ) . 8: }
Hình 4.8: Đặc tả mô-đun INV. Chi tiết của mô-đun INV như sau: Chi tiết của mô-đun INV như sau:
Mô-đun INV kế thừa mô-đun ATA với kiểu protecting (dòng 2). Định nghĩa thuộc tính bất biến inv như một phép toán với 4 tham số đầu vào, các tham số này có kiểu dữ liệu lần lượt là: kiểu dữ liệu không gian trạng thái ATASys, kiểu dữ liệu chuyến bay FId, kiểu dữ liệu đại lý AId và kiểu dữ liệu cuối cùng cũng là kiểu dữ liệu AId, đầu ra của inv thuộc kiểu logic Bool (dòng 3).Các bước tiếp theo của mô-đun (từ dòng 4 đến dòng 6) là khai báo bốn biến để làm tham số cho phép toán inv bao gồm: biến S thuộc kiểu dữ liệu không gian trạng thái ATASys, biến AI và AJ thuộc kiểu dữ liệu đại lý AId, biến FI thuộc kiểu dữ liệu chuyến bay FId. Bước cuối cùng là khai báo ý nghĩa của thuộc tính bất biến inv (dòng 7), (((pc(S,FI,AI) = cs) and (pc(S,FI,AJ) = cs)) implies AI = AJ) có nghĩa là: (((pc(S,FI,AI) = cs) ˄ (pc(S,FI,AJ) = cs)) => AI = AJ), đây là một biểu thức logic, biểu thức logic này có giá trị chân lý là false ở duy nhất một trường hợp là: pc(S,FI,AI) = cs là true và pc(S,FI,AJ) = cs là true nhưng AI = AJ là false, còn lại tất cả các trường hợp khác thì biểu logic này đều cho giá trị chân lý là true. Cũng có nghĩa là: tại một trạng thái S nào đó, nếu có hai đại lý khác nhau AI, AJ cùng đang sử dụng một chuyến bay là FI thì thuộc tính bất biến inv sẽ có giá trị false. Nếu như ta chứng minh được tại mọi trạng thái S thuộc không
gian trạng thái ATASys, giá trị của thuộc tính bất biến inv luôn luôn là true, nghĩa là không có trường hợp tại một trạng thái S nào đó mà có hai đại lý khác nhau AI, AJ cùng đang sử dụng một chuyến bay FI thì có nghĩa là vấn đề xung đột trong quá trình sử dụng các chuyến bay của các đại lý là không xảy ra.
Để áp dụng tư tưởng quy nạp của CafeOBJ trong việc chứng minh tính đúng đắn của các thuộc tính bất biến của hệ thống, ta cần xây dựng thêm mô- đun ISTEP để chứng minh trong trường hợp tổng quát.
1: mod ISTEP{ 2: pr(INV)
-- s được hiểu là trạng thái hiện tại
-- s' được hiểu là trạng thái tiếp theo của s 3: ops s s' : -> ATASys .
-- Bước chứng minh quy nạp 4: pred istep : AId AId
-- Các biến trong CafeOBJ 5: vars AI AJ : AId
6: var FI : FId
7: eq istep(AI,AJ) = inv(s,FI,AI,AJ) implies inv(s',FI,AI,AJ) .
8: }
Hình 4.9: Đặc tả mô-đun ISTEP.
Bước cơ sở: Chứng minh thuộc tính bất biến inv thỏa mãn tại trạng thái khởi tạo init của hệ thống. 1: open INV 2: ops Ai Aj : -> AId . 3: op Fi : -> FId . -- 4: red inv(init,Fi,Ai,Aj) . 5: close
Hình 4.10: Chứng minh tính đúng đắn của thuộc tính bất biến inv tại trạng thái khởi tạo init của hệ thống.
Kết quả trả về của inv sau khi thực hiện đoạn lệnh trên là true. Chứng tỏ
Ta có thể xem lại các bước thực rút gọn để chứng minh một biểu thức logic trong CafeOBJ hoặc cũng có thể tự mình thực hiện từng bước rút gọn bằng tay để đến được kết quả cuối cùng.
Bước quy nạp: Với phương thức chuyển trạng thái want.
Để chứng minh cho trường hợp tổng quát với phương thức chuyển trạng
thái want ta cần khai báo thêm một đại lý thứ ba là Ak ngoài Ai và Aj đã khai
báo và sử dụng trong trường hợp cơ sở ở trạng thái khởi tạo init.
Với việc sử dụng thêm một đại lý thứ ba là Ak, trong trường hợp này,
công đoạn chứng minh sẽ được tác ra thành các công đoạn nhỏ hơn, từ đó ta chứng minh tất cả các công đoạn nhỏ này đều đúng, điều đó tương đương với việc cả công đoạn ban đầu đã được chứng minh là đúng.
1: open INV
-- Khai báo các toán tử 2: ops s s' : -> ATASys . 3: op Fi : -> FId .
4: ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s, -- ta khai báo như sau:
5: eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- Trạng thái tiếp theo
6: eq s' = want(s,Fi,Ak) . -- Kiểm tra tính đúng đắn 7: red inv(s',Fi,Ai,Aj) . 8: close
Hình 4.11: Chứng minh tính đúng đắn của thuộc tính bất biến inv trong trường
hợp tổng quát với phương thức chuyển trạng thái want.
Kết quả thực hiện đoạn lệnh trên trả về một biểu thức logic, ta cần bổ xung thêm tri thức (các luật) để rút gọn biểu thức lôgic này. Ta thấy, khi thực
hiện lệnh want với đại lý Ak thì phải cần kiểm tra điều kiện c-want của Ak, mặt
khác Ak cũng có thể là Ai hoặc không. Do đó, ta có bảng phân tách các trường
Các trường hợp cần chứng minh Các trường hợp của c-want Các trường hợp quan hệ giữa Ai và Ak Các trường hợp quan hệ giữa Aj và Ak 1 c-want(s,Fi,Ak) (Ai = Ak) Aj = Ak
2 not (Aj = Ak)
3
not (Ai = Ak) Aj = Ak
4 not (Aj = Ak)
5 not c-want(s,Fi,Ak)
Hình 4.12: Bảng phân tách các trường hợp cần chứng minh cho thuộc tính bất
biến inv với phương thức chuyển trạng thái want.
Trên đây là tất cả các trường hợp ta cần chứng minh, nếu tất cả các trường
hợp này đúng thì tính đúng đắn của thuộc tính bất biến inv với phương thức
chuyển trạng thái want được chứng minh.
Trường hợp c-want(s,Fi,Ak), Ai = Ak, Aj = Ak:
- c-want(s,Fi,Ak) nghĩa là c-want(s,Fi,Ak) = true, theo định nghĩa của
phương thức c-want thì cần có pc(s,Fi,Ak) = rm. Do đó, ta khai báo trong
CafeOBJ luật: eq pc(s,Fi,Ak) = rm .
- Ai = Ak nghĩa là (Ai = Ak) = true. Do đó, ta khai báo trong CafeOBJ luật
sau : eq Ai = Ak .
- Aj = Ak nghĩa là (Aj = Ak) = true. Do đó, ta khai báo trong CafeOBJ luật
sau : eq Aj = Ak .
Hình 4.13 là phần đặc tả cho trường hợp này trong CafeOBJ để kiểm chứng thuộc tính bất biến inv.
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s
eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-want(s,Fi,Ak)
eq pc(s,Fi,Ak) = rm . -- Ai = Ak
eq Ai = Ak . -- Aj = Ak eq Aj = Ak .
-- Trạng thái tiếp theo của s eq s' = want(s,Fi,Ak) .
-- Kiểm tra tính đúng đắn red inv(s',Fi,Ai,Aj) . close
Hình 4.13: Kiểm chứng trường hợp c-want(s,Fi,Ak), Ai = Ak, Aj = Ak.
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp này
được kiểm chứng là đúng.
Trường hợpc-want(s,Fi,Ak), Ai = Ak, not (Aj = Ak) :
- eq pc(s,Fi,Ak) = rm .
- eq Ai = Ak .
- eq (Aj = Ak) = false .
Hình 4.14 là phần đặc tả cho trường hợp này trong CafeOBJ:
open INV
ops s s' : -> ATASys . op Fi : -> FId .
ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-want(s,Fi,Ak)
eq pc(s,Fi,Ak) = rm . -- Ai = Ak
eq Ai = Ak . -- not (Aj = Ak)
eq (Aj = Ak) = false . eq s' = want(s,Fi,Ak) . -- Kiểm tra tính đúng đắn red inv(s',Fi,Ai,Aj) . close
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp này được kiểm chứng là đúng.
Trường hợp c-want(s,Fi,Ak), not (Ai = Ak), Aj = Ak :
- eq pc(s,Fi,Ak) = rm .
- eq Aj = Ak .
- eq (Ai = Ak) = false .
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-want(s,Fi,Ak)
eq pc(s,Fi,Ak) = rm . -- Aj = Ak
eq Aj = Ak . -- not (Ai = Ak)
eq (Ai = Ak) = false .
-- Trạng thái tiếp theo của s eq s' = want(s,Fi,Ak) .
-- Kiểm tra tính đúng đắn red inv(s',Fi,Ai,Aj) . close
Hình 4.15: Kiểm chứng trường hợp c-want(s,Fi,Ak), not (Ai = Ak), Aj = Ak.
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp này
được kiểm chứng là đúng.
Trường hợpc-want(s,Fi,Ak), not (Ai = Ak), not (Aj = Ak) :
- eq pc(s,Fi,Ak) = rm .
- eq (Aj = Ak) = false .
- eq (Ai = Ak) = false .
Hình 4.16 là phần đặc tả cho trường hợp này trong CafeOBJ để kiểm chứng thuộc tính bất biến inv.
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-want(s,Fi,Ak)
eq pc(s,Fi,Ak) = rm . -- not (Ai = Ak)
eq (Ai = Ak) = false . -- not (Aj = Ak)
eq (Aj = Ak) = false .
-- Trạng thái tiếp theo của s eq s' = want(s,Fi,Ak) .
-- Kiểm tra tính đúng đắn red inv(s',Fi,Ai,Aj) . close
Hình 4.16: Trường hợp c-want(s,Fi,Ak), not (Ai = Ak), not (Aj = Ak). Kết quả thực hiện đoạn lệnh trên trả về một biểu thức logic như sau:
((((pc(s,Fi,Ai) = cs) and (pc(s,Fi,Aj) = cs)) and (Ai = Aj)) xor (((pc(s,Fi,Ai) = cs) and (pc(s,Fi,Aj) = cs)) xor true))
Hình 4.17: Kết quả trường hợp c-want(s,Fi,Ak), not (Ai = Ak), not (Aj = Ak).
Ta thấy biểu thức logic trả về tương đương với inv(s,Fi,Ai,Aj), mặt khác
inv(s,FI:FId,AI:AId,AJ:AId) = true, do đó inv(s,Fi,Ai,Aj) sẽ trả về true, vì Fi, Ai,
Aj là những hằng số cụ thể được thay vào.
Từ suy luận trên, ta có thể biến đổi đặc tả của trường hợp này như sau:
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
-- Giả sử inv đúng với trạng thái s eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-want(s,Fi,Ak)
eq pc(s,Fi,Ak) = rm . -- not (Ai = Ak)
eq (Ai = Ak) = false . -- not (Aj = Ak)
eq (Aj = Ak) = false .
-- Trạng thái tiếp theo của s eq s' = want(s,Fi,Ak) .
-- Kiểm tra tính đúng đắn
red inv(s,Fi,Ai,Aj) implies inv(s',Fi,Ai,Aj) . close
Hình 4.18: Kiểm chứng trường hợp c-want(s,Fi,Ak), not (Ai = Ak), not (Aj = Ak) sử dụng INST, TRANS, HIDE.
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp này
được kiểm chứng là đúng.
Trường hợp not c-want(s,Fi,Ak) :
not c-want(s,Fi,Ak) có nghĩa là c-want(s,Fi,Ak) = false. Do đó, ta khai báo
trong CafeOBJ luật: c-want(s,Fi,Ak) = false .
Hình 4.19 là phần đặc tả cho trường hợp này trong CafeOBJ để kiểm chứng thuộc tính bất biến inv.
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
ops Ai Aj Ak : -> AId .
-- Giả sử inv đúng với trạng thái s eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- not c-want(s,Fi,Ak)
eq c-want(s,Fi,Ak) = false . -- Trạng thái tiếp theo của s eq s' = want(s,Fi,Ak) .
red inv(s',Fi,Ai,Aj) . close
Hình 4.19: Kiểm chứng trường hợp not c-want(s,Fi,Ak) .
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp này
đã được kiểm chứng là đúng.
Tất cả các trường hợp có thể xảy ra đối với việc chứng minh tính đúng
đắn của thuộc tính bất biến inv với phương thức chuyển trạng thái want đều đã
được chứng minh là đúng. Vậy tính đúng đắn của thuộc tính bất biến INV với
phương thức chuyển trạng thái want đã được chứng minh là đúng.
Tương tự ta chứng minh tính đúng đắn của thuộc tính inv với phương thức
chuyển tạng thái try.
Trường hợp 1:
- c-try(s,Fi,Ak) thỏa mãn, có nghĩa là pc(s,Fi,Ak) = wt và top(queue(s,Fi))
= Ak. Do đó, ta khai báo các luật trong CafeOBJ là : eq pc(s,Fi,Ak) = wt ., eq top(queue(s,Fi)) = Ak ..
- Ai = Ak thỏa mãn, có nghĩa là (Ai = Ak) = true, khai báo trong CafeOBJ
luật: eq Ai = Ak..
- Aj = Ak thỏa mãn, có nghĩa là (Aj = Ak) = true, khai báo trong CafeOBJ
luật: eq Aj = Ak..
Đặc tả trường hợp 1 của phương thức try trong CafeOBJ:
open INV
-- Khai báo các hằng bất kỳ ops s s' : -> ATASys .
op Fi : -> FId .
ops Ai Aj Ak : -> AId . -- Khai báo các giả thiết
eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-try(s,Fi,Ak) eq pc(s,Fi,Ak) = wt . eq top(queue(s,Fi)) = Ak . -- Ai = Ak eq Ai = Ak .
-- Aj = Ak eq Aj = Ak .
-- Trạng thái kế tiếp của s eq s' = try(s,Fi,Ak) .
-- Rút gọn để kiểm chứng red inv(s',Fi,Ai,Aj) . close
Hình 4.20: Kiểm chứng trường hợp 1 của phương thức try.
Kết quả thực hiện đoạn lệnh trên trả về giá trị true. Vậy trường hợp 1 của
phương thức try được kiểm chứng là đúng.
Trường hợp 2:
- c-try(s,Fi,Ak) thỏa mãn, có nghĩa là pc(s,Fi,Ak) = wt và top(queue(s,Fi))
= Ak. Do đó, ta khai báo các luật trong CafeOBJ là : eq pc(s,Fi,Ak) = wt ., eq top(queue(s,Fi)) = Ak ..
- Ai = Ak thỏa mãn, có nghĩa là (Ai = Ak) = true, khai báo trong CafeOBJ
luật: eq Ai = Ak..
- not (Aj = Ak), có nghĩa là (Aj = Ak) = false, khai báo trong CafeOBJ luật:
eq (Aj = Ak) = false..
Đặc tả trường hợp 2 của phương thức try trong CafeOBJ:
open INV
-- Khai báo các hằng tùy ý ops s s' : -> ATASys . op Fi : -> FId .
ops Ai Aj Ak : -> AId . --
-- Khai báo các giả thiết
eq inv(s,FI:FId,AI:AId,AJ:AId) = true . -- c-try(s,Fi,Ak) eq pc(s,Fi,Ak) = wt . eq top(queue(s,Fi)) = Ak . -- Ai = Ak eq Ai = Ak . -- ~(Aj = Ak)
-- Định nghĩa trạng thái kế tiếp của s eq s' = try(s,Fi,Ak) .
-- Thực hiện rút gọn để kiểm chứng