#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
#include <iostream>
using namespace std;
#define GeneNumber 4 // 基因長度
#define PopulationSize 10 // 母群數量
#define MaxGeneration 100 // 迭代次數
#define CrossoverRate 0.7 // 交配率
#define MutationRate 0.1 // 突變率
class parent{
public:
int genes[GeneNumber];
double fitness;
double dec_value;
};
// PositionRand(): 隨機取得(交配點/突變位置)
#define PositionRand() (rand()%GeneNumber)
// BinaryRand(): 隨機產生0~1整數(無小數)for(產生基因)
#define BinaryRand() (rand()%2)
// PointRand(): 隨機產生0~1 的亂數(有小數)for(交配/突變率)
#define PointRand() ((double)rand()/(double)RAND_MAX)
// =====================================================
// 進行初始化
void initialize();
// 輪盤式選擇(隨機式)
void CrossoverPool();
// 交配, 交配池中的個體進行交配(兩點交配)
void crossover();
// 突變, 逐一bit 慢慢確認突變
void mutation();
// 計算基因所對應之適應值
void cal_fitness(parent *x);
// 計算基因對應之進制值
void cal_Decimal(parent *x);
// 讓交配點的第二點永遠比第一點大
void swap(int *x,int *b);
// =====================================================
parent population[PopulationSize]; // 母體數量
parent pool[PopulationSize]; // 交配池
parent *best_gene; // 從以前到現在最好的基因
// binary 2 dec,將染色體中的二進位(genes) ,轉為十進位(dec_value)
void cal_Decimal(parent *x)
{
int i,j = 0;
double dec = 0;
for(i=GeneNumber-1; i >= 0; i--){
dec += x->genes[i]*pow((double)2,j);
j++;
}
x->dec_value = dec;
}
//計算適應值 適應函數為31i-i*i
void cal_fitness(parent *x)
{
double i = x->dec_value;
x->fitness = 31*i - i*i;
}
//將a,b兩數互換,讓起始數永遠比終點數小
void swap(int *a,int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
//初始化
void initialize()
{
int i, j,x,y;
for(i=0; i<PopulationSize; i++){
for(j=0; j<GeneNumber; j++){
// 每個母體的基因都是隨機給/1
population[i].genes[j] = BinaryRand();
}
}
// 計算母體基因之進制值
for(x = 0; x < PopulationSize; x++){
cout <<x <<" : bin = ";
for(y = 0; y < GeneNumber; y++){
cout << population[x].genes[y];
}
cout << '\n';
//計算十進位之值並輸出
cal_Decimal(&population[x]);
cout << "Dec = " << population[x].dec_value << '\n';
//計算適應並變輸出
cal_fitness(&population[x]);
cout << "Fitness = "<< population[x].fitness << '\n';
//更新最佳基因
if(x==0)
best_gene = &population[0];
else if(population[x].fitness > best_gene->fitness)
best_gene = &population[x];
cout << "best_gene = "<< best_gene->fitness << '\n';
cout << "======================================="<< '\n';
}
}
//輪盤式選擇
void CrossoverPool()
{
int i,j;
double FitnessSum = 0;//適應值總和
double Fitness_percent[PopulationSize];//每個基因的適應值所占整體的比例
double Fitness_percent_total=0;
int pickup;//抽取個體
//計算適應值總和並輸出
for(i=0; i < PopulationSize; i++){
FitnessSum += population[i].fitness;
}
cout << "FitnessSum = "<< FitnessSum <<'\n';
//計算每個基因的適應值佔總合多少比例並輸出
for(i=0; i < PopulationSize; i++){
Fitness_percent[i] = population[i].fitness / FitnessSum;
cout << "Fitness_percent = " << Fitness_percent[i]<< '\n';
Fitness_percent_total+=Fitness_percent[i];
}
cout << "Fitness_percent_total = " << Fitness_percent_total << '\n';
//選擇基因丟入交配池
for(i=0; i < PopulationSize; i++){
pickup = rand()%PopulationSize;
cout << i << " : Pool = ";
for(j=0; j < GeneNumber; j++){
pool[i].genes[j] = population[pickup].genes[j];
cout << pool[i].genes[j];
}
cout << '\n';
}
}
//兩點交配
void crossover()
{
int i,j;
int PartOfComplete=0;//完成數目
int p1,p2;//交配池中的隨機兩組基因
int pos1=0,pos2=0;//交換點由pos1~pos2
double CrossoverProbability;//交配機率
//重複執行直到交配完10組個體
while(PartOfComplete < PopulationSize){
//隨機選擇兩個個體
p1 = rand() % PopulationSize;
do{ p2 = rand() % PopulationSize;}while(p2 == p1);
CrossoverProbability=PointRand();
cout << "CrossoverProbability = " << CrossoverProbability << '\n';
//交配
if(CrossoverProbability < CrossoverRate){
pos1=PositionRand();
do{
pos2=PositionRand();
}while(pos2 == pos1 || ((pos1 == 0 || pos1 == GeneNumber-1) && (pos1+pos2 == GeneNumber-1)));
//↑↑↑↑↑判斷機制pos1:pos1與pos2不可為同值且pos1與pos2不可同時為第一點與最後一點↑↑↑↑↑
cout << "pos1 = "<< pos1 <<" pos2 = "<< pos2 << '\n';
//強制由左往右做區域的選取
if(pos1>pos2)
swap(&pos1,&pos2);
cout << "pos1 = " << pos1 <<" pos2 = " << pos2 << '\n';
cout << "p1 = " << p1 <<" p2 = " << p2 << '\n';
//第一階段交配
for(i=0; i<pos1; i++){
population[PartOfComplete].genes[i]=pool[p1].genes[i];
population[PartOfComplete+1].genes[i]=pool[p2].genes[i];
}
//第二階段交配
for(i=pos1; i<=pos2; i++){
population[PartOfComplete+1].genes[i]=pool[p1].genes[i];
population[PartOfComplete].genes[i]=pool[p2].genes[i];
}
//第三階段交配
for(i=pos2+1; i<GeneNumber; i++){
population[PartOfComplete].genes[i]=pool[p1].genes[i];
population[PartOfComplete+1].genes[i]=pool[p2].genes[i];
}
//輸出交配後的二進制之值
for(i = 0; i < PopulationSize; i++){
cout <<i <<" : bin = ";
for(j = 0; j < GeneNumber; j++){
cout << population[i].genes[j];
}
cout << '\n';
}
//進行下面兩個個體的交配
PartOfComplete+=2;
}
}
}
//突變
void mutation()
{
int i,j;
int pos;//突變點
double MutationProbability;//突變機率
for(i = 0; i < PopulationSize; i++){
MutationProbability = PointRand();
cout << "MutationProbability = "<< MutationProbability <<'\n';
//是否發生突變
if(MutationProbability < MutationRate){
//突變點
pos = PositionRand();
//做突變點的突變處理
population[i].genes[pos] = !population[i].genes[pos];
cout<<"pos = "<< pos <<'\n';
}
cout << i <<" : bin = ";
for(j = 0; j < GeneNumber; j++){
cout << population[i].genes[j];
}
cout << '\n';
//計算十進制之值並輸出
cal_Decimal(&population[i]);
cout << "Dec = " << population[i].dec_value << '\n';
//計算適應值並輸出
cal_fitness(&population[i]);
cout << "Fitness = "<< population[i].fitness << '\n';
//更新最佳基因
if(population[i].fitness > best_gene->fitness)
best_gene = &population[i];
cout << "best_gene = "<< best_gene->fitness << '\n';
cout << "======================================="<< '\n';
}
}
int main()
{
srand((unsigned)time(NULL));
initialize(); // 初始化
cout<<'\n';
CrossoverPool(); //分配式選擇
cout<<'\n';
crossover(); //兩點交配
cout<<'\n';
mutation(); //突變
cout<<'\n';
cout << "best_gene = "<< best_gene->fitness << '\n';
system("pause");
}