1. 程式人生 > >2017華為軟挑——遺傳演算法

2017華為軟挑——遺傳演算法

///////////////////////////////////////*遺傳演算法 start*////////////////////////////////////////////////////
# define POPSIZE 10		//種群內個體數量  
# define MAXGENS 100		//最大的迭代次數  
static int NVARS = 3;		//變數個數,即用以表示基因型的bit數  
# define PXOVER 0.85		//交換率  
# define PMUTATION 0.3	//突變率  

struct genotype
{
	double gene[MAX_NODE];
	double fitness;
	double upper[MAX_NODE];
	double lower[MAX_NODE];
	double rfitness;
	double cfitness;
};

struct genotype population[POPSIZE + 1];
struct genotype newpopulation[POPSIZE + 1];
///////////////////////////////////////*遺傳演算法 end*//////////////////////////////////////////////////////

///////////////////////////////////////*遺傳演算法 start*////////////////////////////////////////////////////
//遺傳演算法搜尋
void my_GAsearch()
{
	int seed = 772002;
	srand((unsigned)time(NULL));
	GA_initialize(seed);
	evaluate();
	keep_the_best();

	for (int generation = 0; generation < MAXGENS; generation++)
	{
		selector(seed);
		crossover(seed);
		mutate(seed);
		evaluate();
		elitist();
	}
}

//選擇兩個個體進行交叉變異
void crossover(int &seed)  
{  
    const double a = 0.0;  
    const double b = 1.0;  
    int mem;  
    int one;  
    int first = 0;  
    double x;  
  
    for (mem = 0; mem < POPSIZE; ++mem )  
    {  
        //x = r8_uniform_ab ( a, b, seed );  
        x = Dou_uniform_ab( a, b);  
  
        if ( x < PXOVER )  
        {  
            ++first;  
  
            if ( first % 2 == 0 )  
            {  
                Xover ( one, mem, seed );  
            }  
            else  
            {  
                one = mem;  
            }  
        }  
    }  
    return;  
}  

//選出本輪中最優和最差的個體,將本輪中最好的個體賦值給最後一個個體,將上輪中最壞的個體賦值給當前最壞的個體 
void elitist()   
{  
    int i;  
    double best;  
    int best_mem;  
    double worst;  
    int worst_mem;  
  
    best = population[0].fitness;  
    worst = population[0].fitness;  
  
    for (i = 0; i < POPSIZE - 1; ++i )  
    {  
        if ( population[i+1].fitness < population[i].fitness )  
        {  
  
            if ( best <= population[i].fitness )  
            {  
                best = population[i].fitness;  
                best_mem = i;  
            }  
  
            if ( population[i+1].fitness <= worst )  
            {  
                worst = population[i+1].fitness;  
                worst_mem = i + 1;  
            }  
  
        }  
        else  
        {  
  
            if ( population[i].fitness <= worst )  
            {  
                worst = population[i].fitness;  
                worst_mem = i;  
            }  
  
            if ( best <= population[i+1].fitness )  
            {  
                best = population[i+1].fitness;  
                best_mem = i + 1;  
            }  
        }  
    }  
    //   
    //  If the best individual from the new population is better than   
    //  the best individual from the previous population, then   
    //  copy the best from the new population; else replace the   
    //  worst individual from the current population with the   
    //  best one from the previous generation                       
    //  
    if ( population[POPSIZE].fitness <= best )  
    {  
        for ( i = 0; i < NVARS; i++ )  
        {  
            population[POPSIZE].gene[i] = population[best_mem].gene[i];  
        }  
        population[POPSIZE].fitness = population[best_mem].fitness;  
    }  
    else  
    {  
        for ( i = 0; i < NVARS; i++ )  
        {  
            population[worst_mem].gene[i] = population[POPSIZE].gene[i];  
        }  
        population[worst_mem].fitness = population[POPSIZE].fitness;  
    }   
  
    return;  
}  
  
//對遺傳演算法的效果進行評價
void evaluate()
{  
    int member;  
    int i;  
    double x[800+1];  
	int temp_flow(0);	//流量標記
	std::vector<int> m_server;	//取到的時候對應的server
    for ( member = 0; member < POPSIZE; member++ )  
    {  
		int flow(0), cost(0);
		double sum=0;
        for ( i = 0; i < NVARS; i++ )  
        {  
            x[i+1] = population[member].gene[i]; 
        }

		std::vector<int> temp = GA_get_server_pos(x);   
        population[member].fitness = get_fitness(temp, cost, flow); 
		if (flow >= needed_flow)
		{
			if (min_cost > cost)
			{
				min_cost = cost;
				m_server = temp;
			}
		}	//滿足了流量要求,則要求其最小費用
		else
		{
			if (temp_flow < flow)
			{
				temp_flow = flow;
				m_server = temp;
			}
		}	//不滿足流量需求,則滿足最大流量需求
    }  
	xjbs_search(m_server);	//區域性搜尋最優
	GA_update(m_server);
    return;  
}

//使用搜索出來的區域性最優解去更新遺傳的引數
void GA_update(std::vector<int> m_server)
{
	for (int i = 0; i < NVARS; i++)
	{
		for (int j = 0; j < POPSIZE; j++)
		{
			if (CheckIsServer(i, m_server))
			{
				population[j].gene[i] += Dou_uniform_ab(0.0, 0.2);;
			}
			//else
			//	population[j].gene[i] = 0.2;
		}
	}
}

//計算自定義的度量函式
double get_fitness(std::vector<int>& server, int& cost, int& flow)
{
    if(server.size()<=0)
    {
        cout << "get 0 server pos in GA, ERROR" << endl;
        return (-MAXINT);
    }
	Dij_init(server);
    flow = 0;
    cost = Dij_MinCostFlow(net_node_num, (net_node_num+1), flow);
	cost = cost+server.size()*server_cost;
	cout << "server_num:" << server.size() <<" ,loop: min cost: " << cost << 
		" , max flow: " << flow << " / " << needed_flow << endl;
    
	//return flow;
	if(flow >= needed_flow)
	{
		if(min_cost > cost)
		{
			//cout << "find better: " << cost << endl;
			min_server = server;
			min_cost = cost;
			min_path = path;
		}
		return cost;
	}
	else
	{
		return (needed_flow-flow)*10*cost;
	}
} 

//根據遺傳演算法得到的引數的解,得到伺服器的位置
std::vector<int> GA_get_server_pos(double* data)
{
    std::vector<int> result;
	if(nullptr == data)
		return result;

	for(int i=0; i<NVARS-1; i++)
	{
		if(data[i] > 0.88)
			result.push_back(i);
	}

	return result;
}

//my new design function of the distribution  
int Int_uniform_ab(int a, int b)  
{   int tmp;  
    tmp = (rand() % (b-a+1))+ a;  
    return tmp;  
}  
  
//遺傳演算法初始化
void GA_initialize(int& seed)  
{  
    //  Initialize variables within the bounds
	std::vector<int> server;// = min_server;	
	for (int i=0; i<client_node_num; i++)
	{
		server.push_back(client_node[i].innode[0]);
	}
	
	NVARS = net_node_num;//+1;	//設定GA演算法的引數變數的個數為網路中節點的個數

	for (int i = 0; i < NVARS; i++)
	{
		for (int j = 0; j < POPSIZE; j++)
		{
			population[j].fitness = 0;
			population[j].rfitness = 0;
			population[j].cfitness = 0;
			population[j].lower[i] = 0;	//代表不選中該點作為伺服器
			population[j].upper[i] = 1;  //代表選中該點作為伺服器
			if (CheckIsServer(i, must_server))
			{
				population[j].gene[i] = 1.0;
			}
			else if (CheckIsServer(i, forbid_server))
			{
				population[j].gene[i] = 0.0;
			}
			else population[j].gene[i] = r8_uniform_ab(0.2, 0.9, seed);
			//population[j].gene[i] = Dou_uniform_ab(0.0, 1.0);  
		}
	}
}  

//儲存最好的個體到最後一箇中去
void keep_the_best( )   
{  
    int cur_best;  
    int mem;  
    int i;  
  
    cur_best = 0;  
  
    for ( mem = 0; mem < POPSIZE; mem++ )  
    {  
        if ( population[POPSIZE].fitness < population[mem].fitness )  
        {  
            cur_best = mem;  
            population[POPSIZE].fitness = population[mem].fitness;  
        }  
    }  
    //   
    //  Once the best member in the population is found, copy the genes.  
    //  
    for ( i = 0; i < NVARS; i++ )  
    {  
		population[POPSIZE].gene[i] = population[cur_best].gene[i];  
    }  
  
    return;  
}  

//變異
void mutate(int &seed )  
{  
    const double a = 0.0;  
    const double b = 1.0;  
    int i;  
    int j;  
    double lbound;  
    double ubound;  
    double x;  
  
    for ( i = 0; i < POPSIZE; i++ )  
    {  
        for ( j = 0; j < NVARS; j++ )  
        {  
            x = r8_uniform_ab ( a, b, seed );  
            //x = Dou_uniform_ab( a, b);  
            if ( x < PMUTATION )  
            {  
                lbound = population[i].lower[j];  
                ubound = population[i].upper[j];    
                population[i].gene[j] = r8_uniform_ab ( lbound, ubound, seed );  
                //population[i].gene[j] = Dou_uniform_ab( lbound, ubound );  
            }  
        }  
    }  
  
    return;  
}  

//通過隨機種子選取a,b之間的隨機數
double r8_uniform_ab( double a, double b, int &seed )   
{  
    int i4_huge = 2147483647;  
    int k;  
    double value;  
  
    if ( seed == 0 )  
    {  
        std::cerr << "\n";  
        std::cerr << "R8_UNIFORM_AB - Fatal error!\n";  
        std::cerr << "  Input value of SEED = 0.\n";  
        exit ( 1 );  
    }  
  
    k = seed / 127773;  
  
    seed = 16807 * ( seed - k * 127773 ) - k * 2836;  
  
    if ( seed < 0 )  
    {  
        seed = seed + i4_huge;  
    }  
  
    value = ( double ) ( seed ) * 4.656612875E-10;  
  
    value = a + ( b - a ) * value;  
  
    return value;  
}  

//隨機選擇a,b之間的隨機數 
double Dou_uniform_ab(double a, double b)  
{  
    double tmp;  
    //rand() / double(RAND_MAX)可以生成0~1之間的浮點數  
    tmp = a + static_cast<double>(rand())/RAND_MAX*(b-a);  
    return tmp;  
}  

//計算相對適應度和累積適應度,然後根據適應度進行選擇和賦值
void selector(int &seed)  
{  
    const double a = 0.0;  
    const double b = 1.0;  
    int i;  
    int j;  
    int mem;  
    double p;  
    double sum; 
	double max_value(0);

    //  Find the total fitness of the population.  
    sum = 0.0;  
	for (mem = 0; mem < POPSIZE; mem++)
	{
		max_value = max_value<population[mem].fitness?population[mem].fitness:max_value;
	}
    //for ( mem = 0; mem < POPSIZE; mem++ )  
    //{  
    //    sum += max_value - population[mem].fitness;  
    //}  

    //  Calculate the relative fitness of each member.  
    for ( mem = 0; mem < POPSIZE; mem++ )  
    {  
        population[mem].rfitness = (max_value-population[mem].fitness) / max_value;  
    }  
    
    //  Calculate the cumulative fitness.  
    population[0].cfitness = population[0].rfitness;  
    for ( mem = 1; mem < POPSIZE; mem++ )  
    {  
        population[mem].cfitness = population[mem-1].cfitness +         
            population[mem].rfitness;  
    }  

    //  Select survivors using cumulative fitness.   
    for ( i = 0; i < POPSIZE; i++ )  
    {   
        p = r8_uniform_ab ( a, b, seed );  
        //p = Dou_uniform_ab(a,b);  
        if ( p < population[0].cfitness )  
        {  
            newpopulation[i] = population[0];        
        }  
        else  
        {  
            for ( j = 0; j < POPSIZE; j++ )  
            {   
                if ( population[j].cfitness <= p && p < population[j+1].cfitness )  
                {  
                    newpopulation[i] = population[j+1];  
                }  
            }  
        }  
    }  
  
    //  Overwrite the old population with the new one.  
    for ( i = 0; i < POPSIZE; i++ )  
    {  
        population[i] = newpopulation[i];   
    }  
  
    return;       
}

//基因的交叉操作
void Xover( int one, int two, int &seed )  
{  
    int i;  
    int point;  
    double t;  
    //  Select the crossover point.  
    //point = i4_uniform_ab ( 0, NVARS - 1, seed );  
    point = Int_uniform_ab(0, NVARS-1);  

    //  Swap genes in positions 0 through POINT-1.  
    for ( i = 0; i < point; i++ )  
    {  
        t                       = population[one].gene[i];  
        population[one].gene[i] = population[two].gene[i];  
        population[two].gene[i] = t;  
    }  
  
    return;  
} 
///////////////////////////////////////*遺傳演算法 end*//////////////////////////////////////////////////////