BỘ MÔN KHOA HỌC MÁY TÍNHĐỒ ÁN TRÍ TUỆ NHÂN TẠO Phương pháp tìm kiếm có kinh nghiệm A* cho bài toán tìm đường đi trên 1 bản đồ.. Ý tưởng : Sử dụng hàm Heuristics chấp nhận được + tìm ki
Trang 1BỘ MÔN KHOA HỌC MÁY TÍNH
ĐỒ ÁN TRÍ TUỆ NHÂN TẠO
Phương pháp tìm kiếm có kinh nghiệm A* cho bài toán tìm đường đi trên 1 bản đồ.
GVHD: Thầy TS NGÔ HỮU PHÚC
Sinh viên thực hiện: HÀ ANH VŨ
MSSV: 11870277 Lớp: CHKHMT – TPHCM23A11
TP.HCM, Tháng 7 năm 2012
Trang 2MỤC LỤC
Chương 1 : THUẬT TOÁN A* SEARCH
I. Ý tưởng :
Sử dụng hàm Heuristics chấp nhận được + tìm kiếm theo chiều rộng → Loại bỏ những đường đi có chi phí cao
II. Hàm lượng giá :
f(u) = g(u) + h(u)
g(u) = Chi phí để đến u h(u) = Lượng giá từ u đến đích f(u) = Ước lượng tổng giá đến đích qua u
III. Ví dụ về A* Search :
Đầu vào:
Trạng thái đầu A,
Trạng thái đích B
Các giá trị ghi trên cạnh là độ dài đường đi;
Các số cạnh các đỉnh là giá trị hàm h
Yêu cầu: Tìm đường đi ngắn nhất từ A đến B bằng A*.
Không gian trạng thái với hàm đánh giá
Trang 3Thực hiện:
Phát triển đỉnh A sinh ra các đỉnh con C, D, E, F
g(C) = 9, h(C) = 15 → f(C) = 9 + 15 = 24 g(D) = 7, h(D) = 6 → f(D) = 7 + 6 = 13 g(E) = 13, h(E) = 8 → f(E) = 13 + 8 = 21 g(F) = 20, h(F) = 7 → f(F) = 20 + 7 = 27
→ Như vậy, đỉnh D được chọn để phát triển (f(D) = 13)
Phát triển D, nhận được các đỉnh con H và E (mới) Trong đó:
g(H) = g(D) + độ dài cung (D,H) = 7 + 8 = 15 h(H) = 10
→ f(H) = g(H) + h(H) = 15 + 10 = 25
g(E) = g(D) + độ dài cung (D,E) = 7 +4 = 11 h(E) = 8
→ f(E) = g(E) + h(E) = 11 + 8 = 19
Như vậy đỉnh E sẽ được dùng để phát triển tiếp
Tương tự sẽ chọn được các đỉnh K, B (đích)
Với g(B) = 19, h(B) = 0
Đường đi: A → D → E → I →B
IV. Cài đặt thuật toán :
Procedure A*;
Begin
1. Khởi tạo danh sách L chỉ chứa trạng thái đầu.
2. Loop do
2.1 if L rỗng then {thông báo thất bại; stop;}
2.2 Loại trạng thái u ở đầu danh sách L;
2.3 if u là trạng thái đích then {thông báo thành công; stop}
2.4 for mỗi trạng thái v kề u do
{ g(v) ← g(u)+ k(u,v);
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 3
Trang 4f(v) ← g(v)+h(v);
Đặt v vào danh sách L; }
2.5 Sắp xếp L theo thứ tự giảm dần của hàm f sao cho trạng thái có giá trị của hàm f
nhỏ nhất ở đầu danh sách;
3 End;
V. Chứng minh tính tối ưu của A*
• Giả sử thuật toán dừng ở G, với độ dài đường đi là g(G) và ta có h(G)=0 nên
f(G)=g(G)
• Giả sử nghiệm tối ưu không phải là G, tối ưu là G1, với độ dài đường đi là S
• Như vậy, đường đi này bị tách ra ở vị trí N nào đó Khi đó có 2 khả năng:
a. N trùng G1, hoặc
b. N không trùng G1
• Nếu N ≡ G1:
G được chọn trước G1, nên f(G) ≤ f(G1) vì g(G) ≤ g(G1) = S
• Nếu N ≠ G1:
Do h(u) là đánh giá thấp → f(N) = g(N) + h(N) ≤ S
Do G được chọn trước → f(G) ≤ f(N) ≤ S
Vậy G là đường đi tối ưu
VI. Nhận xét về A*
• Nếu hàm h(u) đánh giá thấp nhất thì thuật toán A* là tối ưu
• Nếu các cung không nhỏ hơn một số α nào đó thì A* là đầy đủ.
• Nếu h(u)=0 với mọi u, thuật toán A* chính là thuật toán tìm kiếm tốt nhất đầu tiên với hàm đánh giá g(u)
VII. Phân tích A*
• Đủ?
Có (Trừ phi có vô hạn node với f ≤ f(G) ).
• Độ phức tạp thời gian?
Hàm mũ
• Không gian?
Lưu trữ tất cả các node
• Tối ưu? Có
Trang 5I. Tổ chức lưu trữ trên tập tin :
Để lưu trữ đồ thị trên tập tin, ta lấy ví dụ cụ thể như ví dụ chương 1
Với đồ thị này ta lưu trữ như sau :
10
A 14 B 0 C 15 D 6 E 8 F 7 G 12 H 10 K 2 I 4
4 2 9 3 7 4 13 5 20
0
1 7 6
2 4 4 7 8
2 8 4 9 3
2 6 4 9 6
0
1 8 5
1 1 6
2 1 5 8 9
Trong đó :
- Dòng 1 : cho biết số đỉnh trong đồ thị (trong ví dụ trên đồ thị có 10 đỉnh)
- Dòng 2 :
A 14 B 0 C 15 D 6 E 8 F 7 G 12 H 10 K 2 I 4
Ví dụ : đỉnh A có lượng giá 14, đỉnh B có lượng gia 0, …
- Dòng thứ 3 đến hết : dòng 3 lưu thông tin cho đỉnh 0, dòng 4 lưu thông tin cho đỉnh
1, dòng 5 lưu thông tin cho đỉnh 2, … Thông tin lưu trữ cho từng dòng như sau :
4 2 9 3 7 4 13 5 20
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 5
Lượng giá
Tên
đỉnh
Trọng
số 9
Nối đến đỉnh 2 (đỉnh C)
Số đỉnh
mà đỉnh
này đi
đến
Trang 6II. Code chương trình :
1. Lớp Node : lưu trữ 1 Node của danh sách liên kết đơn
class Node
{
public Node()
{
Value = null;
Next = null;
}
{
Value = V;
Next = null;
}
}
2. Lớp LuuVet : là vùng thông tin của Node, dùng để lưu vết khi tìm đường.
class LuuVet
{
private int m_gv, m_fv;
{
get { return m_v; }
set { m_v = value; }
}
public int fv
{
get { return m_fv; }
set { m_fv = value; }
}
public int gv
{
get { return m_gv; }
set { m_gv = value; }
}
Trang 7public Node nodecha
{
get { return m_nodecha; }
set { m_nodecha = value; }
}
public LuuVet()
{
v = null;
m_nodecha = null;
gv = 0;
fv = 0;
}
{
v = dinh;
gv = GV;
fv = FV;
m_nodecha = dc;
}
{
v = l.v;
gv = l.gv;
fv = l.fv;
m_nodecha = l.m_nodecha;
}
}
3. Lớp danh sách liên kết đơn :
class SingleLinkedList
{
public SingleLinkedList()
{
}
{
if (p == null) return false;
if (Head == null)
Head = p;
else
{
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 7
Trang 8p.Next = Head;
Head = p;
}
return true;
}
{
if (n == null) return false;
if (Head != null)
{
while ( p != null && n.Value.fv > p.Value.fv) {
q = p;
p = p.Next;
}
if (q == null)
AddHead(n);
else
{
q.Next = n;
n.Next = p;
}
}
else
AddHead(n);
return true;
}
{
if (Head == null) return null;
p = Head;
Head = Head.Next;
return p;
}
{
if (n == null) return false;
if (Head == null)
{
Head = n;
Trang 9return true;
}
while (p.Next != null) p = p.Next;
n.Next = null;
p.Next = n;
return true;
}
}
4. Lớp CDinh : lưu trữ thông tin cho 1 đỉnh
class CDinh
{
protected string m_tendinh;
danh gia h(u)
protected int m_index;
public CDinh()
{
m_tendinh = "";
m_luonggia = 0;
}
public CDinh(string tendinh)
{
m_tendinh = tendinh;
m_tapdinhke = null;
m_luonggia = 0;
}
public CDinh(string tendinh,int luonggia)
{
m_tendinh = tendinh;
m_luonggia = luonggia;
m_tapdinhke = null;
}
public string tendinh
{
get { return m_tendinh; }
set { m_tendinh = value; }
}
public int index
{
get { return m_index; }
set { m_index = value; }
}
{
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 9
Trang 10get { return m_tapdinhke; }
set { m_tapdinhke = value; }
}
public int luonggia
{
get { return m_luonggia; }
set { m_luonggia = value; }
}
public int sodinhke()
{
if (m_tapdinhke != null)
return m_tapdinhke.GetLength(0);
else
return 0;
}
public void h()
{
int t=0;
{
if (t > dk.trongso) t = dk.trongso;
}
m_luonggia = t;
}
}
5. Lớp CDinhKe : lưu trữ thông tin mà 1 đỉnh có nối đến
class CDinhKe
{
protected int m_trongso;
{
get { return m_dinhke; }
set { m_dinhke = value; }
}
public int trongso
{
get { return m_trongso; }
set { m_trongso = value; }
}
public CDinhKe()
{
m_dinhke = null;
Trang 11m_trongso = 0;
}
{
m_dinhke = dinh;
m_trongso = 0;
}
{
m_dinhke = dinhke;
m_trongso = trongso;
}
}
6. Lớp AStarSearch : Lớp hiện thực của thuật toán A*
class AStarSearch
{
protected int m_sodinh;
{
get { return m_tapdinh; }
}
public int sodinh
{
get { return m_sodinh; }
set { m_sodinh = value; }
}
public AStarSearch()
{
m_tapdinh = null;
m_sodinh = 0;
}
public bool docDothi(string tenfile)
{
try
{
int i, j,n;
string s = sr.ReadLine();
m_sodinh = int.Parse(s);
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 11
Trang 12s = sr.ReadLine();
for (i = 0; i < m_sodinh; i++)
{
m_tapdinh[i].index = i; m_tapdinh[i].luonggia = int.Parse(ms[i*2+1]); }
for (i = 0; i < m_sodinh; i++)
{
s = sr.ReadLine();
n = int.Parse(ms[0]);
if (n >= 1)
{
dinh i
m_tapdinh[i].tapdinhke = new
CDinhKe[n];//khoi tao so dinh ke cho dinh i
int k = 0;
for (j = 1; j <= n * 2; j++)
{
dk.dinhke =
m_tapdinh[int.Parse(ms[j])];
dk.trongso = int.Parse(ms[++j]);
m_tapdinh[i].tapdinhke[k] = dk;
k++;
}
}
}
return true;
}
{
return false;
}
}
public bool ghiDothi(string tenfile)
{
try
{
Trang 13StringWriter f = new StringWriter();
int i, j;
for (i = 0; i < m_sodinh; i++)
{
f.Write("{0} {1} ",
m_tapdinh[i].tendinh,m_tapdinh[i].luonggia);
}
for (i = 0; i < m_sodinh; i++)
{
f.WriteLine();
int sodk = m_tapdinh[i].sodinhke();
f.Write("{0}", sodk);
for(j=0;j<sodk;j++)
{
f.Write(" {0} {1}",
m_tapdinh[i].tapdinhke[j].dinhke.index,
m_tapdinh[i].tapdinhke[j].trongso);
}
}
return true;
}
{
return false;
}
}
kthuc)
{
if (bdau == null || kthuc == null) return null;
null);
trên đường đi tìm thấy
while (true)
{
if (L.Head == null)
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 13
Trang 14{
return null;
}
T.AddLast(u);
công,stop}
if (u.Value.v == kthuc)
{
return T;
}
if (u.Value.v.tapdinhke != null)
{
{
lv.nodecha = u;
lv.v = v.dinhke;
lv.gv = u.Value.gv + v.trongso;
//u.Value.v.tapdinhke[v.dinhke.index].trongso;
lv.fv = lv.gv + v.dinhke.luonggia;
lv.gv, lv.v.tendinh,
v.dinhke.luonggia, lv.v.tendinh, lv.fv);
theo hàm f
L.InsertASC(n);
}
}
nên ko cần phải làm
Trang 15//thao tác sắp xếp L nữa
}
}
}
7. Chương trình chính :
namespace AStarSearchDemo
{
{
static void Main(string[] args)
{
ass.sodinh);
for (int i = 0; i < ass.sodinh; i++)
{
ass.tapdinh[i].luonggia);
}
Console.WriteLine("==================================");
for (int i = 0; i < ass.sodinh; i++)
{
for (int j = 0; j < cur.sodinhke(); j++)
{
cur.tendinh,
cur.tapdinhke[j].trongso,
cur.tapdinhke[j].dinhke.tendinh,
cur.tapdinhke[j].dinhke.luonggia);
}
}
Console.WriteLine("==================================");
string bd, kt;
Console.Write("Nhap dinh bat dau : ");
Console.Write("Nhap dinh ket thuc : ");
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 15
Trang 16CDinh dbd = new CDinh();
{
if (d.tendinh == bd)
dbd = d;
if (d.tendinh == kt)
dkt = d;
}
if (dbd.tendinh == "" || dkt.tendinh == "")
{
return;
}
if (T != null)
{
while (p.Next != null) p = p.Next;
Console.WriteLine("==================================");
while (p != null && p.Value.v!=dbd)
{
Console.Write("{0} <- ", p.Value.v.tendinh);
p = p.Value.nodecha;
}
if(p!=null)
}
ass.ghiDothi("dothi_out.txt");
}
}
}
Kết quả thực hiện chương trình :
Trang 17III. Hướng phát triển :
Do em nhập viện điều trị và ba của em mất nên thời gian làm bài rất hạn chế, do đó chương trình chưa kịp hiện thực trên 1 bản đồ cụ thể và hàm lượng giá còn chưa tốt Tương lai, chương trình có thể áp dụng để tìm đường trên 1 bản đồ cụ thể với 1 hàm lượng giá tốt hơn
SVTH: Hà Anh Vũ GVHD: TS.Ngô Hữu Phúc Trang 17
Trang 18Trân trọng cám ơn thầy.