遗传算法(GA)解决旅行商(TSP)问题

以下是遗传算法(GA)解决旅行商问题(TSP)源码:

#include <iostream>
#include <vector>
#include <ctime>
#include <algorithm>
#include <cmath>
using namespace std;
#define INF 1000
typedef struct individual{
    vector<int> chrom;
    double fit;
    double percentage;
    int pathL;
};

bool compare(individual a, individual b){ return a.percentage > b.percentage; }

class SGA
{
public:
    SGA();
    SGA(int psize, int gen, int maxgen, double c, double m) :popsize(psize), Genlen(gen), maxgener(maxgen), pc(c), pm(m){}
    ~SGA();
    void Initial(int** a);
    void Select(int** a);
    void Variation();
    void mutation();
    void evolution(int** a);
    void print();
    void updateData(int** a);
private:

    vector<individual > matingpool;
    int popsize;//种群大小
    int Genlen;//基因长度,也即城市个数
    int maxgener;//迭代代数
    double pc;
    double pm;
    bool IsNotExit(individual vc, int start, int end, int value);
    vector<int> BuildRandomSequence(int len);
};

SGA::SGA()
{
}

bool SGA::IsNotExit(individual vc, int start, int len, int value)
{
    for (size_t t = start; t != start + len; t++) if (vc.chrom[t] == value) return false;
    return true;
}

//随机产生序列,也即随机产生个体
vector<int> SGA::BuildRandomSequence(int length)
{
    vector<int> vc;
    int i;
    for (i = 0; i < length; i++)  vc.push_back(i);
    int x = 0, tmp = 0;
    for (i = length - 1; i > 0; i--) {
        //x = random.Next(0, i + 1);
        x = rand() % (i + 1);
        tmp = vc[i];
        vc[i] = vc[x];
        vc[x] = tmp;
    }
    return vc;
}

//更新每个个体的fitness
void SGA::updateData(int** a)
{
    double ftotal = 0;
    int path = 0;
    for (size_t t = 0; t < matingpool.size(); t++)
    {
        for (size_t x = 1; x < Genlen; x++) 
            path += *((int*)a + Genlen*matingpool[t].chrom[x - 1] + matingpool[t].chrom[x]);
        path += *((int*)a + Genlen*matingpool[t].chrom[0] + matingpool[t].chrom[Genlen-1]);
        matingpool[t].pathL = path;
        matingpool[t].fit = 1.0 / path;
        path = 0;
        ftotal += matingpool[t].fit;
    }
    for (size_t tt = 0; tt < matingpool.size(); tt++)
    {
        matingpool[tt].percentage = matingpool[tt].fit / ftotal;
    }
}

//初始化种群
void SGA::Initial(int** a)
{
    int i, j=1;
    individual ida;
    int path = 0;
    for (j = 0; j < popsize; j++)
    {
        ida.chrom = BuildRandomSequence(Genlen);
        matingpool.push_back(ida);
    }
    updateData(a);
}

void SGA::Select(int** a)
{
    //选择个体加入 mating pool,可能重复
    vector<individual> vcida;

    updateData(a);
    for (size_t i = 0; i < matingpool.size(); i++)
    {
        vcida.push_back(matingpool[i]);
    }
    matingpool.clear();

    double rate;
    double ff = 0.0;
    srand((unsigned)time(NULL));
    while (1)
    {
        rate = rand()*1.0 / RAND_MAX;
        for (int i = 0; i < popsize; i++)
        {
            if (rate>ff && rate <= vcida[i].percentage + ff)
            {
                matingpool.push_back(vcida[i]);
                break;
            }
            ff += vcida[i].percentage;
        }
        ff = 0.0;
        if (matingpool.size() == popsize) break;
    }
    updateData(a);
}


void SGA::Variation()
{
    //Parent交叉产生Offspring,pc为交叉率,即参加交叉运算的染色体数占全部染色体总数的百分比
    int pcd = popsize / 2 * pc;
    vector<individual> crw;
    sort(matingpool.begin(), matingpool.end(), compare);

    int cnt = 0;
    for (size_t i = popsize-1; cnt!=2*pcd; i--,cnt++)
    {
        crw.push_back(matingpool[i]);
    } 

    int i,j;
    srand((unsigned)time(NULL));
    int start = rand() % (Genlen - 3);
    int length = rand() % (Genlen - start);

    individual a, b,o1,o2;
    vector<int> ttp;
    for (i = 0; i != 2 * pcd; i+=2)
    {
        a = crw[i];
        b = crw[i+1];
        o1 = a;
        o2 = b;

        ttp.clear();
        for (j = 0; j != Genlen; j++)
        {
            if (IsNotExit(o1, start, length, b.chrom[j]))
                ttp.push_back(b.chrom[j]);
        }

        for (j = 0; j < start; j++)
        {
            o1.chrom[j] = ttp[j];
        }
        for (j = start+length; j < Genlen; j++)
        {
            o1.chrom[j] = ttp[j - start - length ];
        }

        ttp.clear();

        for (j = 0; j != Genlen; j++)
        {
            if (IsNotExit(o2, start, length, a.chrom[j]))
                ttp.push_back(a.chrom[j]);
        }

        for (j = 0; j < start; j++)
        {
            o2.chrom[j] = ttp[j];
        }
        for (j = start + length ; j < Genlen; j++)
        {
            o2.chrom[j] = ttp[j - start - length ];
        }
        matingpool.push_back(o1);
        matingpool.push_back(o2);
    }

    crw.clear();
    ttp.clear();
}
//突变操作
void SGA::mutation()
{
    int pcd = popsize * pm;
    int i, pos1,pos2, tp,tt;
    srand((unsigned)time(NULL));
    for (i = 0; i < pcd; i++)
    {
        tp = rand() % matingpool.size();
        pos1 = rand() % Genlen;
        pos2 = rand() % Genlen;
        tt = matingpool[tp].chrom[pos1];
        matingpool[tp].chrom[pos1]= matingpool[tp].chrom[pos2];
        matingpool[tp].chrom[pos2] = tt;
    }
}
//进化操作
void SGA::evolution(int** a)
{
    int gen = 0;
    while (gen != maxgener)
    {
        Variation();
        mutation();
        Select(a);
        gen++;
    }
}

void SGA::print()
{
    int i,k, P=10000;
    for (i = 0; i < popsize; i++)
    {
        if (matingpool[i].pathL < P)
        {
            P = matingpool[i].pathL;
            k = i;
        }
    }
    cout << "最短距离: " << matingpool[k].pathL << endl;
    cout << "最短路径: " ;
    for (i = 0; i < Genlen; i++) cout << matingpool[k].chrom[i] << " ";
    cout << matingpool[k].chrom[0];
    cout << endl;
}

SGA::~SGA()
{
}

猜你喜欢

转载自blog.csdn.net/qithon/article/details/51005018