美文网首页
禁忌算法、遗传算法,HEAD算法求解图染色问题(K-Colori

禁忌算法、遗传算法,HEAD算法求解图染色问题(K-Colori

作者: 缱绻顾 | 来源:发表于2018-04-25 17:21 被阅读0次

    具体可参考本人博客GitHub
    HEAD算法论文中得到了K=47的结果,但是运算量太大,本人并没有得到。
    算法主要参考了 hujinglovekmg《禁忌搜索算法解决图着色问题》和华科吕志鹏老师的教学ppt《Chapter 4 Hybrid Evolutionary Algorithm: A Case Study on Graph Coloring》

    核心代码部分

    01 判断条件优化

    在ppt中,关于禁忌算法的描述如下图:


    禁忌搜索算法

    步骤3.3,会计算出delt相同的moves,而相同的moves中,tabu & non-tabu moves可能同时存在。而在步骤3.4中,在上述情况存在时,若满足aspiration,则会优先选择tabu moves。而我们希望的,应该是在此种情况时,tabu & non-tabu moves一起随机选择。因此,可以把判断条件写为

    if (tmp_delt <= delt && ( iter> h_tabu[j]|| (tmp_delt + f)<best_f)) { // 1&&(2||3)
        if (tmp_delt < delt) {//当前解小于本次迭代最优解,则重新开始保存解
        equ_count = 0;
        delt = tmp_delt;
        }
        equ_delt[equ_count][0] = i;
        equ_delt[equ_count][1] = j;
        equ_count++;
    }
    

    在计算完所有的critical one-moves后,再从equ_delt保存的moves中,随机选一个。

        int tmp = rand() % equ_count;//有多个解时,随机选择
        sel_vertex = equ_delt[tmp][0];
        sel_color = equ_delt[tmp][1];
    

    其中,变量delt表示本次迭代的最好解,变量tmp_delt表示当次计算出的delt,变量best_f表示历史最好解。i和 j 分别表示顶点和颜色。
    若满足条件(1&&2),则是non-tabu move;若满足条件(1&&3),则是tabu move。

    02 随机选解的另一种方法

    另有一种并不需要每次都保存下相同delt的move的方法。

    if (tmp_delt <= delt && ( iter> h_tabu[j]|| (tmp_delt + f)<best_f)) { // 1&&(2||3){
        if (tmp_delt < delt) {
        equ_count = 1;
        delt = tmp_delt;
        sel_vertex = i;
        sel_color = j;
        }
        if (rand() % equ_count == 0) {
        sel_vertex = i;
        sel_color = j;
      }
      equ_count++;
    }                           
    
    • equ_count==1时,第一个move有1/1的概率取得(此时(rand() % equ_count == 0)的概率为1);
    • equ_count==2时,第一个相等的move有1/1*(1-1/2)=1/2的概率取得,第二个相等的move有1/2的概率取得;
    • equ_count==3时,第一个相等move有1/1*1/2*(1-1/3)=1/3的概率取得,第二个相等的move有1/2*(1-1/3)=1/3的概率取得,第三个相等的move有1/3的概率取得;
      ……
      依次类推.
      但是rand()函数和取余的运算,耗时较大。
    if (rand() % equ_count == 0) {
        sel_vertex = i;
        sel_color = j;
    }// 耗时约为3/10000毫秒
    
    equ_delt[equ_count][0] = i;
    equ_delt[equ_count][1] = j;
    //耗时约为7/10000000毫秒
    

    所以在equ_count已知范围,并且范围不大(避免数组出现问题)的情况下,用前节的方法会更好。
    在本例中,equ_count的最大值为N*(K-1),N为总顶点数,K为总颜色数。即在一次迭代中,可以得到相同delt的moves,最多有N*(K-1)个。

    运行结果

    • i5-7400 CPU,8.00GB
    • vs 2017
    • 采用O2(代码速度)最快编译。vs->属性->c/c++->优化->O2
    • release版本
    • 算例为DSJC500.5.col,颜色数为49
    迭代次数 时间(ms) 迭代频率(次/s)
    1 6637998 20931 317137
    2 23955577 75391 317751
    3 38922336 123361 315516
    4 96602832 302124 319746
    5 12942501 40556 319127
    6 2570572 8239 312000
    7 139941246 439614 318328
    8 218616457 690711 316509
    9 52939800 168495 314192
    10 7037286 21899 321352
    11 9168899 28408 322758
    12 13672252 41232 331593
    平均值 51917313 163413.4 318834

    非核心部分

    01 初始化读取文件

    算例DSJC500.5.col的格式为

    DSJC500.5.col的部分截图
    • “edge”后的数字分别代表顶点总数和边的总数;
    • “e”后为两相邻顶点,其中,第一个数字都是大于第二个数字的,不会有重复。
      因此,需要以空格和换行符为界,把每个词分开。
      代码如下:
    #include<string>
    #include<fstream>
    using namespace std;
    void readData(string fileName)
    {
        ifstream ifs;
        ifs.open(fileName);
        string str;
        ifs>>str;
        while(!ifs.eof())
        {
            if(str=="edge")
            {
                ifs>>N; //int N,顶点数目
                //其他代码
            }
            if(str=="e")
            {
                int m,n;
                ifs>>m>>n;
                //其他代码
            }
            ifs>>str;
        }
        ifs.close();
    }
    

    ifstream ifs;即可实现把文件内容读入不同类型的变量。

    02 随机生成初始解

    #include<stdlib.h>
        sol = new int[N];//每个顶点的颜色
        srand(time(NULL));
        for (int i = 0; i < N; i++)
        {   
            sol[i] = rand() % K;  //给每个点随机着色    
        }
    

    注意,rand()生成的随机数,实际上是伪随机数,srand()则决定了选择的随机数序列是哪一个。srand(time(NULL))则是按照系统实际,选择随机数序列,若不加上这一句,则每次都会得到相同的初始解。

    小结

    本文中的禁忌搜索算法的迭代次数与初始解的关系很大,怎样才能迅速收敛到最优解,还需思考。
    算例DSJC500.5.col的历史最优解为48,用纯禁忌算法已经很难算出来。
    越简单的数据类型,效率越高。最开始我用了vector,后来用了链表,再后来全改成了数组,速度有了很大的提升。

    相关文章

      网友评论

          本文标题:禁忌算法、遗传算法,HEAD算法求解图染色问题(K-Colori

          本文链接:https://www.haomeiwen.com/subject/fiselftx.html