遗传算法解决TSP问题C++代码,写成类和主函数的形式

交叉算子用的pbx算子,自己写的交叉方法。

这个类名是GenAlgTSP,求解y=3*a^2+24*b+5*c^2+d^3+e+2f+2*g^3的最大值,a,b,c,d,e,f,g取值为0到6。也就是0到6做一个最优排序,使得y值最大。适应度函数你可以自己改,我这里设定的不太好,就是y本身。

先是GenAlgTSP.h文件,代码如下

#include"stdafx.h"
#include
#include
#include
#include
#include
#define len 7 //数字范围,即染色体长度
typedef struct Chrom                           // 结构体类型,为单个染色体的结构;

{
    int bit[len];//一共len长度bit来对染色体进行编码。取值为10进制。
    int fit;//适应值

    double rfit;//相对的fit值,即所占的百分比

    double cfit;//积累概率

}chrom;
class GenAlgTSP{
private:

public:
    void evpop(chrom popcurrent[100]);//进行种群的初始化
    bool check(chrom *p, int pop, int num, int k);//检查初始化时是否已存在节点
    int y(chrom popcurrent); //函数:求个体的适应度,适应度函数为y=3*a^2+24*b+5*c^2+d^3+e+2f+2*g^3
    void pickchroms(chrom popcurrent[100]);//选择操作

    void pickchroms_new(chrom popcurrent[100]); // 基于概率分布
    void crossover(chrom popnext[100]);//交叉操作
    int findLocInPar(int data,int i);//寻找第一个父亲选定节点在第二个父亲的位置

    void mutation(chrom popnext[100]);//突变

    double r8_uniform_ab(double a, double b, int &seed);//生成a~b之间均匀分布的数字

    chrom popcurrent[100];                        // 初始种群规模为;

    chrom popnext[100];                           // 更新后种群规模仍为;

};

然后是GenalgTSP.cpp文件,代码如下

#include "stdafx.h"
#include "GenAlgTSP.h"
//#include "stdafx.h"
void GenAlgTSP::evpop(chrom popcurrent[100])// 函数:随机生成初始种群;
{
    int r;
    int sum = 0;
    for (int i = 0; i<100; i++)
    {
        for (int j = 0; j         {
            r = rand() % len;//产生0~len之间的随机数
            while (check(popcurrent, i, j, r))//随机产生城市序号,即为city.colony[i][j]赋值
            {
                r = rand() % len;
            }

            popcurrent[i].bit[j] = r;
        }
        popcurrent[i].fit = y(popcurrent[i]); // 计算染色体的适应度值

        sum = sum + popcurrent[i].fit;
    }
    for (int i = 0; i < 100; i++)

    {

        popcurrent[i].rfit = popcurrent[i].fit / sum;

        popcurrent[i].cfit = 0;//将其初始化为0

    }


}
bool GenAlgTSP::check(chrom *p, int pop, int num, int k)/*用来检查新生成的节点是否在当前群体中*/
{
    int i;
    for (i = 0; i < num; i++){
        if (k ==(*(p+pop)).bit[i])
            return true;//新生成节点存在于已经生成的路径中
    }
    return false;//新生成节点没有存在于已经生成的路径中
}

int GenAlgTSP::y(chrom popcurrent){
    int sum=0,j;
        for (j = 0; j < len; j++){
            if (j == 0)
                sum = sum + 3 * popcurrent.bit[j] * popcurrent.bit[j];
            else if (j == 1)
                sum = sum + 24 * popcurrent.bit[j];
            else if (j == 2)
                sum = sum + 5 * popcurrent.bit[j] * popcurrent.bit[j];
            else if (j == 3)
                sum = sum + popcurrent.bit[j] * popcurrent.bit[j] * popcurrent.bit[j];
            else if (j == 4)
                sum = sum + popcurrent.bit[j];
            else if (j == 5)
                sum = sum + 2 * popcurrent.bit[j];
            else if (j == 6)
                sum = sum + popcurrent.bit[j] * popcurrent.bit[j] * popcurrent.bit[j];
        }
        return sum;
}
void GenAlgTSP::pickchroms(chrom popcurrent[100])//选择操作

    int i, j;

    chrom temp;                                // 中间变量

    //因此此处设计的是个个体,所以参数是

    for (i = 0; i<99; i++)                           // 根据个体适应度来排序;(冒泡法)

    {

        for (j = 0; j<99 - i; j++)

        {

            if (popcurrent[j + 1].fit>popcurrent[j].fit)

            {

                temp = popcurrent[j + 1];

                popcurrent[j + 1] = popcurrent[j];

                popcurrent[j] = temp;

            }

        }

    }
    _flushall();/* 清除所有缓冲区 */
}
void GenAlgTSP::pickchroms_new(chrom popcurrent[100]) // 基于概率分布
{
    int men;

    int i; int j;

    double p;

    double sum = 0.0;

    //find the total fitness of the population

    for (men = 0; men < 100; men++)

    {

        sum = sum + popnext[men].fit;

    }

    //calculate the relative fitness of each member

    for (men = 0; men < 100; men++)

    {

        popnext[men].rfit = popnext[men].fit / sum;

    }

    //calculate the cumulative fitness,即计算积累概率

    popcurrent[0].cfit = popcurrent[0].rfit;

    for (men = 1; men < 100; men++)

    {

        popnext[men].cfit = popnext[men - 1].cfit + popnext[men].rfit;

    }

 

    for (i = 0; i < 100; i++)

    {//产生0~1之间的随机数

        //p = r8_uniform_ab ( 0, 1, seed );//通过函数生成0~1之间均匀分布的数字

        p = rand() % 10;//

        p = p / 10;

        if (p < popnext[0].cfit)

        {

            popcurrent[i] = popnext[0];

        }

        else

        {

            for (j = 0; j < 100; j++)

            {

                if (popnext[j].cfit <= p && p < popnext[j + 1].cfit)

                {

                    popcurrent[i] = popcurrent[j + 1];

                }

            }

        }

    }

    //  Overwrite the old population with the new one.

    //

    for (i = 0; i < 100; i++)

    {

        popnext[i] = popcurrent[i];

    }

}
double GenAlgTSP::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;

}
}
void GenAlgTSP::crossover(chrom popnext[100])//交叉操作,计算新适应度,调适应度函数
//适应度前4的个体不参与交叉,4到51号的个体配对交叉,产生48个后代赋值给第52到99号个体。
//交叉算子采用PBX算子交叉
{
    int i,random1=0, random2=0,L1,L2,L3,L4;
    while (random1 == random2){
        random1 = rand()%len;
        random2 = rand() % len;

    }
    for (i = 4; i <= 50; i = i + 2){
        L1 = findLocInPar(popnext[i].bit[random1],i);//L1表示偶数父亲的选定节点在另一父亲对应节点的位置
        L2 = findLocInPar(popnext[i].bit[random2],i);//L2同L1
        L3 = findLocInPar(popnext[i + 1].bit[random1], (i+1));//L3表示奇数父亲选定节点在另一父亲对应节点的位置
        L4 = findLocInPar(popnext[i + 1].bit[random2], (i + 1));//L3同L4
        for (int k = 0,x=0; x         {
            
            if ((k != random1)&&(k != random2)){
                if ((x != L1)&&(x != L2)){
                    popnext[i + 48].bit[k] = popnext[i + 1].bit[x];
                    x++;
                    k++;
                }
                else
                    x++;
            }
            else if (k == random1){
                popnext[i + 48].bit[k] = popnext[i].bit[random1];
                k++;
            }
            else
            {
                popnext[i + 48].bit[k] = popnext[i].bit[random2];
                k++;
            }
        }//偶数父代得到子代
        for (int k = 0, x = 0; x < len||k < len;)
        {
            if ((k != random1) && (k != random2)){
                if ((x != L3) && (x != L4)){
                    popnext[i + 48+1].bit[k] = popnext[i].bit[x];
                    x++;
                    k++;
                }
                else
                    x++;
            }
            else if (k == random1){
                popnext[i + 48+1].bit[k] = popnext[i+1].bit[random1];
                k++;
            }
            else
            {
                popnext[i + 48+1].bit[k] = popnext[i+1].bit[random2];
                k++;
            }
        }
    }//交叉结束
    for (int i=0; i < 100; i++)//为新一代计算适应度值
    {
        popnext[i].fit = y(popnext[i]);        // 为新个体计算适应度值;
    }
}
int GenAlgTSP::findLocInPar(int data,int i)
{
    if (i % 2 == 0){
        int j;
        for (j = 0; j < len;j++)
        if (popnext[i+1].bit[j] == data)
            return j;
    }
    else{
        int j;
        for (j = 0; j < len;j++)
        if (popnext[i-1].bit[j] == data)
            return j;
    }
}
void GenAlgTSP::mutation(chrom popnext[100])//突变
{
    int random;

    int row, col,col2,t;

    //srand(time(0)); 

    random = rand() % 50;  // 随机产生到之间的数;

    //变异操作也要遵从一定的概率来进行,一般设置为0到0.5之间

    //

    if (random == 25)                              // random==25的概率只有2%,即变异率为,所以是以小概率进行变异!!

    {

        col = rand() % len;                            // 随机产生要变异的基因位号;

        row = rand() % 100;                            // 随机产生要变异的染色体号;
        col2 = rand() % len;                           // 随机产生要变异的基因位号;


        t = popnext[row].bit[col];
        popnext[row].bit[col] = popnext[row].bit[col2];
        popnext[row].bit[col2] = t;
        /***************************************************************************************************************************/
        popnext[row].fit = y(popnext[row]);     // 计算变异后的适应度值;

        

    }


}
 

注意,概率分布函数没什么用,这个算法没有用到,可以酌情删去。

最后是main函数

#include "stdafx.h"
#include "GenAlgTSP.h"

void main()                                    // 主函数;

{

    int num;                                    // 迭代次数;

    int i, j, l, Max, k;

    Max = 0;                                      // 函数最大值

 

    printf("\nWelcome to the Genetic Algorithm!\n");  // 

    printf("The Algorithm is based on the function 函数为y=3*a^2+24*b+5*c^2+d^3+e+2f+2*g^3 to find the maximum value of the function.\n");

 

enter:printf("\nPlease enter the no. of iterations\n请输入您要设定的迭代数 : ");

    scanf_s("%d", &num);                           // 输入迭代次数,传送给参数 num;

 

    if (num <1)

        goto enter;                                 // 判断输入的迭代次数是否为负或零,是的话重新输入;

    //不同的随机数可能结果不同??那是当所设置的迭代次数过少时,染色体的基因型过早地陷入局部最优

    srand(time(0));
    GenAlgTSP genalg;

    genalg.evpop(genalg.popcurrent);    // 随机产生初始种群;

    //是否需要指定x的取值范围呢?6bit来表示数字,第一位为符号位,5bit表示数字大小。所以,取值范围为-32~+31

    Max = genalg.popcurrent[0].fit;//对Max值进行初始化

 

    for (i = 0; i< num; i++)                          // 开始迭代;

    {

 

        printf("\ni = %d\n", i);                 // 输出当前迭代次数;

 

        for (j = 0; j<100; j++)

        {

            genalg.popnext[j] = genalg.popcurrent[j];           // 更新种群;

        }

 

        genalg.pickchroms(genalg.popnext);                    // 挑选优秀个体;

        genalg.crossover(genalg.popnext);                     // 交叉得到新个体;

        genalg.mutation(genalg.popnext);                      // 变异得到新个体;

 

        for (j = 0; j<100; j++)

        {

            genalg.popcurrent[j] = genalg.popnext[j];              // 种群更替;

        }

 

    }  // 等待迭代终止;

    //对于真正随机数是需要注意取较大的迭代次数
    int A[len];

    for (l = 0; l<100; l++)

    {

        if (genalg.popcurrent[l].fit > Max)

        {

            Max = genalg.popcurrent[l].fit;

            //k = genalg.y(genalg.popcurrent[l]);//此时的value即为所求的x值
            for (int i = 0; i < len; i++)
                A[i] = genalg.popcurrent[l].bit[i];

        }

 

    }
    printf("\n 当排序等于");
    for(int i = 0; i < len;i++)
      printf("%d ", A[i]);
    printf("\n函数得到最大值为: %d ", Max);

    printf("\nPress any key to end ! ");

 

    _flushall();                                 // 清除所有缓冲区;

    _getche();                                   // 从控制台取字符,不以回车为结束;

 

}
 

 

 

你可能感兴趣的:(遗传算法解决TSP问题C++代码,写成类和主函数的形式)