Tải bản đầy đủ (.doc) (29 trang)

XÂY DỰNG CHƯƠNG TRÌNH SỬ DỤNG THUẬT TOÁN TKCT ĐỂ GIẢIBÀI TOÁN NGƯỜI DU LỊCH

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (451.9 KB, 29 trang )

Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI
VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG
*
BÀI TẬP LỚN
TRÍ TUỆ NHÂN TẠO
TÊN ĐỀ TÀI
XÂY DỰNG CHƯƠNG TRÌNH SỬ DỤNG THUẬT TOÁN TKCT* ĐỂ GIẢI
BÀI TOÁN NGƯỜI DU LỊCH
Học viên thực hiện: 1. Trần Thị Thùy Dương
2. Nguyễn Thị Thu Hằng
3. Nguyễn Thị Hồng
4. Nguyễn Văn Ninh
5. Hoàng Thị Minh Tâm
Lớp: Cao học 12ACNTT- HY
Giảng viên hướng dẫn: Ths. Nguyễn Thị Ngọc Bích
NĂM 2012
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
MỤC LỤC
I.TỔNG QUAN VỀ TRÍ TUỆ NHÂN TẠO 3
II.BÀI TOÁN NGƯỜI DU LỊCH 4
II.1 Phát biểu bài toán 4
2.1.1 Lịch sử bài toán TSP 5
2.1.2 Mô tả bài toán TSP 7
2.1.3 Phân loại bài toán 7
2.2 Các giải thuật giải bài toán người du lịch 8
2.2.1 Các giải thuật để tìm lời giải chính xác 8
2.2.2 Heuristic và các giải thuật xấp xỉ 9
2.2.3 Giải thuật Heuristics tìm đường đi có giá nhỏ nhất với tri thức bổ sung
TKCT* 11
2.3 Phân ch thiết kế giải thuật Heuris&cs 'm đường đi có giá nhỏ nhất với tri thức bổ sung TKCT*


11
2.3.1 Chu trình Hammilton 11
12
2.3.2 Giải thuật Heuristics tìm đường đi có giá nhỏ nhất với tri thức bổ sung
TKCT* 12
2.4 Mã nguồn 13
2.5 Kết quả thực hiện 27
2.6 Đánh giá độ phức tạp của thuật toán 27
2.7 Ý nghĩa 28
III.KẾT LUẬN 29
2
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
I. TỔNG QUAN VỀ TRÍ TUỆ NHÂN TẠO
Trí Tuệ Nhân Tạo (Artificial Intelligence) là một ngành mới, nhưng phát triển
rất mạnh mẽ và đem lại nhiều kết quả to lớn. Con người thường tự cho mình là sinh
vật thông minh vì khả năng trí tuệ đóng vai trò quan trong trong cuộc sống. Trong văn
học cũng đã từng có những câu chuyện đề cao về trí thông minh của con người.
Trí Tuệ Nhân Tạo chỉ mới hình thành từ năm 1956. Tuy nhiên, việc nghiên cứu
trí tuệ đã có từ lâu. Trên 2000 năm trước, các nhà triết học đã tìm hiểu về cách thức
nhìn nhận, học tập, nhớ và suy lý. Việc ra đời của máy tính điện tử vào những năm 50
của thế kỷ 20 đã sinh ra khuynh hướng đưa các lĩnh vực nghiên cứu trí tuệ về các vấn
đề lý thuyết và thực nghiệm trên máy.
Trí tuệ nhân tạo nghiên cứu về cách hành xử (hay cơ chế của các hành vi) thông
minh (intelligent behaviour) ở người và máy.
Trí tuệ nhân tạo được xây dựng lý thuyết đầy đủ về thông minh để có thể giải
thích được hoạt động thông minh của sinh vật và áp dụng được các hiểu biết vào các
máy móc nói chung, nhằm phục vụ cho con người. (Hay nói cách khác tạo chiếc máy
tính có khả năng nhận thức, suy luận và phản ứng).
Vai trò của trí tuệ nhân tạo:
Trí tuệ nhân tạo bao quát rất nhiều lĩnh vực nghiên cứu hẹp. Nó nghiên cứu từ

các lĩnh vực tổng quát như máy nhận biết, suy luận logic, đến các bài toán như chơi
cờ, chứng minh định lý. Thường thì các nhà khoa học ở các lĩnh vực khác tìm đến với
trí tuệ nhân tạo ở các kỹ thuật hệ thống hoá và tự động hoá các xử lý tri thức cũng như
các phương pháp thuộc lĩnh vực mang tính người.
Trí tuệ nhân tạo nghiên cứu kỹ thuật làm cho máy tính có thể “suy nghĩ một
cách thông minh” và mô phỏng quá trình suy nghĩ của con người khi đưa ra những
quyết định, lời giải. Trên cơ sở đó, thiết kế các chương trình cho máy tính để giải
quyết bài toán.
Sự ra đời và phát triển của Trí tuệ nhân tạo đã tạo ra một bước nhảy vọt về chất
trong kỹ thuật và kỹ nghệ xử lý thông tin. Trí tuệ nhân tạo chính là cơ sở của công
nghệ xử lý thông tin mới, độc lập với công nghệ xử lý thông tin truyền thống dựa trên
văn bản giấy tờ. Điều này được thể hiện qua các mặt sau:
- Nhờ những công cụ hình thức hoá (các mô hinh logic ngôn ngữ, logic mờ, ),
các tri thức thủ tục và tri thức mô tả có thể biểu diễn được trong máy. Do vậy quá trình
giải bài toán được tiến hành hữu hiệu hơn.
3
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
- Mô hình logic ngôn ngữ đã mở rộng khả năng ứng dụng của máy tính trong
lĩnh vực đòi hỏi tri thức chuyên gia ở trình độ cao, rất khó như: y học, sinh học, địa lý,
tự động hóa.
- Một số phần mềm trí tuệ nhân tạo thể hiện tính thích nghi và tính mềm dẻo đối
với các lớp bài toán thuộc nhiều lĩnh vực khác nhau.
- Khi máy tính được trang bị các phần mềm trí tuệ nhân tạo ghép mạng sẽ cho
phép giải quyết những bài toán cỡ lớn và phân tán.
So sánh kỹ thuật lập trình truyền thống và kỹ thuật xử lý tri thức
trong TTNT
Truyền thống TTNT
Xử lý dữ liệu Xử lý tri thức
Xử lý theo các thuật toán Xử lý theo các thuật giải Heuristics
Xử lý tuần tự theo lô Xử lý theo chế độ tương tác cao (ngôn ngữ tự

nhiên, có giao tiếp với bên ngoài)
Không giải thích trong quá trình
thực hiện
Có thể giải thích hành vi hệ thống trong quá trình
thực hiện
Một số chuyên ngành (lĩnh vực ứng dụng) của trí tuệ nhân tạo:
- Các phương pháp tìm kiếm lời giải
- Hệ chuyên gia
- Xử lý ngôn ngữ tự nhiên
- Lý thuyết nhận dạng
- Lập kế hoạch và Người máy (Robot)
- Máy học
- Các mô hình thần kinh (Mạng Neuron và giải thuật di truyền)

Trong các lĩnh vực nghiên cứu của Trí Tuệ Nhân Tạo, chúng ta thường xuyên
phải đối đầu với các bài toán sử dụng tri thức, vì vậy ta phải có những kỹ thuật để giải
quyết các vấn đề (bài toán) đó bằng tri thức và bài toán người đi du lịch là một ví dụ.
II. BÀI TOÁN NGƯỜI DU LỊCH
II.1 Phát biểu bài toán
Bài toán người du lịch (Travelling Salesman problem (TSP)) là một bài toán
khá nổi tiếng trong lĩnh vực tối ưu tổ hợp được nghiên cứu trong lý thuyết khoa học
máy tính. Nội dung của nó khá đơn giản, nó được phát biểu như sau: Cho một danh
sách các thành phố và khoảng cách giữa chúng, nhiệm vụ là phải tìm đường đi ngắn
nhất có thể mà chỉ thăm mỗi thành phố đúng một lần.
4
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
Bài toán được lần đầu tiên đưa ra như một vấn đề toán học vào năm 1930 và là
một trong số những bài toán được nghiên cứu chuyên sâu trong lĩnh vực tổ hợp thời
đó. Nó được sử dụng như một sự đánh giá cho nhiều phương thức tối ưu khác nhau.
Thậm chí bài toán là thuộc lớp NP khó, một lượng rất lớn các heuristic và phương thức

tìm kiếm cụ thể đã được biết đến vì vậy một vài trường hợp của bài toán với khoảng
chục nghìn thành phố đã được giải quyết.
TSP có một vài ứng dụng thậm chí trong dạng thức nguyên thuỷ của nó như lập
kế hoạch, logistic, và sản xuất các microchip. Thay đổi đi chút ít nó xuất hiện như một
bài toán con trong rất nhiều lĩnh vực như việc phân tích gen trong sinh học. Trong
những ứng dụng này, khái niệm thành phố có thể thay đổi thành khách hàng, các điểm
hàn trên bảng mạch, các mảnh DNA trong gen, và khái niệm khoảng cách có thể biểu
diễn bởi thời gian du lịch hay giá thành , hay giống như sự so sánh giữa các mảnh
DNA với nhau. Trong nhiều ứng dụng, các hạn chế truyền thống như giới hạn tài
nguyên hay giới hạn thời gian thậm chí còn làm cho bài toán trở nên khó hơn.
Trong lý thuyết của độ phức tạp tính toán, phiên bản quyết định của bài toán
TSP thuộc lớp NP-complete. Vì vậy không có giải thuật hiệu quả nào cho việc giải bài
toán TSP. Hay nói cách khác, giống như thời gian chạy tồi nhất cho bất ký giải thuật
nào cho bài toán TSP tăng theo hàm mũ với số lượng thành phố, vì vậy thậm chí nhiều
trường hợp với vài trăm thành phố cũng đã mất vài năm CPU để giải một cách chính
xác.
2.1.1 Lịch sử bài toán TSP
Nguồn gốc của bài toán người du lịch đến nay vẫn chưa rõ ràng. Một cuốn sách
cho người du lịch từ năm 1832 đã đề cập tới vấn đề và bao gồm vài ví dụ về các đường
đi từ đức qua Thụy sỹ nhưng không chứa đựng ý nghĩa toán học nào
Vấn đề toán học liên quan tới bài toán người du lịch đã được nhắc đến trong
những năm 1800 bởi nhà toán học ireland W. R. Hamilton và nhà toán học người Anh
Thomas Kirkman. Trò chơi Icosian Game của Hamilton là một trò đố vui dựa trên cơ
sở tìm chu trình Hamilton. Dạng tổng quát của bài toán TSP được nghiên cứ bởi các
nhà toán học suốt những năm 1930 ở đại học Harvard, đáng chú ý là Karl Menger
người đã định nghĩa bài toán, xem xét giải thuật brute-force và quan sát thấy tính
không tối ưu của heuristic dựa trên láng giếng gần nhất.
Bài toán người du lịch, tìm đường đi ngắn nhất cho
người thương nhân (salesman), hay còn gọi là người chào
hàng xuất phát từ một thành phố, đi qua lần lượt tất cả các

thành phố duy nhất một lần và quay về thành phố ban đầu
với chi phí rẻ nhất. Nó nhanh chóng trở thành bài toán khó
thách thức toàn thế giới bởi độ phức tạp thuật toán tăng
theo hàm số mũ (trong chuyên ngành thuật toán người ta
còn gọi chúng là những bài toán NP-khó). Người ta bắt đầu thử và công bố các kết quả
5
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
giải bài toán này trên máy tính từ năm 1954 (49 đỉnh), cho đến năm 2004 bài toán giải
được với số đỉnh lên tới 24.978, và dự báo sẽ còn tiếp tục tăng cao nữa. Bài toán có thể
phát biểu dưới ngôn ngữ đồ thị như sau :
Cho đồ thị n đỉnh đầy đủ và có trọng số G = (V-tập đỉnh, E-tập cạnh) có hoặc vô
hướng. Tìm chu trình Halmilton:
có tổng trọng số
là nhỏ nhất.
Hassler Whitney ở đại học Princeton University là ngừời đầu tiên đặt tên người
du lịch cho bài toán không lâu sau đó.
Trong những năm 1950 và 1960 , bài toán trở nên ngày càng phổ biến trong khoa
học ở châu Âu và Mỹ. Những đóng góp đáng chú ý được kể đến như George Dantzig,
Delbert Ray Fulkerson và Selmer M. Johnson tại RAND Corporation ở Santa Monica,
những người đã trình bày bài toán như bài toán số nguyên tuyến tính và phát triển
phương thức cắt cho lời giải của nó. Với những phương thức mới này họ đã giải được
một thí dụ của bài toán với 49 thành phố để xây dựng một cách tối ưu và chứng minh
rằng không còn đường đi nào ngắn hơn nữa. Trong những thập kỷ tiếp theo, bài toán
được nghiên cứu bởi rất nhiều nhà nghiên cứ từ toán học , khoa học máy tính , hóa học
,vật lý và những khoa học khác.
Richard M. Karp năm 1972 chỉ ra rằng bài toán chu trình Hamiltonian thuộc lớp
NP-complete, và qua đó chỉ ra tính NP khó (NP-hardness ) của bài toán TSP. Điều này
giải thích một cách khoa học cho độ phức tạp tính toán của việc tìm lời giải tối ưu cho
bài toán .
Nhiều thành tựu đã đạt được trong suốt những năm cuối thập kỷ 1970 và 1980,

khi Grötschel, Padberg, Rinaldi và những người khác cố gắng giải một cách chính xác
một thể hiện của bài toán với 2392 thành phố, sử dụng phương thức cắt và branch-and-
bound.
Trong những năm 1990 Applegate, Bixby, Chvátal, và Cook đã phát triển chương
trình Concorde mà đã được sử dụng nhiều trong việc giải các bài toán TSP cho đến
nay. Gerhard Reinelt đã công bố thư viện TSPLIB vào năm 1991, đó là một tập các
thể hiện của bài toán TSP với nhiều độ khó khác nhau, và đã được sử dụng bởi nhiều
nhóm nghiên cứu khác nhau để so sánh kết quả. Năm 2005, Cook và những người
6
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
khác đã tính được độ dài tối ưu cho chu trình với thể hiện của bài toán TSP lên tới
33,810 thành phố , được lấy ra từ bài toán xây dựng layout cho microchip, cho tới nay
vẫn là thể hiện lớn nhất trong các thể hiện ở TSPLIB. Nhiều thể hiện khác với hàng
triệu thành phố, lời giải tìm được có thể chứng minh nằm sai khác 1% so với lời giải
tối ưu.
2.1.2 Mô tả bài toán TSP
TSP có thể được mô hình như một đồ thị , các đỉnh của
đồ thị tương ứng với các thành phố và các cạnh thì
tương ứng với đường nối giữa các thành phố, chiều dài
của một cạnh tương ứng với khoảng cách giữa 2 thành
phố. Một đường đi trong bài toán TSP là một chu trình
Hamilton trên đồ thị và một lời giải tối ưu của bài toán
là chu trình Hamilton ngắn nhất.
Thường thì đồ thị là đồ thị đầy đủ , vì vậy mọi cặp cạnh đều được nối bởi các
cạnh. Đây là bước đơn giản hóa bài toán vì việc tìm chu trình Hamilton trong một đồ
thị đầy đủ là dễ. Các bài toán mà không phải 2 thành phố nào cũng được nối với nhau
có thể được chuyển đổi thành đồ thị đầy đủ bằng cách thêm những cạnh có độ dài lớn
giữa cách thành phố này, những cạnh sẽ không xuất hiện trong chu trình tối ưu.
2.1.3 Phân loại bài toán
 Đối xứng và bất đối xứng

Trong bài toán đối xứng khoảng cách giữa các thành phố là như nhau theo hai hướng,
vì vậy đồ thị biểu diễn là đồ thị vô hướng. Sự đối xứng này làm giảm một nửa số lời
giải có thể.
Trong bài toán bất đối xứng, khoảng cách từ thành phố này đến thành phố khác không
nhất thiết phải bằng khoảng cách theo hướng ngược lại, thậm chí co thể không có kết
nối theo chiều ngược lại. Vì vậy graph biểu diễn bài toán bất đối xứng là đồ thị có
hướng. Lấy ví dụ mô hình đường một chiều trong giao thông chẳng hạn.
 Với khoảng cách là metric
Trong bài toán metric TSP khoảng cách giữa các thành phố phải thỏa mãn điều kiện
của bất đẳng thức tam giác. Điều này có thể phát biểu rằng đường nối trực tiếp từ A
đến B không bao giờ dài hơn đường đi từ A tới B mà qua C trung gian
Những chiều dài cạnh này định nghĩa một metric trong tập các đỉnh . Khi các thành
phố được xem như những điểm trên tấm hình, nhiều hàm khoảng cách tự nhiên là các
metric ví dụ như :
7
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
• Trong bài toán Euclidian TSP khoảng cách giữa 2 thành phố là khoảng cách
Euclide giữa hai điểm tương ứng.
• Trong bài toán Rectilinear TSP khoảng cách giữa 2 thành phố là tổng hai tọa độ
x và y của chúng. Metric này thường được gọi là khoảng cách Manhattan hay
city-block metric.
• Trong maximum metric, khoảng cách giữa 2 thành phố là max của độ chênh
lêch tọa độ x và y của chúng.
Hai metric cuối xuất hiện trong việc định hướng một máy mà đào tập các hố trong
mạch in. Manhattan metric tương ứng tới máy căn chỉnh tọa độ thứ nhất rồi tới tọa độ
kia, vì vậy thời gian di chuyển tới một điểm mới là tống cả 2 hướng di chuyển.
Maximum metric tương ứng với mày mà chỉnh cả 2 tọa độ cùng 1 lúc vì vậy thời gian
để di chuyển tới một điểm mới quyết định bởi di chuyển dài hơn.
 Với khoảng cách không là metric
Khoảng cách không thỏa mãn bất đắng thức tam giác phát sinh trong nhiều bài toán

định tuyến. Ví dụ trong một kiểu vận tải , như du lịch bằng máy bay có thể nhanh hơn
mặc dù khoảng cách di chuyển là xa hơn.
2.2 Các giải thuật giải bài toán người du lịch
2.2.1 Các giải thuật để tìm lời giải chính xác
Lời giải trực tiếp nhất có thể là thử tất cả các hoán vị và xem hoán vị nào là tốt
nhất ( dùng brute-force). Thời gian chạy cho cách tiếp cận này là O(n!), vì vậy cách
tiếp cận này thậm chí không thể thực hiện với chỉ 20 thành phố. Một trong số những
ứng dụng mới đây nhất của quy hoạch động là giải thuật có độ phức tạp O(n
2
2
n
) và
yêu cầu không gian bộ nhớ là hàm mũ.
Cải thiện tốc độ cho cách giải thuật trên là hầu như không thể. Ví dụ, thậm chí là rất
khó tìm một giải thuật chính xác cho bài toán TSP chạy trong độ phức tạp O(1.9999
n
)
.
Những cách tiếp cận khác bao gồm:
• Rất nhiều giải thuật branch-and-bound, có thể sử dụng để giải các bài toán TSP
với khoảng 40-60 thành phố.
• Các giải thuật cải thiện dần dần sử dụng kỹ thuật ghi nhớ lại của linear
programming. Có thể làm việc tốt cho khoảng 200 thành phố.
• Thực hiện branch-and-bound và cut cho các bài toán cụ thể , đây là phương
thức sử dụng để giải quyết các bài toán với số lượng lớn thành phố. Cách tiếp
cận này đang giữ kỷ lục hiện tại giải quyết được bài toán TSP với 85,900 thành
phố.
8
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
Lời giải chính xác cho bài toán với 15,112 thành phố ở đức từ TSPLIB đã được

tìm ra năm 2001 sử dụng phương thức lát cắt đề xuất bởi George Dantzig, Ray
Fulkerson, và Selmer Johnson vào năm 1954, dựa trên linear programming. Quá trình
tính toán đã được thực hiện trong mạng máy tính gồm 110 bộ vi xử lý tại đại học Rice
University và Princeton University. Tổng thời gian tính toán tương đương với
22.6 năm trong một máy đơn vi xử lý tốc độ 500 MHz. Vào tháng 5-2004, bài toán
người du lịch thăm tất cả 24,978 thành phố ở thụy điển đã được giải quyết : đoạn
đường ngắn nhất vào khoảng 72,500 kilomet đã được tìm thấy và đã được chứng minh
rằng không có đường đi nào ngắn hơn.
Vào tháng 3 năm 2005, bài toán người du lịch với 33,810 điểm trong 1 mạch in đã
được giải quyết sử dung công cụ Concorde TSP Solver: đoạn đường tối ưu dài
66,048,945 đơn vị đã được tìm thấy và đã được chứng minh không có đường đi nào
ngắn hơn tổng khối lượng tính toán mất khoảng 15.7 năm CPU (Cook et al. 2006).
Vào tháng 4 năm 2006 một bài toán với 85,900 điểm cũng đã được giải quyết bởi
Concorde TSP Solver, và mất khoảng 136 năm CPU .
2.2.2 Heuristic và các giải thuật xấp xỉ
Rất nhiều heuristics và giải thuật xấp xỉ, có thể đưa ra nhanh chóng lời giải tốt đã
được đề xuất. Các phương thức hiện đại có thể tìm lời giải cho bài toán cực lớn (hàng
triệu thành phố) trong khoảng thời gian chấp nhận được với lời giải xấp xỉ chỉ khác 2-
3% so với lời giải tối ưu.
Một vài kiểu heuristic đã được tìm ra.
 Heuristics xây dựng
Giải thuật láng giềng gần nhất nearest neighbour (NN) (hay còn gọi là giải
thuật tham lam greedy algorithm) để cho người du lịch chọn thành phố gần nhất chưa
thăm trong lần di chuyển tiếp theo. Giải thuật này nhanh chóng đưa ra một đường đi
ngắn và hiệu quả . Cho khoảng N thành phố phân bố ngẫu nhiêu trên mặt phẳng trung
bình giải thuật này đưa ra lời giải có chiều dài xấp xỉ 1.25 * lần chiều dài của đường
đi tối ưu.
Tuy nhiên, có nhiều cách sắp xếp đặc biệt các thành phố làm cho giải thuật NN
đưa ra đường đi tồi tệ nhất (Gutin, Yeo, and Zverovich, 2002). Điều này đúng cho cả
bài toán TSP đối xứng và bất đối xứng (Gutin and Yeo, 2007).

Gần đây một heuristic mới được đưa ra ,Match Twice and Stitch (MTS)
(Kahng, Reda 2004. MTS đã cho thấy tính hiệu quả hơn hẳn so với những heuristic
xây dựng hiện tại . MTS thực hiện hai lần khớp tuần tự , mà lần khớp thứ 2 được thực
hiện sau khi xóa tất cả các cạnh của lần khớp thứ nhất, để đưa ra tập tất cả các chu
trình. Sau đó chu trình được đóng lại để đưa ra đường đi cuối cùng
 Cải tiến từng bước
• Chuyển cặp, hay heuristic Lin-Kernighan.
9
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
Kỹ thuật chuyển cặp hay '2-opt' bao gồm việc lặp lại việc xóa 2 cạnh và thay chúng
bằng hai cạnh khác nối đoạn tạo bởi cạnh bị xóa tạo thành đường di ngắn hơn. Đây là
trường hợp đặc biệt của phương thức k-opt.
• k-opt heuristic
Lấy một đường đi và xóa k cạnh đôi một không có điểm chung. Xây đựng lại đường đi
từ những mảnh còn lại để không có hai mảnh đường đi nào lối với nhau (không nối hai
điểm đầu cuối của 2 mảnh với nhau sẽ tạo thành đường đi khép kín). Điều này làm đơn
giản hóabài toán TSP thành bài toán đơn giản hơn rất nhiều. Mỗi điểm đầu cuối có thể
được nối tới 2k − 2 điểm khác có thể: trong số 2k tổng số điểm đầu cuối có thể, trừ ra
hai điểm đầu cuối của mảnh đang xem xét . Bài toán đơn giản hóa 2k thành phố TSP
có thể giải sử dụng brute force để tìm tổ hợp tốt nhất của các mảnh ban đầu. Kỹ thuật
k-opt là trường hợp riêng của kỹ thuât V-opt hay variable-opt . Kỹ thuật phổ biến của
k-opt là 3-opt, được giới thiệu bởi Shen Lin của Bell Labs vào năm 1965. Có một
trường hợp đặc biệt của 3-opt khi mà cách cạnh là có thể không nhất thiết không có
điểm chung (hai trong số các cạnh kề với nhau). Trong thực tế, có thể đạt được những
phát triển đáng kể của kỹ thuật 2-opt không nhất thiết phải sử dụng 3-opt bằgn cách
giới hạn 3-changes thành trườn hợp riêng với hai cạnh xóa đi nối với nhau. Kỹ thuật
này được gọi là 2.5-opt nằm giữa 2-opt và 3-opt, hiểu theo cả 2 nghĩa của chất lượng
lời giải đạt được và thời gian để tìm được lời giải.
• V'-opt heuristic
Kỹ thuật variable-opt method giống như , nhưng là sự tông quát hóa của k-opt kỹ

thuật. Trong khi kỹ thuật k-opt xóa đi một số lựong cố định (k) cạnh từ đường đi ban
đầu kỹ thuật variable-opt không xóa đi một số lượng cạnh cố định. Thay vì vậy nó
phát triển tập này khi quá trình tìm kiếm tiếp tục. Phương thức nổi tiếng trong gia đình
này là phương thức Lin-Kernighan . Shen Lin và Brian Kernighan lần đầu tiên đưa ra
phương thức của họ năm 1972 và nó là heuris tic đáng tin cậy nhát cho việc giải bài
toán người du lịch trong suốt hai thập kỷ . Những kỹ thuật tiên tiến hơn được phát
triển tại Bell Labs cuối những năm 1980 bởi David Johnson và đội nghiên cứu của
ông. Những phương thức này , đôi khi được gọi là Lin-Kernighan-Johnson xây dựng
trên phương thức Lin-Kernighan , thêm ý tưởng từ tabu search và evolutionary
computing. Kỹ thuật cơ sở Lin-Kernighan technique mang lại kết quả được đảm bảo ít
nhất là bằn so với 3-opt. Phương thức Lin-Kernighan-Johnson tính một đường đi Lin-
Kernighan , và sau đó xáo trộn đường đi bằng cách đột biến (xóa ít nhất 4 cạnh và nối
lại đường đi bằng cách khác , sau đó thực v-opt trên đường đi mới). Quá trình đột biến
thường đủ để di chuyển đường đi ra khỏi cục bộ địa phương (local minimum). Kỹ
thuật V-opt được xem như một trong số những heuristic mạnh cho bài toán và có thể
giải quyết các trường hợp đặc biệt, như bài toán chu trình Hamilton và những bài toán
TSP không phải metric mà những heuristic khác không giải quyết được.
10
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
2.2.3 Giải thuật Heuristics tìm đường đi có giá nhỏ nhất với tri thức bổ sung
TKCT*
Thủ tục TKCT là giải thuật tìm kiếm đường đi tối ưu khi chỉ xét tới các thông
tin về đỉnh (toán tử B), các cung và giá thành của chúng (c: A→R
+
). Tuy vậy, giải
thuật này không thể áp dụng được khi bài toán trở nên phức tạp do đòi hỏi phải tháo
một số lượng lớn các nút. Đối với nhiều bài toán việc tìm kiếm đường đi tối ưu sẽ
được định hướng tập trung hơn xung quanh đường đi tốt nhất nếu sử dụng các hướng
tập trung hơn xung quanh đường đi tốt nhất nếu sử dụng các thông tin đặc tả về bài
toán. Theo định nghĩa các thông tin này gọi là các heuristics.

Các kỹ thuật sử dụng heuristtics gọi là các mẹo giải.
Thuật toán này tìm một đường đi từ một đỉnh khởi đầu tới một đỉnh đích cho
trước hoặc tới một đỉnh thỏa mãn một điều kiện đích mà theo bài toán này thì đỉnh
đích là đỉnh khởi đầu sau khi đi qua tất các đỉnh trong đồ thị. Thuật toán sử dụng một
"đánh giá heuristic" để xếp loại từng đỉnh theo ước lượng về tuyến đường tốt nhất đi
qua đỉnh đó. Thuật toán này duyệt các đỉnh theo thứ tự của đánh giá heuristic này.
Để biết những tuyến đường nào có khả năng sẽ dẫn tới đích, TKCT* sử dụng
"đánh giá heuristic" về khoảng cách từ điểm bất kỳ cho trước tới đích. Trong trường
hợp tìm đường đi, đánh giá này có thể là khoảng cách đường chim bay - một đánh giá
xấp xỉ, thường dùng cho khoảng cách của đường giao thông.
Điểm khác biệt của TKCT* đối với tìm kiếm theo lựa chọn tốt nhất là nó còn
tính đến khoảng cách đã đi qua. Điều đó làm cho TKCT* "đầy đủ" và "tối ưu", nghĩa
là, TKCT* sẽ luôn luôn tìm thấy đường đi ngắn nhất nếu tồn tại một đường đi như thế.
TKCT* không đảm bảo sẽ chạy nhanh hơn các thuật toán tìm kiếm đơn giản hơn.
Trong một môi trường dạng mê cung, cách duy nhất để đến đích có thể là trước hết
phải đi về phía xa đích và cuối cùng mới quay lại. Trong trường hợp đó, việc thử các
nút theo thứ tự "gần đích hơn thì được thử trước" có thể gây tốn thời gian.
2.3 Phân tích thiết kế giải thuật Heuristics tìm đường đi có giá nhỏ nhất với
tri thức bổ sung TKCT*
2.3.1 Chu trình Hammilton
Trong toán học, ngành lý thuyết đồ thị, một đường đi Hamilton là một đường đi
trong đồ thị vô hướng đi qua tất cả các đỉnh của đồ thị, mỗi đỉnh đúng một lần. Một
Chu trình Hamilton là một đường đi Hamilton sau đi qua tất cả các đỉnh của đồ thị thì
trở về đỉnh xuất phát.
Một đồ thị có chu trình Hamilton được gọi là đồ thị Hamilton, đồ thị có đường đi
Hamilton được gọi là đồ thị nửa Hamilton.
Bài toán tìm đường đi và chu trình như vậy được gọi là bài toán Hamilton. Bài toán
Hamilton là NP đầy đủ.
11
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch

Tên gọi đường đi và chu trình Hamilton là gọi theo tên của William Rowan
Hamilton .
Bài toán người di lịch có thể được biểu diễn khái quát bằng một đồ thị có trọng
số G(N,A) với N là tâp hợp các nút mô tả cho các thành phố, A là tập hợp các cung mô
tả đoạn đường giữa hai thành phố.
Mỗi cung (i,j) thuộc A được gán một giá trị dij mô tả chiều dài của đường đi
giữa hai đỉnh i, j với i, j thuộc N. Mục đích cuối cùng của bài toán người du lịch chính
là tìm ra chu trình Hamilton ngắn nhất của đồ thị G có n đỉnh với n là số thành phố mà
người du lịch phải đi qua. Như vậy, kết quả tốt nhất của bài toán chính là một hoán vị
π của các đỉnh {1, 2,…, n}, sao cho chiều dài f(π) là nhỏ nhất. f(π) được tính theo công
thức sau:
2.3.2 Giải thuật Heuristics tìm đường đi có giá nhỏ nhất với tri thức bổ sung
TKCT*
TKCT* lưu giữ một tập các lời giải chưa hoàn chỉnh, nghĩa là các đường đi qua
đồ thị, bắt đầu từ nút xuất phát. Thứ tự ưu tiên gán cho một đường đi được quyết
định bởi hàm được gọi là hàm ước lượng heuristics.
Trong đó, là chi phí của đường đi cho đến thời điểm hiện tại, nghĩa là tổng
trọng số của các cạnh đã đi qua. là hàm đánh giá heuristic về chi phí nhỏ nhất để
đến đích từ . Ví dụ, nếu "chi phí" được tính là khoảng cách đã đi qua, khoảng cách
đường chim bay giữa hai điểm trên một bản đồ là một đánh giá heuristic cho khoảng
cách còn phải đi tiếp. Hàm có giá trị càng thấp thì độ ưu tiên của càng cao.
Vào: Đồ thị G = (N, A) với đỉnh là các thành phố cần đi qua, đỉnh gốc S0.
Tập đỉnh đích: DICH
f
0
: N→ R
+

Ra: Tìm đường đi từ S0 đến đích.
Phương pháp:

{ MO= {S0}; f0(S0) = g(0) + h(0);
While (M0 <> Φ)
{ S= getmoi(MO);
DONG = DONG U {S};
if S € DICH exit(“Thành công”);
12
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
if child (S) <> Φ
for each s € child(S)
if s € MO U DONG
MO= MO U {s};
f(s) = g(s) + h(s);
if f(s)cũ > f(s) mới MO= MO U {s};
}
Printf (“Không thành công”);
}
2.4 Mã nguồn
2.4.1 Cấu trúc file A_Star\A_Star
// Khai báo
int n, s, t;
int[,] a;
int[] h, g, f;
List<int> path = new List<int>();
public void ReadFile(string pathFile)
Hàm đọc dữ liệu từ file ra
public void ReadFile(string pathFile)
{
string[] tmp = new string[0];
string st; int i, j;
StreamReader sr = new StreamReader(pathFile);

st = sr.ReadLine();
tmp = st.Split(' ');
n = int.Parse(tmp[0]);
13
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
s = int.Parse(tmp[1]);
t = int.Parse(tmp[2]);
a = new int[n, n];
h = new int[n];
g = new int[n];
f = new int[n];
st = sr.ReadLine();
tmp = st.Split(' ');
for (i = 0; i < n; ++i)
h[i] = int.Parse(tmp[i]);
st = sr.ReadLine();
i = 0;
while (st != null && st != "")
{
tmp = st.Split(' ');
for (j = 0; j < n; ++j)
a[i, j] = int.Parse(tmp[j]);
i++;
st = sr.ReadLine();
}
sr.Close();
}
public void PrintGraph()
Hàm in đồ thị
public void PrintGraph()

14
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
{
int i, j;
Console.WriteLine("Matrix of Graph:");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; ++j)
Console.Write("{0,3}", a[i, j]);
Console.WriteLine();
}
Console.WriteLine("Estimated h(u) from u to goal:");
for (int u = 0; u < n; ++u)
Console.Write("{0,3}", h[u]);
Console.WriteLine();
Console.WriteLine("Start Point:" + s);
Console.WriteLine("Terminal Point:" + t);
}
public void A_Star_Search()
Hàm duyệt đường đi
public void A_Star_Search()
{
List<int> open = new List<int>();
List<int> closed = new List<int>();
bool ok = false; int u, tmp;
open.Add(s);
while (true)
15
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
{

if (open.Count == 0)
{
ok = false; break;
}
u = open[0];
path.Add(u);
closed.Add(u);
Console.Write("open: ");
for (int k = 0; k < open.Count; ++k)
Console.Write("{0,3}", open[k]);
Console.WriteLine();
Console.Write("closed: ");
for (int k = 0; k < closed.Count; ++k)
Console.Write("{0,3}", closed[k]);
Console.WriteLine();
open.Remove(u);
if (u == t)
{
ok = true; break;
}
for (int v = 0; v < n; ++v)
if (a[u, v] > 0 && !closed.Contains(v))
{
16
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
int tmp_gv = g[u] + a[u, v];
int tmp_fv = tmp_gv + h[v];
if (open.Contains(v))
if (f[v] <= tmp_fv) continue;
else open.Remove(v);

g[v] = tmp_gv;
f[v] = tmp_fv;
open.Add(v);
}
for (int i = 0; i < open.Count - 1; ++i)
for (int j = open.Count - 1; j > i; j)
if (f[open[j]] < f[open[j - 1]])
{
tmp = open[j];
open[j] = open[j - 1];
open[j - 1] = tmp;
}
}
if (ok)
{
Console.WriteLine("Contours of A star search:");
for (int k = 0; k < path.Count; ++k)
Console.Write("{0,3}", path[k]);
}
else
17
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
Console.WriteLine("unsuccessful!");
}
2.4.2 Cấu trúc file A sao_di du lich
Khai báo
const int size = 100;
int maxE = 100;
int maxC = size * maxE;
int C[size][size];

int X[size+1];
int T[size];
int BestWay[size+1];
int FREE[size];
int minSpending;
int M,N;
void Enter ()
Hàm nhập thành phố, chi phí và trọng số h
void Enter ()
{
int i,j,k;
cout << " CITY: " ; cin >> N;
cout << " TRAFFIC ROAD: "; cin >> M;
for ( i = 1; i <= N; i++ )
{
for ( j = 1; j <= N; j++ )
{
18
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
if ( i == j ) C[i][j] = 0;
else C[i][j] = maxC;
}
}
for ( k = 1; k <= M; k++ )
{
cout << "Enter i: "; cin >> i;
cout << "Enter j: "; cin >> j;
cout << "Cost : "; cin >> C[i][j];
C[j][i] = C[i][j];
}

}
void InI()
Hàm gán giá trị đường đi ban đầu
void InI()
{
for ( int i = 1; i <= N; i++ )
{ FREE[i] = 1; }
FREE[1] = 0;
X[1] = 1;
T[1] = 0;
minSpending = maxC;
}
void BACKTRACK ( int i )
Hàm tìm đường đi với giá trị nhỏ nhất. Nhập đỉnh bắt đầu
19
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
void BACKTRACK ( int i )
{
for ( int j = 2; j <= N; j++ )
{
if ( FREE[j] )
{
X[i] = j;
T[i] = T[i-1] + C[X[i-1]][j];
if (( T[i] + C[i][1]) < minSpending )
{
if ( i < N )
{
FREE[j] = 0;
BACKTRACK ( i + 1 );

FREE[j] = 1;
}
else
{
for ( int var = 1; var <= N; var++ )
{
BestWay[var] = X[var];
}
minSpending = T[N] + C[X[N]][1]; }
}
else goto finish;
20
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
}
}
finish:
}
void PRINT()
Hàm in Kết quả
void PRINT()
{
if ( minSpending == maxC )
{ cout << "NO SOLUTION "; }
else
{
for ( int i = 1; i <= N; i++ )
{ cout << BestWay[i] << "->"; }
cout << " Minimum Spending is : " << minSpending;
}
}

2.4.3 Cấu trúc file A_sao_Bai 2.15\ThuatToanA_sao
TTA.Nhap();
Hàm đọc thông tin từ file lưu trữ danh sách cạch và ma trận trọng số.
public void Nhap()
{
int hang = -1, cot = 0;
StreamReader h = new StreamReader(path);
string str = h.ReadLine();
21
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
n = int.Parse(str);
MaTranKe = new int[n, n];
str = h.ReadLine();
while (str != null)
{
hang++;
cot = 0;
foreach (string tmp in str.Split(' '))
{
int x = int.Parse(tmp);
MaTranKe[hang, cot] = x;
cot++;
}
str = h.ReadLine();
}
h.Close();
// khoi tao ma tran trong so
using (StreamReader dr = File.OpenText(path1))
{
string str1 = dr.ReadLine();

// so phan tu nay cung bang so dinh cua ma tran
int sophantu = int.Parse(str1);
Hn = new int[sophantu];
string[] tmp = new string[sophantu];
str1 = dr.ReadLine();
22
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
tmp = str1.Split(' ');
for (i = 0; i < tmp.Length; i++)
{ Hn[i] = int.Parse(tmp[i]); }
}
}
TTA.Hien();
Hiển thị ma trận cạnh và hàm đánh giá
public void Hien()
{
Console.WriteLine("Hien ma tran canh");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
Console.Write("{0} ", MaTranKe[i, j]);
Console.WriteLine();
}
Console.WriteLine("Hien ham danh gia");
for (i = 0; i < n; i++)
{ Console.Write("{0} ", Hn[i]); }
Console.WriteLine();
// nhập đỉnh xuất phát và kết thúc
Console.Write("Nhap dinh xuat phat xp=");
xp = int.Parse(Console.ReadLine());

Console.Write("Nhap dinh ket thuc KT=");
kt = int.Parse(Console.ReadLine());
23
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
}
TTA.Duyet();
Duyệt A* và đưa ra kết quả
public void Duyet()
{
if (Duyet_Asao())
{
Console.WriteLine();
Console.WriteLine("da tim thay ket qua");
Console.WriteLine("Hien duong di ngan nhat theo A*");
for (j = 0; j < KetQua.Length; j++)
{
if (j < KetQua.Length - 1) Console.Write("Dinh:{0},{1},{2}\t",
KetQua[j].Dinh, KetQua[j].Giatri_Gn, KetQua[j].Giatri_Fn + "==>");
else Console.WriteLine("Dinh:{0},{1},{2}", KetQua[j].Dinh,
KetQua[j].Giatri_Gn, KetQua[j].Giatri_Fn);
}
}
else Console.WriteLine("Khong tim thay ket qua");
}
private bool Duyet_Asao() {
bool TimThay = false;
// khoi tao doi tuong Stack
Stack A = new Stack();
//Khoi tao node Sau
Node Sau = new Node();

24
Báo cáo bài tập lớn Trí tuệ nhân tạo Bài toán người đi du lịch
Sau = null;
//khoi tạo Node Tmp
Node Tmp = new Node();
Tmp = null;
//Cho đỉnh xuất phát vào Stack
A.Put(ref Sau, xp,0, Hn[xp]+0);
// đường đi từ đỉnh xp tới xp =0;nên đường đi thưc tế =Đường chim bay + 0;
// thực hiện vòng lặp
do
{
// kiểm tra Stack có rỗng hay không
if (A.Empty(Sau))// kết quả đúng thì thoát khỏi chương trình
{
Console.WriteLine("\n danh sach rong");
break;// thoát khỏi chương trình
}
// nếu không rỗng thì loại đỉnh ở cuối danh sách ra
Tmp = A.Pop(ref Sau);
Console.WriteLine();
Console.Write("lay ra dinh {0},{1},{2}", Tmp.TênDinh,
Tmp.DuongDi_Gn,Tmp.DuongDithucTe_Fn + " co dinh con: ");
//Cho đỉnh vào mảng kết quả đường đi
Array.Resize(ref KetQua, ++d);
KetQua[d - 1].Dinh = Tmp.TênDinh;
KetQua[d - 1].Giatri_Gn = Tmp.DuongDi_Gn;
KetQua[d - 1].Giatri_Fn = Tmp.DuongDithucTe_Fn;
25

×