2017華為軟挑——禁忌搜尋演算法
阿新 • • 發佈:2019-02-16
static int tabu_list_lenth = 0; //禁忌表的長度 static int tabu_max_times = 5000; //禁忌表的最大迭代次數 std::deque<std::vector<int>> tabu_list; //使用雙向佇列作為禁忌表 //禁忌搜尋初始化 void tabu_init() { int tabu_lenth = client_node_num*2;//(client_node_num - 1) / 2; //計算禁忌表的長度 tabu_list_lenth = tabu_lenth; //tabu_list = std::deque<std::vector<int>>(tabu_list_lenth); //定義一個禁忌表長度的雙向佇列 } //判斷當前交換是否在禁忌表中,存在返回true,不存在返回false bool is_tabulist(int pos_1, int pos_2) { swap_int(pos_1, pos_2); unsigned int tabu_size(tabu_list.size()); for (unsigned int i=0; i<tabu_size; i++) { std::vector<int> vec = tabu_list[i]; if (vec.size()>0) if ((pos_1==vec[0]) && (pos_2==vec[1])) return true; //該值存在於禁忌表中 } return false; } //更新禁忌表 void flush_tabulist(int pos_1, int pos_2) { if (!is_tabulist(pos_1, pos_2)) //不存在於禁忌表中 { swap_int(pos_1, pos_2); //按照小大次序排列 std::vector<int> vec; vec.push_back(pos_1); vec.push_back(pos_2); if ((int)tabu_list.size() < tabu_list_lenth) //禁忌表沒有滿 { tabu_list.push_back(vec); } else //禁忌表已經被填滿了,刪除最先進來的元素,將新的元素新增進來 { cout << "臥槽,禁忌表都滿了!" << endl; tabu_list.pop_front(); tabu_list.push_back(vec); } } } //交換兩個數的值 void swap_int(int& pos_1, int& pos_2) { if (pos_1 > pos_2) { int temp = pos_1; pos_1 = pos_2; pos_2 = temp; } } //獲取該點沒有存在於禁忌表中的點 std::vector<int> neighbour_node(int node, std::vector<int>& may_server) { node = node > net_node_num ? (node-2*net_node_num) : node; //對於選擇該點不存在的情況 std::vector<int> result; unsigned int temp_size(net_node[node].outnode.size()); //臨時記錄大小的 for (unsigned int i = 0; i < temp_size; i++) { if (!is_tabulist(node, net_node[node].outnode[i]) && CheckIsServer(net_node[node].outnode[i], may_server)) //當前對值沒有存在於禁忌表中 result.push_back(net_node[node].outnode[i]); } //搜尋出度 temp_size = net_node[node].innode.size(); //臨時記錄大小的 for (unsigned int i = 0; i < temp_size; i++) { if (!is_tabulist(node, net_node[node].innode[i]) && CheckIsServer(net_node[node].innode[i], may_server)) //當前對值沒有存在於禁忌表中 result.push_back(net_node[node].innode[i]); } //搜尋入度 if (!is_tabulist(node, node+2*net_node_num)) //這裡判斷與不存在的點的配對是指不選擇該點 result.push_back(node+2*net_node_num); return result; } //獲取low和high範圍內的一個隨機值 int get_random_pos(int low, int high) { int result = static_cast<unsigned int>(rand())%high; return result; } //獲取向量中伺服器的個數 int get_server_count(std::vector<int> vec) { int result(0); unsigned int temp_size(vec.size()); for (unsigned int i=0; i<temp_size; i++) { if (vec[i] < net_node_num) result++; } return result; } //去除那些已經排除了的點 std::vector<int> clean_server(std::vector<int> vec) { std::vector<int> result; int temp_size((int)vec.size()); for(int i=0; i<temp_size; i++) if(vec[i] < net_node_num) result.push_back(vec[i]); return result; } //禁忌搜尋 void tabu_search() { tabu_init(); //禁忌搜尋初始化 int iterator_times = tabu_max_times; int result_size((int)min_server.size()); std::vector<int> may_server = xjbs_getserver(0); //得到可能會是伺服器的節點 srand((unsigned)time(0)); //弄個隨機種子 while (iterator_times>0) { //執行時間判斷 clock_t temp_end = clock(); if(((double)(temp_end-start)/CLOCKS_PER_SEC) > tabu_time) break; int change_pos = get_random_pos(0, result_size); //隨機的產生需要替換掉的點 cout << "需要出去的點:" << min_server[change_pos] << endl; std::vector<int> neighbours = neighbour_node(change_pos, may_server); //獲取該點領域的點 cout << "鄰域點的個數:" << neighbours.size() << "\t"; if(neighbours.size()<=0)//鄰域的個數為0跳過 { --iterator_times; continue; } int temp_min_cost(MAXINT), temp_best_node(change_pos); for (unsigned int i = 0; i < neighbours.size(); i++) { min_server[change_pos] = neighbours[i]; //使用領域替換掉指定的點 int flow(0), cost(-1); my_search_init(clean_server(min_server)); cost = MinCostFlow(net_node_num, (net_node_num + 1), flow); cost += get_server_count(min_server)*server_cost; if (flow >= needed_flow) { if (temp_min_cost>cost) { temp_min_cost = cost; min_path = path; temp_best_node = neighbours[i]; } } cout << neighbours[i] << "\t"; } //搜尋領域中最佳的點 if (change_pos == temp_best_node) cout << "麻痺,在 " << min_server[change_pos] << " 的領域中沒有找到優化的解" << endl; min_server[change_pos] = temp_best_node; //使用最好的領域替換掉指定的點 if (min_cost>temp_min_cost) //藐視準則 { count = 0; cout << "find better: " << temp_min_cost << endl; min_server[change_pos] = temp_best_node; //使用領域替換掉指定的點 tabu_list.clear(); min_cost = temp_min_cost; flush_tabulist(change_pos, temp_best_node); //加入到禁忌表中 } else { for (unsigned int i = 0; i < neighbours.size(); i++) { flush_tabulist(change_pos, neighbours[i]); //加入到禁忌表中 } } --iterator_times; } cout << "\nthe result after " << tabu_max_times << " times search" << endl; cout << "the min_cost is: " << min_cost << endl; }