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 1MÔ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 thuật tiến hóa và công dụng của nó Giúp SV biết cách sử dụng các mẫu thiết kế Singleton, Prototype, Abstract Factory trong từng yêu cầu cụ thể
II Nội dung :
Xây dựng module thực hiện gii thuật tiến hóa trên các cá thể chứa số thực Ý tởng gii thuật tiến hóa nh sau :
1 lúc ầu, ta có 1 thế hệ gồm n cá thể, mỗi cá thể có 1 giá trị ặc trng (specval)
và có ộ thích nghi (fitness) xác ịnh
2 quá trình tiến hóa của mỗi thế hệ diễn ra theo c chế lặp, mỗi chu kỳ tiến hóa
có các hot ộng sau :
- xác ịnh li ộ thich nghi của từng cá thể
- chọn lựa 1 số cá thể có ộ thích nghi cao nhất ể giữ chúng li làm nồng cốt cho thế hệ mới
- cho các cá thể này phối giống ể to ra các cá thể con cho ủ số lợng
- chọn 1 số cá thể và cho chúng ột biến thành các thể khác
III Chuẩn ầu ra :
Nắm vững tính chất, công dụng của các mẫu thiết kế Singleton, Prototype, Abstract Factory ể có thể dùng li mẫu này trong bất kỳ vị trí nào của chng trình mới cần xây dựng
IV Qui trình xây dựng chng trình
Thế hệ các cá thể ầu tiên
Thế hệ các cá thể kế tiếp
1 xác ịnh li ộ thich nghi của từng
cá thể
2 chọn lựa 1 số cá thể có ộ thích nghi cao nhất ể giữ chúng li làm nồng cốt cho thế hệ mới
3 cho các cá thể này phối giống ể to ra các cá thể con cho ủ số lợng
4 chọn 1 số cá thể và cho chúng ột biến thành các thể khác
Trang 21 Chy VS Net, chọn menu File.New.Project ể hiển thị cửa sổ New Project
2 Mở rộng mục Visual C# trong TreeView "Project Types", chọn mục Window, chọn icon "Windows Form Application" trong listbox "Templates" bên phi, thiết lập th mục chứa Project trong listbox "Location", nhập tên Project vào textbox
"Name:" (td BaiTH5), click button OK ể to Project theo các thông số ã khai báo
3 Form ầu tiên của ứng dụng ã hiển thị trong cửa sổ thiết kế, việc thiết kế form
là quá trình lặp 4 thao tác to mới/xóa/hiệu chỉnh thuộc tính/to hàm xử lý sự kiện cho từng ối tợng cần dùng trong form Ta s giới thiệu yêu cầu của ứng dụng sau Bây giờ ta s xây dựng th viện chứa các thành phần miêu t thuật gii tiến hóa tổng quát
4 Dời chuột về gốc cây Project trong cửa sổ "Solution Explorer", ấn phi chuột trên phần tử gốc này, chọn option Add.New Folder, ặt tên cho folder mới là GenLib
5 Thờng bài toán dùng thuật gii tiến hóa cần to thế hệ ầu tiên các cá thể 1 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 của nhiều phần tử trong phần mềm ợc nhất quán, ta s to 1 ối tợng duy nhất chuyên phục
vụ to số ngẫu nhiên ể bo m phần tử to số ngẫu nhiên là duy nhất, ta dùng mẫu thiết kế Singleton Hãy hiện thực ối tợng này có các dịch vụ sau :
to số nguyên ngẫu nhiên bất kỳ
to số nguyên ngẫu nhiên nằm trong khong từ 0 tới n
to số thực ngẫu nhiên nằm trong khong từ 0 tới 1
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là MyRandom.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
classMyRandom {
//hàm khởi to private ể cấm bên ngoài to ối tợng MyRandom
private MyRandom() { }
//thông tin dùng chung trong class
privatestaticMyRandom myrnd = newMyRandom();
publicstaticMyRandom getInstance() { return myrnd; }
//thông tin trong ối tợng
privateRandom rnd = newRandom();
//tác vụ to số nguyên ngẫu nhiên bất kỳ
publicint RndInt() { return rnd.Next(); }
//tác vụ to số nguyên ngẫu nhiên trong khong từ 0 ến n
publicint RndInt(int n) { return rnd.Next(n); }
//tác vụ to số thực ngẫu nhiên từ 0 tới 1
publicdouble RndDouble() { return rnd.NextDouble(); }
}
Lu ý rằng ta ã dùng mẫu Adapter ể xây dựng class MyRandom dựa trên class Random của NET
Trang 36 ịnh nghĩa interface cho ối tợng cá thể của thuật gii tiến hóa tổng quát có cá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 mình
nhân bn vô tính mình
gii mã mình thành chuỗi vn bn
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là IIndividual.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceIIndividual : IComparable<IIndividual> {
//thuộc tính luận lý SpecValue : chỉ ọ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 mình
void muter();
//hàm to ối tợng mới 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();
}
7 Viết thêm class abstract chứa những thông tin chung mà các ối tợng cá thể khác nhau s dùng Dĩ nhiên class này phi hiện thực interface IIndividual : Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là AbstractIndividual.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
abstractclassAbstractIndividual : IIndividual {
protecteddouble fitness = 0.0;
protectedbool muted = false;
public AbstractIndividual()
{
}
//thuộc tính luận lý SpecValue : ọc/ghi
publicabstractObject SpecValue { get; set; }
Trang 4publicbool Muted
{
get { return muted; }
set { muted = value; }
}
publicdouble Fitness
{
get { return fitness; }
set { fitness = value; }
}
//hàm so sánh với cá thể khác (phục vụ sắp xếp danh sách)
publicint CompareTo(IIndividual o)
{
if (o.Fitness == Fitness)
return 0;
elseif (Fitness < o.Fitness)
return -1;
return 1;
}
//hàm nhân bn mình theo mẫu Prototype
publicabstractIIndividual clone();
//hàm ột biến mình
publicabstractvoid muter();
//hàm phối giống với other
publicabstractIIndividual cross(IIndividual other);
}
8 Ta cần ối tợng mục tiêu chuyên ánh giá cá thể ể tính ộ thích nghi của các 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 này
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là ITarget.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceITarget {
//tác vụ tính toán cá thể
double eval(IIndividual ind);
}
9 Bây giờ ta ịnh nghĩa interface cho ối tợng thế hệ với các tính chất sau :
lúc ầu cha có cá thể nào
cho phép thêm từng cá thể vào, số lợng các thể là bất kỳ
cho phép tham kho số lợng cá thể
Trang 5 tiến hóa sang thế hệ mới theo 2 phng pháp : phối giống và ột biến
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là IPopulation.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceIPopulation {
//hàm tr về số cá thể
int size();
//hàm thêm cá thể mới vào thế hệ
void add(IIndividual individu);
//thuộc tính truy xuất cá thể thứ i
IIndividualthis[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 thế hệ mới
IPopulation evoluer(ITarget cible);
}
10 Ta hiện thực ối tợng thế hệ, ối tợng này s chứa thuật gii tiến hóa tổng quát
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là Population.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
classPopulation : IPopulation {
//qun lý thế hệ các cá thể bằng class List<T> của NET
privateList<IIndividual> individus = newList<IIndividual>();
//dùng ối tợng to số ngẫu nhiên duy nhất trong toàn chng trình
privatestaticMyRandom rnd = MyRandom.getInstance();
//hàm tr về số cá thể
publicint size() {
return individus.Count();
}
//hàm thêm cá thể mới vào thế hệ
publicvoid add(IIndividual individu) {
individus.Add(individu);
}
//thuộc tính truy xuất cá thể thứ i
publicIIndividualthis[int i] {
get { return individus[i]; }
}
//hàm gii mã ối tợng thành chuỗi vn bn
publicoverrideString ToString() {
String buf = "[";
Trang 6bool 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 thế hệ mới
publicIPopulation evoluer(ITarget cible) {
//tính ộ thích nghi các cá thể và sắp xếp chúng
evaluer(cible);
//to thế hệ mới
Population pop = reproduire();
//cho 5% cá thể bị ột biến
pop.muter(0.05);
//tính li ộ thích nghi các cá thể và sắp xếp chúng
//pop.evaluer(cible);
return pop;
}
//hàm tính ộ thích nghi của từng cá thể và sắp xếp các cá thể theo ộ thích nghi của chúng
privatevoid evaluer(ITarget cible) {
//lặp tính ộ thích nghi của từng cá thể
foreach (IIndividual ind in individus)
{
ind.Fitness = cible.eval(ind);
}
//sắp xếp các cá thể theo ộ thích nghi của chúng
Sort();
}
//hàm sắp xếp thự tự các cá thể theo ngữ nghĩa xác ịnh
privatevoid Sort() {
individus.Sort();
individus.Reverse();
}
//hàm ột biến cho cá thể
privatevoid 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<IIndividual> subl = individus.GetRange(1, individus.Count - 1);
//xử lý ột biến cho từng cá thể với xác suất ratio
Trang 7foreach (IIndividual ind in subl) {
if (rnd.RndDouble() < ratio)
ind.muter();
}
}
//hàm to thế hế mới
privatePopulation reproduire() {
//chọn 20% cá thể có ộ thích nghi tốt nhất
int max = individus.Count() / 5;
Population pop = newPopulation();
//cho chúng thành cá thể của thế hệ mới
for (int i = 0; i < max; i++) {
pop.add(individus[i].clone());
}
//lặp phối giống từng cặp cá thể ã có (chọn ngẫu nhiên) ể to thêm 80% cá thể mới 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 các ối tợng mà chng trình ứng dụng dùng ối tợng Factory có kh nng nh sau :
to ợc 1 thế hệ cá thể với số lợng xác ịnh
to ợc ối tợng mục tiêu của bài toán
Dời chuột về th mục GenLib trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là IPopulationFactory.cs, chọn button Add ể máy to 1 interface mới Viết code cho interface này nh sau :
interfaceIPopulationFactory {
//hàm to ối tợng mục tiêu
ITarget createTarget() ;
//hàm to thế hệ có size cá thể ngẫu nhiên
IPopulation createRandomPopulation(int size) ;
}
12 Bây giờ ta thử áp dụng thuật gii tiến hóa vào bài toán n gin nh sau : ta lấy 1 số thực mục tiêu ngẫu nhiên, ta to ngẫu nhiên 1 thế 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 trong th viện GenLib ể xem thế hệ số thực ban ầu có hội tụ về giá trị mục miêu hay không ?
Trang 813 Ta ịnh nghĩa class MyDouble ể qun lý số thực MyDouble chính là giá trị ặc trng của cá thể cần tiến hóa
Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là MyDouble.cs, chọn button Add
ể máy to 1 class mới Viết code cho class này nh sau :
classMyDouble {
privatedouble val;
public MyDouble(double v) { val = v; }
publicdouble Val
{
get { return val; }
set { val = value; }
}
//hàm gii mã ối tợng mục tiêu ra chuỗi vn bn
publicoverrideString ToString()
{
String buf = String.Format("{0:f5}", val);
return buf;
}
}
14 Hiện thực ối tợng cá thể có các tính chất cụ thể nh sau :
giá trị ặc trng là ối tợng MyDouble qun lý số thực từ 0 tới 1
ộ fitness là số thực, càng lớn nghĩa là càng thích nghi tốt
phối giống với cá thể khác ể to cá thể con có giá trị ặc trng bằng trung bình cộng của cha m
ột biến mình theo nguyên tắc : to 1 các thể mới ngẫu nhiên, ột biến giá trị ặc trng của mình bằng trung bình cộng của cá thể mới với mình
nhân bn vô tính mình (dùng mẫu Prototype)
gii mã mình thành chuỗi vn bn miêu t giá trị ặc trng
Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”,
ấn phi chuột vào nó ể 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 là DoubleIndividual.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
//giá trị ặc trng của cá thể
private MyDouble spVal;
//ộ thích nghi của 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 duy nhất trong toà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 9public 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ụ sắp 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 của mình MyDouble o2 = other.SpecValue as MyDouble;//giá trị ặc trng của ối tác //to cá thể con
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ể hiện hành
public void muter() {
//ột biến tối a 10% biên ộ giá trị ặc trng
// spVal += (rnd.RndDouble() < 0.5 ? 1 : -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 mới 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 :
nó có giá trị ặc trng là MyDouble chứa 1 số thực từ 0 tới 1 giống nh các
cá thể
tính ộ fitness của cá thể theo công thức 1/((sv1-sv2)^2), trong ố sv1 là giá trị ặc trng của nó và sv2 là giá trị ặc trng của cá thể cần tính toán Dời chuột về phần tử gốc của cây Project trong cửa sổ “Solution Explorer”, ấn phi chuột vào nó ể 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 là DoubleTarget.cs, chọn button Add ể máy to 1 class mới Viết code cho class này nh sau :
//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 duy nhất trong 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 của ối tợng theo ngữ nghĩa mong muốn
//càng gần với mục tiêu càng có ộ thích nghi cao
public double eval(IIndividual i) {
MyDouble o1 = i.SpecValue as MyDouble;
if (o1 == null ) return 0;
return 1 / ((o1.Val - val) * (o1.Val - val));