Chương 2 CÁC CÔNG CỤ ĐẶC TẢ
3.1. Các thuật toán
3.1.3. Thuật toán xây dựng đồ thị trọng số G phục vụ kiểm chứng LDI
Ý tưởng: Tư tưởng cơ bản trong xây dựng đồ thị trọng số G là “rời rạc hóa” đồ thị đạt được nguyên RG bằng cách xây dựng mỗi cung (vi,vj,[l,u]) sẽ được thay bằng một họ các đường đi nối vi, vj sao cho độ dài (trọng số) của các đường đi lần lượt là các số nguyên l, l+1, … , u. Tức cung (vi,vj,[l,u]) được cụ thể hóa thành u-l-1 đường đi nối vi, vj thể hiện tính rời rạc hóa được của LDI. Điều này được thực hiện trên giả thiết RG không chứa cung vô hạn.
Thuật toán xây dựng đồ thị trọng số G = (V,E,) từ RG = (V1,E1) (không chứa cung vô hạn) được thực hiện theo các bước sau:
Bước 1: V = V1, E = E1.
Bước 2: Đối với mỗi cung e = (vi,vj,[lij,uij]) tập đỉnh V, cung E và hàm trọng số
: V E R của G được mở rộng thành:
1. V = V { 1, 2,..., uij1 ij ij
ij v v
v } và (vijk ) = cvi , với k = 0,1,2,…, uij-1 (với qui ước vij0 cho vi và uij
ij
v cho vj),
3. E = E {(vijk,vijk1)|k=0..uij-1}, và (vijk,vijk1) = 1, k = 0..uij-1, 4. E = E {(vijk,vj)|k = lij..uij-1}, và (vijk,vj) = 0, k = lij..uij-1. Chú ý: Trường hợp lij uij đồ thị sẽ có 2 cung từ uij1
ij
v đến vj, một cung có trọng số 1 và cung cịn lại có trọng số 0 (xem hình bên dưới). Để đảm bảo G là đồ thị đơn ta sẽ “chia đơi” cung có trọng số 0 thành 2 cung bằng cách thêm đỉnh uij
ij
v và cung này
được thay bằng 2 cung ( uij1
ij
v , uij
ij
v ) và ( uij
ij
v ,vj). Thuật toán này sẽ được cụ thể hóa trong phần cài đặt, xem cài đặt này trong phần Phụ lục A.
Hình sau đây minh họa cho việc xây dựng G từ một đồ thị RG đơn giản với 2 cung.
Hình 3.1: Xây dựng đồ thị G từ đồ thị vùng đạt được nguyên RG 3.1.4. Thuật toán kiểm chứng LDI 3.1.4. Thuật toán kiểm chứng LDI
Ý tưởng thuật toán: Thuật toán được xây dựng theo kỹ thuật vét cạn để duyệt mọi đường đi với mọi đỉnh xuất phát cố định của đồ thị trọng số đạt được G. Thuật toán
được xây dựng gồm 2 hàm, hàm thứ nhất là traverse(vstart) duyệt mọi đường đi xuất phát từ một đỉnh vstart cố định, và hàm thứ 2 là Checking-LDI sẽ gọi hàm
traverse(vstart) với mọi đỉnh vstart V để quyết định tính thỏa của ơtơmat A đối với LDI.
Hàm traverse(vstart) được xây dựng theo kỹ thuật quay lui như sau: đường đi p xuất phát từ đỉnh ban đầu vstart của G với l(p) = 0 và (p) = 0, đi dọc theo các cạnh tới
các đỉnh mới cho đến khi l(p) ≥ A. Bắt đầu từ thời điểm l(p) ≥ A trở đi, tại mỗi đỉnh mới nếu l(p) > B thì thuật tốn quay lui. Ngược lại (tức B ≥ l(p) ≥ A) nếu θ(p) > M thì thuật toán dừng và cho câu trả lời G |≠ LDI và nếu θ(p) ≤ M thì thuật tốn đi tiếp đến các đỉnh khác. Thuật tốn quay lui khi khơng cịn đỉnh mới để đi tiếp thì dừng lại và cho câu trả lời G |= LDI.
Trường hợp B = ∞, để tránh vịng lặp vơ hạn, thủ tục sẽ xử lý các chu trình gặp được từ lúc l(p) ≥ A trở đi như sau: Nếu chu trình dương thì thuật tốn dừng và kết luận G |≠ LDI. Nếu chu trình âm hoặc bằng 0 thì việc đặt chu trình này vào đường đi là khơng cần thiết vì giá của đường đi vẫn khơng tăng, do vậy thuật toán quay lui.
Để cài đặt thuật toán sử dụng một ngăn xếp p để lưu lại đường đi. Mỗi phần tử
của p gồm 2 thành phần: tên đỉnh x và tập đỉnh Ax chưa thăm bởi x. Thủ tục succ(p) sẽ trả lại đỉnh y Ax (với x là đỉnh cuối của p) và đồng thời loại y ra khỏi Ax. Như vậy x có thể xuất hiện nhiều lần trong p, tuy nhiên tại mỗi vị trí xuất hiện các tập đỉnh Ax là hồn tồn độc lập với nhau và đều được tạo bởi Adj(x) là tập các đỉnh kề của x.
Các biến tồn thể được sử dụng trong thuật tốn gồm: v, v’ để chỉ đỉnh cuối của p và đỉnh sẽ được bổ sung ở bước tiếp theo. Biến preach dùng để lưu lại vị trí tại đó đường đi p đạt đến độ dài A (các chu trình chỉ được xử lý nếu xuất hiện sau vị trí preach). Để điều khiển việc đánh dấu này thuật toán sử dụng biến preach như một biến lôgic nhận giá trị 1 nếu l(p) ≥ A và 0 nếu ngược lại. Hàm succ(p) tìm và trả lại đỉnh tiếp theo (đồng thời loại khỏi tập chưa thăm) hoặc trả lại giá trị NULL. Các hàm l(p), θ(p), l(C), θ(C) trả lại độ dài và giá của đường đi p và chu trình C. Thủ tục pop(p) loại phần tử cuối ra khỏi p và đồng thời tính tốn lại các giá trị l(p), θ(p). Thủ tục push(x, Adj(x), p) thêm đỉnh x cùng tập Ax = Adj(x) vào cuối p và đồng thời tính tốn lại các giá trị l(p), θ(p). Cuối cùng thuật toán trả lại giá trị TRUE nếu LDI được thoả bởi G và
FALSE trong trường hợp ngược lại. Sơ đồ của các thuật toán traverse(vstart) và
Checking-LDI được cho trong các bảng 3.4 và 3.5.
{input : G =(V,E),D}
{output : TRUE nếu và chỉ nếu G(vstart) |= D} Function Traverse(vstart): Boolean;
Begin
p = ; push(vstart,Adj(vstart),p); while p ≠ do begin
if succ(p) == NULL then begin pop(p); loop;end; {quay lui} v’ = succ(p); push(v’, Adj(v’),p);
if l(p) < A then begin reach = 0; loop;end;
if reach == 0 then begin preach = v’; reach =1; end; if l(p) > B then begin pop(p); loop;end; {quay lui} if ((p) > M) then return FALSE; {A ≤ l(p) ≤ B }
if C (đoạn từ preach đến v’) và B = then begin if (C) > 0 then return FALSE;
if (C) ≤ 0 then pop(p); {quay lui} end ;
end;
return TRUE; End;
Bảng 3.4: Thuật toán kiểm chứng LDI với đỉnh xuất phát cố định
{input: G =(V,E), D}
{output: G |= D hoặc G |≠ D} Function Chekcking-LDI: Boolean; Begin
for với mỗi đỉnh v V do begin
if Traverse(v) == FALSE then return G |≠ LDI; end;
return G |= LDI; End ;
Bảng 3.5: Thuật toán kiểm chứng LDI tổng quát
Nhận xét: Thuật toán kiểm chứng LDI Checking-LDI có độ phức tạp cao, độ phức tạp hàm mũ trong trường hợp xấu nhất vì phải duyệt qua tất cả các chu trình của đồ thị bằng phương pháp vét cạn quay lui.
3.2. Các chi tiết kỹ thuật
Luận văn thực hiện cài đặt công cụ phần mềm kiểm chứng trên nền web sử dụng ngơn ngữ lập trình PHP, một ngơn ngữ lập trình mã nguồn mở, rất mạnh, đặc biệt là hồn tồn miễn phí để viết mã, với hi vọng phần mềm sẽ sử dụng được sức mạnh của các web server để giải quyết bài tốn kiểm chứng cơng thức LDI có độ phức tạp hàm mũ hiệu quả hơn. Thông tin về môi trường cài đặt như sau:
– Ngơn ngữ lập trình: PHP-5.2.8 – Web server: Apache
– Ngồi ra cịn sử dụng: Html, Javascript, Template engine smarty, v.v… Để phục vụ cho việc viết mã, luận văn cũng đã xây dựng một framework đơn giản theo mơ hình MVC (Model - View - Controller), MVC là một trong những mơ hình thiết kế được sử dụng rất phổ biến hiện nay trong kỹ thuật phần mềm.
Cấu trúc thư mục source code được thiết kế như hình sau:
Hình 3.2: Cấu trúc thư mục source code
3.3. Đầu vào và đầu ra của bộ kiểm thử
Đầu vào (Input) của bộ kiểm chứng là một hệ thời gian thực được đặc tả bằng một hệ các ôtômat thời gian ở dạng tổng quát A=<L, l0, , X, I, E>, tức là có tập đồng hồ X = {x1,x2,…,xn} và các ràng buộc có dạng := x c | x c | x c | x c | x – y c | x – y c | , ở đây x, y X và c N. Các thuộc tính (tính chất) mong muốn của hệ thống được đặc tả bằng công thức LDI. Các đặc tả này được lưu trong các file *.txt, các file *.txt này là đầu vào của bộ kiểm thử.
Đầu ra (Output) của bộ kiểm chứng gồm:
– Hiển thị lên màn hình các bước chính của q trình kiểm chứng và hiển thị các đồ thị tương ứng với từng bước.
– Đưa ra câu trả lời “đúng” nếu hệ ôtômat thỏa công thức LDI hoặc “sai” nếu bộ kiểm chứng chỉ ra được 1 bộ dữ liệu hệ ôtômat không thỏa công thức LDI.
Mô tả một cách chi tiết hơn, bộ kiểm chứng sẽ hoạt động theo thứ tự các bước sau:
1) Bộ kiểm chứng sẽ đọc hệ ôtômat thời gian, các hệ số của công thức LDI từ file *.txt và chuyển đổi thành dữ liệu có cấu trúc lưu vào các biến trong chương trình.
2) Chương trình sẽ tự động nhận biết nếu hệ có nhiều hơn 1 ơtơmat thì sẽ thực hiện tạo ra 1 ôtômat hợp song song của các ơtơmat thành phần, cịn nếu hệ chỉ có 1 ơtơmat thì sẽ khơng làm gì mà giữ nguyên.
3) Chuyển ôtômat hoặc ôtômat hợp song song (trường hợp hệ thống có nhiều
hơn 1 ơtơmat) thành đồ thị vùng đạt được nguyên dựa trên kĩ thuật ε- ngun
hóa được trình bày tại chương 4 trong Luận án Tiến sĩ Toán học của TS.
Phạm Hồng Thái.
4) Chuyển đồ thị vùng đạt được nguyên sang đồ thị trọng số phục vụ kiểm chứng LDI bằng kĩ thuật rời rạc hóa.
5) Duyệt đồ thị trọng số LDI, tính tốn và đưa ra kết luận ơtơmat thỏa công thức LDI hay không, tức là hệ thống được đặc tả có thỏa mãn các tính chất của hệ thống được đặc tả hay khơng. Trường hợp khơng thỏa thì phải chỉ ra được nơi xảy ra lỗi trong hệ thống.
6) Vẽ đồ họa và hiển thị lên màn hình các đồ thị ơtơmat, đồ thị vùng đạt được nguyên và đồ thị trọng số LDI.
3.4. Cấu trúc dữ liệu
Sử dụng ngơn ngữ lập trình PHP để mơ tả các cấu trúc dữ liệu lưu trữ các ôtômat, đồ thị vùng đạt được nguyên, đồ thị trọng số phục vụ kiểm chứng LDI và các cấu trúc dữ liệu khác để sử dụng trong chương trình.
3.4.1. File dữ liệu đầu vào
Dữ liệu đầu vào được cho dưới dạng ôtômat thời gian, các hệ số của vị trí của ơtơmat và các hệ số A, B, M của công thức LDI được lưu trong 1 file *.txt. Chương trình sẽ đọc dữ liệu từ file *.txt và tính tốn để được kết quả: ôtômat, ôtômat hợp song song đạt được, đồ thị vùng đạt được nguyên, đồ thị trọng số phục vụ LDI, kết quả kiểm chứng, thời gian chạy chương trình.
File dữ liệu đầu vào *.txt được thiết kế như sau:
(nếu giá trị nào đó là vơ cùng thì thay bằng chữ U)
Dòng 1: {Hệ số A}_{Hệ số B}_{Hệ số M} // hệ số của công thức LDI
Dịng 2: {số đỉnh}_{tên vị trí ban đầu} // ơtơmat 1
Dịng 3: {tên vị trí}#xi_low_up|xj_low_up|…#{hệ số ldi} // ơtơmat 1
({tên vị trí}#{các ràng buộc}#{hệ số ldi}) //mỗi đỉnh 1 dịng
…
Dịng i: {số cạnh} // ơtơmat 1
Dòng i+1: li#xi_xj_low_up|…#{nhãn}#xi_1|xj_1|…#lj // ôtômat 1
(phép chuyển e = < li, (low <= xi - xj <=up,…), {nhãn},{ xi, xj,…}, lj >)
….
(nếu có ơtơmat 2,3,… thì lặp lại từ dịng 2 và lưu vào các dịng tiếp theo)
Ví dụ 3.1: Một hệ thống được đặc tả bằng ôtômat thời gian:
Hình 3.3: Ơtơmat thời gian
Tính chất mong muốn được đặc tả bằng cơng thức LDI: 0 l s1 - s2 5 Khi đó file otomat1.txt có nội dung như sau:
0_U_5 2_s1 s1#x2_0_5#1 s2#x1_0_8|x2_0_10#-1 2 s1#x2_x0_3_U#a#x2_1#s2 s2#x1_x0_6_U|x2_x0_4_U#b#x1_1#s1
3.4.2. Ơtơmat
Thiết kế cấu trúc dữ liệu để lưu trữ các thành phần của ôtômat thời gian A=<L, l0, , X, I, E> được lưu trong file *.txt, ta sẽ sử dụng cấu trúc mảng trong PHP để lưu các thành phần của ôtômat A như sau:
(kí hiệu xxx bên dưới thể hiện 1 giá trị nào đó của phần tử tương ứng)
$aryOtomat = array(
‘init’ => l0, //Vị trí ban đầu
‘numLocation’ => xxx, //số vị trí của ơtơmat
‘numTransition’ => xxx, //số phép chuyển của ôtômat
‘clocks’ => array(x1,x2, …, xn), //là mảng chứa tập các đồng hồ X
‘aryLocation’ => array( //Mảng chứa vị trí và thơng tin các vị trí của ơtơmat ‘{tên vị trí}’ => array( //Mảng chứa thơng tin của 1 vị trí
‘invar’ => array( //Mảng chứa các bất biến của vị trí ‘xi’ => array( // Ràng buôc đồng hồ xi: low <= xi <= up
‘low’ => xxx, //Cận dưới của đồng hồ xi ‘up’ => xxx, //Cận trên của đồng hồ xi ), … ), ‘c’ => xxx //Hệ số LDI ), … ),
‘aryTransition’ => array( //Mảng chứa các phép chuyển i => array( //Phép chuyển thứ i
‘loc_name_from’ => xxx, //Tên vị trí đầu(source) ‘loc_name_to’ => xxx, // Tên của vị trí cuối(target) ‘label’ => xxx, //Nhãn của phép chuyển
‘reset’ => array( //Tập các đồng hồ thiết lập lại bằng 0 (reset) ‘xi’ => 1, //Đồng hồ xi sẽ được gán lại giá trị 0
),
‘guard’ => array( //Mảng chưa các ràng buộc của phép chuyển ‘xi-xj’ => array( //Ràng buộc dạng: low <= xi-xj<= up
‘low’ => xxx, ‘up’ => xxx
),
‘xi’ => array( //Ràng buộc dạng: low <= xi<= up ‘low’ => xxx, ‘up’ => xxx ), … ), ), … ) ); 3.4.3. Công thức LDI
Các hệ số LDI ứng với từng vị trí của ôtômat được đưa vào cấu trúc vị trí của ơtơmat (xem trong phần 3.3.2), cịn các hệ số A, B, M của công thức LDI sẽ được đưa vào trong cấu trúc mảng sau:
$aryLdi = array( ‘A’ => xxx, //Hệ số A ‘B’ => xxx, //Hệ số B ‘M’ => xxx //Hệ số M ); 3.4.4. Đồ thị vùng đạt được nguyên
Đồ thị vùng được thể hiện là 1 mảng chứa các thông tin gồm: số đỉnh, số cạnh, 1 mảng chứa tập đỉnh, 1 mảng chứa tập cạnh.
$aryRegionGraph = array(
‘num_vertex’ => xxx, //số đỉnh
‘num_edge’ => xxx, //số cạnh
‘aryVertex’ => array( //Mảng chứa thông tin các đỉnh
i => array( //Đỉnh thứ i = ID đỉnh, i là số tự tăng, bắt đầu từ 1
‘vertex’ => xxx, //Tên đỉnh có dạng: {tên vị trí}_[region]
‘ldi_c’ => xxx, //Hệ số LDI
),
…
),
‘aryEdge’ => array( //mảng chứa thông tin các cạnh
i => array( //thông tin cạnh thứ i+1, chỉ số bắt đầu từ 0
‘id_form’ => xxx, //ID của đỉnh đầu(source)
‘id_to’ => xxx, //ID của đỉnh cuối (target)
‘duration_low’ => xxx, //Cận dưới thời gian
‘duration_up’ => xxx //Cận trên thời gian
), …
)
);
3.4.5. Đồ thị trọng số phục vụ kiểm chứng LDI
Về mặt cấu trúc thì mảng chứa đồ thị trọng số LDI và mảng chứa đồ thị vùng giống nhau, cụ thể cấu trúc mảng của đồ thị trọng số LDI như sau:
$aryWeighGraphLdi = array( ‘num_vertex’ => xxx, //số đỉnh ‘num_edge’ => xxx, //số cạnh
‘aryVertex’ => array( //Mảng chứa thông tin các đỉnh
i => array( //Đỉnh thứ i = ID đỉnh, i là số tự tăng, bắt đầu từ 1 ‘vertex’ => xxx, //Tên đỉnh
‘ldi_c’ => xxx, //Hệ số LDI ),
… ),
‘aryEdge’ => array(( //mảng chứa thông tin các cạnh i => array( //thông tin cạnh thứ i
‘id_form’ => xxx, //ID của đỉnh đầu(source) ‘id_to’ => xxx, //ID của đỉnh cuối (target) ‘w’ => xxx, //trọng số của cung (weigh)
), … )
);
3.4.6. Đường đi của đồ thị
Sử dụng ngăn xếp là 1 mảng để lưu vết đường đi phục vụ cho thuật toán (vét cạn) duyệt đồ thị trọng số LDI để kiểm chứng công thức LDI, ngăn xếp này lưu tên mỗi đỉnh và tập các đỉnh kề với nó khi thuật tốn duyệt đi qua. Ngăn xếp này được thiết kế như sau:
$aryStackPath = array(
i => array( //thông tin đỉnh thứ i+1 trong đường đi
v => array(v1,v2,…,vk), //đỉnh v và các đỉnh kề với v
…
),
3.5. Thiết kế chương trình
Trong mục này sẽ trình bày một số biểu đồ thiết kế cơ bản chương trình của bộ kiểm thử.
3.5.1. Biểu đồ use case
Dựa trên các yêu cầu của bộ công cụ kiểm chứng được mô tả ở trên, ta xác định và đưa ra use case tổng quát của hệ thống với tác nhân (Actor) ở đây là người thiết kế hoặc người lập trình như sau:
Hình 3.4: Biểu đồ use case mức 1
Hình 3.5: Biểu đồ use case mức 2
Mô tả chi tiết use case:
chứng 1 mơ hình đã chọn.
Chọn mơ hình kiểm chứng: Use case này cho phép người dùng xem và chọn 1 mơ hình để thực hiện kiểm chứng trong danh sách các mơ hình của bài tốn đã chọn.
Chọn bài toán kiểm chứng: Use case này cho phép người dùng chọn 1 bài toán để thực hiện kiểm chứng.
3.5.2. Biểu đồ lớp
Hình 3.6: Biểu đồ lớp
Xác định các lớp tham gia vào các use case:
STT Tên lớp Loại lớp
1. Chọn bài toán kiểm chứng
1.1 List Lớp biên
1.2 ListAction Lớp điều khiển
1.3 OtomatLogic, XmlLogic Lớp thực thể
2. Chọn mơ hình kiểm chứng
2.1 searchModel Lớp biên