Đề tài:- Bài toán người đưa thư-Xây dựng chương trình giải quyết bài toán người đưa thư theo giải thuật gense với phương pháp chọn ElitismI/Bài toán người đưa thư:Bài toán người đưa thư(hay còn gọi là bài toán người du lịch-TSP) là một bài toán về ý niệm rất đơn giản song lại khá kinh điển.Một người đưa thư phải ghé mỗi thành phố trong vùng của anh ta,chính xác một lần rồi trở về điểm khởi hành.Chi phí đi lại giữa từng cặp thành phố được cho trước,anh ta phải lập kế hoạch cho hành trình của mình ra sao để tổng chi phí cho toàn hành trình là tối thiểu.Không gian tìm kiếm của TSP là tập các hoán vị của n thành phố.Bất cứ hoán vị nào của n thành phố này cũng là một lời giải chấp nhận được (là toàn bộ một hành trình qua các thành phố).Lời giải tối ưu là một hoán vị với chi phí tối thiểu của hành trình.Kích thước của không gian tìm kiếm là n! II/Giải thuật genesThuật toán gense mô phỏng tiến hóa tự nhiên ở mức gen sử dụng tư tưởng của chọn lọc tự nhiên.Thuật giải di truyền hình thành dựa trên quan niệm cho rằng quá trình tiến hóa tự nhiên là quá trình hoàn hảo nhất,hợp lí nhất và tự nó đã mang tính tối ưu.Quá trình tiến hóa thể hiện tính tối ưu ở chỗ thế hệ sau bao giờ cũng tốt hơn thế hệ trước.Tiến hóa tự nhiên được duy trì bởi 2 quá trình cơ bản:sinh sản và chọn lọc tự nhiên.Cá thể nào phát triển hơn,thích ứng hơn với môi trường sẽ bị đào thải.Một cá thể mô tả một lời giả ứng viên cho bài toán.Một cá thể “alive”,gọi là quần thể được tiến hóa từ thế hệ này đến thế hệ khác phụ thuộc vào sự thích nghi của cá thể.Thế hệ sinh ra sẽ chứa lời giải của bài toán.Ban đầu sinh ra thế hệ khởi tạo quần thể P(0),chỉ số i chỉ ra thế hệ thứ i.Lặp cho đến khi quần thể hội tụ hoặc tiêu chuẩn kết thúc đạt được.Sau đó đánh giá độ thích nghi của mỗi cá thể trong P(i).Lựa chọn các cha từ P(i) dựa trên độ thích nghi của chúng trong P(i).Áp dụng các toán tử gen(lai ghép và đột biến) từ các cha đã chọn để sinh ra các con.Đạt được thế hệ tiếp theo P(i+1) từ các con và các cá thể ở thế hệ P(i).Các thành phần cơ bản của thuật toán gen:-Mã hóa -Khởi tạo quần thể-Hàm thích nghi-Lựa chọn cho sự kết hợp lại-Lai ghép-Đột biến-Chiến lược thay thế-Tiêu chuẩn kết thúcÁp dụng vào bài toán người đưa thư:-Mã hóa: Sử dụng mã hóa dạng hoán vị.Tất cả các nhiễm sắc thể là chuỗi các số biểu diễn vị trí của các thành phố trong một dãyVí dụ: NST A 1 5 3 2 6 4 7 9 8 NST B 8 5 6 7 2 3 1 4 9-Khởi tạo quần thể: Ta chọn ngẫu nhiên một số cá thể tạo thành một quần thể. -Hàm thích nghi:để tìm ra cá thể tốt hay xấu.Đối với bài toán người đưa thư hàm thích nghi chính là tổng chi phí mà
Nguyễn Hải Linh- Tin học 5A Đề tài: - Bài toán người đưa thư -Xây dựng chương trình giải quyết bài toán theo giải thuật gense với phương pháp chọn Elitism I/Bài toán người đưa thư: Bài toán người đưa thư(hay còn gọi là bài toán người du lịch-TSP) là một bài toán về ý niệm rất đơn giản song lại khá kinh điển.Một người đưa thư phải ghé mỗi thành phố trong vùng của anh ta,chính xác một lần rồi trở về điểm khởi hành.Chi phí đi lại giữa từng cặp thành phố được cho trước,anh ta phải lập kế hoạch cho hành trình của mình ra sao để tổng chi phí cho toàn hành trình là tối thiểu.Không gian tìm kiếm của TSP là tập các hoán vị của n thành phố.Bất cứ hoán vị nào của n thành phố này cũng là một lời giải chấp nhận được (là toàn bộ một hành trình qua các thành phố).Lời giải tối ưu là một hoán vị với chi phí tối thiểu của hành trình.Kích thước của không gian tìm kiếm là n! II/Giải thuật genes Thuật toán gense mô phỏng tiến hóa tự nhiên ở mức gen sử dụng tư tưởng của chọn lọc tự nhiên.Thuật giải di truyền hình thành dựa trên quan niệm cho rằng quá trình tiến hóa tự nhiên là quá trình hoàn hảo nhất,hợp lí nhất và tự nó đã mang tính tối ưu.Quá trình tiến hóa thể hiện tính tối ưu ở chỗ thế hệ sau bao giờ cũng tốt hơn thế hệ trước.Tiến hóa tự nhiên được duy trì bởi 2 quá trình cơ bản:sinh sản và chọn lọc tự nhiên.Cá thể nào phát triển hơn,thích ứng hơn với môi trường sẽ bị đào thải.Một cá thể mô tả một lời giả ứng viên cho bài toán.Một cá thể “alive”,gọi là quần thể được tiến hóa từ thế hệ này đến thế hệ khác phụ thuộc vào sự thích nghi của cá thể.Thế hệ sinh ra sẽ chứa lời giải của bài toán.Ban đầu sinh ra thế hệ khởi tạo quần thể P(0),chỉ số i chỉ ra thế hệ thứ i.Lặp cho đến khi quần thể hội tụ hoặc tiêu chuẩn kết thúc đạt được.Sau đó đánh giá độ thích nghi của mỗi cá thể trong P(i).Lựa chọn các cha từ P(i) dựa trên độ thích nghi của chúng trong P(i).Áp 1 Nguyễn Hải Linh- Tin học 5A dụng các toán tử gen(lai ghép và đột biến) từ các cha đã chọn để sinh ra các con.Đạt được thế hệ tiếp theo P(i+1) từ các con và các cá thể ở thế hệ P(i). Các thành phần cơ bản của thuật toán gen: - Mã hóa - Khởi tạo quần thể - Hàm thích nghi - Lựa chọn cho sự kết hợp lại - Lai ghép - Đột biến - Chiến lược thay thế - Tiêu chuẩn kết thúc Áp dụng vào bài toán người đưa thư: - Mã hóa: Sử dụng mã hóa dạng hoán vị.Tất cả các nhiễm sắc thể là chuỗi các số biểu diễn vị trí của các thành phố trong một dãy Ví dụ: NST A 1 5 3 2 6 4 7 9 8 NST B 8 5 6 7 2 3 1 4 9 - Khởi tạo quần thể: Ta chọn ngẫu nhiên một số cá thể tạo thành một quần thể. - Hàm thích nghi:để tìm ra cá thể tốt hay xấu.Đối với bài toán người đưa thư hàm thích nghi chính là tổng chi phí mà người đó đi hết tất cả các thành phố. - Lựa chọn cho sự kết hợp lại:Sử dụng phương pháp chọn Elitism Phương pháp Elitism cho phép copy những cá thể tốt (hoặc một vài cá thể tốt) sang quần thể mới. Thành phần còn lại của quần thể được tạo từ cách khác. Phương pháp Elitism có thể tăng tốc cho GA, vì nó ngăn không làm mất cá thể tốt. 2 Nguyễn Hải Linh- Tin học 5A - Lai ghép+ đột biến: Single point crossover Lựa chọn một điểm để lai ghép, permutation được sao chép từ điểm đầu tiên đến điểm lai ghép, sau đó cha còn lại được duyệt qua từng số và nếu số đó chưa có trong con, nó được thêm theo thứ tự của NST thứ hai (1 2 3 4 5 | 6 7 8 9) + (4 5 3 6 2 9 1 7 8) = (1 2 3 4 5 6 9 7 8) III/Chương trình 1-Form main: Khi nhấn chuột vào nút nhập thì goi được form nhập Khi nhấn chuột vào nút giải thì gọi được form giải public partial class Form_main: Form { public Form_main() { InitializeComponent(); } private void nhậpToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Form frm in this.MdiChildren) 3 Nguyễn Hải Linh- Tin học 5A { frm.Close(); } Form_nhap fe = new Form_nhap(); fe.MdiParent = this; fe.Show(); nhap.Enabled = false; giai.Enabled = true; } private void giảiToolStripMenuItem_Click(object sender, EventArgs e) { foreach (Form frm in this.MdiChildren) { frm.Close(); } Form_giai fr = new Form_giai(); fr.MdiParent = this; fr.Show(); nhap.Enabled = true; giai.Enabled = false; } private void Form_main_Load(object sender, EventArgs e) { } } } 2-Form nhập 4 Nguyễn Hải Linh- Tin học 5A Trên form nhập ta dùng chuột để chọn vị trí các nhà(thành phố).Sau đó điền giá trị thể hiện chi phí giữa các thành phố vào các ô textbox rồi nhấn vào nút thêm giá để lưu các giá trị vào file: dt1.text để lưu tọa độ của các nhà (thành phố) và dt2.text để lưu giá trị chi phí giữa các nhà. public partial class Form_nhap: Form { dothi dt; TextBox[,] tb; Point[] diem; public Form_nhap() { InitializeComponent(); } // Hàm lưu tọa độ của nhà private void luunha(int x, int y) { StreamReader sr = new StreamReader("dt1.txt"); string sonutcu = sr.ReadLine(); int sonutmoi = Convert.ToInt32(sonutcu) + 1; string temp = sr.ReadToEnd(); sr.Close(); StreamWriter sw = new StreamWriter("dt1.txt"); sw.WriteLine(sonutmoi); sw.WriteLine(temp); string toado = x.ToString() + "," + y.ToString(); sw.Write(toado); sw.Close(); } //Hàm xóa dữ liệu trên file dt1.text và dt2.text private void xoadulieu() { StreamWriter sw1 = new StreamWriter("dt1.txt"); sw1.Write(""); sw1.Close(); StreamWriter sw2 = new StreamWriter("dt2.txt"); sw2.Write(""); sw2.Close(); } private void xoahienthi() { foreach (TextBox tbs in this.tb) { this.Controls.Remove(tbs); } foreach (nha n in dt.Nha) { this.Controls.Remove(n); } } private void hienthi() 5 Nguyễn Hải Linh- Tin học 5A { // Hiển thị nhà: dt = new dothi("dt1.txt"); for (int i = 0; i < dt.Sonha; i++) { this.Controls.Add(dt.Nha[i]); } //Hiên thị giá đường dưới dạng textbox diem = new Point[dt.Sonha]; for (int i = 0; i < dt.Sonha; i++) { diem[i] = new Point(dt.Nha[i].Location.X + dt.Nha[i].Height / 2, dt.Nha[i].Location.Y + dt.Nha[i].Width / 2); } tb = new TextBox[dt.Sonha, dt.Sonha]; for (int i = 0; i < dt.Sonha; i++) { for (int j = 0; j < dt.Sonha; j++) { tb[i, j] = new TextBox(); tb[i, j].Text = "0"; } } for (int i = 0; i < dt.Sonha; i++) { for (int j = i + 1; j < dt.Sonha; j++) { tb[i, j].Size = new Size(23, 18); tb[i, j].Text = dt.Mangcost[i, j].ToString(); tb[i, j].Location = new Point((diem[i].X + diem[j].X) / 2, (diem[i].Y + diem[j].Y) / 2); this.Controls.Add(tb[i, j]); } } } private void luugia() { for (int i = 0; i < dt.Sonha; i++) { for (int j = i+1; j < dt.Sonha; j++) { tb[j, i].Text = tb[i, j].Text; } } StreamWriter sw = new StreamWriter("dt2.txt"); string temp = null; for (int i = 0; i < dt.Sonha; i++) { for (int j = 0; j < dt.Sonha; j++) { temp = temp + tb[i, j].Text + " | "; } 6 Nguyễn Hải Linh- Tin học 5A temp = temp + "\r\n"; } sw.WriteLine(temp); sw.Close(); } private void luugiasauthemnha() { string temp = null; if (dt.Sonha == 0) { StreamWriter sw = new StreamWriter("dt2.txt"); temp = "00 |"; sw.WriteLine(temp); sw.Close(); } else { StreamReader sr = new StreamReader("dt2.txt"); string[] dauvao = new string[dt.Sonha - 1]; for (int i = 0; i < dt.Sonha - 1; i++) { dauvao[i] = sr.ReadLine(); } sr.Close(); StreamWriter sw = new StreamWriter("dt2.txt"); for (int i = 0; i < dt.Sonha - 1; i++) { temp = temp + dauvao[i] + " | 00 |"; temp = temp + "\r\n"; } for (int i = 0; i < dt.Sonha; i++) { temp = temp + "00 | "; } sw.WriteLine(temp); sw.Close(); } } private void themtb() { tb = new TextBox[dt.Sonha, dt.Sonha]; for (int i = 0; i < dt.Sonha; i++) { for (int j = 0; j < dt.Sonha; j++) { tb[i, j] = new TextBox(); tb[i, j].Text = "0"; } } for (int i = 0; i < dt.Sonha; i++) { for (int j = i + 1; j < dt.Sonha; j++) { 7 Nguyễn Hải Linh- Tin học 5A tb[i, j].Size = new Size(23, 18); tb[i, j].Text = dt.Mangcost[i, j].ToString(); tb[i, j].Location = new Point((diem[i].X + diem[j].X) / 2, (diem[i].Y + diem[j].Y) / 2); this.Controls.Add(tb[i, j]); } } } private void Form1_Load(object sender, EventArgs e) { hienthi(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics dohoa = this.CreateGraphics(); Pen to = new Pen(Color.Red, 2); for (int i = 0; i < dt.Sonha; i++) { for (int j = i + 1; j < dt.Sonha; j++) { dohoa.DrawLine(to,diem[i],diem[j]); } } } private void button1_Click(object sender, EventArgs e) { luugia(); } private void Form1_MouseDown(object sender, MouseEventArgs e) { if (checkBox1.Checked) { xoahienthi(); luunha(e.X, e.Y); dt = new dothi("dt1.txt"); hienthi(); this.Refresh(); } } private void button2_Click(object sender, EventArgs e) { xoahienthi(); xoadulieu(); dt = new dothi(); checkBox1.Checked = true; hienthi(); this.Refresh(); } } } 8 Nguyễn Hải Linh- Tin học 5A 3-Form giải: Sau khi đã kích chuột vào nút thêm giá trên form nhập.Kích vào “giải” trên form 2 thì xuất hiên form giải.Trên form giải ta kích chuột vào nút “giải” thì sẽ được kết quả của bài toán. public partial class Form_giai: Form { public Form_giai() { InitializeComponent(); } dothi dt; TextBox[,] tb; Point[] diem; private void hienthi() { // Hiển thị nhà: dt = new dothi("dt1.txt","dt2.txt"); 9 Nguyễn Hải Linh- Tin học 5A for (int i = 0; i < dt.Sonha; i++) { this.Controls.Add(dt.Nha[i]); } //Hiên thị giá đường dưới dạng textbox diem = new Point[dt.Sonha]; for (int i = 0; i < dt.Sonha; i++) { diem[i] = new Point(dt.Nha[i].Location.X + dt.Nha[i].Height / 2, dt.Nha[i].Location.Y + dt.Nha[i].Width / 2); } tb = new TextBox[dt.Sonha, dt.Sonha]; for (int i = 0; i < dt.Sonha; i++) { for (int j = 0; j < dt.Sonha; j++) { tb[i, j] = new TextBox(); tb[i, j].Text = "0"; } } for (int i = 0; i < dt.Sonha; i++) { for (int j = i + 1; j < dt.Sonha; j++) { tb[i, j].Size = new Size(23, 18); tb[i, j].Text = dt.Mangcost[i, j].ToString(); tb[i, j].Location = new Point((diem[i].X + diem[j].X) / 2, (diem[i].Y + diem[j].Y) / 2); this.Controls.Add(tb[i, j]); } } } private void button1_Click(object sender, EventArgs e) { dothi dt = new dothi("dt1.txt", "dt2.txt"); gene ge = new gene(dt, 10, 5, 100); ge.tinhtoan(); Graphics dohoa = this.CreateGraphics(); Pen to = new Pen(Color.Blue, 4); for (int i = 0; i < dt.Sonha-1; i++) { dohoa.DrawLine(to, diem[ge.KQ[i]], diem[ge.KQ[i+1]]); } string temp = "Quần thể lai:"+ "\n"; string temp2 = "Quần thể đầu:"+ "\n"; string temp3 = "Cá thể chọn từ quần thể"+ "\n"; for (int j = 0; j < ge.laiquanthe().GetLength(0); j++) { for (int i = 0; i < ge.DT.Sonha; i++) 10 . từng số và nếu số đó chưa có trong con, nó được thêm theo thứ tự của NST thứ hai (1 2 3 4 5 | 6 7 8 9) + (4 5 3 6 2 9 1 7 8) = (1 2 3 4 5 6 9 7 8) III/Chương