TSP问题(换位表达,启发式交叉,启发式变异)C++实现

旅行商问题

一 染色体表达方式

染色体的表达方式采用换位表达,它是TSP巡回的最自然的表达,如下图:
在这里插入图片描述

它的访问顺序为 3-2-5-4-7-1-6-9-8,染色体中基因的值表示城市,基因的顺序表示访问城市的顺序,这种表达的搜索空间是城市顺序“换位”的集合,采用传统的单点交叉时,可能导致非法的巡回。

二 染色体交叉

本课题中的染色体交叉使用的是启发式交叉,启发式交叉的步骤如下(最近邻点法):
步骤1:从一对双亲中随机地选取一个城市最为开始城市,
步骤2:由当前城市出发,选择一条不构成循环的最短边(由双亲表达的)。若两边都构成循环,则随机选取一个能使巡回继续的城市;
步骤3:如巡回完成,停机;否则转第2步。
在这里插入图片描述

启发式交叉法明显优于其他方法

三 染色体变异

本课题中的染色体变异使用的是启发式变异,采用邻域技术,以获得后代的改进。启发式变异过程如下:
步骤1:随机地选出λ个基因;
步骤2:按所有选出基因的可能的换位产生邻域;
步骤3:评估所有邻域点,选出最好的作为变异产生的后代。
在这里插入图片描述

四 种群的适值函数

本课题中的适值函数为一个染色体中相邻两个基因的距离的加和,以及首尾两个城市的距离。

五 种群的选择策略

本课题中的选择策略是从交叉后代,变异后代,和原来的父代中选择最好的前n(n表示种群数量)个。

六 种群的初始化方法

本种群的初始化方法是从源文件读取城市信息,确定城市数量,通过城市数量产生m(表示城市数量)个不同的随机数,通过客户的输入的种群大小k,随机产生k个染色体。

七 程序设计说明

1、遗传算法结构图
在这里插入图片描述

2、种群初始化流程图
在这里插入图片描述

3、染色体交叉流程图
在这里插入图片描述

4、染色体变异流程图

在这里插入图片描述
在这里插入图片描述

5、种群更新
在这里插入图片描述

八、程序

//  东北大学信息科学与工程学院2020级硕士荆黎明
//  染色体的编码方式:换位表达
//  染色体的交叉方式:启发式交叉
//  染色体的变异方式:启发式变异
// Created by jlm on 2020/10/19.
//
#include <iostream>
#include "class.h"
#include <ctime>	// 产生随机数种子

using namespace std;

int main()
{
    
    
    PrintMessage();

    srand(time(NULL));	// 设置随机数种子

    TSP tsp;

    tsp.InitiPopul();
    cout << "/*************************************种群开始迭代*************************************" << endl;
    for (int i = 0; i != tsp.GetPopulationAlgebra(); i++)
    {
    
    
        cout << i+1 << "代" << endl << endl;;
        tsp.Crossover();
        tsp.HeuristicMutation();
        tsp.Update();
        tsp.Print();
        cout << "/*************************************"<<i+1 << "代交叉变异结束" <<
             "*************************************/" << endl;
    }

    return 0;
}


//
// Created by jlm on 2020/10/19.
//

#ifndef TSP_CLASS_H
#define TSP_CLASS_H

#include <iostream>
#include <string>
#include <vector>

using namespace std;

struct Data {
    
    
    int PopulationAlgebra;	// 种群代数
    double NumPopulation;	// 种群数量
    double CrossoverRate;	// 交叉率
    double MutationRate;	// 突变率
};

typedef struct city{
    
    
    std::string name;
    double x;
    double y;
}p;

typedef struct DistTable{
    
    
    double distance;
    int table;
} DT;

// 输出文件信息
void PrintMessage(void) ;

class BaseTsp{
    
    
public:
    BaseTsp();
    // 显示路径
    void ShowRoute(vector<int> &vi) const;

    // 获得两个城市的距离
    double GetTwoCityDist(int firstCity, int secondCity) const;

    // 获得n个城市的路径
    void GetCityDist(const vector<int> &vi, double &distance) const;

    // 生成随机数
    void GeneratorRand(vector<int> &vi) const;

    // 获得nCity数据
    int GetnCity(void) const;

    // 打印染色体
    void printFunc(const vector<int> &vi) const;

private:
    void ReadCityData();
    vector<p> vCity;
    int nCity;
};

class TSP: public BaseTsp
{
    
    
public:
    TSP(int Size, double CrossoverRate, double MutationRate, int PopulationAlgebra);
    TSP(struct Data data);
    TSP();
    void InitiPopul(void);
    void Crossover(void);
    void HeuristicMutation(void);
    void Update(void);
    void Print(void);

public:
    // 获得种群代数
    int GetPopulationAlgebra(void) const;

private:
    // 两个父代产生一个子代
    void GeneratorOffspring( const vector<int> &va, const vector<int> &vb, vector<int> &offspring) const;

    // 确定定位点
    int DeterminePoint(const vector<int> &vi, const int &value) const;

    // 为种群生成一个随机数列,该数列作为种群中各个染色体的交叉率 、变异率
    void ForPopulRand(vector<double> &vd) const;

    // 根据适值选择变异的子代
    void SelectOffspring(const vector<vector<int> > &mutoffspring, vector<int> &bestMuOffspring) const;

    // 基因换位,传入一个父代基因,输出全排列后的所有基因
    void GeneTransposition(const vector<int> &vpa, vector<vector<int> > &vvGene) const;

    // 全排列算法 传入一个数组,产生一个全排列数组
    void Permutation(vector<int> &vi, vector<int>::iterator begin,
                     vector<int>::iterator end, vector<vector<int> > &vvi) const;

    // 生成n个不同的随机数,范围0~n;
    void GeneratorRand(int n, int start, int end, vector<int> & vi) const;

    // 对基因进行插值
    void Interpolation(const vector<int> &position, const vector<int> &vGene, vector<vector<int> > &vvGene) const;

    // 根据适值选择子代,子代的个数为种群的数量
    void SelectOffspring(vector<vector<int> > &vparent);

    // 寻找最后一个元素是否前面出现过
    bool findFun(vector<int> &vi) const;

    int DeleteFun(vector<int> & vtParent, vector<int> & voffspring) const;

    void InputData(struct Data & data) const;

private:
    int Size;	//种群数量
    double CrossoverRate;	//交叉率
    double MutationRate; 	// 突变率
    int PopulationAlgebra;  // 种群迭代次数

    vector<vector<int> > vParent;   // 父代染色体
    vector<vector<int> > vOffspring;    // 交叉产生的染色体
    vector<vector<int> > vMutOffspring; // 变异产生的染色体
};

#endif //TSP_CLASS_H

//
// Created by jlm on 2020/10/19.
//
#include "class.h"
#include <iostream>
#include <fstream>
#include <cstdlib>	// support for exit()	//随机数
#include <cmath>
#include <ctime>	// 产生随机数种子
#include <vector>
#include <algorithm> 	//  for sort() 排序函数

using namespace std;

/*
 * @BaseTsp()构造函数
 */
BaseTsp::BaseTsp()
{
    
    
    ReadCityData();
}
/*
 @ ReadCityDate() :实现文件数据读取
 */
void BaseTsp::ReadCityData()
{
    
    

    cout << "Enter name of data file: ";
    string filename;
    cin >> filename;


    ifstream file(filename);
    if(!file.is_open())
    {
    
    
        cerr << "文件未能打开:" << filename << endl;
        cerr << "程序终止\n";
        exit(EXIT_FAILURE);		// should include <cstdlib>
    }

    p City;	// 城市的结构体
    nCity = 0;
    file >> City.name >> City.x >> City.y ;
    while(file.good())
    {
    
    
        vCity.push_back(City);
        nCity++;
        file >> City.name >> City.x >> City.y ;
    }

    if(file.eof())
    {
    
    
        cout <<" 文件数据信息读取完成.\n";
    }
    else if (file.fail())
    {
    
    
        cout << " 文件数据信息不匹配.\n";
    }
    else
    {
    
    
        cout << " 由未知原因导致程序输入异常终止.\n";
    }
    file.close();

    cout << "数据读取完成..." << endl;
}
/*
 * @ShowRoute:该函数实现输出巡回路径
 * @ vi : 染色体
 */
void BaseTsp::ShowRoute(vector<int> &vi) const
{
    
    
    cout << "最优路径:  " ;
    //向屏幕输出结果
    int num = 0;
    for (auto a:vi)
    {
    
    
        cout << vCity[a - 1].name << "->" ;
        num++;
        if(num % 20 == 0)   // 20个城市换行
            cout << endl;
    }
    cout << vCity[vi[0] - 1].name << endl;
}
/*
 * @GetTwoCityDist():该函数实现两个城市距离计算
 * @返回值:两个城市间的距离
 * @firstCity: 第一个城市的序号
 * @secondCity: 第二个城市的序号
 */
double BaseTsp::GetTwoCityDist(int firstCity, int secondCity) const
{
    
    
    double distance;
    distance = sqrt((vCity[firstCity - 1].x - vCity[secondCity - 1].x)*(vCity[firstCity - 1].x - vCity[secondCity - 1].x)
                    +(vCity[firstCity - 1].y - vCity[secondCity - 1].y)*(vCity[firstCity - 1].y - vCity[secondCity - 1].y));
    return distance;
}

void BaseTsp::GetCityDist(const vector<int> &vi, double &distance) const
{
    
    
    distance = 0;
    int n = vi.size();
    for (int i = 0; i < n - 1; i++)
    {
    
    
        distance += GetTwoCityDist(vi[i], vi[i+1]);
    }
    // 最后回到原点
    distance += GetTwoCityDist(vi[n - 1], vi[0]);
}
/*
 *@GetnCity:获得城市的数量
 */
int BaseTsp::GetnCity(void) const
{
    
    
    return nCity;
}
/*
 * @GeneratorRand:为染色体产生随机数,随机数范围位【1,城市的数量】
 * @vi: 染色体
 */
void BaseTsp::GeneratorRand(vector<int> &vi) const	// for chromosome(染色体)
{
    
    
    int numCity = GetnCity();
    int randNum;
    int j;
    for (int i = 0; i < numCity; i++)
    {
    
    
        while(1)
        {
    
    
            randNum = rand() % numCity + 1;	// 获取固定区间[m,n]的随机数的公式 rand % (n - m + 1) + m
            for (j = 0; j < i; j++)
                if(vi[j] == randNum)	break;	// 检查重复
            if (j == i)	// 没有重复,保存到vi中
            {
    
    
                vi.push_back(randNum);
                break;
            }
        }
    }
}

/*
 * @printFunc(): 打印染色体
 */
void BaseTsp::printFunc(const vector<int> &vi) const
{
    
    
    for (auto a:vi)
    {
    
    
        cout << a << "  ";
    }
    cout << endl;
}

/*
 * @TSP: TSP() 的构造函数
 * @ Size: 种群的数量
 * @ CrossoverRate: 种群的交叉率
 * @ MutationRate: 种群的变异率
 */
TSP::TSP(int Size, double CrossoverRate, double MutationRate, int PopulationAlgebra):BaseTsp()
{
    
    
    this -> Size = Size;
    this -> CrossoverRate = CrossoverRate;
    this -> MutationRate = MutationRate;
    this -> PopulationAlgebra = PopulationAlgebra;
}
/*
 * @TSP():构造函数
 * @data: 结构体
 */
TSP::TSP( struct Data data):BaseTsp()
{
    
    
   this -> Size = data.NumPopulation;
   this -> CrossoverRate = data.CrossoverRate;
   this -> MutationRate = data.MutationRate;
   this -> PopulationAlgebra = data.PopulationAlgebra;
}

TSP::TSP() :BaseTsp()
{
    
    
    struct Data data;
    InputData(data);
    this -> Size = data.NumPopulation;
    this -> CrossoverRate = data.CrossoverRate;
    this -> MutationRate = data.MutationRate;
    this -> PopulationAlgebra = data.PopulationAlgebra;
}
/*
 * @InitiPopul(): tsp的初始化函数,并打印产生的初始种群
 */
void TSP::InitiPopul(void)
{
    
    
    for (int i = 0; i < Size; i++)
    {
    
    
        vector<int> vi;
        BaseTsp::GeneratorRand(vi);
        vParent.push_back(vi);
    }

    // 打印出初始种群
    cout << "初始种群" <<endl;
    int i = 0;
    for (auto a:vParent)
    {
    
    
        cout << ++i << "#         ";
        printFunc(a);
    }
}

/*
 * @Crossover():种群交叉,并打印种群交叉产生的子代
 */
void TSP::Crossover(void)
{
    
    
    vector<double> vd;	// 存储各个染色体的交叉率
    ForPopulRand(vd);

    // 寻找小于交叉率的染色体
    vector<int> vc;	// 存储染色体小于交叉率的序号
    for (int i = 0; i != vd.size(); i++)
    {
    
    
        if (vd[i] <= CrossoverRate)
        {
    
    
            vc.push_back(i);
        }
    }

    if (vc.size()%2)	// 删除一个数,使得产生偶数个父代
    {
    
    
        int t = rand() % vc.size();		// 随机产生一个数
        vc.erase(vc.begin() + t);
    }

    // 随机选择两个染色体进行交叉

    int nNum = vc.size()/2;	// 进行交叉的次数
    for (int i = 0; i != nNum; i++)
    {
    
    
        int vaPoint = rand() % vc.size();
        int vaValue = vc[vaPoint];	// 父代1号索引值
        vc.erase(vc.cbegin() + vaPoint);

        int vbPoint = rand() % vc.size();
        int vbValue = vc[vbPoint];	// 父代2号索引值
        vc.erase(vc.cbegin() + vbPoint);

        vector<int> offspring;	// 存储交叉的子代

        GeneratorOffspring(vParent[vaValue],vParent[vbValue],offspring);
        vOffspring.push_back(offspring);
    }
}
/*
 * @GeneratorOffspring():两个染色体进行交叉,产生子代染色体
 * @va: 父代染色体
 * @vb: 父代染色体
 * @offspring: 交叉产生的子代染色体
 */
void TSP::GeneratorOffspring( const vector<int> &va, const vector<int> &vb,
                              vector<int> &offspring) const
{
    
    
    int nCity = GetnCity();

    int firstCity = rand() % nCity + 1;	// 随机选择一个城市作为开始,随机数的产生范围为[1, ncity]
    offspring.push_back(firstCity);	// 第一个基因

    int vaPoint, vbPoint;
    int count = 0;

    vaPoint = DeterminePoint(va, firstCity);
    vbPoint = DeterminePoint(vb, firstCity);

    vector<int> vtParent(va.begin(),va.end());

    while (offspring.size() != nCity)
    {
    
    
        if (vaPoint == nCity - 1)
        {
    
    
            vaPoint = -1;
        }
        if (vbPoint == nCity - 1)
        {
    
    
            vbPoint = -1;
        }

        double distanceOne = GetTwoCityDist(offspring[offspring.size() - 1],va[vaPoint + 1]);
        double distanceTwo = GetTwoCityDist(offspring[offspring.size() - 1], vb[vbPoint + 1]);

        if (distanceOne >= distanceTwo)
        {
    
    
            offspring.push_back(vb[vbPoint + 1]);

            if (findFun(offspring)) //最后一个元素和前面的基因(元素)重复
            {
    
    
                offspring.push_back(va[vaPoint + 1]);
                if(findFun(offspring))
                {
    
    
                    //随机选择一个城市
                    int city = DeleteFun(vtParent, offspring);
                    offspring.push_back(city);
                    vaPoint = DeterminePoint(va, city);
                    vbPoint = DeterminePoint(vb, city);
                }
                else
                {
    
    
                    vaPoint = vaPoint + 1;
                    vbPoint = DeterminePoint(vb, va[vaPoint]);
                }
            }
            else
            {
    
    
                vaPoint = DeterminePoint(va, vb[vbPoint + 1]);
                vbPoint = vbPoint + 1;
            }
        }
        else
        {
    
    
            offspring.push_back(va[vaPoint + 1]);
            if (findFun(offspring))
            {
    
    
                offspring.push_back(vb[vbPoint + 1]);
                if (findFun(offspring))
                {
    
    
                    // 随机选择一个城市
                    int city = DeleteFun(vtParent, offspring);
                    offspring.push_back(city);
                    vaPoint = DeterminePoint(va, city);
                    vbPoint = DeterminePoint(vb, city);
                }
                else
                {
    
    
                    vaPoint = DeterminePoint(va, vb[vbPoint + 1]);
                    vbPoint = vbPoint + 1;
                }
            }
            else
            {
    
    
                vaPoint = vaPoint + 1;
                vbPoint = DeterminePoint(vb, va[vaPoint]);
            }
        }
    }
}
/*
 * @DeleteFun():删除添加的重复城市,并随机选择一个城市
 * @vtParent: 父代
 * @voffspring: 子代
 */
int TSP::DeleteFun(vector<int> & vtParent, vector<int> &voffspring) const
{
    
    
    for (int i = 0; i != voffspring.size(); i++)
    {
    
    
        for (int j = 0; j != vtParent.size(); j++)
        {
    
    
            if (voffspring[i] == vtParent[j])
            {
    
    
                vtParent.erase(vtParent.begin() + j);
                j = j - 1;
            }
        }
    }

    int cityPoint = rand() % vtParent.size()  + 1;
    return vtParent[cityPoint - 1];
}

/*
 *@ findFun : 查找染色体中前面已经出现的城市,若出现则删除
 */

bool TSP::findFun( vector<int> &vi) const
{
    
    
    for (int i = 0; i != vi.size()- 1; i++)	// 减去2的原因是value
    {
    
    
        if (vi[i] == vi[vi.size() - 1])
        {
    
    
            vi.erase(vi.cbegin() + vi.size() - 1);
            return true;
        }
    }
    return false;
}

/*
 * @DeterminePoint():该函数的功能是确定value值在染色体的vi的位置
 * @ vi: 染色体
 * @ value: 染色体的某个值
 */
int TSP::DeterminePoint(const vector<int> &vi, const int &value) const
{
    
    
    for (int i = 0; i != vi.size(); i++)
    {
    
    
        if (value == vi[i])
        {
    
    
            return i;
        }
    }
}
/*
@function :函数功能为为种群生成一个随机数列,该随机数列可作为交叉率和突变率
@ vd : vd存储的是生成的随机数列
*/
void TSP::ForPopulRand(vector<double> &vd) const
{
    
    
    srand(time(NULL));
    double randNum;
    const int N = 99;		// 两位小数
    for (int i = 0; i < Size; i++)
    {
    
    
        randNum = rand() %(N + 1)/(double) (N + 1);	// 生成0-1间的随机数
        vd.push_back(randNum);
    }
}

/*
 * @ HeuristicMutation(): 该函数的动能是对染色体进行变异
 */
void TSP::HeuristicMutation(void)
{
    
    
    // 第一步:根据突变率选择变异的父代
    vector<double>  vd;	// 存储的是各个染色体的突变率
    ForPopulRand(vd);

    vector<int> vmu;	// 存储需要突变的染色体序号

    for (int i = 0; i != vd.size(); i++)
    {
    
    
        if (vd[i] <= MutationRate)
        {
    
    
            vmu.push_back(i);
        }
    }

    for (int i = 0; i != vmu.size(); i++)
    {
    
    
        vector<vector<int> > vvGene;	// 存储全排列后的所有染色体
        GeneTransposition(vParent[vmu[i]], vvGene);

        // 对于每个染色体选择最优的子代
        vector<int> bestMuOffspring;
        SelectOffspring(vvGene, bestMuOffspring);
        vMutOffspring.push_back(bestMuOffspring);
    }
}

/*
@function:基因换位,传入一个父代基因,输出全排列后的所有染色体
@vpa: 表示父代基因
@vvGene: 表示生成的变异基因(已经除去了和父代相同的基因)
*/
void TSP::GeneTransposition(const vector<int> &vpa, vector<vector<int> > &vvGene) const
{
    
    

    int numGene = rand() % (vpa.size() - 2) + 2;	// 选择numGene 个基因,范围在[2~vpa.size()-1]

    // 对n个基因位置进行插值
    vector<int> vi;	// vi 存储变异基因的位置
    GeneratorRand(numGene, 0, vpa.size() - 1, vi);
    Interpolation(vi, vpa, vvGene);
}

// 对基因进行插值,生成基因全排列
/*
@ position : 存储的是随机选择的基因位置
@ vGene : 传入的父代基因
@ vvGene : 生成基因全排列
*/
void TSP::Interpolation(const vector<int> &position, const vector<int> &vGene, vector<vector<int> > &vvGene) const
{
    
    
    vector<int> vTemp;	// 装载随机选择的基因
    for (auto a:position)
    {
    
    
        vTemp.push_back(vGene[a]);
    }

    vector<int> vtemp(vTemp.begin(),vTemp.end());

    // 对选择的基因进行全排列
    vector<vector<int> > vvgene;	// 存储选择的基因的全排列
    Permutation(vTemp, vTemp.begin(), vTemp.end(), vvgene);

    // 删除和原始基因一样的序列
    int numGene = vvgene.size();
    for (auto it = vvgene.cbegin(); it != vvgene.cend(); it++)
    {
    
    
        for (int j = 0; j != (*it).size(); j++)
        {
    
    
            if((*it)[j] == vtemp[j])
            {
    
    
                if(j == (*it).size() - 1)
                {
    
    
                    vvgene.erase(it);
                }
            }
            else
            {
    
    
                break;
            }
        }
        if(numGene != vvgene.size())	// 已经找到重复基因,跳出循环
        {
    
    
            break;
        }
    }
    // 将生成的全排列数组分配到基因中
    vector<int> gene(vGene.begin(),vGene.end());

    for (auto a:vvgene)
    {
    
    
        int i = 0;
        for (auto b:a)
        {
    
    
            gene[position[i]] = b;
            i++;
        }
        vvGene.push_back(gene);
    }
}

/*
function: 该函数的功能是生成n个数的全排列
@vi:存储的是需要进行全排列的n个数
@begin:存储的是vi的首迭代器
@end: 存储的是vi的尾迭代器
*/
void TSP::Permutation(vector<int> &vi, vector<int>::iterator begin,
                      vector<int>::iterator end, vector<vector<int> > &vvi) const
{
    
    
    if (begin == end)//递归的基础部分
    {
    
    
        vector<int> temp;
        for (vector<int>::iterator it = vi.begin(); it != end; it++)
        {
    
    
            temp.push_back(*it);
        }
        vvi.push_back(temp);
    }
    else
    {
    
    
        for (auto it = begin; it != end; it++)
        {
    
    
            swap(*begin, *it);
            Permutation(vi, begin+1, end, vvi);
            swap(*begin, *it);
        }
    }
}

/*
@ n : 产生随机数的个数
@ start :
@ end : [start end] 产生随机数的范围
@ vi :生成的随机数	(存储随机选择的基因位置)
*/
void TSP::GeneratorRand(int n, int start, int end, vector<int> &vi) const
{
    
    
    int randNum;
    int j;
    for (int i = 0; i != n; i++)
    {
    
    
        while(1)
        {
    
    
            randNum = rand() % (end - start + 1) + start;
            for (j = 0; j < i; j++)
            {
    
    
                if (vi[j] == randNum)
                    break;
            }
            if (j == i)
            {
    
    
                vi.push_back(randNum);
                break;
            }
        }
    }
}
/*
 * @ Update():该函数的功能是更新种群
 */
void TSP::Update(void)
{
    
    
    for (auto a:vOffspring)
    {
    
    
        vParent.push_back(a);
    }
    for (auto a:vMutOffspring)
    {
    
    
        vParent.push_back(a);
    }

    SelectOffspring(vParent);
}
/*
 * @SelectOffspring(): 该函数的功能是选择最优的染色体(选择的数量是初始种群的个数)
 * @ vparent: 需要进行选择的种群
 */
void TSP::SelectOffspring(vector<vector<int> > &vparent)
{
    
    
    vector<DT> vDT;	// 存储距离和标号

    for (int i = 0; i != vparent.size(); i++)
    {
    
    
        DT dt;
        GetCityDist(vparent[i], dt.distance);
        dt.table = i;
        vDT.push_back(dt);
    }

    sort(vDT.begin(),vDT.end(),
         []( struct DistTable &dtOne,  struct DistTable &dtTwo){
    
     return (dtOne.distance < dtTwo.distance);
         });

    for (int i = 0; i != vDT.size(); i++)
    {
    
    
        for (int j = i + 1; j != vDT.size(); j++)
        {
    
    
            if (vDT[i].distance == vDT[j].distance)
            {
    
    
                vDT.erase(vDT.begin() + i);
                j = j - 1;
            }
        }
    }

    vector<vector<int> > VPARENT;
    for (int i = 0; i != Size; i++)
    {
    
    
        VPARENT.push_back(vparent[vDT[i].table]);
    }

    vparent.clear();	// 删除所有元素

    for (auto a:VPARENT)
    {
    
    
        vparent.push_back(a);
    }
}

/*
 * Print(): 该函数的功能是打印种群的最优路径和最优路径距离
 */
void TSP::Print()
{
    
    
//    cout << "交叉产生的后代" << endl;
//    for (int i = 0; i != vOffspring.size(); i++)
//    {
    
    
//        cout << i+1 << "#         ";
//        printFunc(vOffspring[i]);
//    }
//    cout << "变异产生的后代" << endl;
//    for (int i = 0; i != vMutOffspring.size(); i++)
//    {
    
    
//        cout << i+1 << "#         ";
//        printFunc(vMutOffspring[i]);
//    }
    vOffspring.clear(); // 删除本代产生的交叉子代
    vMutOffspring.clear();  // 删除本代变异产生的子代
//    cout << "物竞天择,适者生存后的种群" << endl;
//    for (int i = 0; i != vParent.size(); i++)
//    {
    
    
//        cout << i+1 << "#         ";
//        printFunc(vParent[i]);
//    }

    vector<int> bestSoulation;
    SelectOffspring(vParent, bestSoulation);
    cout << "该种群中的最优解:" << endl;
    printFunc(bestSoulation);

    double distance ;
    GetCityDist(bestSoulation, distance);

    ShowRoute(bestSoulation);
    cout << "该种群中的最短路径为:" << distance << endl;
    
    // 将distance存储在CSV格式文件中
    static int start = 0;
	ofstream oFile;
	if (start == 0)	// 第一代 
	{
    
    
		oFile.open("distance.csv");
		oFile << distance << endl;
		oFile.close();
	}
	oFile.open("distance.csv", ofstream::app);	// 为了保留文件内容,必须显示指定app模式
	oFile << distance << endl;
	oFile.close(); 
	start++;
}

/*
@ function : 根据适值选择最好的子代
@ mutoffspring : 变异基因的全排列组合
@ bestMuOffspring:  选择出最好的子代
*/
void TSP::SelectOffspring(const vector<vector<int> > &mutoffspring, vector<int> &bestMuOffspring) const
{
    
    
    vector<double> vd;	// 存储城市路径的总距离
    for (auto a:mutoffspring)
    {
    
    
        double distance;
        GetCityDist(a,distance);
        vd.push_back(distance);
    }

    double min = vd[0];
    int minKpoint = 0;
    for (int i = 0; i != vd.size(); i++)
    {
    
    
        if (vd[i] <= min)
        {
    
    
            minKpoint = i;
        }
    }

    for (auto a:mutoffspring[minKpoint])
    {
    
    
        bestMuOffspring.push_back(a);
    }
}

int TSP::GetPopulationAlgebra(void) const
{
    
    
    return (PopulationAlgebra);
}

void TSP::InputData(struct Data & data) const
{
    
    
    cout << "请输入数据信息:种群代数,种群数量,种群交叉率,种群突变率等" << endl << endl;
    cout << "种群代数: " ;
    cin >> data.PopulationAlgebra;
    cout << "种群数量:";
    cin >> data.NumPopulation;
    cout << "种群交叉率:";
    cin >> data.CrossoverRate;
    cout << "种群突变率:";
    cin >> data.MutationRate;
}

/*
 * @PringMessage(): 该函数的功能是打印程序信息
 */
void PrintMessage(void)
{
    
    
	cout << "学校:东北大学" << endl;
    cout << "学院:信息科学与工程学院" << endl;
    cout << "专业:控制科学与工程" << endl;
    cout << "学号:2000764" << endl;
    cout << "班级:2005班" << endl;
    cout << "姓名:荆黎明" << endl;

    cout << endl << endl;
    cout << "注:" << endl;
    cout << "本程序的调试工作是在Ubuntu18.04上完成的!!!" << endl;
    cout << "染色体的编码方式:换位表达" << endl;
    cout << "染色体的交叉方式:启发式交叉" << endl;
    cout << "染色体的变异方式:启发式变异" << endl;
    cout << endl << endl;
}


猜你喜欢

转载自blog.csdn.net/jlm7689235/article/details/109853159