HỌC VIỆN KỸ THUẬT QUÂN SỰ
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO MÔN HỌC
TRÍ TUỆ NHÂN TẠO
Giáo viên hướng dẫn: Ngô Hữu Phúc
HÀ NỘI 3/2010
Báo cáo môn trí tuệ nhân tạo
I-Đề tài:
Mô tả không gian trạng thái bài toán người đưa thư(Travelling Saleman
Problem – PST) và dùng giải thuật Local Search để giải quyết.
II-Mô tả bài toán:
- Bài toán người đưa thư là một bài toán cổ điển, thuộc tối ưu rời rạc hay tổ
hợp. Đây là một minh họa điển hình cho lớp bài toán trong lý thuyết độ
phức tạp tính toán.
- Nội dung: Có một người giao hàng cần đi giao hàng tại n thành phố. Xuất
phát từ một thành phố nào đó, đi qua các thành phố khác để giao hàng và
trở về thành phố ban đầu. Mỗi thành phố chỉ đến một lần, khoảng cách từ
một thành phố đến các thành phố khác là xác định được. Hãy tìm một chu
trình (một đường đi khép kín thỏa mãn điều kiện trên) sao cho tổng độ dài
các cạnh là nhỏ nhất.
III-Giao diện chính của chương trình:
Chương trình được thiết kế trên Visual Basic 2005 sử dụng ngôn ngữ
VB.Net.
Bao gồm:
- Picturebox: để biểu diễn không gian trạng thái của bài toán
- Textbox: để nhập vào số thành phố
- Nút khởi tạo: khởi tạo các trọng số (khoảng cách giữa 2 thành phố)
- Nút Generate để vẽ không gian trạng thái của bài toàn dựa vào số thành
phố nhập vào.
- Combobox: chọn điểm (thành phố)xuất phát.
- Chạy: chạy thuật toán local search để tìm đường đi ngắn nhất cho bài
toán.
IV- Ví dụ:
- Số thành phố nhập vào là 5
- Khởi tạo trọng số (khoảng cách) giữa các thành phố như hình vẽ:
- Sau khi chạy chương trình với điểm xuất phát là thành phố 2 ta được kết
quả như sau:
-
- Đường đi ngắn nhất của ví dụ là đường màu đỏ và có tổng độ dài là 101.
Có thể thử thay đổi điểm xuất phát để thấy rằng: kết quả của bài toán có
thay đổi nhưng ít hoặc không đáng kể.
V- Thuật toán:
Thuật toán chính được sử dụng trong chương trình là Local Search. Theo
đó sau khi điểm xuất phát được xác định thì thuật toán sẽ tìm tại điểm đó có
những đường nào có thể đi tiếp và chọn ra đường đi ngắn nhất. Cho đến khi đi
hết tất cả các thành phố phải qua rồi quay lại điểm xuất phát, mỗi thành phố chỉ
đi qua một lần.
Hạn chế chính của thuật toán: đây là giải thuật mang tính local, không kèm
theo sự ước lượng và phán đoán. Do đó lời giải của bài toàn thường là không tối
ưu. Và thuật toán dễ rơi vào vòng lặp không thoát ra được.
Áp dụng vào bài toán người đưa thư:
- Khởi tạo số thành phố
- Khai báo 1 mảng 2 chiều a(i, j) để lưu khoảng cách giữa các thành phố với
i và j là số thành phố.
- Nhập dữ liệu (khoảng cách) cho mảng
- Chọn điểm xuất phát s
- Xét giá trị của mảng a(s, j):
• tìm min (a(s, j))
• Xác định j tại đó a(s,j) min
- J sẽ là thành phố được đi qua tiếp theo.
- Trước khi xét tiếp đỉnh J phải xóa đi giá trị a (s, j) và a (j, s) để đảm bảo sẽ
không quay lại thành phố vừa đi qua.
- Tiếp tục xét giá trị của mảng a(s, j) (với s = j) và lặp lại quá trình trên.
Nhưng lần này khi xóa thì sẽ xóa cả mảng a (s, j) và mảng a(j,s).
- TH1: Nếu trong quá trình xét mà xác định được điểm tiếp theo chính là
điểm xuất phát thì sẽ kiểm tra xem đã đi đủ số thành phố cần đi qua chưa.
Nếu chưa thì sẽ quay lại đỉnh vừa rồi và xét tiếp trừ điểm xuất phát ra.
Ngược lại nếu đã đủ số thành phố cần đi qua thì dừng thuật toán.
- TH2: Nếu điểm tiếp theo chỉ có còn điểm xuất phát mà số thành phố đi qua
chưa đủ thì đó là bài toán không có lời giải. Dừng thuật toán.
- TH3: Hoặc sau khi đến thành phố thứ n (không phải thành phố xuất phát)
mà không còn đường đi tiếp thì đấy cũng là bài toán không có lời giải.
Dừng thuật toán.
- Từ đầu thuật toán sẽ có 1 biến đếm để đếm độ dài quãng đường đã đi
qua.
VI – Code:
a. Nút khởi tạo:
- Số thành phố nhập vào nhỏ hơn 2 thì báo lỗi
If tp <= 2 Then
MsgBox("So thanh pho nhap vao phai lon hon 2")
Exit Sub
Else
- Gán giá trị cho các phần tử trong 2 mảng a(i,j) và a1(i,j)
For i = 1 To tp
For j = 1 To tp
a(i, j) = max
a1(i, j) = max
Next
Next
- Nhập khoảng cách giữa các thành phố vào nửa ma trận chéo trên của
a(i,j)
For i = 1 To tp
For j = i + 1 To tp
a(i, j) = InputBox("Nhap khoang cach tu
thanh pho " & i & " den thanh pho " & j, "", max)
a(j, i) = a(i, j)
Next
Next
End If
b. Nút Generate:
- Tạo 1 mảng chứa các phần tử có giá trị random để gán cho các điểm
Randomize()
For i = 1 To (tp * 2)
random(i) = Int(Rnd() * 400) + 1
Next
- Tạo số point đúng bằng số thành phố nhập vào (mỗi point là một thành
phố):
• ứng với mỗi point sẽ là 1 vòng tròn và số thứ tự của point đó
Dim f As Integer = 1
Dim font As New Font("arial", 16)
For i = 1 To tp
point(i) = New Point(random(f), random(f + 1))
g.DrawEllipse(pen3, random(f) - 10, random(f +
1) - 10, 20, 20)
g.DrawString(Convert.ToString(i), font,
Brushes.BlueViolet, random(f) - 10, random(f + 1) - 10)
f += 2
Next
- Kiểm tra trong mảng a(i,j) nếu có giá trị khác max thì nối point i với point j
For i = 1 To tp
For j = i + 1 To tp
If (a(i, j) <> max) Then
g.DrawLine(pen, point(i), point(j))
End If
Next
Next
- Add tọa độ các point vào combobox (mỗi point sẽ là 1 phần tử của
combobox)
For i = 1 To tp
ComboBox1.Items.Add(point(i))
Next
c. Nút Chạy:
- Lấy chỉ số của phần tử mà combobox đang được chỉ định
Dim index As Integer = ComboBox1.SelectedIndex + 1
- Đổ giá trị trong mảng a(i,j) vào mảng a1(i,j) để lưu lại các giá trị khởi tạo
ban đầu
For i = 1 To tp
For j = 1 To tp
a1(i, j) = a(i, j)
a1(j, i) = a(j, i)
Next
Next
- Tìm đoạn đường ngắn nhất xuất phát từ điểm ban đầu
For i = 1 To tp
If (a1(index, i) < min) Then
min = a1(index, i)
End If
Next
dodai += min
For i = 1 To tp
If a1(index, i) = min Then
t = i
duongdi(2) = t
End If
Next
a1(index, t) = max
a1(t, index) = max
Dim dem As Integer = 1
- Tìm đoạn đường ngắn nhất từ điểm hiện tại đến các điểm tiếp theo
For j = 1 To tp - 1
min = max
For i = 1 To tp
If a1(t, i) < min Then
min = a1(t, i)
End If
Next
dodai += min
- TH1: không về được điểm xuất phát hoặc về được điểm xuất phát nhưng
không qua được tất cả các đỉnh
If min = max Then
MsgBox("Bai toan khong co loi giai")
Exit Sub
End If
t2 = t
For i = 1 To tp
If a1(t, i) = min Then
t = i
Exit For
End If
Next
If t = index Then
- TH2: tìm được điểm xuất phát sau khi đi hết các TP
If dem = tp - 1 Then
dem += 1
duongdi(j + 2) = i
Exit For
- TH3: Về điểm xuất phát nhưng chưa qua hết các TP. Quay lại đỉnh trước
đó và bỏ qua đỉnh xuất phát ở lần xét tiếp theo
Else
a1(index, t2) = max
a1(t2, index) = a1(index, t2)
t = t2
j -= 1
dodai -= min
Continue For
End If
Else
- Sau khi tìm được đỉnh đến tiếp theo thì xóa hết các thông tin của đỉnh
trước đấy trong mảng a1(i,j) để đảm bảo không bị quay lại.
dem += 1
duongdi(j + 2) = i
For i = 1 To tp
a1(t2, i) = max
a1(i, t2) = max
Next
Continue For
End If
Next
- Thông báo thứ tự các thành phố đã đi qua và tổng độ dài của đoạn đường
For i = 1 To tp
MsgBox(duongdi(i))
g.DrawLine(pen2, point(duongdi(i)),
point(duongdi(i + 1)))
Next
MsgBox("Tong do dai doan duong la " & dodai)
- Refresh lại combobox và picturebox khi chọn thành phố khác
dodai = 0
For i = 1 To tp
point(i) = New Point(random(f), random(f + 1))
g.DrawEllipse(pen3, random(f) - 10, random(f +
1) - 10, 20, 20)
g.DrawString(Convert.ToString(i), font,
Brushes.BlueViolet, random(f) - 10, random(f + 1) - 10)
f += 2
Next
For i = 1 To tp
For j = i + 1 To tp
If (a(i, j) <> max) Then
g.DrawLine(pen, point(i), point(j))
End If
Next
Next
VII- Nhận xét và đánh giá:
- Về thuật toán:Đối với tất cả những bài toán thuộc lớp PTS (có lời giải) thì
thuật toán local search luôn cho lời giải mặc dù lời giải không phải là tối
ưu. Tuy nhiên lời giải sẽ gần như không có đột biến và nếu rơi vào vòng
lặp hoặc đường cụt thì sẽ không thoát ra được. Chẳng hạn như bài toán
đang xét là có lời giải, nhưng vì tại 1 điểm, thuật toán chọn giá trị nhỏ nhất,
dẫn đến ngõ cụt thì bài toán đấy trở thành không có lời giải.
- Về chương trình:Do chương trình được viết trong thời gian ngắn và chỉ
mang tính chất mô phỏng thuật toán nên còn rất nhiều hạn chế về mặt lâp
trình.
Giao diện vẫn còn phức tạp.
Chương trình khi chạy tốn bộ nhớ
- Cuối cùng do còn thiếu kinh nghiệm về lập trình cũng như sự hạn chế về
mặt thuật toán nên chương trình chỉ có thể mô tả được một cách đơn giản
nhất của thuật toán. Mong thầy bỏ qua và tiếp tục hướng dẫn em.