2017華為軟挑——遺傳演算法
阿新 • • 發佈:2019-01-24
///////////////////////////////////////*遺傳演算法 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*//////////////////////////////////////////////////////