Bài toán tìm đường đi trong đồ thị hệthống

Một phần của tài liệu (LUẬN văn THẠC sĩ) một số thuật toán đánh giá độ tin cậy của hệ thống (Trang 35)

2.2.1 Một số khái niệm:

- Cạnh: nối hai đỉnh khác nhau của đồ thị. Ví dụ: cạnh nối đỉnh i và j , ký hiệu là (i,j).

- Cung: là cạnh có hướng. Ví dụ: cạnh nối 2 đỉnh i và j tương ứng 2 cung (i,j) và (j,i) và có (i,j)=(j,i).

- Đường đi bắt đầu từ một định và kết thúc tại chính đỉnh đó gọi là chu trình hay vòng lặp. Độ dài của đường đi bằng số các cạnh(cung) trong đường đi đó.

- Đường(chu trình) trong đồ thị được gọi là đơn nếu nó đi qua mỗi cạnh đúng một lần.

- Đường(chu trình) trong đồ thị được gọi là sơ cấp nếu nó đi qua mỗi đỉnh đúng một lần.

- Đường đi qua tất cả các đỉnh gọi là đường đi đầy đủ.

2.2.2 Thuật toán tìm tất cả đường đi trong ma trận liên kết

a. Trường hợp đồ thị cần biểu diễn là vô hướng:

Ma trận đồ thị vô hướng [1] là ma trận đối xứng, tức là các phần tử đối xứng qua đường chéo chính sẽ tương ứng nhau. Có thể được biểu diễn một cách đơn giản bằng ma trận kề vuông cấp n, với n là đỉnh của đồ thị. Phần tử δij ở hàng i, cột j ( i,j = 0,1,2,….n) được xác định như sau:

- δij =1 nếu cặp đỉnh xi và xj có cạnh nối với nhau.

- δij = 0 nếu cặp đỉnh xi và xj không có cạnh nào nối với nhau. Bằng cách trên ta sẽ nhận được ma trận biểu diễn đồ thị đã cho.

b. Trường hợp đồ thị cần biểu diễn là có hướng:

Có thể được biểu diễn một cách đơn giản bằng ma trận kề vuông cấp n, với n là số đỉnh của đồ thị. Phần tử δij ở hàng j, cột j (i,j=0,1,2,….n) được xác định như sau:

- δij =1 nếu cặp đỉnh (xj, xj )có cung.

- δij = 0 nếu cặp đỉnh (xi, xj ) không có cung nào.

Chú ý: Ma trận biểu diễn đồ thị đơn là ma trận logic. Thuật toán:

Cho: Bk = A B*k-1(*) Trong đó:

- Bk : cột ma trận kết quả của phép nhân (*) - Bk-1 là kết quả của phép chuyển đồi Bk-1;

Vậy bài toán đặt ra ở đây là cho ma trận A và ma trận cột B1, hay tìm tất cả đường đi có thể có từ nguồn (điểm phát) tới đích (điểm nhận).

+) Bước 1: kiểm tra ma trận cột B1 có chứa cung bắt đầu từ đỉnh nguồn hay không. Nếu cung tồn tại thì ghi nhận đường đi đó và thay thế cung đó bưởi giá trị 0. Sự thay đổi sẽ cho ta kết quả là B*1;

+) Bước 2: Xét với k =2

+) Bước 3: Thực hiện phép tính (*) để tìm giá trị Bk tương ứng.

+) Bước 4: Kiểm tra Bk bắt đầu từ nguồn, nếu đường đi tồn tại thì ghi nhớ và thay thế cung đó bởi giá trị 0. Nếu đường đi xuất hiện trong Bk là đường đi đầy đủ thì thay thế Bk = 0. Sự thay đổi cho kết quả là B*k .

+) Bước 5: Kiểm tra B*k . Nếu B*k = 0 thì thực hiện tiếp bước 7. Nếu B*k ≠ 0 thì thực hiện tiếp bước 6.

+) Bước 6: Kiểm tra điều kiện k ≤ n-1. Nếu thỏa mãn điều kiện k<n-1 thì tăng k lên 1 và thực hiện tiếp bước 3. Nếu k = n-1 thì thực hiện bước 7.

+) Bước 7: Kiểm tra lại danh sách đường đi và kết quả nhận được là danh sách các đường đi có thể có tử đỉnh đầu tới đỉnh cuối.

Nhận xét:

- Thuật toán tương đối phức tạp. - Phù hợp với các đồ thị nhỏ .

- Dài và dễ nhầm lẫn khi sử dụng cho các đồ thị lớn vì các phần tử của ma trận lúc này là các chuỗi dài.

c. Xây dựng hàm tìm kiếm tất cả các đường đi giữa hai nút trong ma trận liên kết.

Vì các đường mà chúng ta tìm kiếm phải khác nhau và không lặp lại, như thế có nghĩa là chúng có thể khác nhau về độ dài, số đỉnh của mỗi đường đi. Rõ rãng nếu ta ký hiệu mỗi đỉnh là một số, thì ta có thể lưu mỗi đường đi từ đỉnh đầu (nguồn) đến đỉnh cuối (đích) như một mảng (hoặc một chuỗi) mà có chiều dài không lớn hơn kích thước của ma trận liên kết và tất cả các đường đi tìm được ta có thể lưu vào một tập các mảng (tập các hàng – mỗi hàng là một mảng) do vậy số hàng chính bằng số các đường đi tìm được. Để thực hiện điều nay ta cần phải xác định loại của tất cả các đường đi như:

unsigned int K [maxN [maxK]

unsigned int i_line,

unsigned int Leng [maxN]

Tất cả các đường đi được lưu trong ma trận hai chiều K, với i_line dòng, chiều dài mỗi đường đi được lưu trong ma trận Leng.

Các biến maxN (số lượng tối đa các đường đi), maxK (kích cỡ tối đa của ma trận) phải được khai báo hạn chế để tiết kiệm tài nguyên bộ nhớ khi chạy chương trình.

Tuy nhiên để viết chương trình này ta cần thêm các tham số: - Số lượng các đỉnh trong đường đi đang tìm kiếm; - Chiều dài của đường đi này.

- Các đường đi hiện tại là một mảng số thứ tự tất cả các đỉnh của đồ thị thông qua các đường dẫn đã tìm được.

Hình 2.3: Mô hình hàm tìm kiếm tất cả các đường đi trong ma trận liên kết

Hàm tìm kiếm tất cả các đường đi giữa hai nút trong ma trận liên kết được viết bởi ngôn ngữ C++, dưới đây là một đoạn code khai báo cho hàm này.

/* funtion Find: Tìm kiếm vét cạn theo quy tắc đệ

quy tất cac đường đi từ đỉnh Dau(I_ISTOK) đến đỉnh Cuoi(I_STOK)

/*

Void Find(

unsigned int A[maxK][maxK], //ma trận liên kết

unsigned int P[maxK] //ma trận chua cac duong di tim duoc

unsigned int L, //Chieu dai duong di dang tim kiem

unsigned int N,//Kich co ma tran lien ket

unsigned int i_istok //Index ISTOK

unsigned int i_stok //Index STOK

unsigned int i_end //gia tri dinh cuoi

unsigned int A[maxK][maxK, //M.tran chua d.di dang tim

unsigned int A[maxK][maxK],//ma tran chua cac duong di tu //STOK

unsigned int Leng[maxN] //toi STOK voi i_line dong ma

unsigned int&i_line //chieu dai duong di luu trong //ma tran leng

2.2.3 Thuật toán tìm tất cả đường đi trong ma trận liên kết trong lý thuyết đồ thị đồ thị

Theo lý thuyết phần 2.2.2 thì thuật toán được mô tả là phức tạp, có thể nhầm lẫn. Chính vì vậy dẫn đến một yêu cầu cần phát triển thuật toán tìm đường đi giữa hai đỉnh của đồ thị.

a. Thuật toán tìm kiếm theo chiều rộng:

Mô tả thuật toán:

- Xuất phát từ một đỉnh và đi tới đỉnh kề nó, tiếp tục cho tới khi không còn đỉnh nào để đi.

- Trong quá trình đi tới đỉnh kề, tiến hành lưu lại đỉnh cha của đỉnh kề để khi đi ngược lại từ đỉnh kết thúc đến đỉnh xuất phát, ta có được đường đi ngắn nhất.

Đánh giá thuật toán:

Thuật toán tìm kiếm theo chiều rộng làm tiêu tốn khá nhiều thời gian và không gian bộ nhớ.

Gọi b là hệ số nhánh (số nhánh tối đa của một đỉnh bất kì) Gọi d là chiều cao của đường đi đáp án.

Khi đó:

+ Thời gian tiêu tốn: bd

+ Không gian tiêu tốn: bd

Ưu và nhược điểm:

* Ưu điểm:

- Sử dụng kỹ thuật vét cạn không gian trạng thái bài toán vì vậy sẽ tìm được lời giải nếu có.

* Nhược điểm:

- Tìm kiếm giải thuật theo thuật toán định trước, do vậy tìm kiếm một cách máy móc, không nhận ra ngay giải thuật khi không có thông tin hỗ trợ tìm kiếm.

- Không phù hợp với các không gian bài toán lớn. - Không hiệu quả nếu lời giải ở sâu

- Giao tiếp người dùng không thân thiện. Do duyệt qua nhiều nút, việc tìm kiếm không tập chung vào một chủ đề.

b. Thuật toán tìm kiếm theo chiều sâu(Depth First Seach)

Mô tả thuật toán:

- Trước hết, mọi đỉnh x kề với S tất nhiên sẽ đến được từ S. Với mỗi đỉnh x kề với S đó thì tất nhiên những đỉnh y kề với x cũng đến được với S.

- Để không đỉnh nào bị liệt kê tới hai lần, ta sử dụng kỹ thuật đánh dấu. Mỗi lần thăm một đỉnh, ta đánh dấu đỉnh đó lại để các bước duyệt đệ quy kế tiếp sẽ không tiếp tục đuyệt đỉnh đó.

Đánh giá thuật toán:

- Thuật toán tìm kiếm theo chiều sâu làm tiêu tốn khá nhiều thời gian tương tự như thuật toán tìm kiếm theo chiều rộng nhưng tiết kiệm hơn về không gian bộ nhớ.

+ Độ phức tạp: bd (b: hệ số nhánh)

+ Không gian bộ nhớ: bd (d chiều cao đường đi đáp án)

Ưu điểm và nhược điểm:

Ưu điểm:

- Nếu bài toán có lời giải, phương pháp tìm kiếm theo chiều sâu đảm bảo ra lời giải.

- Kĩ thuật tìm kiếm sâu tập chung vào đích. - Tiết kiệm thời gian nếu lời giải ở rất sâu.

- Không phù hợp với không gian bài toán lớn.

- Có thể không tìm được ra lời giải nếu chọn đỉnh ban đầu không thích hợp.

- Không tìm ra lời giải trong thời gian vừa phải.

2.2.4 Kết luận

Trong chương này chúng có nói đến thuật toán tìm đường đi giữa hai nút. Thuật toán ở phần 2.2.2 nói về việc tìm tất cả đường đi giữa hai nút trong ma trận liên kết, còn thuật toán ở phần 2.2.3 nói về việc tìm tất cả các đường đi giữa hai nút của ma trận liên kết trong lý thuyết đồ thị. Hai thuật toán này có ưu điểm và nhược điểm riêng.

Thuật toán ở phần 2.2.2 chỉ thích hợp với những đồ thì có kích thước tương đối nhỏ, trong thuật toán yêu cầu ta phải tính toán được các thành phần Bk và B*k thì mới tiến hành các bước tiếp theo của thuật toán được. Với đồ thị có kích thước lớn hơn thì việc tính toán các thành phần này tương đối phức tạp, dài và dễ nhầm lẫn vì các phần tử của ma trận nay là một chuỗi dài.

Thuật toán ở phần 2.2.3 là sự phát triển hơn của thuật toán ở phần 2.2.2. Ta có thể dựa vào việc tìm đường đi ngắn nhất giữa hai nút của lý thuyết đồ thị đã được học để phát triển thành thuật toán tìm tất cả các đường đi. Ý tưởng của thuật toán này là dữ liệu được lưu dưới dạng ma trận liên kết. Tại giao điểm giữa cột i và hàng j của ma trận A sẽ được viết là 1 nếu cặp nếu cặp đỉnh xi và xj có cạnh nối với nhau, sẽ được viết là 0 nếu cặp cạnh xi và xj không có cạnh nối với nhau

Để hiểu rõ hơn về thuật toán ta xét ví dụ sau:

Hình 2.5b: Đồ thị có hướng

Đồ thị như hình 2.5a và 2.5b được chuyển thành dạng ma trận liên kết tương ứng là A1 và A2 trong đó các phần tử là 0 hoặc (i,j):

iA1= [ 0 (1,2) (1,3) (2,1) 0 (2,3) (3,1) (3,2) 0 (1,4) 0 0 (2,5) (3,4) 0 (4,1) 0 (4,3) 0 (5,2) 0 0 (4,5) (5,4) 0 ] = [ 0 12 13 21 0 23 31 32 0 14 0 0 25 34 0 41 0 43 0 52 0 0 45 54 0 ] A2 = [ 0 (1,2) (1,3) 0 0 (2,3) 0 0 0 (1,4) 0 0 (2,5) (3,4) 0 0 0 0 0 0 0 0 (4,5) 0 0 ] = [ 0 12 13 0 0 23 0 0 0 14 0 0 25 34 0 0 0 0 0 0 0 0 45 0 0 ]

Ở đây ta đã đơn giản hoá cách viết các phần tử trong ma trận, bỏ dấu ngoặc đơn và dấu phẩy giữa hai đỉnh kết nối với nhau. Ví dụ (1,2) = 12,...

Ta sẽ sử dụng thuật toán 2.1.2 đã nói ở trên để áp dụng với ma trận A1

có đỉnh nguồn là 1 và đỉnh đích 6: A1= [ 0 12 13 21 0 23 31 32 0 14 0 0 25 34 0 41 0 43 0 52 0 0 45 54 0 ] ; B1 = [ 0 25 0 45 0 ] ; B* 1 = [ 0 25 0 45 0 ] Các bước tiếp theo của thuật toán được thực hiện như sau:

B2 = [ 12 ∗ 25 ∨ 14 ∗ 45 0 32 ∗ 25 ∨ 34 ∗ 45 0 52 ∗ 25 ∨ 54 ∗ 45 ] ; B* 2 = [ 0 0 32 ∗ 25 ∨ 34 ∗ 45 0 0 ] B3= [ 13 ∗ 32 ∗ 25 ∨ 13 ∗ 34 ∗ 45 23 ∗ 32 ∗ 25 ∨ 23 ∗ 34 ∗ 45 0 43 ∗ 32 ∗ 25 ∨ 43 ∗ 34 ∗ 45 0 ] ; B*3 = [ 0 23 ∗ 34 ∗ 45 0 43 ∗ 32 ∗ 25 0 ] B4= [ 12 ∗ 23 ∗ 34 ∗ 45 ∨ 14 ∗ 43 ∗ 32 ∗ 25 0 32 ∗ 23 ∗ 34 ∗ 45 ∨ 34 ∗ 43 ∗ 32 ∗ 25 0 52 ∗ 23 ∗ 34 ∗ 45 ∨ 54 ∗ 43 ∗ 32 ∗ 25] B*4= [ 0 0 0 0 52 ∗ 23 ∗ 34 ∗ 45 ∨ 54 ∗ 43 ∗ 32 ∗ 25]

Vì ở bước 6 của thuật toán khi gặp điều kiện k=n-1 (4=5-1) thì ta dừng lại và liệt kê tất cả các đường đi đã tìm được. Vậy ta dừng thuật toán tìm tất cả các đường đi của ma trận A1 tại bước này.

Ta thấyđể tìm đường đi theo thuật toán 2.1.2 thì ta phải tính được ma trận B1, B2, B3, B4 như trên và danh sách tất cả các đường đi từ đỉnh 1 đến đỉnh 5 nhận được là:

1→2→5; 1→4→5; 1→3→2→5; 1→3→4→5; 1→2→3→4→5; 1→4→3→2→5;

Nếu ta áp dụng thuật toán 2.1.5 tìm kiếm theo chiều sâu thì kết quả sẽ như sau:

Ma trận A1 sẽ được viết lại như sau:

A1= [ 0 1 1 1 0 1 1 1 0 1 0 0 1 1 0 1 0 1 0 1

Xuất phát từ đỉnh 1 ta đi tiếp đến đỉnh 2, từ đỉnh 2 ta đi tiếp đến đỉnh 3, tiếp đến đỉnh 4, tiếp đến đỉnh 5 ta dừng lại vì đỉnh 5 đã là đỉnh cuối. Vậy ta được đường đi 1→2→3→4→5.

Từ đỉnh 5 ta quay lại đỉnh 4 nhưng từ đỉnh 4 không có đường nào khác đến đỉnh 5 ngoài đường đã nói ở trên nên ta quay lại đỉnh 3, từ đỉnh 3 ta có thể quay lại đỉnh 2 hoặc đỉnh 1:

- Nếu quay lại đỉnh 2 thì từ đỉnh 2 ta có thể đi tiếp đến đỉnh 5, vậy ta có đường đi là 1→2→5.

- Nếu quay lại đỉnh 1 thì ta có thể đi tiếp đến đỉnh 3, tiếp đỉnh 4 và 5, vậy ta có đường đi 1→3→4→5 hoặc từ đỉnh 3 ta đi tiếp đến đỉnh 2 và tiếp đến đỉnh 5, vậy ta có đường đi là 1→3→2→5;

- Từ đỉnh 1 ta cũng có thể đi đến đỉnh 4 và đi tiếp đến đỉnh 5, vậy ta có đường đi 1→4→5 hoặc từ 4 ta có thể quay về đỉnh 3 rồi về đỉnh 2 và đi tiếp đến đỉnh 5, vậy ta có đường đi 1→4→3→2→5;

Áp dụng thuật toán 2.1.5 này cho ta kết quả là các đường đi: 1→2→3→4→5; 1→2→5; 1→3→4→5 ; 1→3→2→5; 1→4→5 và1→4→3→2→5. Kết quả này trùng với kết quả tính theo thuật toán 2.1.4

=>Hai thuật toán 2.2.2 và 2.2.3 cho ta kết quảtương tự nhau.

Dựa vào kết quả ví dụ và các phân tích ở trên thì thuật toán ở phần 2.2.3 thích hợp để xây dựng chương trình tìm tất cả các đường đi giữa hai nút trong ma trận liên kết.

2.3 Bài toán tối thiểu các toán tử logic

Khái niệm: tối thiểu hóa là tìm dạng biểu diễn đơn giản nhất của hàm. Khi đó sẽ giảm được tối đa số cổng để thực hiện hàm. Hiện nay vẫn chưa có phương pháp tối ưu nào có thể thực hiện việc tối thiểu hóa một cách tối ưu. Việc tối thiểu hóa có thể thực hiện bằng một trong hai cách cơ bản.

2.3.1 Biến đổi đại số

Việc tối thiểu hóa các toán tử logic thường dựa trên các hằng đẳng thức Boole hay còn được gọi là các luật trong Boole.

Một đại số Boole[1] là một cấu trúc đại số gồm một tập hợp S chứa ít nhất 2 phần tử, được kí hiệu là 0 và 1, cùng hai phép toán hai ngôi “+” (tuyển - ˅) và “.” (hội - ˄ ) và phép toán 1 ngôi “ˉ” (phủ định) thỏa mãn các luật sau:

(1). Luật giao hoán a) a.b = b.a

b) a + b = b + a (2). Luật kết hợp

a) (a.b).c = a.(b.c)

b) (a+b) + c = a + (b+c) (3). Luật phân phối

a) a.(b+c) = (a.b)+(a.c) b) a+(b.c) = (a+b).(a+c) (4). Luật đồng nhất a) a.1 = a b) a+0 = a (5). Luật trội a) a+1 = 1 b) a.0 = 0 (6). Luật tồn tại phần tử bù

Một phần của tài liệu (LUẬN văn THẠC sĩ) một số thuật toán đánh giá độ tin cậy của hệ thống (Trang 35)

Tải bản đầy đủ (PDF)

(73 trang)