You are on page 1of 16

BỘ GIÁO DỤC VÀ ĐÀO TẠO

TRƯỜNG ĐẠI HỌC BÁCH KHOA TP.HCM


KHOA KỸ THUẬT XÂY DỰNG

BÁO CÁO
BÀI TẬP LỚN
ĐẠI SỐ TUYẾN TÍNH

ĐỀ TÀI 3:

Giảng viên hướng dẫn : Huỳnh Thái Duy Phương


Lớp : L22
Nhóm thực hiện: 3

1
MỤC LỤC
A.DANH SÁCH NHÓM
B.PHẦN MỞ ĐẦU
C.PHẦN NỘI DUNG
I. Bài toán tìm đường đi ngắn nhất trong lý thuyết đồ
thị
1.1 Lý thuyết đồ thị
1.2 Phát biểu bài toán tìm đường đi ngắn nhất
trong lý thuyết đồ thị
II.Ứng dụng của đại số tuyến tính trong bài toán “
Tìm đường đi ngắn nhất”
2.1 Thuật toán Floyd Warshall đối với bài toán
tìm đường đi ngắn nhất trong lý thuyết đồ thị
2.2 Đường đi ngắn nhất xuất phát từ 1 đỉnh,thuật
toán Ford-bellman
2.3 Trường hợp ma trận không âm.Thuật toán
Dijkstra
III. Chương trình Mathlab để giải bài toán “ Tìm
đường đi ngắn nhất”

2
A.Danh sách Nhóm
Nhóm: 3
-Danh sách sinh viên:

STT Họ tên MSSV

1 1914104
Nguyễn Văn Lý

2 1914188
Võ Phạm Nhật Minh

3 1914215
Đặng Hoài Nam

4 1914290
Phan Thanh Ngân

5 1914387
Nguyễn Thảo Nguyên

6 1915771
Trần Võ Ngọc Thủy Trúc

7 1914503
Lê Thị Yến Nhi

8 1911826
Nguyễn Đình Phát

1914688
9 Lê Vĩnh Phúc

3
B.Phần mở đầu
Trong các ứng dụng thực tế, vài toán tìm đường đi ngắn nhất giữa hai
đỉnh của một đồ thị liên thông có một ý nghĩa to lớn. Có thể dẫn về bài
toán như vậy nhiều bài toán thực tế quan trọng.
Ví dụ, bài toán chọn một hành trình tiết kiệm nhất (theo tiêu chuẩn hoặc
khoảng cách hoặc thời gian hoặc chi phí) trên một mạng giao thông
đường bộ, đường thủy hoặc đường không; bài toán chọn một phương
pháp tiết kiệm nhất để đưa ra một hệ thống động lực từ trạng thái xuất
phát đến trạng một trạng thái đích, bài toán lập lịch thi công các công
các công đoạn trong một công trình thi công lớn, bài toán lựa chọn
đường truyền tin với chi phí nhỏ nhất trong mạng thông tin, v.v…
Hiện nay có rất nhiều phương pháp để giải các bài toán như vậy. Thế
nhưng, thông thường, các thuật toán được xây dựng dựa trên cơ sở lý
thuyết đồ thị tỏ ra là các thuật toán có hiệu quả cao nhất.

4
C.Phần nội dung
I. Bài toán tìm đường đi ngắn nhất trong lý thuyết đồ
thị
1.1 Lý thuyết đồ thị
Trong toán học và tin học, lý thuyết đồ thị (tiếng Anh: graph theory) nghiên cứu các tính
chất của đồ thị. Một cách không chính thức, đồ thị là một tập các đối tượng được gọi là
các đỉnh (hoặc nút) nối với nhau bởi các cạnh (hoặc cung). Cạnh có thể có hướng hoặc vô
hướng. Đồ thị thường được vẽ dưới dạng một tập các điểm (các đỉnh nối với nhau bằng các
đoạn thẳng (các cạnh).
Đồ thị biểu diễn được rất nhiều cấu trúc, nhiều bài toán thực tế có thể được biểu diễn bằng
đồ thị. Ví dụ, cấu trúc liên kết của một website có thể được biểu diễn bằng một đồ thị có
hướng như sau: các đỉnh là các trang web hiện có tại website, tồn tại một cạnh có hướng
nối từ trang A tới trang B khi và chỉ khi A có chứa 1 liên kết tới B. Do vậy, sự phát triển
của các thuật toán xử lý đồ thị là một trong các mối quan tâm chính của khoa học máy tính.
Cấu trúc đồ thị có thể được mở rộng bằng cách gán trọng số cho mỗi cạnh. Có thể sử dụng
đồ thị có trọng số để biểu diễn nhiều khái niệm khác nhau. Ví dụ, nếu đồ thị biểu diễn một
mạng đường giao thông, các trọng số có thể là độ dài của mỗi con đường. Một cách khác
để mở rộng đồ thị cơ bản là quy định hướng cho các cạnh của đồ thị (như đối với các trang
web, A liên kết tới B, nhưng B không nhất thiết cũng liên kết tới A). Loại đồ thị này được
gọi là đồ thị có hướng. Một đồ thị có hướng với các cạnh có trọng số được gọi là một lưới.
Các lưới có nhiều ứng dụng trong khía cạnh thực tiễn của lý thuyết đồ thị, chẳng hạn, phân
tích lưới có thể dùng để mô hình hoá và phân tích mạng lưới giao thông hoặc nhằm "phát
hiện" hình dáng của Internet - (Xem thêm các ứng dụng đưới đây. Mặc dù vậy, cũng nên
lưu ý rằng trong phân tích lưới, thì định nghĩa của khái niệm "lưới" có thể khác nhau và
thường được chỉ ra bằng một đồ thị đơn giản).

1.2 Phát biểu bài toán tìm đường đi ngắn nhất


trong lý thuyết đồ thị
Nếu đồ thị biểu diễn một mạng lưới giao thông, thì người ta không chỉ quan tâm tới việc có
tồn tại đường đi từ một đỉnh này tới đỉnh khác hay không, mà người ta còn quan tâm tới
con đường tối ưu nhất, ngắn nhất có thể.
Trong lý thuyết đồ thị, bài toán đường đi ngắn nhất giữa hai đỉnh cho trước là bài toán tìm
một đường đi giữa chúng sao cho tổng các trọng số của các cạnh tạo nên đường đi đó là
nhỏ nhất. Định nghĩa một cách hình thức, cho trước một đồ thị có trọng số G=(V,E,w)
(nghĩa là một tập đỉnh V, một tập cạnh E, và một hàm trọng số có giá trị thực w : E → R),
cho trước một đỉnh u thuộc V, tìm một đường đi P từ u tới một đỉnh v thuộc V sao cho:

nhỏ nhất trong tất cả các đường đi từ u tới v. Bài toán đường đi ngắn nhất giữa mọi cặp đỉnh là
một bài toán tương tự, trong đó ta phải tìm các đường đi ngắn nhất cho mọi cặp đỉnh u và v.

5
Các thuật toán thường được dùng để giải quyết những bài toán này là:
_Thuật toán Floyd Warshall đối với bài toán tìm đường đi ngắn nhất trong lý thuyết đồ thị
_ Đường đi ngắn nhất xuất phát từ 1 đỉnh,thuật toán Ford-bellman
_ Trường hợp ma trận không âm.Thuật toán Dijkstra

II.Ứng dụng của đại số tuyến tính để giải bài toán


“Tìm đường đi ngắn nhất”.
2.1 Đường đi ngắn nhất từ một đỉnh. Thuật toán
Ford-Bellman
Phần lớn các thuật toán tìm khoảng cách giữa hai đỉnh s và t được xây dựng nhờ kỹ thuật
tính toán mà ta có thể mô tả đại thể như sau: từ ma trận trọng số a[u,v], u,v ∈ V, ta tính cận
trên d[v] của khoảng cách từ s đến tất cả các đỉnh v ∈ V. Mỗi khi phát hiện
d[u] + a[u,v] < d[v] (1)
cận trên d[v] sẽ được làm tốt lên: d[v] + a[u,v].
Quá trình đó sẽ kết thúc khi nào chúng ta không làm tốt thêm được bất kỳ cận trên nào.
Khi đó, rõ ràng giá trị của mỗi d[v] sẽ cho khoảng cách từ đỉnh s đến đỉnh v. Khi thể hiện
kỹ thuật tính toán này trên máy tính, cận trên d[v] sẽ được gọi là nhãn của đỉnh v, còn việc
tính lại các cận này sẽ được gọi là thủ tục gán. Nhận thấy rằng để tính khoảng cách từ s đến
t, ở đây, ta phải tính khoảng cách từ s đến tất cả các đỉnh còn lại của đồ thị. Hiện nay vẫn
chưa biết thuật toán nào cho phép tìm đường đi ngắn nhất giữa hai đỉnh làm việc thực sự
hiệu quả hơn những thuật toán tìm đường đi ngắn nhất từ một đỉnh đến tất cả các đỉnh còn
lại.
Sơ đồ tính toán mà ta vừa mô tả còn chưa xác định, bởi vì còn phải chỉ ra thứ tự các đỉnh u
và vậy để kiểm tra điều kiện (1). Thứ tự chọn này có ảnh hưởng rất lớn đến hiệu quả của
thuật toán.
Bây giờ ta sẽ mô tả thuât toán Ford-Bellman tìm đường đi ngắn nhất từ đỉnh s đến tất cả
các đỉnh còn lại của đồ thị. Thuật toán làm việc trong trường hợp trọng số của các cung là
tuỳ ý, nhưng giả thiết rằng trong đồ thị không có chu trình âm.
 Thuật toán Ford-Bellman:
Thuật toán Bellman-Ford là một trong những thuật toán dùng để tìm đường đi ngắn nhất
(chỉ áp dụng cho đồ thị có hướng) từ một điểm tới một điểm nào đó, và mở rộng ra là tìm
đường đi ngắn nhất từ 1 điểm tới mọi điểm còn lại của đồ thị.

Ý tưởng thuật toán Bellman-Ford:

 Ta thực hiện duyệt V lần, với V là số đỉnh của đồ thị.


 Với mỗi lần duyệt, ta tìm tất cả các cạnh mà đường đi qua cạnh đó sẽ rút ngắn
đường đi ngắn nhất từ đỉnh gốc tới một đỉnh khác.
 Ở lần duyệt thứ V, nếu còn bất kỳ cạnh nào có thể rút ngắn đường đi, điều đó
chứng tỏ đồ thị có chu trình âm, và ta kết thúc thuật toán.

6
Tính đúng đắn của ý tưởng này được chứng minh quy nạp.

Ta có khẳng định sau: Ở thời điểm mà ta đã đi qua i lần duyệt thì những mệnh đề sau được
coi là đúng:

 Nếu khoảng cách từ điểm gốc tới 1 điểm u không phải là +INF, thì khoảng cách đó
đúng bằng độ dài 1 đường đi nào đó từ gốc tới u.
 Với đỉnh u đó, nếu tồn tại đường đi từ gốc tới u mà đi qua tối đa i cạnh, thì độ dài
đường đi ngắn nhất sẽ không vượt quá độ dài đường đi kể trên.
Quá trình chứng minh quy nạp:

 Trường hợp cơ bản: i = 0. Ta chưa duyệt qua lần nào, nên cả 2 điều đều hiển nhiên
đúng (Đường đi ngắn nhất tới đỉnh gốc bằng 0, hiển nhiên vì điểm xuất phát và đích
trùng nhau, còn đường đi ngắn nhất tới các đỉnh khác bằng +INF vì ta không có bất
kỳ đường đi nào được tìm thấy để tới chúng).
 Trường hợp quy nạp:
 Mệnh đề 1 rõ ràng đúng. Ta tưởng tượng, nếu trong quá trình duyệt cạnh,
xuất hiện cạnh (u, v) với trọng số w có thể tối ưu hóa đường đi ngắn nhất của
v được, thì đương nhiên ta cập nhật độ dài đó: dist[v] = dist[u] + w. Rõ ràng
dist[v] là độ dài một đường đi từ gốc tới v, hay chính xác hơn là đường đi từ
gốc tới u, rồi đi qua cạnh (u, v) tới v.
 Với mệnh đề 2, ta tiếp tục sử dụng giả sử về cạnh (u, v) trọng số w như ở
trên. Với giả thuyết quy nạp, dist[u] sẽ không vượt quá độ dài bất kỳ đường đi
từ gốc tới u mà đi qua tối đa (i-1) cạnh. Do đó, cộng đồng thời 2 vế, ta sẽ có
(dist[u] + w_min) không vượt quá độ dài bất kỳ đường đi nào từ gốc tới u với
lượng cạnh không quá (i-1), rồi đi qua cạnh (u, v). Hay nói cách khác, không
có đường đi nào từ gốc tới v với lượng cạnh không quá i (khớp với giả thuyết
quy nạp).
Ta lại nhận thấy, đường đi ngắn nhất hiển nhiên không có chu trình (nên nhớ rằng ta không
xét chu trình âm, vì nó sẽ khiến đường đi kéo dài vô tận và độ dài tiến tới -INF, còn nếu
chu trình không âm thì việc đi lặp lại chu trình vô nghĩa), vậy nên một đường đi giữa 2
đỉnh sẽ chỉ có tối đa V-1 cạnh.
Vậy nên, thuật toán Bellman-Ford sẽ chỉ cần V lần duyệt cạnh – lần duyệt thứ V sẽ là lần
duyệt để kiểm tra chu trình âm: Nếu có đường đi được cập nhật mới ở lần duyệt này, hẳn là
đã có 1 đường đi tối ưu nào đó có V cạnh – điều này là vô lý với đồ thị không có chu trình
âm.

Ta xét ví dụ với đồ thị có hướng sau (giả định các đường đi là một chiều, chỉ đi từ đỉnh có
số thứ tự thấp hơn tới đỉnh có số thứ tự cao hơn, số có màu đỏ cạnh mỗi đỉnh là độ dài
đường đi ngắn nhất từ gốc tới đỉnh đó, và đỉnh gốc là đỉnh 1):

7
Thực hiện lần duyệt đầu tiên, ta cập nhật được đường đi ngắn nhất thông qua các cạnh (1,
2); (1, 3); (1, 4):

Tương tự với lần duyệt thứ 2, cạnh (2, 5) và (3, 4) là các cạnh tối ưu:

Với lần duyệt thứ 3, chỉ có cạnh (4, 5) cải tiến đường đi tối ưu:

Tới lần duyệt thứ 4, ta thấy không còn cạnh nào có thể tối ưu hóa bất kỳ đường đi ngắn
nhất nào nữa. Tới đây, ta hoàn toàn có thể dừng duyệt (vì chắc chắn việc không còn cạnh
có thể tối ưu cũng đồng nghĩa với việc không có chu trình âm trong đồ thị).

Độ phức tạp của thuật toán sẽ là O(VE) – khá lớn, nên nếu đồ thị không có cạnh có trọng
số âm, thuật toán Dijkstra sẽ là một hướng tiếp cận hữu dụng hơn.
 

8
2.2 Trường hợp ma trận không âm.Thuật toán
Dijkstra
Thuật toán Dijkstra là một trong những thuật toán cơ bản dùng để tìm đường đi ngắn nhất
từ một điểm tới một điểm nào đó, và mở rộng ra là tìm đường đi ngắn nhất từ 1 điểm tới
mọi điểm còn lại của đồ thị, với điều kiện các trọng số của đồ thị đó không âm.

Trước hết, về khâu tổ chức dữ liệu: ta xây dựng một mảng 1D chứa đường đi ngắn nhất
giữa đỉnh đang xét tới tất cả các đỉnh còn lại, giá trị ngầm định bằng +INF.

Nói tóm lại, độ phức tạp không gian của thuật toán sẽ là O(V).
Ta xét đồ thị vô hướng sau (số màu đỏ là đường đi ngắn nhất xuất phát từ đỉnh 1 tới đỉnh
được xét):

Quá trình thực hiện thuật toán Dijkstra sẽ diễn ra như sau:

 Chọn một điểm bất kỳ chưa được duyệt và có đường đi ngắn nhất từ điểm gốc tới
nó là nhỏ nhất.
 Từ điểm đó, loang đường đi ra tất cả các đỉnh kề cận, và cập nhật lại đường đi ngắn
nhất tới các đỉnh đó nếu đường đi mới tối ưu hơn.
 Nếu còn điểm chưa được duyệt (hoặc chưa tìm được điểm đích, tùy yêu cầu đề bài),
ta trở lại bước 1.
Ta sẽ phân tích tuần tự theo nền tảng ý tưởng này:

Đầu tiên, ta xét đỉnh 1 (vì đường đi ngắn nhất từ 1 tới 1 hiển nhiên có độ dài 0).

Sau quá trình cập nhật, ta có các giá trị đường đi ngắn nhất mới:

Tiếp theo, ta duyệt đỉnh 5 (đường đi ngắn nhất từ 1 tới 5 có độ dài 1).

9
Sau cập nhật, ta thu được các giá trị mới:

Tiếp theo, ta duyệt đỉnh 4 (đường đi ngắn nhất từ 1 tới 4 có độ dài 3).

Sau cập nhật, ta thu được các giá trị mới:

Cứ tiếp tục như vậy cho tới khi duyệt hết đỉnh, ta sẽ thu được các giá trị hoàn chỉnh:

Sở dĩ phương pháp tham lam này đúng bởi, ta đã ngầm định đặt ra điều kiện trước: các
trọng số của các cạnh phải là các số không âm. Do đó, việc duyệt liên tục từ các đỉnh có độ
dài đường đi ngắn nhất là cực tiểu sẽ luôn được đảm bảo tính chính xác: ta không thể xuất
phát từ bất kỳ đỉnh nào khác qua một giá trị trung gian mà thu được đường đi nhỏ nhất từ
đỉnh gốc tới đỉnh cực tiểu ta đang xét thậm chí còn nhỏ hơn nữa được.

10
Ví dụ  Tìm đường đi ngắn nhất từ 1 đến các đỉnh còn lại của đồ thị ở hình dưới đây

Hình: Minh họa thuật toán Dijkstra.

Kết quả tính toán theo thuật toán được trình bày theo bảng dưới đây. Qui ước viết
hai thành phần của nhãn theo thứ tự: d[v]. Đỉnh được đánh dấu * là đỉnh được chọn
để cố định nhãn ở bước lặp đang xét, nhãn của nó không biến đổi ở các bước tiếp
theo, vì thế ta đánh dấu -.
Bước lặp Đỉnh 1 Đỉnh 2 Đỉnh 3 Đỉnh 4 Đỉnh 5 Đỉnh 6

Khởi tạo 0,1 1,1* ∞ ,1 ∞ ,1 ∞ ,1 ∞ ,1

1 - - 6,2 3,2* ∞ ,1 8,2

2 - - 4,4* - 7,4 8,2

3 - -   - 7,4 5,3*

4 - -   - 6,6* -

2.3 Thuật toán Floyd Warshall đối với bài toán


tìm đường đi ngắn nhất trong lý thuyết đồ thị
Trong những bài toán đường đi ngắn nhất mà chúng ta cần thông tin về đường đi giữa
nhiều cặp đỉnh, ta có xu hướng là sẽ tính toán đường đi ngắn nhất giữa mọi cặp đỉnh.

Thuật toán Floyd-Warshall là một thuật toán phù hợp để thực hiện tác vụ này

Floyd hay còn gọi là Floyd-Warshall là thuật toán để tìm đường đi ngắn nhất giữa mọi cặp
đỉnh. Floyd hoạt động được trên đồ thị có hướng, có thể có trọng số âm, tuy nhiên không
có chu trình âm. Ngoài ra, Floyd còn có thể được dùng để phát hiện chu trình âm.

Trước hết, ta cần phải nắm về khâu tổ chức dữ liệu: đường đi ngắn nhất giữa 2 đỉnh bất kỳ sẽ
được lưu trong một mảng 2 chiều, ngầm định sẽ có giá trị là +INF nếu không có đường nối
trực tiếp giữa chúng, hoặc nếu có đường nối thì giá trị ban đầu sẽ là trọng số của đường nối đó.
11
Các tính toán sau này sẽ là so sánh giữa đường đi ngắn nhất hiện tại với một đường đi trung
gian (giả sử, với 2 đỉnh A và B, ta so sánh đường đi ngắn nhất hiện thời giữa 2 đỉnh này với
tổng độ dài đường đi ngắn nhất từ A và từ B tới 1 đỉnh C trung gian nào đó)

Ta xét đồ thị vô hướng sau: 

Từ quy tắc trên, mảng 2D chứa đường đi ngắn nhất ban đầu sẽ được khởi tạo như sau:

Từ đây, quá trình thực hiện thuật toán Floyd-Warshall sẽ diễn ra như sau:

 Chọn lần lượt từng đỉnh của đồ thị làm đỉnh trung gian (ta quy ước là C).
 Chọn một cặp 2 đỉnh phân biệt và không trùng với đỉnh trung gian (ta quy ước lần
lượt là A và B).
 Thực hiện so sánh như ở trên: đường đi ngắn nhất giữa A và B sẽ bằng giá trị nhỏ
nhất của:
 Giá trị đường đi ngắn nhất hiện thời giữa A và B.
 Tổng của giá trị đường đi ngắn nhất hiện thời giữa A và C, và đường đi ngắn nhất
hiện thời giữa B và C.
Ta sẽ phân tích tuần tự theo nền tảng ý tưởng này:

Đầu tiên, C = 1. Nhờ đỉnh 1 làm trung gian, ta thấy xuất hiện đường đi từ đỉnh 2 tới đỉnh 4
(độ dài 14), và từ đỉnh 2 tới đỉnh 5 (độ dài 6).

Đường đi trung gian qua đỉnh 1 để đi từ đỉnh 4 tới đỉnh 5 không tối ưu về chiều dài (9 + 1
> 2) nên ta không cập nhật lại đường đi ngắn nhất giữa 2 đỉnh 4 và 5

Mảng 2D lúc này trở thành:

12
Tiếp theo, ta duyệt tới C = 2.

Đường đi từ 3 tới 1 (độ dài 7), từ 3 tới 5 (độ dài 8) được hình thành.

Đường đi từ 3 tới 4 không cập nhật độ dài (7 < 2 + 5 + 9).

Mảng 2D lúc này trở thành:

Cứ tiếp tục lựa chọn C như vậy cho tới hết, ta sẽ thu được mảng 2D hoàn chỉnh:

Giả sử, qua mảng này, ta thấy đường đi ngắn nhất từ đỉnh 2 tới đỉnh 4 có độ dài 8. Dựa theo đồ
thị thì nó là đoạn đường sau: 

13
III. Chương trình Mathlab để giải bài toán “ Tìm
đường đi ngắn nhất”
 Code matlab áp dụng thuật toán Floyd:
function timduongdingannhat
A = input('nhap ma tran ke tu do thi, A=');
n = size(A, 1);
for k=1:n

Aik = repmat(A(:,k), 1, n);


Akj = repmat(A(k,:), n, 1);
A = min(A, Aik+Akj);
end
disp('ma tran ke sau khi xu li bang thuat toan Floyd');
disp(A);
disp('nhap 2 diem de tim duong di ngan nhat');
x=input('diem dau:');
y=input('diem cuoi:');
disp('do dai cua duong di ngan nhat la:');
disp(A(x,y));
end

Ví dụ: lấy bài ví dụ trên mục 2.3


Kết quả:

14
 Code matlab áp dụng hàm có sẵn:
function timduongdingannhat
s = input('nhap cac diem dau:');
t = input('nhap cac diem den:');
weights = input('nhap do dai duong di t??ng ung theo do thi,d=');
G = digraph(s,t,weights);
plot(G,'EdgeLabel',G.Edges.Weight);
t=plot(G,'EdgeLabel',G.Edges.Weight);
disp('nhap 2 diem de tim duong di ngan nhat');
x = input('nhap diem dau:');
y = input('nhap diem cuoi:');
[duongdi, dodai] = shortestpath(G,x,y);
highlight(t,duongdi,'EdgeColor','r');
disp('thu tu duong di ngan nhat:');disp(duongdi);
disp('do dai cua duong di ngan nhat la:');disp(dodai);
end

Ví dụ: lấy bài ví dụ trên mục 2.3


Kết quả:

15
--------HẾT--------

16

You might also like