当前位置:   article > 正文

遗传算法C++实现求解VRP问题_vrp遗传算法编码

vrp遗传算法编码

 车辆路径问题(Vehicle Routing Problem, VRP)

1.问题描述

车辆路线问题(VRP):一定数量的客户,各自有不同数量的货物需求,配送中心向客户提供货物,由一个车队负责分送货物,组织适当的行车路线,目 标是使得客户的需求得到满足,并能在一定的约束下,达到诸如路程最短、成本最小、耗费时间最少等目的。

2.VRP基因编码和解码方法 

假设1:仅有1个配送中心,在某一时刻,所有负责配送的车同时从 配送中心出发,分别完成各自的配送任务后,再回到配送中心(送奶路线);

假设2:配送中心有若干辆车(如6辆),一辆车可负责一个或多个点的配送任 务,且每个配送点只被服务一次。

假设3:每辆车有一定的载重量(如90t)和里程限制(如 200km),车的载重和行驶里程不可超过指定的值。

假设4:车辆必须在客户允许的时间窗处进行配送服务,此处采用硬时间窗

·编码

对于此问题,采用自然数编码,每个自然数代表一个客户,0代表配送中心,例如:

2

5837194610

·解码

在解码过程中应该使每辆车在满足各种约束条件下为尽可能多的客 户提供服务。首先,安排第一辆车从配送中心0出发,到序列中的第一 个客户2处为其提供服务,服务完后再综合考虑车辆容量限制、行驶总路程限制以及序列中第二个客户5的时间窗限制等条件,决定是否直接到客户5处提供服务。 假若条件允许,则到客户5处,服务完再分析是否直接到客户8处提 供服务,依次类推;假若不能为客户8提供服务,则该辆车直接由客户5处返回配送中心,形成一个配送回路0->2->5->0。

接下来,安排第二辆车从配送中心0出发,直接到客户8处,服务完 再分析是否到后续客户3处为其服务。

依此类推,直到所有的客户都被服务为止,将客户序列拆分成了若 干个满足约束条件的配送回路,对应一个可行解。

注:为了使任何一个个体解码后都能对应可行解,本节假设从配送中心派一辆车单独为某一个客户提供服务,都可以在该客户的第一个时间窗内到达并完成服务。在实际中,假若从配送中心出发的车辆直接到 某个客户处服务,不能在该客户的第一个时间窗内完成服务,则说明该客户的第一个时间窗不可用,可以删掉该时间窗。因此,这种假设是有 意义的。

本程序可以调节是否可用交叉和变异,及其参数值,以及锦标赛法选取的后代数目可在参数设置区进行调节(默认0.1倍种群大小) ,仅仅将下面的两个数据文件与GA.cpp文件放在一个工程目录下即可运行代码。

3.实例:

设有一配送中心为10个客户提供货物配送服务,序号0表示配送中心, 序号1,2,…,10表示10个需求点。

配送中心共有6辆同型号的车辆,每辆车的最大装载量均为90t,每辆车的最长行驶距离均200km;

动用每辆车的固定成本均为50元,每辆车行驶每公里成本为20元;

配送中心及各个需求点之间的距离见表1;

车辆在配送中心及各个需求点之间的行驶时间见表2;

各个需求点的需求量、服务时间及可利用的时间窗见表3;

为了使总配送成本达到最少,需要安排多少辆车完成配送任务?每辆车的配送路径是什么?

 

 

 4.算法设计

(1)选择算子:随机遍历抽样(Stochastic universal sampling,SUS)

随机遍历抽样是轮盘选择的修改版本。使用相同的轮盘,比例相同,但使用多个选择点,只旋转一次转盘就可以同时选择所有个体。 这种选择方法可以防止个体被过分反复选择,从而避免了具有特别高适应度的个体垄断下一代。因此,它为较低适应度的个体提供了被选择的机会, 从而减少了原始轮盘选择方法的不公平性。

 (2)交叉算子:2点交叉(2-point crossover)+ 交叉映射+交叉概率

在2点交叉中, 交换两个父代个体中交叉点之间的基因序列,并形成交叉映射关系, 再按照交叉映射关系对其他位点的基因进行变换,得到两个新个体。

上面的两个父代对于选定的交叉点可以形成如下交叉映射关系:

4—5、8—7、2—10、11—3。

按照这样的映射关系,交叉后得到两个新个体

 

 (3)变异算子:交换突变(Swap mutation)+变异概率

(4)终止规则

采用一定的进化代数N作为终止规则,即当进化代数达到N时,终止计算,并把历代种群个出现的适应度最大的个体作为问题的最优解输出。

5.算法实现

(1)语言:C++

(2)环境:

操作系统:windows10家庭版

IDE:Visual Studio 2022

CPU:Intel Core i7-10875H 2.3GHz   实际速度:约4.3Ghz

内存:16GB DDR4 2933MHz

(3)源代码

  1. //Time.h
  2. #pragma once
  3. #include<stdexcept>
  4. // 时间窗类
  5. class Time
  6. {
  7. public:
  8. // 默认构造函数
  9. Time() :start{ 0 }, end{ 24 } {}
  10. Time(unsigned start_, unsigned end_) :start{ start_ }, end{ end_ } {}
  11. //运算符重载
  12. bool operator<=>(const Time& other_time_window)const = delete;
  13. bool operator==(const Time& other_time_window)const = default;
  14. const auto& operator[](size_t index)const
  15. {
  16. if (index == 0)return start;
  17. if (index == 1)return end;
  18. throw std::out_of_range{ " Time 对象下标越界!" };
  19. }
  20. unsigned start; // 起始时刻
  21. unsigned end; // 结束时刻
  22. };

  1. // Customer.h
  2. #pragma once
  3. #include<array>
  4. #include<vector>
  5. #include<compare>
  6. #include"Time.h"
  7. const size_t Window_num{ 2 }; // 时间窗个数
  8. // 客户类,包括配送中心
  9. class Customer
  10. {
  11. public:
  12. // 默认构造函数
  13. Customer();
  14. // 主构造函数
  15. Customer(unsigned number, unsigned requirement, double service_time, std::array<Time, Window_num> time_window);
  16. // 删除副本成员
  17. Customer(const Customer&) = delete;
  18. Customer& operator=(const Customer&) = delete;
  19. // 默认移动成员
  20. Customer(Customer&&)noexcept = default;
  21. Customer& operator=(Customer&&)noexcept = default;
  22. //运算符重载
  23. bool operator==(const Customer& other_customer) const { return m_number == other_customer.get_number(); }
  24. const auto& operator[](size_t index)const { return m_time_window.at(index); }
  25. auto& operator[](size_t index) { return const_cast<Time&>(std::as_const(*this)[index]); }
  26. // 类型转换
  27. operator size_t()const { return m_number; }
  28. // 访问器 //
  29. const unsigned get_number() const { return m_number; }
  30. const unsigned get_requirement() const { return m_requirement; }
  31. const double get_service_time() const { return m_service_time; }
  32. // 展示顾客属性
  33. void show_customer() const;
  34. // 获得与另一个顾客的距离
  35. unsigned get_distance(const size_t other_customer_number)const;
  36. unsigned get_distance(const Customer& other_customer)const;
  37. unsigned get_distance(const Customer* other_customer)const;
  38. // 判断是否在时间窗内
  39. double is_in_window(double time)const;
  40. // 访问器 //
  41. // 无更改器 //
  42. // 展示固有参数
  43. static void show_parameters();
  44. static const Customer Distribution_Center; // 配送中心
  45. inline static std::vector<std::vector<int> > Distance_Matrix{}; // 客户以及配送中心之间的距离矩阵
  46. inline static std::vector<Customer> Customer_Array{}; // 客户序列,一般只在初始化时添加,不可修改
  47. inline static int Size{}; // 配送中心+客户数
  48. private:
  49. unsigned m_number; // 序号
  50. unsigned m_requirement; // 需求量,单位t
  51. double m_service_time; // 服务用时
  52. std::array<Time, Window_num> m_time_window{}; // 时间窗
  53. };
  1. // Car.h
  2. #pragma once
  3. #include"Customer.h"
  4. // 车辆类
  5. class Car
  6. {
  7. public:
  8. // 主构造函数
  9. explicit Car(unsigned number) :m_number{ number } {}
  10. // 默认副本成员
  11. Car(const Car&) = default;
  12. Car& operator=(const Car&) = default;
  13. // 默认移动成员
  14. Car(Car&&)noexcept = default;
  15. Car& operator=(Car&&)noexcept = default;
  16. //运算符重载
  17. const Customer* operator[](int index)const;
  18. Customer* operator[](int index) { return const_cast<Customer*>(std::as_const(*this)[index]); }
  19. // 类型转换
  20. operator size_t()const { return m_number; }
  21. // 访问器 //
  22. unsigned get_cost()const { return m_cost; }
  23. // 展示车辆属性
  24. void show_car()const;
  25. // 访问器 //
  26. // 更改器 //
  27. // 在路线后添加一个客户
  28. bool add_customer(const Customer* customer);
  29. //void add_customer(const Customer& customer);
  30. // 在时刻表后添加对应的时刻
  31. //void add_time(double time) { m_time.push_back(time); }
  32. // 计算配送成本
  33. void calculate_cost();
  34. // 更新时刻表
  35. bool update_time_list();
  36. // 更改器 //
  37. // 展示固有参数
  38. static void show_parameters(int choice = 0);
  39. inline static unsigned Max_Amount{ 6 }; // 车辆最大数量
  40. inline static unsigned Max_Load{ 90 }; // 车辆载重量,单位t
  41. inline static unsigned Max_Distance{ 200 }; // 车辆最大行驶距离,单位km
  42. inline static unsigned Fixed_Cost{ 50 }; // 车辆固定成本
  43. inline static unsigned Variable_Cost{ 20 }; // 车辆单位距离行驶成本
  44. inline static std::vector<std::vector<double> > Time_Matrix{}; // 汽车配送时间矩阵
  45. private:
  46. unsigned m_number; // 车辆汽车序号
  47. unsigned m_load{}; // 车辆车实际载重量
  48. unsigned m_distance_traveled{}; // 车辆车实际行驶距离
  49. std::vector<const Customer*> m_route{}; // 车辆车所经过的路径数组,包括出发和返回配送中心
  50. std::vector<double> m_time{}; // 车辆车到达时刻,与路径数组大小相同
  51. int m_customer_number{}; // 车辆车路径经过的客户数
  52. unsigned m_cost{}; // 车辆车成本,包括变动和固定成本
  53. };

  1. //Individual.h
  2. #pragma once
  3. #include"Car.h"
  4. // 个体类
  5. class Individual
  6. {
  7. public:
  8. // 默认构造函数
  9. Individual() :m_DNA{}, m_fitness{}, m_genetic_probability{}, m_sum_probability{}, m_cost{ 999999 }, m_number_of_violations{ 999999 } {}
  10. // 主构造函数
  11. Individual(const std::vector<int>& dna, unsigned cost = 0, std::vector<Car> car_array = std::vector<Car>{}, unsigned number_of_violations = 0);
  12. // 运算符重载
  13. const int& operator[](size_t index)const { return m_DNA.at(index); }
  14. int& operator[](size_t index) { return const_cast<int&>(std::as_const(*this)[index]); }
  15. // 访问器 //
  16. const auto& get_DNA()const { return m_DNA; }
  17. const unsigned get_cost()const { return m_cost; }
  18. const double get_fitness()const { return m_fitness; }
  19. const double get_genetic_probability()const { return m_genetic_probability; }
  20. const double get_sum_probability()const { return m_sum_probability; }
  21. const unsigned get_number_of_violations()const { return m_number_of_violations; }
  22. // 访问器 //
  23. // 更改器 //
  24. auto& set_DNA() { return m_DNA; }
  25. void update_fitness() { m_fitness = 1.0/m_cost; }
  26. void multiply_fitness(double value, unsigned times) { m_fitness *= pow(value, times); }
  27. void set_genetic_probability(double probability) { m_genetic_probability = probability; }
  28. void set_sum_probability(double sum_probability) { m_sum_probability = sum_probability; }
  29. // 解码
  30. void decode();
  31. // 更新并展示解
  32. void Update_and_display_solutions();
  33. // 计算成本
  34. unsigned update_cost();
  35. // 展示个体
  36. void show_individual()const;
  37. // 更改器 //
  38. static std::vector<Individual> Best_Individuals; // 最优个体,包括多个
  39. private:
  40. std::vector<int> m_DNA; // 基因序列
  41. double m_fitness; // 适应度,为成本的倒数
  42. double m_genetic_probability; // 遗传概率
  43. double m_sum_probability; // 轮盘赌累加值,左闭右开区间时,该个体成功遗传子代
  44. // 性状 //
  45. unsigned m_cost; // 成本
  46. std::vector<Car> m_car_array{}; // 电动车序列
  47. unsigned m_number_of_violations; // 违法约束次数
  48. // 性状 //
  49. };
  1. // Genetic_Algorithm.h
  2. #pragma once
  3. #include<string>
  4. #include"Individual.h"
  5. // 遗传算法类
  6. class Genetic_Algorithm
  7. {
  8. public:
  9. // 默认构造函数
  10. Genetic_Algorithm() = default;
  11. // 删除副本成员
  12. Genetic_Algorithm(const Genetic_Algorithm&) = delete;
  13. Genetic_Algorithm& operator=(const Genetic_Algorithm&) = delete;
  14. // 默认移动成员
  15. Genetic_Algorithm(Genetic_Algorithm&&)noexcept = default;
  16. Genetic_Algorithm& operator=(Genetic_Algorithm&&)noexcept = default;
  17. // 初始化种群
  18. void initialize();
  19. // 获得适应度
  20. void get_fitness();
  21. // 获得遗传概率
  22. void get_genetic_probability();
  23. // 获得轮盘赌累加概率
  24. void get_sum_probability();
  25. // 遗传算子 //
  26. // 选择算子,轮盘赌多选法
  27. void selection();
  28. // 交叉算子,两点交叉+映射法
  29. void crossover();
  30. // 变异算子,两点交换变异
  31. void mutation();
  32. // 遗传算子 //
  33. // 遗传算法入口
  34. void genetic_algorithm();
  35. // 展示固有参数
  36. static void show_parameters(int choice = 0);
  37. inline static size_t Po_Size{ 512 }; // 种群规模,一般为20~300
  38. inline static size_t Iterations{ 512 }; // 进化代数,一般为100~500
  39. inline static double Crossover_P{ 0.5 }; // 交叉概率,一般为0.4~0.99
  40. inline static double Mutation_P{ 1.0/1024 }; // 变异概率,一般为0.001~0.2
  41. inline static const double Punish{ 0.125 }; // 惩罚系数
  42. static Individual Best_Individual_in_History; // 历史最优个体
  43. private:
  44. std::vector<Individual> m_population{}; // 种群
  45. };
  1. //UI_Manage.h
  2. #pragma once
  3. #include"Genetic_Algorithm.h"
  4. class UI_Manage
  5. {
  6. public:
  7. // 展示菜单
  8. void Show_Menu()const;
  9. // 退出程序0
  10. void exit_system()const { exit(0); }
  11. // 读取文件1
  12. bool read_file(std::string_view distance_file = "节点距离.txt", std::string_view time_file = "行驶时间.txt", std::string_view customer_file = "客户需求和服务时间.txt");
  13. // 展示所有参数2
  14. void show_all_parameters()const;
  15. // 展示文件路径3
  16. void show_file_path()const;
  17. // 开始求解4
  18. void start_solve(std::string_view distance_file = "节点距离.txt", std::string_view time_file = "行驶时间.txt", std::string_view customer_file = "客户需求和服务时间.txt");
  19. // 修改参数5
  20. void modify_parameters();
  21. private:
  22. bool m_file_read{ false };
  23. };
  1. //Customer.cpp
  2. #include "Customer.h"
  3. #include<iostream>
  4. #include<format>
  5. using
  6. std::array,
  7. std::cout, std::endl,
  8. std::format;
  9. const Customer Customer::Distribution_Center{};
  10. // 默认构造函数
  11. Customer::Customer() :m_number{}, m_requirement{}, m_service_time{}, m_time_window{} {}
  12. // 主构造函数
  13. Customer::Customer(unsigned number, unsigned requirement, double service_time, std::array<Time, Window_num> time_window)
  14. :m_number{number},
  15. m_requirement{ requirement },
  16. m_service_time{ service_time },
  17. m_time_window {time_window}
  18. {}
  19. // 访问器 //
  20. // 判断是否在时间窗内,不在,则返回负数
  21. double Customer::is_in_window(double time)const
  22. {
  23. if (time < (*this)[0][0])
  24. {
  25. // 在第一个窗口前
  26. return time - (*this)[0][0];
  27. }
  28. else if (time <= (*this)[0][1])
  29. {
  30. // 在第一个窗口
  31. return 0;
  32. }
  33. else if (time < (*this)[1][0])
  34. {
  35. // 在两窗口中
  36. return time - (*this)[1][0];
  37. }
  38. else if (time <= (*this)[1][1])
  39. {
  40. // 在第二个窗口
  41. return 0;
  42. }
  43. else
  44. {
  45. // 在第二个窗口后,不能调整
  46. return 1;
  47. }
  48. }
  49. // 展示顾客属性
  50. void Customer::show_customer() const
  51. {
  52. cout << format("|{:4}|{:4}|{:.2f}|{:>2}{:<2},{:>2}{:<2}|{:>2}{:<2},{:>2}{:<2}|",
  53. m_number, m_requirement, m_service_time,
  54. "[", m_time_window[0].start, m_time_window[0].end, "]",
  55. "[", m_time_window[1].start, m_time_window[1].end, "]");
  56. }
  57. // 获得与另一个顾客的距离
  58. unsigned Customer::get_distance(const size_t other_customer_number)const
  59. {
  60. return Distance_Matrix[this->m_number][other_customer_number];
  61. }
  62. unsigned Customer::get_distance(const Customer& other_customer)const
  63. {
  64. return this->get_distance(static_cast<size_t>(other_customer.m_number));
  65. }
  66. unsigned Customer::get_distance(const Customer* other_customer)const
  67. {
  68. return this->get_distance(static_cast<size_t>(other_customer->m_number));
  69. }
  70. // 访问器 //
  71. void Customer::show_parameters()
  72. {
  73. using std::vector;
  74. cout << format("{}{}\n", "配送中心 + 客户数:", Size);
  75. cout << format("{:^30}\n", "节点距离矩阵");
  76. if (Distance_Matrix.empty())
  77. {
  78. cout << "距离矩阵为空!\n";
  79. }
  80. else
  81. {
  82. for (const auto& row : Distance_Matrix)
  83. {
  84. for (const auto& distance : row)
  85. {
  86. cout << format("{:2} ", distance);
  87. }
  88. cout << endl;
  89. }
  90. }
  91. cout << format("{:^30}\n", "客户序列");
  92. if (Distance_Matrix.empty())
  93. {
  94. cout << "客户序列为空!\n";
  95. }
  96. else
  97. {
  98. for (const auto& customer : Customer_Array)
  99. {
  100. customer.show_customer();
  101. cout << endl;
  102. }
  103. }
  104. }
  1. // Car.cpp
  2. #include "Car.h"
  3. #include<iostream>
  4. #include<format>
  5. using
  6. std::cout,std::endl,
  7. std::format,
  8. std::vector;
  9. // 运算符重载
  10. const Customer* Car::operator[](int index)const
  11. {
  12. if (index >= 0)return m_route.at(index);
  13. else return m_route.at(0);
  14. }
  15. // 访问器 //
  16. // 展示车辆属性
  17. void Car::show_car()const
  18. {
  19. if (m_route.empty())
  20. {
  21. cout << format("车辆{}未发车!", m_number);
  22. return;
  23. }
  24. cout << format("{:6}{:2}{:6}:{:^7}", "车辆", m_number, "路线", 0);
  25. for (const Customer* customer : m_route)
  26. {
  27. cout << format("{:<4}{:<3}", "->", customer->get_number());
  28. }
  29. cout << "-> 0 " << endl;
  30. double start_time{ m_time[0] - Time_Matrix[0][*m_route[0]] };
  31. double end_time{ m_time.back() + Time_Matrix[*m_route.back()][0] + m_route.back()->get_service_time() };
  32. cout << format("{:6}{:2}{:6}:{:^9.2f}", "车辆", m_number, "时刻表", start_time);
  33. for (const auto& time : m_time)
  34. {
  35. cout << format("{:^7.2f}", time);
  36. }
  37. cout << format("{:^7.2f}\n", end_time);
  38. cout << "成本:" << m_cost << endl;
  39. cout << "载重:" << m_load << endl;
  40. cout << "行程:" << m_distance_traveled << endl;
  41. }
  42. // 访问器 //
  43. // 更改器 //
  44. // 在路线后添加一个客户
  45. bool Car::add_customer(const Customer* customer)
  46. {
  47. m_route.push_back(customer);
  48. ++m_customer_number;
  49. unsigned load{ m_load };
  50. load += customer->get_requirement();
  51. if (load > Max_Load)
  52. {
  53. // 超重
  54. m_route.pop_back();
  55. --m_customer_number;
  56. return false;
  57. }
  58. unsigned distance_traveled{ m_distance_traveled };
  59. if (m_customer_number < 2)
  60. {
  61. distance_traveled += 2 * customer->get_distance(Customer::Distribution_Center);
  62. }
  63. else
  64. {
  65. distance_traveled -= (*this)[m_customer_number - 2]->get_distance(Customer::Distribution_Center);
  66. distance_traveled += customer->get_distance((*this)[m_customer_number - 2]);
  67. distance_traveled += customer->get_distance(Customer::Distribution_Center);
  68. }
  69. if (distance_traveled > Max_Distance)
  70. {
  71. // 超过路程限制
  72. m_route.pop_back();
  73. --m_customer_number;
  74. return false;
  75. }
  76. if (!update_time_list())
  77. {
  78. // 不符合时间窗限制
  79. m_route.pop_back();
  80. --m_customer_number;
  81. return false;
  82. }
  83. // 都满足限制,成功添加一个新客户
  84. m_load = load;
  85. m_distance_traveled = distance_traveled;
  86. return true;
  87. }
  88. // 计算配送成本
  89. void Car::calculate_cost()
  90. {
  91. unsigned variable_cost{};
  92. variable_cost += Variable_Cost * (*this)[0]->get_distance(Customer::Distribution_Center);
  93. for (int i{}; i < m_route.size() - 1; ++i)
  94. {
  95. variable_cost += Variable_Cost * (*this)[i]->get_distance((*this)[i + 1]);
  96. }
  97. variable_cost += Variable_Cost * m_route.back()->get_distance(Customer::Distribution_Center);
  98. m_cost = Fixed_Cost + variable_cost;
  99. }
  100. // 更新时刻表
  101. bool Car::update_time_list()
  102. {
  103. size_t right_customer_number{ *m_route.back() };
  104. if (m_customer_number < 2)
  105. {
  106. m_time.push_back(Time_Matrix[0][right_customer_number]);
  107. return true;
  108. }
  109. else
  110. {
  111. size_t left_customer_number{ *m_route[m_customer_number - 2ull] };
  112. vector<double> time_array{ m_time }; // 创建一个副本
  113. double new_time{ time_array[m_customer_number - 2ull] };
  114. new_time += m_route[m_customer_number - 2ull]->get_service_time() + Time_Matrix[left_customer_number][right_customer_number];
  115. time_array.push_back(new_time);
  116. // 检查所有客户的时间窗是否全部满足
  117. for (int index{}; index < m_customer_number; ++index)
  118. {
  119. double time{ time_array[index] };
  120. double time_difference{ m_route[index]->is_in_window(time) };
  121. if (time_difference == 1)
  122. {
  123. // 无法调整时刻表,时刻表原封不动
  124. return false;
  125. }
  126. else if (time_difference < 0)
  127. {
  128. // 尝试调整时刻表
  129. for (auto& time : time_array)
  130. {
  131. time -= time_difference;
  132. }
  133. index = -1;
  134. }
  135. else
  136. {
  137. // 符合此客户的时间约束
  138. continue;
  139. }
  140. }
  141. // 确定满足条件后,将修改后的副本移动到汽车时刻表中
  142. m_time = move(time_array);
  143. return true;
  144. }
  145. }
  146. // 更改器 //
  147. //展示固有参数,参数为0时,输出矩阵
  148. void Car::show_parameters(int choice)
  149. {
  150. if (choice == 0)
  151. {
  152. cout << format("{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n",
  153. "车辆最大数量:", Max_Amount,
  154. "车辆载重量,单位t:", Max_Load,
  155. "车辆最大行驶距离,单位km:", Max_Distance,
  156. "车辆固定成本:", Fixed_Cost,
  157. "车辆单位距离行驶成本:", Variable_Cost);
  158. cout << format("{:^50}\n", "汽车配送时间矩阵");
  159. if (Time_Matrix.empty())
  160. {
  161. cout << "汽车配送时间矩阵为空!\n";
  162. }
  163. else
  164. {
  165. for (const auto& row : Time_Matrix)
  166. {
  167. for (const auto& time : row)
  168. {
  169. cout << format("{:.2f} ", time);
  170. }
  171. cout << "\n\n";
  172. }
  173. }
  174. }
  175. else if (choice == 1)
  176. {
  177. cout << format("{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n{:26}{:<4}\n",
  178. "1.车辆最大数量:", Max_Amount,
  179. "2.车辆载重量,单位t:", Max_Load,
  180. "3.车辆最大行驶距离,单位km:", Max_Distance,
  181. "4.车辆固定成本:", Fixed_Cost,
  182. "5.车辆单位距离行驶成本:", Variable_Cost);
  183. }
  184. }

  1. // Individual.cpp
  2. #include "Individual.h"
  3. #include<iostream>
  4. #include<format>
  5. //#define DEBUG
  6. using
  7. std::vector,
  8. std::move,
  9. std::cout, std::endl,
  10. std::format;
  11. // 静态成员
  12. vector<Individual> Individual::Best_Individuals{ Individual{} };
  13. // 主构造函数
  14. Individual::Individual(const vector<int>& dna, unsigned cost, vector<Car> car_array ,unsigned number_of_violations)
  15. :m_DNA{ dna }, m_fitness{}, m_genetic_probability{}, m_sum_probability{},
  16. m_cost{ cost }, m_car_array{ car_array } ,m_number_of_violations{ number_of_violations }
  17. {}
  18. // 更改器 //
  19. // 解码
  20. void Individual::decode()
  21. {
  22. // dna序列转化为客户序列dna_to_customer
  23. vector<const Customer*> dna_to_customer{};
  24. for (int gen : m_DNA)
  25. {
  26. for (const Customer& customer : Customer::Customer_Array)
  27. {
  28. if (static_cast<int>(customer) == gen)
  29. {
  30. dna_to_customer.push_back(&customer);
  31. break;
  32. }
  33. }
  34. }
  35. // 重置性状为空
  36. m_car_array.clear();
  37. m_cost = 0;
  38. m_number_of_violations = 0;
  39. // 所有客户添加到汽车序列中
  40. Car car = Car{ static_cast<unsigned>(m_car_array.size() + 1) };
  41. for (const auto* customer : dna_to_customer)
  42. {
  43. if (car.add_customer(customer))
  44. {
  45. // 添加成功,继续添加
  46. continue;
  47. }
  48. else
  49. {
  50. // 添加失败,调用新车
  51. m_car_array.push_back(move(car));
  52. car = Car{ static_cast<unsigned>(m_car_array.size() + 1) };
  53. car.add_customer(customer);
  54. if (m_car_array.size() <= Car::Max_Amount)
  55. {
  56. // 调用一辆车后,符合车辆数目约束
  57. continue;
  58. }
  59. else
  60. {
  61. // 汽车已用完,施加惩罚,每多调用一辆新车,多一次惩罚
  62. ++m_number_of_violations;
  63. }
  64. }
  65. }
  66. m_car_array.push_back(move(car));
  67. }
  68. // 更新并展示最优解
  69. void Individual::Update_and_display_solutions()
  70. {
  71. update_cost();
  72. // 更新最优解
  73. if (m_number_of_violations == Best_Individuals.front().m_number_of_violations)
  74. {
  75. if (m_cost < Best_Individuals.front().m_cost)
  76. {
  77. // 找到更优解
  78. Best_Individuals.clear();
  79. Best_Individuals.push_back(*this);
  80. Best_Individuals.back().decode();
  81. Best_Individuals.back().update_cost();
  82. cout << format("{}\n", "找到更优解:");
  83. show_individual();
  84. cout << endl;
  85. }
  86. else if (m_cost == Best_Individuals.front().m_cost)
  87. {
  88. // 找到另一目标值相同的解
  89. bool flag{false};
  90. for (const auto& best_individual : Best_Individuals)
  91. {
  92. if (m_DNA == best_individual.get_DNA())
  93. {
  94. flag = true;
  95. break;
  96. }
  97. }
  98. if (!flag)// flag为0,说明这个解和已找到的最优解都不同
  99. {
  100. Best_Individuals.push_back(*this);
  101. Best_Individuals.back().decode();
  102. Best_Individuals.back().update_cost();
  103. cout << format("{}\n", "找到另一更优解:");
  104. show_individual();
  105. cout << endl;
  106. }
  107. }
  108. }
  109. else if (m_number_of_violations < Best_Individuals.front().m_number_of_violations)
  110. {
  111. // 找到更优解
  112. Best_Individuals.clear();
  113. Best_Individuals.push_back(*this);
  114. Best_Individuals.back().decode();
  115. Best_Individuals.back().update_cost();
  116. cout << format("{}\n", "找到更优解:");
  117. show_individual();
  118. cout << endl;
  119. }
  120. }
  121. // 计算成本
  122. unsigned Individual::update_cost()
  123. {
  124. for (Car& car : m_car_array)
  125. {
  126. car.calculate_cost();
  127. m_cost += car.get_cost();
  128. }
  129. return m_cost;
  130. }
  131. // 展示个体
  132. void Individual::show_individual()const
  133. {
  134. cout << format("\n{:-^80}\n{:*^80}\n", "", "");
  135. for (const Car& car : m_car_array)
  136. {
  137. car.show_car();
  138. cout << endl;
  139. }
  140. cout << format("{}:{}\n", "总成本", m_cost);
  141. if (m_number_of_violations > 0)
  142. {
  143. // 违反了约束
  144. cout << format("{}:{}\n", "违反约束次数", m_number_of_violations);
  145. }
  146. else
  147. {
  148. cout << format("{}\n{:*^80}\n{:-^80}\n", "符合约束", "", "");
  149. }
  150. }
  151. // 更改器 //
  1. // Genetic_Algorithm.cpp
  2. #include "Genetic_Algorithm.h"
  3. #include<format>
  4. #include<iostream>
  5. #include<random>
  6. #include<functional>
  7. //#define DEBUG
  8. using
  9. std::vector, std::array,
  10. std::format,
  11. std::cout, std::endl,
  12. std::move;
  13. Individual Genetic_Algorithm::Best_Individual_in_History{ vector<int>{1, 6, 10, 5, 2, 9, 7, 8, 4, 3} };
  14. // 类外函数 //
  15. // 生成伪随机正整数,左闭右闭区间
  16. unsigned Pseudo_random_number(unsigned min, unsigned max)
  17. {
  18. using std::random_device, std::default_random_engine, std::uniform_int_distribution;
  19. random_device seeder; // 真随机数作为种子
  20. default_random_engine generator{ seeder() }; // 伪随机数生成器
  21. uniform_int_distribution<unsigned> distribution{ min,max }; // 整数均匀分布
  22. return distribution(generator);
  23. }
  24. // 伪随机数生成器PRNG,正整数类,左闭右闭区间
  25. auto create_pseudo_random_number_generator(unsigned min, unsigned max)
  26. {
  27. using std::random_device, std::default_random_engine, std::uniform_int_distribution, std::bind;
  28. random_device seeder; // 真随机数作为种子
  29. default_random_engine generator{ seeder() }; // 伪随机数生成器
  30. uniform_int_distribution<unsigned> distribution{ min,max }; // 整数均匀分布
  31. return bind(distribution, generator);
  32. }
  33. // 生成伪随机实数,左闭右开区间
  34. double Pseudo_random_number(double min, double max)
  35. {
  36. using std::random_device, std::default_random_engine, std::uniform_real_distribution;
  37. random_device seeder; // 真随机数作为种子
  38. default_random_engine generator{ seeder() }; // 伪随机数生成器
  39. uniform_real_distribution<double> distribution{ min,max }; // 实数均匀分布
  40. return distribution(generator);
  41. }
  42. // 伪随机数生成器PRNG,实数类,左闭右开区间
  43. auto create_pseudo_random_number_generator(double min, double max)
  44. {
  45. using std::random_device, std::default_random_engine, std::uniform_real_distribution, std::bind;
  46. random_device seeder; // 真随机数作为种子
  47. default_random_engine generator{ seeder() }; // 伪随机数生成器
  48. uniform_real_distribution<double> distribution{ min,max }; // 实数均匀分布
  49. return bind(distribution, generator);
  50. }
  51. // 函数模板,实现交换两个基本类型的值
  52. template<typename T>
  53. void swap(T& left, T& right)
  54. {
  55. T temp{ left };
  56. left = move(right);
  57. right = move(temp);
  58. }
  59. // 初始化种群
  60. void Genetic_Algorithm::initialize()
  61. {
  62. Mutation_P = 1.0 / 1024;
  63. m_population.reserve(Po_Size);
  64. for (size_t i{}; i < Po_Size; ++i)
  65. {
  66. vector<int>dna{};
  67. dna.reserve(Customer::Size - 1ull);
  68. for (int gen{ 1 }; gen < Customer::Size; ++gen)
  69. {
  70. dna.push_back(gen);
  71. }
  72. auto random_index{ create_pseudo_random_number_generator(0u,Customer::Size - 2u) };
  73. for (int times{}; times < Customer::Size; ++times)
  74. {
  75. swap(dna[random_index()], dna[random_index()]);
  76. }
  77. m_population.push_back(Individual{ dna });
  78. }
  79. }
  80. // 获得适应度
  81. void Genetic_Algorithm::get_fitness()
  82. {
  83. for (Individual& individual:m_population)
  84. {
  85. individual.decode();
  86. individual.Update_and_display_solutions();
  87. individual.update_fitness();
  88. if (individual.get_number_of_violations() > 0)
  89. {
  90. unsigned punish_times{ individual.get_number_of_violations() };
  91. individual.multiply_fitness(Punish, punish_times);
  92. }
  93. }
  94. }
  95. // 获得遗传概率
  96. void Genetic_Algorithm::get_genetic_probability()
  97. {
  98. double sum{};
  99. for (const Individual& individual : m_population)
  100. {
  101. sum += individual.get_fitness();
  102. }
  103. for (Individual& individual : m_population)
  104. {
  105. individual.set_genetic_probability(individual.get_fitness() / sum);
  106. }
  107. }
  108. // 获得轮盘赌累加概率
  109. void Genetic_Algorithm::get_sum_probability()
  110. {
  111. for (double sum{}; Individual& individual : m_population)
  112. {
  113. sum += individual.get_genetic_probability();
  114. individual.set_sum_probability(sum);
  115. }
  116. m_population.back().set_sum_probability(1.0); // 最后一个体,轮盘赌值为1,消除double类型的误差
  117. }
  118. // 遗传算子 //
  119. // 选择算子,轮盘赌多选法
  120. void Genetic_Algorithm::selection()
  121. {
  122. vector<unsigned> son_number(Po_Size,0); // 索引对应的子代数量
  123. static auto random{ create_pseudo_random_number_generator(0.0,1.0) };
  124. double point{ random() };
  125. const double add_number{ 1.0 / Po_Size };
  126. for (size_t times{}, next_index{}; times < Po_Size; ++times)
  127. {
  128. for (size_t index{ next_index }; index < Po_Size; ++index)
  129. {
  130. if (point < m_population[index].get_sum_probability())
  131. {
  132. next_index = index;
  133. ++son_number[index];
  134. point += add_number;
  135. if (point > 1.0)
  136. {
  137. --point;
  138. next_index = 0;
  139. }
  140. break;
  141. }
  142. }
  143. }
  144. vector<Individual> son_population{};
  145. son_population.reserve(Po_Size);
  146. for (size_t index{}; index < Po_Size; ++index)
  147. {
  148. for (unsigned times{}; times < son_number[index]; ++times)
  149. {
  150. son_population.push_back(m_population[index]);
  151. }
  152. }
  153. m_population = move(son_population);
  154. }
  155. // 交叉算子,两点交叉+映射法
  156. void Genetic_Algorithm::crossover()
  157. {
  158. using std::pair, std::make_pair;
  159. // spouse:配偶,夫妻
  160. auto random_spouse_index{ create_pseudo_random_number_generator(0u, static_cast<unsigned>(Po_Size) - 1u) };
  161. auto random_cross_point_index{ create_pseudo_random_number_generator(0u, Customer::Size - 2u) };
  162. for (size_t spouse{}; spouse < Po_Size / 2; ++spouse)
  163. {
  164. if (Pseudo_random_number(0, 1.0) < Crossover_P)
  165. {
  166. // 开始交叉
  167. Individual& father{ m_population[random_spouse_index()] };
  168. Individual& mother{ m_population[random_spouse_index()] };
  169. // 交叉点位置
  170. size_t cross_point_left{ random_cross_point_index() };
  171. size_t cross_point_right{ random_cross_point_index() };
  172. if (cross_point_left > cross_point_right) { swap(cross_point_left, cross_point_right); }
  173. vector<pair<int, int>> Map_from_father_to_mother{};
  174. Map_from_father_to_mother.reserve(cross_point_right - cross_point_left + 1);
  175. // 交换基因
  176. for (size_t cross_point{ cross_point_left }; cross_point <= cross_point_right; ++cross_point)
  177. {
  178. int& father_gen{ father[cross_point] };
  179. int& mother_gen{ mother[cross_point] };
  180. Map_from_father_to_mother.push_back(make_pair(father_gen, mother_gen));
  181. swap(father_gen, mother_gen);
  182. }
  183. // 映射
  184. for (const pair<int,int>& map : Map_from_father_to_mother)
  185. {
  186. for (int& gen : father.set_DNA())
  187. {
  188. if (int switch_gen{ map.first }; gen == map.second)
  189. {
  190. swap(gen, switch_gen);
  191. break;
  192. }
  193. }
  194. for (int& gen : mother.set_DNA())
  195. {
  196. if (int switch_gen{ map.second }; gen == map.first)
  197. {
  198. swap(gen, switch_gen);
  199. break;
  200. }
  201. }
  202. }
  203. }
  204. }
  205. }
  206. // 变异算子,两点交换变异
  207. void Genetic_Algorithm::mutation()
  208. {
  209. static auto random{ create_pseudo_random_number_generator(0.0, 1.0) };
  210. auto random_exchange_point{ create_pseudo_random_number_generator(0u, Customer::Size - 2u) };
  211. for (auto& individual : m_population)
  212. {
  213. if (random() < Mutation_P)
  214. {
  215. // 开始变异
  216. swap(individual[random_exchange_point()], individual[random_exchange_point()]);
  217. }
  218. }
  219. }
  220. // 遗传算子 //
  221. // 遗传算法入口
  222. void Genetic_Algorithm::genetic_algorithm()
  223. {
  224. // 初始化种群
  225. initialize();
  226. for (size_t generation{}; generation <= Iterations; ++generation)
  227. {
  228. if (generation % 10ull == 0)
  229. {
  230. cout << format("{:->50}{:^5}{:-<50}\n", "第", generation, "代");
  231. }
  232. // 获得适应度
  233. get_fitness();
  234. // 获得遗传概率
  235. get_genetic_probability();
  236. // 获得轮盘赌累加概率
  237. get_sum_probability();
  238. // 遗传算子 //
  239. // 选择算子,轮盘赌多选法
  240. selection();
  241. // 交叉算子,两点交叉+映射法
  242. crossover();
  243. // 变异算子,两点交换变异
  244. mutation();
  245. // 遗传算子 //
  246. // 遗传概率调整
  247. if ((generation + 1) % 128ull == 0)
  248. {
  249. static auto random_0_to_1{ create_pseudo_random_number_generator(0.0,1.0) };
  250. Crossover_P = random_0_to_1();
  251. static const double mutation_probability_Increase{ (1.0 - Mutation_P) / Iterations * 64 };
  252. Mutation_P += mutation_probability_Increase;
  253. cout << "交叉概率:" << Crossover_P
  254. << "\n变异概率:" << Mutation_P << "\n";
  255. }
  256. }
  257. get_fitness();
  258. Best_Individual_in_History.decode();
  259. Best_Individual_in_History.update_cost();
  260. if (Individual::Best_Individuals.size() == 1)
  261. {
  262. cout << "\n找到唯一最优解:\n";
  263. Individual::Best_Individuals.front().show_individual();
  264. if (Individual::Best_Individuals.front().get_DNA() == Best_Individual_in_History.get_DNA())
  265. {
  266. cout << "\n本次最优解与历史最优解目标值相同!\n";
  267. }
  268. else
  269. {
  270. cout << "\n历史最优解:\n";
  271. Best_Individual_in_History.show_individual();
  272. }
  273. }
  274. else if (Individual::Best_Individuals.size() > 1)
  275. {
  276. cout << "\n找到多个最优解:\n";
  277. for (const auto& best_individual : Individual::Best_Individuals)
  278. {
  279. best_individual.show_individual();
  280. }
  281. if (Individual::Best_Individuals.front().get_cost() == Best_Individual_in_History.get_cost())
  282. {
  283. cout << "\n本次最优解与历史最优解目标值相同!\n";
  284. }
  285. else
  286. {
  287. cout << "\n历史最优解:\n";
  288. Best_Individual_in_History.show_individual();
  289. }
  290. }
  291. }
  292. // 展示固有参数
  293. void Genetic_Algorithm::show_parameters(int choice)
  294. {
  295. if (choice == 0)
  296. {
  297. cout << format("{:12}{:^6}\n{:12}{:^6}\n{:12}{:^6}\n{:12}{:^6}\n{:12}{:^6}\n",
  298. "种群规模:", Po_Size,
  299. "进化代数:", Iterations,
  300. "交叉概率:", Crossover_P,
  301. "变异概率:", Mutation_P,
  302. "惩罚系数:", Punish);
  303. }
  304. else if (choice == 1)
  305. {
  306. cout << format("{:12}{:^6}\n{:12}{:^6}\n{:12}{:^6}\n{:12}{:^6}\n",
  307. "6.种群规模:", Po_Size,
  308. "7.进化代数:", Iterations,
  309. "8.交叉概率:", Crossover_P,
  310. "9.变异概率:", Mutation_P);
  311. }
  312. }
  1. //UI_Manage.cpp
  2. #include "UI_Manage.h"
  3. #include<iostream>
  4. #include<format>
  5. #include<fstream>
  6. #include<Windows.h>
  7. using
  8. std::string_view, std::string,
  9. std::cout, std::endl,
  10. std::format;
  11. // 展示菜单
  12. void UI_Manage::Show_Menu()const
  13. {
  14. cout << format("{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n{:*^30}\n",
  15. ""
  16. ," 遗传算法v1.0 "
  17. ," by : 雷海泷 "
  18. ,"0. 退出 "
  19. ,"1. 读取文件 "
  20. ,"2. 展示参数 "
  21. ,"3.展示文件路径"
  22. ,"4. 开始求解 "
  23. ,"5. 修改参数 "
  24. ,"");
  25. }
  26. // 读取文件1
  27. bool UI_Manage::read_file(string_view distance_file, string_view time_file, string_view customer_file)
  28. {
  29. using std::ifstream, std::ios, std::vector, std::array, std::move;
  30. ifstream distance_ifs{ string{distance_file},ios::in };
  31. ifstream time_ifs{ string{time_file},ios::in };
  32. ifstream customer_ifs{ string{customer_file},ios::in };
  33. char buf[100]{};
  34. GetCurrentDirectoryA(100, buf);
  35. if (!distance_ifs.is_open())
  36. {
  37. cout << format("文件{}\\{}打开失败!\n", buf, distance_file);
  38. time_ifs.close();
  39. customer_ifs.close();
  40. return false;
  41. }
  42. else if (!time_ifs.is_open())
  43. {
  44. cout << format("文件{}\\{}打开失败!\n", buf, time_file);
  45. distance_ifs.close();
  46. customer_ifs.close();
  47. return false;
  48. }
  49. else if (!customer_ifs.is_open())
  50. {
  51. cout << format("文件{}\\{}打开失败!\n", buf, customer_file);
  52. distance_ifs.close();
  53. time_ifs.close();
  54. return false;
  55. }
  56. else
  57. {
  58. Customer::Distance_Matrix.clear();
  59. Car::Time_Matrix.clear();
  60. Customer::Customer_Array.clear();
  61. Customer::Customer_Array.push_back(move(Customer{}));
  62. unsigned number, requirement, time_start1, time_end1, time_start2, time_end2;
  63. double service_time;
  64. while (customer_ifs >> number
  65. && customer_ifs >> requirement
  66. && customer_ifs >> service_time
  67. && customer_ifs >> time_start1
  68. && customer_ifs >> time_end1
  69. && customer_ifs >> time_start2
  70. && customer_ifs >> time_end2)
  71. {
  72. Customer::Customer_Array.push_back(move(Customer{ number,requirement,service_time, array<Time, Window_num> { Time{ time_start1, time_end1 }, Time{ time_start2, time_end2 } } }));
  73. }
  74. Customer::Size = static_cast<int>(Customer::Customer_Array.size());
  75. cout << format("文件{}\\{}读取成功!\n", buf, customer_file);
  76. customer_ifs.close();
  77. for (size_t i{}; i < Customer::Size; ++i)
  78. {
  79. vector<int> distance_row{};
  80. int distance;
  81. for (size_t j{}; j < Customer::Size && distance_ifs >> distance; ++j)
  82. {
  83. distance_row.push_back(distance);
  84. }
  85. Customer::Distance_Matrix.push_back(move(distance_row));
  86. vector<double> time_row{};
  87. double time;
  88. for (size_t j{}; j < Customer::Size && time_ifs >> time; ++j)
  89. {
  90. time_row.push_back(time);
  91. }
  92. Car::Time_Matrix.push_back(move(time_row));
  93. }
  94. cout << format("文件{}\\{}读取成功!\n", buf, distance_file);
  95. distance_ifs.close();
  96. cout << format("文件{}\\{}读取成功!\n", buf, time_file);
  97. time_ifs.close();
  98. m_file_read = true;
  99. return true;
  100. }
  101. }
  102. // 展示所有参数2
  103. void UI_Manage::show_all_parameters()const
  104. {
  105. if (!m_file_read)
  106. {
  107. cout << "未读取文件!\n";
  108. system("pause");
  109. }
  110. else
  111. {
  112. // Customer
  113. cout << format("{:-^30}\n", "客户与配送中心参数");
  114. Customer::show_parameters();
  115. // Car
  116. cout << format("{:-^30}\n", "车辆参数");
  117. Car::show_parameters();
  118. // Genetic_Algorithm
  119. cout << format("{:-^30}\n", "遗传算法参数");
  120. Genetic_Algorithm::show_parameters();
  121. }
  122. }
  123. // 展示文件路径3
  124. void UI_Manage::show_file_path()const
  125. {
  126. char buf[100]{};
  127. GetCurrentDirectoryA(100, buf);
  128. cout << format("{}:{}\\\n", "当前路径", buf);
  129. }
  130. // 开始求解4
  131. void UI_Manage::start_solve(string_view distance_file, string_view time_file, string_view customer_file)
  132. {
  133. if (!m_file_read)
  134. {
  135. cout << "未读取文件!\n";
  136. system("pause");
  137. return;
  138. }
  139. read_file(distance_file, time_file, customer_file);
  140. Genetic_Algorithm GA{};
  141. LARGE_INTEGER start_time, end_time, frequency;
  142. QueryPerformanceFrequency(&frequency);
  143. QueryPerformanceCounter(&start_time);
  144. GA.genetic_algorithm();
  145. QueryPerformanceCounter(&end_time);
  146. long long run_time{ (end_time.QuadPart - start_time.QuadPart) * 1'000 / frequency.QuadPart };
  147. long long minute{run_time / 60'000 };
  148. long long second{ (run_time - minute * 60'000) / 1'000 };
  149. long long millisecond{ run_time - minute * 60'000 - second * 1'000 };
  150. cout << format("{}{}{}{}{}{}{}\n", "用时 ", minute, "分", second, "秒", millisecond, "毫秒");
  151. }
  152. // 修改参数5
  153. void UI_Manage::modify_parameters()
  154. {
  155. using std::cin;
  156. if (!m_file_read)
  157. {
  158. cout << "未读取文件!\n";
  159. system("pause");
  160. return;
  161. }
  162. int choice{ -1 };
  163. while (true)
  164. {
  165. cout << "可修改的参数:\n";
  166. cout << format("{:}\n", "0.退出");
  167. Car::show_parameters(1);
  168. Genetic_Algorithm::show_parameters(1);
  169. cout << "请输入您的选择:" << endl;
  170. cin >> choice;
  171. //输入检查
  172. if (cin.fail())
  173. {
  174. cout << "输入错误!" << endl;
  175. cin.clear();
  176. cin.ignore(1024, '\n');
  177. system("pause");
  178. continue;
  179. }
  180. switch (choice)
  181. {
  182. case 0:// 退出
  183. return;
  184. case 1:// 1.车辆最大数量
  185. {
  186. unsigned input_value{ Car::Max_Amount };
  187. cout << "修改为:";
  188. cin >> input_value;
  189. //输入检查
  190. if (cin.fail())
  191. {
  192. cout << "输入错误!" << endl;
  193. cin.clear();
  194. cin.ignore(1024, '\n');
  195. system("pause");
  196. continue;
  197. }
  198. Car::Max_Amount = input_value;
  199. break;
  200. }
  201. case 2:// 2.车辆载重量
  202. {
  203. unsigned input_value{ Car::Max_Load };
  204. cout << "修改为:";
  205. cin >> input_value;
  206. //输入检查
  207. if (cin.fail())
  208. {
  209. cout << "输入错误!" << endl;
  210. cin.clear();
  211. cin.ignore(1024, '\n');
  212. system("pause");
  213. continue;
  214. }
  215. Car::Max_Load = input_value;
  216. break;
  217. }
  218. case 3:// 3.车辆最大行驶距离
  219. {
  220. unsigned input_value{ Car::Max_Distance };
  221. cout << "修改为:";
  222. cin >> input_value;
  223. //输入检查
  224. if (cin.fail())
  225. {
  226. cout << "输入错误!" << endl;
  227. cin.clear();
  228. cin.ignore(1024, '\n');
  229. system("pause");
  230. continue;
  231. }
  232. Car::Max_Distance = input_value;
  233. break;
  234. }
  235. case 4:// 4.车辆固定成本
  236. {
  237. unsigned input_value{ Car::Fixed_Cost };
  238. cout << "修改为:";
  239. cin >> input_value;
  240. //输入检查
  241. if (cin.fail())
  242. {
  243. cout << "输入错误!" << endl;
  244. cin.clear();
  245. cin.ignore(1024, '\n');
  246. system("pause");
  247. continue;
  248. }
  249. Car::Fixed_Cost = input_value;
  250. break;
  251. }
  252. case 5:// 5.车辆单位距离行驶成本
  253. {
  254. unsigned input_value{ Car::Variable_Cost };
  255. cout << "修改为:";
  256. cin >> input_value;
  257. //输入检查
  258. if (cin.fail())
  259. {
  260. cout << "输入错误!" << endl;
  261. cin.clear();
  262. cin.ignore(1024, '\n');
  263. system("pause");
  264. continue;
  265. }
  266. Car::Variable_Cost = input_value;
  267. break;
  268. }
  269. case 6:// 6.种群规模
  270. {
  271. size_t input_value{ Genetic_Algorithm::Po_Size };
  272. cout << "修改为:";
  273. cin >> input_value;
  274. //输入检查
  275. if (cin.fail())
  276. {
  277. cout << "输入错误!" << endl;
  278. cin.clear();
  279. cin.ignore(1024, '\n');
  280. system("pause");
  281. continue;
  282. }
  283. Genetic_Algorithm::Po_Size = input_value;
  284. break;
  285. }
  286. case 7:// 7.进化代数
  287. {
  288. size_t input_value{ Genetic_Algorithm::Iterations };
  289. cout << "修改为:";
  290. cin >> input_value;
  291. //输入检查
  292. if (cin.fail())
  293. {
  294. cout << "输入错误!" << endl;
  295. cin.clear();
  296. cin.ignore(1024, '\n');
  297. system("pause");
  298. continue;
  299. }
  300. Genetic_Algorithm::Iterations = input_value;
  301. break;
  302. }
  303. case 8:// 8.交叉概率
  304. {
  305. double input_value{ Genetic_Algorithm::Crossover_P };
  306. cout << "修改为:";
  307. cin >> input_value;
  308. //输入检查
  309. if (cin.fail())
  310. {
  311. cout << "输入错误!" << endl;
  312. cin.clear();
  313. cin.ignore(1024, '\n');
  314. system("pause");
  315. continue;
  316. }
  317. Genetic_Algorithm::Crossover_P = input_value;
  318. break;
  319. }
  320. case 9:// 9.变异概率
  321. {
  322. double input_value{ Genetic_Algorithm::Mutation_P };
  323. cout << "修改为:";
  324. cin >> input_value;
  325. //输入检查
  326. if (cin.fail())
  327. {
  328. cout << "输入错误!" << endl;
  329. cin.clear();
  330. cin.ignore(1024, '\n');
  331. system("pause");
  332. continue;
  333. }
  334. Genetic_Algorithm::Mutation_P = input_value;
  335. break;
  336. }
  337. default://输入错误
  338. cout << "输入错误!" << endl;
  339. system("pause");
  340. break;
  341. }
  342. system("cls");
  343. }
  344. }
  1. // 遗传算法v1.0.cpp
  2. #include<iostream>
  3. #include<format>
  4. #include<Windows.h>
  5. #include"UI_Manage.h"
  6. using
  7. std::cout, std::cin,std::endl,
  8. std::format,
  9. std::vector, std::array;
  10. int main()
  11. {
  12. try
  13. {
  14. UI_Manage ui;
  15. int choice{ -1 };
  16. while (true)
  17. {
  18. ui.Show_Menu();
  19. cout << "请输入您的选择:" << endl;
  20. cin >> choice;
  21. //输入检查
  22. if (cin.fail())
  23. {
  24. cout << "输入错误!即将返回菜单!" << endl;
  25. cin.clear();
  26. cin.ignore(1024, '\n');
  27. system("pause");
  28. continue;
  29. }
  30. switch (choice)
  31. {
  32. case 0:// 退出程序
  33. ui.exit_system();
  34. break;
  35. case 1:// 读取文件
  36. ui.read_file();
  37. system("pause");
  38. break;
  39. case 2:// 展示所有参数
  40. ui.show_all_parameters();
  41. system("pause");
  42. break;
  43. case 3:// 展示当前路径
  44. ui.show_file_path();
  45. system("pause");
  46. break;
  47. case 4:// 开始求解
  48. ui.start_solve();
  49. system("pause");
  50. break;
  51. case 5:// 修改参数
  52. ui.modify_parameters();
  53. break;
  54. default:// 输入错误
  55. cout << "输入错误!即将返回菜单!" << endl;
  56. system("pause");
  57. break;
  58. }
  59. system("cls");
  60. }
  61. return 0;
  62. }
  63. catch (const std::exception& trouble)
  64. {
  65. cout << "发生异常:" << trouble.what() << endl;
  66. system("pause");
  67. }
  68. }

6.程序结果:

(1)初始界面:

 (2)程序参数(可修改)

 (3)求解结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/575710
推荐阅读
相关标签
  

闽ICP备14008679号