IV/ HIỆN THỰC CHƯƠNG TRÌNH DƯỚI DẠNG MÁY HỮU HẠN TRẠNG THÁ
SƠ ĐỒ GIẢI THUẬT GEN E:
Trước hết hiện thực chiến thuật thi đấu dưới dạng máy hữu hạn, giá trị fitness gán cho mỗi FSM chính là số điểm đạt được sau một vòng thi đấu với các FSM khác. Các bước thực hiện giải thuật như sau:
Dưới đây là phần hiện thực ở dạng tóm lược nhằm mục đích giải thích thân chương trình chính:
// khai báo dữ liệu
const size_t SSZ=2; // kích thước bảng input, output const size_t NSZ=3; // số trạng thái ban đầu
char SSET[2]={'C', 'D'}; // bảng kí hiệu
const size_t POP_SZ=PopSize; // số chiến thuật khảo sát trong một thế // hệ
// các biến dùng trong chương trình size_t n, i, j, k, inc; double vf; char mj, mk, tj; EvolvingFSM<char, SSZ, char, SSZ> *vm; RouletteWheel<double> *rw; RandDev devgen; FSM_TranData<char> td[NSZ][SSZ]; EVFSM_MuteWts wts= { WeightO, WeightT, WeightA,
WeightD, WeightN };
// phân bố vùng lưu trữ cho cộng đồng
EvolvingFSM<char, SSZ, char, SSZ> **pop=
new EvolvingFSM<char, SSZ, char, SSZ>* [POP_SZ]; EvolvingFSM<char, SSZ, char, SSZ> **newpop=
new EvolvingFSM<char, SSZ, char, SSZ> *[POP_SZ]; double *fit=new double[POP_SZ];
// các con trỏ dùng cho việc sắp xếp
EvolvingFSM<char, SSZ, char, SSZ> **ptrm=pop-1; double *ptrf=fit-1;
// tạo cộng đồng ban đầu for (j=0; j<POP_SZ; ++j) {
for (n=0; n<NSZ; ++n) {
for (i=0; i<SSZ; ++i) { td[n][i].NextState=size_t(devgen()*float(NSZ)); if (devgen()<0.5F) td[n][i].Osym=SSET[0]; else td[n][i].Osym=SSET[1]; } }
pop[j]=new EvolvingFSM<char, SSZ, char, SSZ>
(NSZ, &td[0][0], SSET, SSET, 0,wts); }
size_t g=0;
// bắt đầu vòng lặp chính while (1)
{
// khởi tạo trận đấu double totf=0; double avgf=0;
// xác lập trạng thái ban đầu của các FSM và xoá mảng fitness for (j=0; j<POP_SZ; ++j)
{
pop[j]->Reset(); fit[j]=0.0; }
// đánh giá fitness qua thi đấu for (j=0; j<POP_SZ; ++j) {
for (k=j; k<POP_SZ; ++k) {
// khởi tạo trạng thái ban đầu pop[j]->Reset();
pop[k]->Reset(); // chọn nước đi đầu tiên
FirstMove=(EVMove)intFirstMove; switch (FirstMove) { case EVM_DEFECT: mj='D'; mk='D'; break; case EVM_COOPER: mj='C'; mk='C'; break; case EVM_RANDOM: if (devgen() < 0.5F) mj='C'; else mj='D'; if (devgen() < 0.5F) mk='C'; else mk='D'; } //end switch n=1;
// tính toán fitness theo các nước đi while (1) { if (mj==SSET[0]) { if (mk==SSET[0]) { fit[j]+=PayoffCC; fit[k]+=PayoffCC; } else { fit[j]+=PayoffCD; fit[k]+=PayoffDC; } } else
{ if (mk==SSET[0]) { fit[j]+=PayoffDC; fit[k]+=PayoffCD; } else { fit[j]+=PayoffDD; fit[k]+=PayoffDD; } }
// thoát nếu xong if (n==TestLen)
break;
// chuyển trạng thái dựa trên nước đi trước đối thủ tj=pop[j]->Transition(mk);
mk=pop[k]->Transition(mj); mj=tj;
// nước đi kế tiếp ++n;
} // end while } //end for
} //end for
// sắp xếp để lựa chiến thuật vượt trội của vòng thi đấu for (inc=1; inc <=POP_SZ/9; inc =3*inc+1);
for ( ; inc>0; inc/=3) {
for (i=inc+1; i<=POP_SZ; i +=inc) {
vf=ptrf[i]; vm=ptrm[i]; j=i;
while ((j>inc) && (ptrf[j-inc]<vf)) { ptrf[j]=ptrf[j-inc]; ptrm[j]=ptrm[j-inc]; j -=inc; } ptrf[j]=vf; ptrm[j]=vm; } }
// chấm dứt khi hết số vòng thi đấu if (g==TestSize)
// chuẩn hoá tuyến tính để điều chỉnh các giá trị của mảng // fitness if (FitScale) { fit[0]=FitLinBase; i=1;
while (fit[i-1] > FitLinDec) {
fit[i]=fit[i-1]-FitLinDec; ++i;
}
for ( ; i<POP_SZ; ++i) fit[i]=FitLinMin; }
// chọn chiến thuật vượt trội ở vòng này để khảo sát tiếp ở vòng // sau
newpop[0]= new EvolvingFSM<char,SSZ, char , SSZ> (*(pop[0]));
// sản sinh các chiến thuật mới
rw= new RouletteWheel<double>(POP_SZ, fit); for (j=1; j<POP_SZ; ++j)
{
i=rw->GetIndex();
newpop[j]= new EvolvingFSM<char,SSZ, char , SSZ> (*(pop[i]));
if (devgen()<(MuteRate / 100))
newpop[j]->Mutate(1, MaxState); // thay minstate=1 }
delete rw;
// copy để tạo thế hệ tiếp theo và lặp lại for (j=0; j<POP_SZ; ++j)
{
delete pop[j]; }
for (j=0; j<POP_SZ; ++j)
pop[j]= new EvolvingFSM<char,SSZ, char , SSZ> (*(newpop[j])); for (j=0; j<POP_SZ; ++j) { delete newpop[j]; } ++g; } // end while // giải phóng các vùng lưu trữ
for (j=0; j<POP_SZ; ++j) delete pop[j]; delete [] pop; delete [] newpop; delete [] fit; V- NHẬN XÉT:
Qua nhiều lần chạy thử chương trình , có thể rút ra một số nhận xét sau:
Một chiến thuật muốn được nổi trội trong thi đấu phải mang những đặc điểm: có tính hợp tác (C-C :3 điểm), biết khai thác hành vi của đối thủ (D-C : 5 điểm). Diễn tiến các vòng đấu cho thấy sự xuất hiện nhiều mẫu nước đi mang tính lặp lại
trong các chiến thuật. Một trong những mẫu phổ biến là sự luân phiên giưã hai đấu thủ để có các nước đi trái ngược nhau tạo ra số điểm trung bình cho mỗi nước đi là 2.5. Điều này cho thấy ưu thế trong sinh sản của các chiến thuật thành công. Các chiến thuật luôn đi D hoặc C không bao giờ chiếm ưu thế lâu dài, vì dễ bị đối
thủ khai thác. Hơn nữa các chiến thuật luôn đi D sẽ ghi điểm nghèo nàn khi phải thi đấu với nhau.
Một số chiến thuật được đánh giá cao như "Tit-for-Tat"- bắt trước nước đi của đối thủ, chiến thuật Pavlov-giữ nguyên nước đi khi ghi điểm cao và thay đổi nước đi khi bị điểm thấp cũng được tìm thấy qua kết quả ghi nhận . Ưu điểm của giải thuật Gene trong tìm kiếm có chọn lọc được khẳng định nếu nhận xét với bộ thông số nhập vào, sẽ tương ứng với hơn nửa tỉ các chiến thuật phải khảo sát. Ở đây chỉ dưới mức 100.000 chiến thuật ta đã có được những kết quả khả quan. ---******---
CHƯƠNG VIII
BÀI TOÁN TÌM ĐƯỜNG ĐI NGẮN NHẤT(The Traveling Salesman Problem - TSP)