I. Thuật toán di truyền. Thuật toán di truyền (TTDT) là thuật toán bắt chước sự chọn lọc tự nhiên và di truyền. Trong tự nhiên, các cá thể khỏe, có khả năng thích nghi tốt với môi trường sẽ được tái sinh và nhân bản ở các thế hệ sau. Mỗi cá thể có cấu trúc gien đặc trưng cho phẩm chất của cá thể đó. Trong quá trình sinh sản, các cá thể con có thể thừa hưởng các phẩm chất của cả cha và mẹ, cấu trúc gien của nó mang một phần cấu trúc gien của cha và mẹ. Ngoài ra, trong quá trình tiến hóa, có thể xảy ra hiện tượng đột biến, cấu trúc gien của cá thể con có thể chứa các gien mà cả cha và mẹ đều không có. Trong TTDT, mỗi cá thể được mã hóa bởi một cấu trúc dữ liệu mô tả cấu trúc gien của cá thể đó, ta sẽ gọi nó là nhiễm sắc thể (chroniosome). Mỗi nhiễm sắc thể được tạo thành từ các đơn vị được gọi là gien. Chẳng hạn, trong các TTDT cổ điển, các nhiễm sắc thể là các chuỗi nhị phân, tức là mỗi cá thể được biểu diễn bởi một chuỗi nhị phân. TTDT sẽ làm việc trên các quần thể gồm nhiều cá thể. Một quần thể ứng với một giai đoạn phát triển sẽ được gọi là một thế hệ. Từ thế hệ ban đầu được tạo ra, TTDT bắt chước chọn lọc tự nhiên và di truyền để biến đổi các thế hệ. TTDT sử dụng các toán tử cơ bản sau đây để biến đổi các thế hệ. • Toán tử tái sinh (reproduction) (còn được gọi là toán tử chọn lọc (selection)). Các cá thể tốt được chọn lọc để đưa vào thế hệ sau. Sự lựa chọn này được thực hiện dựa vào độ thích nghi với môi trường của mỗi cá thể. Ta sẽ gọi hàm ứng mỗi cá thể với độ thích nghi của nó là hàm thích nghi (fitness function). • Toán tử lai ghép (crossover). Hai cá thể cha và mẹ trao đổi các gien để tạo ra hai cá thể con. • Toán tử đột biến (mutation). Một cá thể thay đổi một số gien để tạo thành cá thể mới. Tất cả các toán tử trên khi thực hiện đều mang tính ngẫu nhiên. **Các bước cơ bản của giải thuật di truyền: 1. Khởi tạo 1 quần thể ban đầu gồm các chuỗi nhiễm sắc thể. 2. Xác định giá trị mục tiêu cho từng nhiễm sắc thể tương ứng. 3. Tạo các nhiễm sắc thể mới dựa trên các toán tử di truyền. 4. Loại bớt các nhiễm sắc thể có độ thích nghi thấp. 5. Xác định hàm mục tiêu cho các nhiễm sắc thể mới và đưa vào quần thể. 6. Kiểm tra thỏa mãn điều kiện dừng.Nếu điều kiện đúng, lấy ra nhiễm sắc thể tốt nhất, giải thuật dừng lại; ngược lại, quay về bước 3.
Trang 1HỌC VIỆN KỸ THUẬT QUÂN SỰ
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO MÔN HỌC TRÍ TUỆ NHÂN TẠO
Giáo viên hướng dẫn: Ngô Hữu Phúc
HÀ NỘI 3/2010
Trang 2I Thuật toán di truyền.
Thuật toán di truyền (TTDT) là thuật toán bắt chước sự chọn lọc tự nhiên và di truyền Trong tự nhiên, các cá thể khỏe, có khả năng thích nghi tốt với môi trường sẽ được tái sinh và nhân bản ở các thế hệ sau Mỗi cá thể có cấu trúc gien đặc trưng cho phẩm chất của cá thể đó Trong quá trình sinh sản, các cá thể con có thể thừa hưởng các phẩm chất của cả cha và mẹ, cấu trúc gien của nó mang một phần cấu trúc gien của cha và mẹ Ngoài ra, trong quá trình tiến hóa, có thể xảy
ra hiện tượng đột biến, cấu trúc gien của cá thể con có thể chứa các gien mà cả cha và mẹ đều không có
Trong TTDT, mỗi cá thể được mã hóa bởi một cấu trúc dữ liệu mô tả cấu trúc gien của cá thể đó,
ta sẽ gọi nó là nhiễm sắc thể (chroniosome) Mỗi nhiễm sắc thể được tạo thành từ các đơn vị
được gọi là gien Chẳng hạn, trong các TTDT cổ điển, các nhiễm sắc thể là các chuỗi nhị phân, tức là mỗi cá thể được biểu diễn bởi một chuỗi nhị phân
TTDT sẽ làm việc trên các quần thể gồm nhiều cá thể Một quần thể ứng với một giai đoạn phát
triển sẽ được gọi là một thế hệ Từ thế hệ ban đầu được tạo ra, TTDT bắt chước chọn lọc tự
nhiên và di truyền để biến đổi các thế hệ TTDT sử dụng các toán tử cơ bản sau đây để biến đổi các thế hệ
Toán tử tái sinh (reproduction) (còn được gọi là toán tử chọn lọc (selection)) Các cá thể
tốt được chọn lọc để đưa vào thế hệ sau Sự lựa chọn này được thực hiện dựa vào độ thích nghi
với môi trường của mỗi cá thể Ta sẽ gọi hàm ứng mỗi cá thể với độ thích nghi của nó là hàm
thích nghi (fitness function).
Toán tử lai ghép (crossover) Hai cá thể cha và mẹ trao đổi các gien để tạo ra hai cá thể
con
Toán tử đột biến (mutation) Một cá thể thay đổi một số gien để tạo thành cá thể mới.
Tất cả các toán tử trên khi thực hiện đều mang tính ngẫu nhiên
**Các bước cơ bản của giải thuật di truyền:
1 Khởi tạo 1 quần thể ban đầu gồm các chuỗi nhiễm sắc thể
2 Xác định giá trị mục tiêu cho từng nhiễm sắc thể tương ứng
3 Tạo các nhiễm sắc thể mới dựa trên các toán tử di truyền
4 Loại bớt các nhiễm sắc thể có độ thích nghi thấp
5 Xác định hàm mục tiêu cho các nhiễm sắc thể mới và đưa vào quần thể
6 Kiểm tra thỏa mãn điều kiện dừng.Nếu điều kiện đúng, lấy ra nhiễm sắc thể tốt nhất, giải thuật dừng lại; ngược lại, quay về bước 3
Trang 3**Cấu trúc cơ bản của TTDT là như sau:
Simple Genetic Algorithm{}
{
Initialize the Population;
Calculate Fitness Function;
While (Fitness != Optimal Value)
{
Selection
Crossover
Mutation
Calculate Fitness Function
}
}
Trong thủ tục trên, điều kiện kết thúc vòng lặp có thể là một số thế hệ đủ lớn nào đó, hoặc độ thích nghi của các cá thể tốt nhất trong các thế hệ kế tiếp nhau khác nhau không đáng kể Khi thuật toán dừng, cá thể tốt nhất trong thế hệ cuối cùng được chọn làm nghiệm cần tìm
Ta xét chi tiết cách mã hóa,toán tử chọn lọc và các toán tử di truyền (lai ghép, đột biến) trong các TTDT:
1.Mã hóa:
Mã hóa nhị phân
Là dạng mã hóa phổ biến nhất và cách mã hóa chuỗi bit thay đổi tùy theo vấn đề.
Làm việc với integer tốt hơn floating point
*Ưu điểm:
Dễ giao phối (mating) Biểu diễn nhiễm sắc thể với 1 số ít gen
Trang 4*Khuyết điểm:
Không thể giới hạn các thay đổi dễ dàng
Tiến hành hiệu chỉnh sau khi mate
VD: A: 0101101100010011
B: 1011010110110101
Mã hóa hoán vị
Nhiễm sắc thể là 1 chuỗi số thực, được biểu diễn theo thứ tự
*Ưu điểm: hữu dụng cho các vấn đề thứ tự
*Khuyết điểm: có thể phải hiệu chỉnh sau khi mate
VD: A:8549102367
B: 9102438576
Mã hóa giá trị
Mỗi nhiễm sắc thể là chuỗi giá trị
Giá trị là bất cứ thứ gì liên quan đến vấn đề như: số, ký tự, đối tượng…
VD:
A: [red], [black], [blue], [yellow], [red], [green]
B: 1.8765, 3.9821, 9.1283, 6.8344, 4.116, 2.192
C: ABCKDEIFGHNWLSWWEKPOIKNGVCI
Mã hóa cây
Được dùng chủ yếu để rút ra các biểu thức chương trình
*Ưu điểm: biểu diễn không gian tìm kiếm không giới hạn (open-ended)
*Khuyết điểm: xảy ra lỗi tiềm tàng,phát triển theo hướng không thể kiểm soát, khi phát triển lớn thì rất khó hiểu và không để đơn giản hóa
2 Chọn lọc: Việc chọn lọc các cá thể từ một quần thể dựa trên độ thích nghi của mỗi cá thể Các
cá thể có độ thích nghi cao có nhiều khả năng được chọn Cần nhấn mạnh rằng, hàm thích nghi
chỉ cần là một hàm thực dương, nó có thể không tuyến tính, không liên tục, không khả vi Quá
trình chọn lọc được thực hiện theo kỹ thuật quay bánh xe
Trang 5Giả sử thế hệ hiện thời P(t) gồm có n cá thể {x1, ,xn} Số n được gọi là cỡ của quần thể Với mỗi
cá thể xi, ta tính độ thích nghi của nó f(xi) Tính tổng các độ thích nghi của tất cả các cá thể trong quần thể:
Mỗi lần chọn lọc, ta thực hiện hai bước sau:
Sinh ra một số thực ngẫu nhiên q trong khoảng (0, F);
xk là cá thể được chọn, nếu k là số nhỏ nhất sao cho
Việc chọn lọc theo hai bước trên có thể minh họa như sau: Ta có một bánh xe được chia thành n phần, mỗi phần ứng với độ thích nghi của một cá thể (hình 3.5) Một mũi tên chỉ vào bánh xe Quay bánh xe, khi bánh xe dừng, mũi tên chỉ vào phần nào, cá thể ứng với phần đó được chọn
Rõ ràng là với cách chọn này, các cá thể có thể có độ thích nghi càng cao càng có khả năng được chọn Các cá thể có độ thích nghi cao có thể có một hay nhiều bản sao, các cá thể có độ thích nghi thấp có thể không có mặt ở thế hệ sau
3 Lai ghép: Trên cá thể được chọn lọc, ta tíến hành toán tử lai ghép Đầu tiên ta cần đưa ra xác
suất lai ghép pc xác suất này cho ta hy vọng có pc.n cá thể được lai ghép (n là cỡ của quần thể) Với mỗi cá thể ta thực hiện hai bước sau:
Sinh ra số thực ngẫu nhiên r trong đoạn [0, 1];
Nếu r < pc thì cá thể đó được chọn để lai ghép
Từ các cá thể được chọn để lai ghép, người ta cặp đôi chúng một cách ngẫu nhiên.Trong trường hợp các nhiễm sắc thể là các chuỗi nhị phân có độ dài cố định m, ta có thể thực hiện lai ghép như sau: với mỗi cặp,sinh ra một số nguyên ngẫu nhiên p trên đoạn [0,m-1],
p là vị trí điểm ghép Cặp gồm 2 nhiễm sắc thể:
n
1 i f(xi) F
k i
xi f
1
4 ) (
Trang 6a = (a 1, , a p, a p+1, , a m )
a = (b 1, , b p, b p+1, , b m )
được thay bởi 2 con là:
a' = (a 1, , a p, b p+1, , b m ) b' = (b 1, , b p, a p+1, , a m )
4 Đột biến: Ta thực hiện toán tử đột biến trên các cá thể có được sau quá trình lai ghép Đột biến
là thay đổi trạng thái một số gien nào đó trong nhiễm sắc thể Mỗi gien chịu đột biến với xác suất
pm Xác suất đột biến pm do ta xác định và là xác suất thấp Sau đây là toán tử đột biến trên các nhiễm sắc thể chuỗi nhị phân
Với mỗi vị trí i trong nhiễm sắc thể:
a = (a 1, , a i, , a m )
Ta sinh ra một số thực nghiệm ngẫu nhiên pi trong [0,1] Qua đột biến a được biến thành a’ như sau:
a' = (a' 1, , a' i, , a' m )
Trong đó:
a' i = a i nếu pi pm
1 - a i nếu pi < pm
Sau quá trình chọn lọc, lai ghép, đột biến, một thế hệ mới được sinh ra Công việc còn lại của thuật toán di truyền bây giờ chỉ là lặp lại các bước trên
*** Đặc điểm hội tụ của thuật toán
Khi áp dụng thuật toán di truyền cho các vấn đề thực tế thường rất khó khăn.Nguyên nhân:
+ Cách biểu diễn gene có thể tạo ra không gian tìm kiếm khác với không gian thực của bài toán
Trang 7+ Số bước lặp khi cài đặt thường không xác định trước.
+ Kích thước quần thể thường có giới hạn
Trong một số trường hợp, thuật toán không thể tìm được lời giải tối ưu do hội tụ sớm về lời giải tối ưu cục bộ Hội tụ sớm là vấn đề của thuật toán di truyền cũng như các giải thuật tối
ưu khác Nếu hội tụ xảy ra quá nhanh thì các thông tin đáng tin cậy đang phát triển trong quần thể thường bị bỏ qua Nguyên nhân của sự hội tụ sớm liên quan tới 2 vấn đề:
+ Quy mô và loại sai số do cơ chế tạo mẫu
+ Bản chất của hàm mục tiêu
**Điều kiện dừng của giải thuật:
Có hai loại điều kiện dừng cơ bản Các điều kiện này dùng các đặc trưng tìm kiếm để quyết định ngừng quá trình tìm kiếm
Dựa trên cấu trúc nhiễm sắc thể: do sự hội tụ của quần thể bằng cách kiểm soát số alen được hội tụ, ở đây alen được coi như hội tụ nếu 1 số phần trăm quần thể đã định trước có cùng (hoặc tương đương đối với các biểu diễn không nhị phân) giá trị trong alen này.Nếu số alen hội tụ vượt quá số phần trăm nào đó của tổng số alen, việc tìm kiếm sẽ kết thúc
Dựa trên ý nghĩa đặc biệt của 1 nhiễm sắc thể: đo tiến bộ của giải thuật trong một số thế hệ cho trước.Nếu tiến bộ này nhỏ hơn một hằng số ɛ xác định,kết thúc tìm kiếm
II Chương trình.
Trang 81 Class Knapsack.
*Properties:
+ knapsackMaxWeight: khối lượng tối đa của balô
+ knapsackCurrentWeight: khối lượng hiện thời của balô
+ knapsackValue: giá trị của balô
+ fitness: chỉ số Fitness
*Method:
+ Overload: để kiểm tra xem khối lượng hiện tại của túi đã vượt quá khối lượng max chưa
+ ShowItem: in số lượng các đồ vật trong túi dưới dạng gene
publicclassKnapsack
{
privateint knapsackMaxWeight, knapsackCurrentWeight = 0, knapsackValue = 0, fitness; privateItem[] listItem = null;
publicint[] listItemAmount;
publicstring strItems = "";
Trang 9publicint Fitness
{
get { return fitness; }
}
publicint KnapsackCurrentWeight
{
get { return knapsackCurrentWeight; }
}
publicint KnapsackValue
{
get { return knapsackValue; }
}
publicItem[] ListItem
{
get { return listItem; }
set
{
listItem = value;
}
}
public Knapsack(int knapsackMaxWeight)
{
this.knapsackMaxWeight = knapsackMaxWeight;
}
public Knapsack(int knapsackMaxWeight, Item[] listItem)
{
this.knapsackMaxWeight = knapsackMaxWeight;
this.listItem = listItem;
listItemAmount = newint[ListItem.Length];
int i = 0;
foreach (Item item in listItem)
{
knapsackCurrentWeight += (item.ItemWeight * item.ItemAmount); knapsackValue += (item.ItemValue * item.ItemAmount);
listItemAmount[i] = item.ItemAmount;
i++;
}
if (!overload()) fitness = knapsackValue;
Trang 10else
{
fitness = knapsackValue - knapsackCurrentWeight;
}
}
publicBoolean overload()
{
if (knapsackCurrentWeight > knapsackMaxWeight) returntrue; elsereturnfalse;
}
publicstring showItem()
{
string s = "";
int i;
for (i = 0; i < listItemAmount.Length - 1; i++)
s += listItemAmount[i] + ", ";
s += listItemAmount[i].ToString();
return s;
}
}
2.Class Item.
*Properties
itemValue: giá trị của đồ vật
itemWeight: khối lượng của đồ vật
itemAmount: số lượng đồ vật
publicclassItem
{
privateint itemValue, itemWeight, itemAmount;
publicint ItemWeight
{
Trang 11get { return itemWeight; }
set { itemWeight = value; }
}
publicint ItemValue
{
get { return itemValue; }
set { itemValue = value; }
}
publicint ItemAmount
{
get { return itemAmount; }
set { itemAmount = value; }
}
public Item(int itemValue, int itemWeight)
{
this.itemValue = itemValue;
this.itemWeight = itemWeight;
}
}
3.Class Gas.
publicclassGAs
{
//properties
privateRandom rand;
publicint knapsackWeight,knapsackAmount;
privateint maxValue = 0;
privateint mutationProp;
privateItem[] listItem;
publicKnapsack[] listKnapsack;
publicKnapsack ksBestCurrent;
//constructor
public GAs(int knapsackWeight, int knapsackAmount, Item[] listItem, int mutationProp, int
TotalGeneration)
{
this.knapsackWeight = knapsackWeight;
Trang 12this.knapsackAmount = knapsackAmount;
this.mutationProp = mutationProp;
this.listItem = listItem;
rand = newRandom();
initialize();
selectionForNewGeneration(listKnapsack);
}
//method privatevoid initialize() {
// Thế hệ đầu tiên: tất cả các gene đều được chấp nhận int i = 0; listKnapsack = newKnapsack[knapsackAmount]; Knapsack knapsack; while (i < knapsackAmount) {
Item[] newList = listItem; foreach (Item item in newList) {
item.ItemAmount = rand.Next(0, Convert.ToInt32(knapsackWeight / (item.ItemWeight))); }
knapsack = newKnapsack(knapsackWeight, newList); if ((!knapsack.overload()) && (knapsack.KnapsackValue > 0)) {
listKnapsack[i] = knapsack; if (knapsack.KnapsackValue > maxValue) {
maxValue = knapsack.KnapsackValue; ksBestCurrent = knapsack; }
i++;
}
}
for (i = 0; i < listKnapsack.Length; i++) {
Trang 13System.Windows.Forms.MessageBox.Show(listKnapsack[i].showItem()); }
}
publicvoid selectionForNewGeneration(Knapsack[] oldListKnapsack)
{
for (int i = 0; i < oldListKnapsack.Length; i++)
{
if (oldListKnapsack[i] == null) break;
for (int j = i; j < oldListKnapsack.Length; j++)
{
if (oldListKnapsack[j] == null) break;
Knapsack ksTemp;
if (oldListKnapsack[i].Fitness > oldListKnapsack[j].Fitness)
{
ksTemp = oldListKnapsack[i];
oldListKnapsack[i] = oldListKnapsack[j];
oldListKnapsack[j] = ksTemp;
}
}
}
int count = 0;
while (count < knapsackAmount)
{
listKnapsack[count++] = oldListKnapsack[oldListKnapsack.Length - 1 - knapsackAmount + count];
}
}
publicKnapsack[] selectionForRecombination()
{
int fitnessTotal = 0, i = 0, times;
foreach (Knapsack knapsack in listKnapsack)
{
if (knapsack != null)
fitnessTotal += knapsack.Fitness;
}
times = rand.Next(knapsackAmount - 10, knapsackAmount + 10);
if (times < 0) times = knapsackAmount;
if (times % 2 != 0) times += 1;
Trang 14Knapsack[] selectedKnapsacks = newKnapsack[times];
while (i < times)
{
int randNumber = rand.Next(1, fitnessTotal);
int currentTotal = 0, pos = 0;
while (currentTotal <= randNumber)
{
currentTotal += listKnapsack[pos++].Fitness;
}
if (i != 0 && selectedKnapsacks[i - 1].Fitness != listKnapsack[pos - 1].Fitness) {
i++;
}
selectedKnapsacks[i] = listKnapsack[pos - 1];
}
return selectedKnapsacks;
}
publicint[,] encoding(Knapsack[] selectedKnapsacks)
{
int[,] encodedListKnapsack = newint[selectedKnapsacks.Length, listItem.Length]; for (int i = 0; i < selectedKnapsacks.Length; i++)
{
if (selectedKnapsacks[i] == null) break;
for (int j = 0; j < selectedKnapsacks[i].ListItem.Length; j++)
{
if (selectedKnapsacks[i].ListItem[j] == null) break;
encodedListKnapsack[i, j] = selectedKnapsacks[i].listItemAmount[j];
}
}
return encodedListKnapsack;
}
publicint[,] crossover(int[,] encodedListKnapsack)
{
int[,] encodedNewGeneration = newint[encodedListKnapsack.GetLength(0), encodedListKnapsack.GetLength(1)];
int startPart2 = encodedListKnapsack.GetLength(1) / 4,
startPart3 = startPart2 * 3;
for (int i = 0; i < encodedListKnapsack.GetLength(0) - 1; i += 2)