Microsoft Word Bai 5 1 docx Trang 1 MÔN CÁC MẪU THIẾT KẾ HỚNG ỐI TỢNG Bài thực hành số 5 1 Xây dựng và kiểm thử thuật gii tiến hóa trên các cá thể n gin I Mục tiêu Giúp SV làm quen với gii t[.]
Trang MÔN : CÁC MẪU THIẾT KẾ HỚNG ỐI TỢNG Bài thực hành số 5.1 : Xây dựng kiểm thử thuật gii tiến hóa cá thể n gin I Mục tiêu : Giúp SV làm quen với gii thuật tiến hóa cơng dụng Giúp SV biết cách sử dụng mẫu thiết kế Singleton, Prototype, Abstract Factory yêu cầu cụ thể II Nội dung : Xây dựng module thực gii thuật tiến hóa cá thể chứa số thực Ý tởng gii thuật tiến hóa nh sau : lúc ầu, ta hệ gồm n cá thể, cá thể có giá trị ặc trng (specval) có ộ thích nghi (fitness) xác ịnh q trình tiến hóa hệ diễn theo c chế lặp, chu kỳ tiến hóa có hot ộng sau : - xác ịnh li ộ thich nghi cá thể - chọn lựa số cá thể có ộ thích nghi cao ể giữ chúng li làm nồng cốt cho hệ - cho cá thể phối giống ể to cá thể cho ủ số lợng - chọn số cá thể cho chúng ột biến thành thể khác Thế hệ cá thể ầu tiên xác ịnh li ộ thich nghi cá thể chọn lựa số cá thể có ộ thích nghi cao ể giữ chúng li làm nồng cốt cho hệ cho cá thể phối giống ể to cá thể cho ủ số lợng chọn số cá thể cho chúng ột biến thành thể khác Thế hệ cá thể III Chuẩn ầu : Nắm vững tính chất, cơng dụng mẫu thiết kế Singleton, Prototype, Abstract Factory ể dùng li mẫu vị trí chng trình cần xây dựng IV Qui trình xây dựng chng trình Trang Chy VS Net, chọn menu File.New.Project ể hiển thị cửa sổ New Project Mở rộng mục Visual C# TreeView "Project Types", chọn mục Window, chọn icon "Windows Form Application" listbox "Templates" bên phi, thiết lập th mục chứa Project listbox "Location", nhập tên Project vào textbox "Name:" (td BaiTH5), click button OK ể to Project theo thông số ã khai báo Form ầu tiên ứng dụng ã hiển thị cửa sổ thiết kế, việc thiết kế form trình lặp thao tác to mới/xóa/hiệu chỉnh thuộc tính/to hàm xử lý kiện cho ối tợng cần dùng form Ta s giới thiệu yêu cầu ứng dụng sau Bây ta s xây dựng th viện chứa thành phần miêu t thuật gii tiến hóa tổng quát Dời chuột gốc Project cửa sổ "Solution Explorer", ấn phi chuột phần tử gốc này, chọn option Add.New Folder, ặt tên cho folder GenLib Thờng tốn dùng thuật gii tiến hóa cần to hệ ầu tiên cá thể cách ngẫu nhiên Việc to ối tợng ngẫu nhiên thờng liên quan ến việc to số nguyên, số thực ngẫu nhiên ể việc lấy số ngẫu nhiên nhiều phần tử phần mềm ợc quán, ta s to ối tợng chuyên phục vụ to số ngẫu nhiên ể bo m phần tử to số ngẫu nhiên nhất, ta dùng mẫu thiết kế Singleton Hãy thực ối tợng có dịch vụ sau : to số nguyên ngẫu nhiên to số nguyên ngẫu nhiên nằm khong từ tới n to số thực ngẫu nhiên nằm khong từ tới Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class MyRandom.cs, chọn button Add ể máy to class Viết code cho class nh sau : class MyRandom { //hàm khởi to private ể cấm bên to ối tợng MyRandom private MyRandom() { } //thông tin dùng chung class private static MyRandom myrnd = new MyRandom(); public static MyRandom getInstance() { return myrnd; } //thông tin ối tợng private Random rnd = new Random(); //tác vụ to số nguyên ngẫu nhiên public int RndInt() { return rnd.Next(); } //tác vụ to số nguyên ngẫu nhiên khong từ ến n public int RndInt(int n) { return rnd.Next(n); } //tác vụ to số thực ngẫu nhiên từ tới public double RndDouble() { return rnd.NextDouble(); } } Lu ý ta ã dùng mẫu Adapter ể xây dựng class MyRandom dựa class Random NET Trang ịnh nghĩa interface cho ối tợng cá thể thuật gii tiến hóa tổng quát có dịch vụ sau : tham kho giá trị ặc trng tham kho/hiệu chỉnh ộ fitness phối giống với cá thể khác ột biến nhân bn vơ tính gii mã thành chuỗi vn bn Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface IIndividual.cs, chọn button Add ể máy to interface Viết code cho interface nh sau : interface IIndividual : IComparable { //thuộc tính luận lý SpecValue : ọc Object SpecValue {get;} //thuộc tính luận lý Fitness : ọc/ghi double Fitness {get; set;} //hàm phối giống với other IIndividual cross(IIndividual other); //hàm ột biến void muter(); //hàm to ối tợng theo c chế nhân bn vơ tính (dùng mẫu Prototype) IIndividual clone(); //hàm gii mã ối tợng thành dng chuỗi vn bn String ToString(); } Viết thêm class abstract chứa thông tin chung mà ối tợng cá thể khác s dùng Dĩ nhiên class phi thực interface IIndividual : Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class AbstractIndividual.cs, chọn button Add ể máy to class Viết code cho class nh sau : abstract class AbstractIndividual : IIndividual { protected double fitness = 0.0; protected bool muted = false; public AbstractIndividual() { } //thuộc tính luận lý SpecValue : ọc/ghi public abstract Object SpecValue { get; set; } Trang public bool Muted { get { return muted; } set { muted = value; } } public double Fitness { get { return fitness; } set { fitness = value; } } //hàm so sánh với cá thể khác (phục vụ xếp danh sách) public int CompareTo(IIndividual o) { if (o.Fitness == Fitness) return 0; else if (Fitness < o.Fitness) return -1; return 1; } //hàm nhân bn theo mẫu Prototype public abstract IIndividual clone(); //hàm ột biến public abstract void muter(); //hàm phối giống với other public abstract IIndividual cross(IIndividual other); } Ta cần ối tợng mục tiêu chuyên ánh giá cá thể ể tính ộ thích nghi thể ó theo ngữ nghĩa xác ịnh Trớc hết ta ịnh nghĩa interface tối thiểu cho ối tợng mục tiêu Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface ITarget.cs, chọn button Add ể máy to interface Viết code cho interface nh sau : interface ITarget { //tác vụ tính tốn cá thể double eval(IIndividual ind); } Bây ta ịnh nghĩa interface cho ối tợng hệ với tính chất sau : lúc ầu cha có cá thể cho phép thêm cá thể vào, số lợng thể cho phép tham kho số lợng cá thể Trang tiến hóa sang hệ theo phng pháp : phối giống ột biến Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface IPopulation.cs, chọn button Add ể máy to interface Viết code cho interface nh sau : interface IPopulation { //hàm tr số cá thể int size(); //hàm thêm cá thể vào hệ void add(IIndividual individu); //thuộc tính truy xuất cá thể thứ i IIndividual this[int i] { get; } //hàm gii mã ối tợng thành chuỗi vn bn String ToString(); //hàm tiến hóa sang hệ IPopulation evoluer(ITarget cible); } 10 Ta thực ối tợng hệ, ối tợng s chứa thuật gii tiến hóa tổng quát Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class Population.cs, chọn button Add ể máy to class Viết code cho class nh sau : class Population : IPopulation { //qun lý hệ cá thể class List NET private List individus = new List(); //dùng ối tợng to số ngẫu nhiên tồn chng trình private static MyRandom rnd = MyRandom.getInstance(); //hàm tr số cá thể public int size() { return individus.Count(); } //hàm thêm cá thể vào hệ public void add(IIndividual individu) { individus.Add(individu); } //thuộc tính truy xuất cá thể thứ i public IIndividual this[int i] { get { return individus[i]; } } //hàm gii mã ối tợng thành chuỗi vn bn public override String ToString() { String buf = "["; Trang bool fstart = true; for (int i = 0; i < individus.Count(); i++) if (fstart) { fstart = false; buf += individus[i].ToString(); } else buf += ", " + individus[i].ToString(); return buf + "]"; } //hàm tiến hóa sang hệ public IPopulation evoluer(ITarget cible) { //tính ộ thích nghi cá thể xếp chúng evaluer(cible); //to hệ Population pop = reproduire(); //cho 5% cá thể bị ột biến pop.muter(0.05); //tính li ộ thích nghi cá thể xếp chúng //pop.evaluer(cible); return pop; } //hàm tính ộ thích nghi cá thể xếp cá thể theo ộ thích nghi chúng private void evaluer(ITarget cible) { //lặp tính ộ thích nghi cá thể foreach (IIndividual ind in individus) { ind.Fitness = cible.eval(ind); } //sắp xếp cá thể theo ộ thích nghi chúng Sort(); } //hàm xếp thự tự cá thể theo ngữ nghĩa xác ịnh private void Sort() { individus.Sort(); individus.Reverse(); } //hàm ột biến cho cá thể private void muter(double ratio) { //to tập hợp cá thể cần ột biến (trừ cá thể ầu tiên có ộ thích nghi tốt nhất) List subl = individus.GetRange(1, individus.Count - 1); //xử lý ột biến cho cá thể với xác suất ratio Trang foreach (IIndividual ind in subl) { if (rnd.RndDouble() < ratio) ind.muter(); } } //hàm to hế private Population reproduire() { //chọn 20% cá thể có ộ thích nghi tốt int max = individus.Count() / 5; Population pop = new Population(); //cho chúng thành cá thể hệ for (int i = 0; i < max; i++) { pop.add(individus[i].clone()); } //lặp phối giống cặp cá thể ã có (chọn ngẫu nhiên) ể to thêm 80% cá thể for (int i = max; i < size(); i++) { int mec = rnd.RndInt(max); int mef = rnd.RndInt(max); pop.add(individus[mec].cross(individus[mef])); } return pop; } } 11 Ta dùng mẫu Abstract Factory ể cung cấp dịch vụ to ối tợng mà chng trình ứng dụng dùng ối tợng Factory có kh nng nh sau : to ợc hệ cá thể với số lợng xác ịnh to ợc ối tợng mục tiêu toán Dời chuột th mục GenLib cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.New Item ể hiển thị cửa sổ “Add New Item”, chọn mục “Interface”, hiệu chỉnh tên interface IPopulationFactory.cs, chọn button Add ể máy to interface Viết code cho interface nh sau : interface IPopulationFactory { //hàm to ối tợng mục tiêu ITarget createTarget() ; //hàm to hệ có size cá thể ngẫu nhiên IPopulation createRandomPopulation(int size) ; } 12 Bây ta thử áp dụng thuật gii tiến hóa vào toán n gin nh sau : ta lấy số thực mục tiêu ngẫu nhiên, ta to ngẫu nhiên hệ xuất phát gồm n số thực có ngẫu nhiên Thử áp dụng thuật gii tiến hóa tổng quát ợc xây dựng th viện GenLib ể xem hệ số thực ban ầu có hội tụ giá trị mục miêu hay không ? Trang 13 Ta ịnh nghĩa class MyDouble ể qun lý số thực MyDouble giá trị ặc trng cá thể cần tiến hóa Dời chuột phần tử gốc Project cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, hiệu chỉnh tên class MyDouble.cs, chọn button Add ể máy to class Viết code cho class nh sau : class MyDouble { private double val; public MyDouble(double v) { val = v; } public double Val { get { return val; } set { val = value; } } //hàm gii mã ối tợng mục tiêu chuỗi vn bn public override String ToString() { String buf = String.Format("{0:f5}", val); return buf; } } 14 Hiện thực ối tợng cá thể có tính chất cụ thể nh sau : giá trị ặc trng ối tợng MyDouble qun lý số thực từ tới ộ fitness số thực, lớn nghĩa thích nghi tốt phối giống với cá thể khác ể to cá thể có giá trị ặc trng trung bình cộng cha m ột biến theo nguyên tắc : to thể ngẫu nhiên, ột biến giá trị ặc trng trung bình cộng cá thể với nhân bn vơ tính (dùng mẫu Prototype) gii mã thành chuỗi vn bn miêu t giá trị ặc trng Dời chuột phần tử gốc Project cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, hiệu chỉnh tên class DoubleIndividual.cs, chọn button Add ể máy to class Viết code cho class nh sau : using BaiTH5.GenLib; class DoubleIndividual : IIndividual { //giá trị ặc trng cá thể private MyDouble spVal; //ộ thích nghi cá thể private double fitness = 0.0; //thuộc tính miêu t ã bị ộ biến cha private bool muted = false; //ối tợng to số ngẫu nhiên tồn chng trình private static MyRandom rnd = MyRandom.getInstance(); //hàm khởi to cá thể có giá trị ặc trng ngẫu nhiên Trang public DoubleIndividual() { this.spVal = new MyDouble(rnd.RndDouble()); } //hàm khởi to cá thể có giá trị ặc trng xác ịnh public DoubleIndividual(MyDouble valeurPropre) { this.spVal = valeurPropre; } //hiện thực thuộc tính luận lý Muted public bool Muted { get { return muted; } set { muted = value; } } //hiện thực thuộc tính luận lý SpecValue public Object SpecValue { get { return spVal; } set { spVal = (MyDouble)value; } } //hiện thực thuộc tính luận lý Fitness public double Fitness { get { return fitness; } set { fitness = value; } } //hàm gii mã ối tợng thành chuỗi vn bn public override String ToString() { //return String.Format("vp={0:f4}, fit={1:f4}",valeurPropre, fitness); return String.Format("{0:f5}", spVal); } //hàm so sánh với cá thể khác (phục vụ xếp danh sách) public int CompareTo(IIndividual o) { if (o.Fitness == Fitness) return 0; else if (Fitness < o.Fitness) return -1; return 1; } //hàm phối giống với cá thể khác public IIndividual cross(IIndividual other) { MyDouble o1 = SpecValue as MyDouble; //giá trị ặc trng MyDouble o2 = other.SpecValue as MyDouble;//giá trị ặc trng ối tác //to cá thể if (o1 == null && o2 == null) return new DoubleIndividual(new MyDouble(0)); if (o1 == null) return other; if (o2 == null) return this; return new DoubleIndividual(new MyDouble((o1.Val + o2.Val) / 2)); } Trang 10 //hàm ột biến cá thể hành public void muter() { //ột biến tối a 10% biên ộ giá trị ặc trng // spVal += (rnd.RndDouble() < 0.5 ? : -1) * rnd.RndDouble() * 0.1 * spVal; //theo trung bình cộng với giá trị ặc trng ngẫu nhiên spVal = new MyDouble((spVal.Val + rnd.RndDouble()) / 2); //theo giá trị ặc trng ngẫu nhiên // spVal = Math.random(); } //hàm to ối tợng theo c chế nhân bn vơ tính (dùng mẫu Prototype) public IIndividual clone() { return new DoubleIndividual(spVal); } } 15 Hiện thực ối tợng mục tiêu nh sau : có giá trị ặc trng MyDouble chứa số thực từ tới giống nh cá thể tính ộ fitness cá thể theo công thức 1/((sv1-sv2)^2), ố sv1 giá trị ặc trng sv2 giá trị ặc trng cá thể cần tính tốn Dời chuột phần tử gốc Project cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class DoubleTarget.cs, chọn button Add ể máy to class Viết code cho class nh sau : using BaiTH5.GenLib; class DoubleTarget : ITarget { //giá trị mục tiêu mà ta mong muốn t ợc private double val; //ối tợng to số ngẫu nhiên toàn chng trình private MyRandom rnd = MyRandom.getInstance(); //hàm khởi to ngẫu nhiên giá trị mục tiêu public DoubleTarget() { val = rnd.RndDouble(); } //hàm khởi to giá trị mục tiêu xác ịnh public DoubleTarget(double d) { val = d; } //hàm tính ộ thích nghi ối tợng theo ngữ nghĩa mong muốn //càng gần với mục tiêu có ộ thích nghi cao public double eval(IIndividual i) { MyDouble o1 = i.SpecValue as MyDouble; if (o1 == null) return 0; return / ((o1.Val - val) * (o1.Val - val)); Trang 11 } //tác vụ tính tốn trị cá thể public double getVal(IIndividual i) { MyDouble o1 = i.SpecValue as MyDouble; if (o1 == null) return 0; return o1.Val; } //hàm tr giá trị mục tiêu public double getValue() { return val; } //hàm gii mã ối tợng mục tiêu chuỗi vn bn public override String ToString() { String buf = String.Format("Giá trị mong muốn : {0:f5}", val); return buf; } } 16 Hiện thực ối tợng Factory cho ứng dụng nh sau : Dời chuột phần tử gốc Project cửa sổ “Solution Explorer”, ấn phi chuột vào ể hiển thị menu lệnh, chọn chức nng Add.Class ể hiển thị cửa sổ “Add New Item”, chọn mục “Class”, hiệu chỉnh tên class DoublePopFactory.cs, chọn button Add ể máy to class Viết code cho class nh sau : using BaiTH6.GenLib; class DoublePopFactory : IPopulationFactory { //hàm to ối tợng mục tiêu public ITarget createTarget() { return new DoubleTarget(); } //hàm to hệ có size cá thể ngẫu nhiên public IPopulation createRandomPopulation(int size) { //to hệ rỗng IPopulation pop = new Population(); //lặp thêm cá thể vào hệ for (int i = 0; i < size; i++) { pop.add(new DoubleIndividual()); } return pop; } } 17 Nếu cửa sổ ToolBox cha hiển thị chi tiết, chọn menu View.Toolbox ể hiển thị (thờng nằm bên trái hình) Click chuột vào button (Auto Hide) nằm góc phi cửa sổ ToolBox ể chuyển chế ộ hiển thị thờng trực 18 Duyệt tìm phần tử Button cửa sổ ToolBox, chọn v góc trái Form Vào cửa sổ thuộc tính Button hiệu chỉnh li thuộc tính Text = Trang 12 "Start", thuộc tính (Name) = btnStart To hàm xử lý kiện Click Button viết on code kiểm thử thuật gii tiến hóa nh sau : using System.IO; using BaiTH6.GenLib; private void btnStart_Click(object sender, EventArgs e){ int popSize = 20; int nbGens = 10; //to ối tợng qun lý file ể ghi liệu StreamWriter oFile = new StreamWriter("data.txt", true, Encoding.Unicode); //xuất số cá thể hệ file oFile.WriteLine("Ta sử dụng cộng ồng có " + popSize + " cá thể"); //to ối tợng Factory cho ứng dụng IPopulationFactory pf = new DoublePopFactory(); //nhờ Factory to ngẫu nhiên hệ ầu tiên IPopulation pop = pf.createRandomPopulation(popSize); //nhờ Factory to ối tợng mục tiêu cần hội tụ tới ITarget vc = pf.createTarget(); //xuất ối tợng mục tiêu file oFile.WriteLine(vc); //lặp tiến hóa hệ với số lầ lặp xác ịnh for (int i = 0; i < nbGens; i++) { //xuất hệ hành file oFile.WriteLine("Thế hệ " + i + ":"); oFile.WriteLine(pop); pop = pop.evoluer(vc); } //xuất hệ cuối file oFile.WriteLine("Kết qu : " + pop); //óng file oFile.Close(); } 19 Dịch chy chng trình Nếu có lỗi sửa, hết lỗi chng trình s chy Chức nng chng trình to thử hệ gồm popSize cá thể, cho tiến hóa nbGen chu kỳ, chu kỳ tiến hóa chng trình xuất giá trị ặc trng cá thể hệ hành file ể kiểm tra 20 Dùng trình WordPad mở file data.txt th mục chứa file kh thi chng trình, quan sát xem giá trị mục tiêu bao nhiêu, giá trị ặc trng ban ầu cá thể, giá trị ặc trng cá thể theo hệ giá trị ặc trng cá thể hệ cuối So sánh xem chúng có gần sát với giá trị mục tiêu không ?