Advertisement
Guest User

Untitled

a guest
May 22nd, 2019
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.23 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include <iostream>
  4. #include <string>
  5. #include <ctime>
  6. #include <cstdlib>
  7. #include <cmath>
  8. #include <vector>
  9. #include <algorithm>
  10.  
  11. using namespace std;
  12.  
  13. class City
  14. {
  15. private:
  16. int x;
  17. int y;
  18.  
  19. public:
  20. //constructs a city at chosen x,y location
  21. City(int x, int y)
  22. {
  23. this->x = x;
  24. this->y = y;
  25. }
  26.  
  27. int getX()
  28. {
  29. return this->x;
  30. }
  31.  
  32. int getY()
  33. {
  34. return this->y;
  35. }
  36.  
  37. double distanceTo(City city)
  38. {
  39. int xDistance = abs(getX() - city.getX());
  40. int yDistance = abs(getY() - city.getY());
  41. double distance = sqrt((xDistance*xDistance) + (yDistance*yDistance));
  42.  
  43. return distance;
  44. }
  45. };
  46.  
  47. class TourManager
  48. {
  49. private:
  50. //holds the cities
  51.  
  52. // удерживает города
  53. vector<City> destinationCities;
  54.  
  55. public:
  56. //adds a destination city
  57. //добавляет город назначения
  58. void addCity(City city)
  59. {
  60. destinationCities.push_back(city);
  61. }
  62.  
  63. //get a city
  64. // получить город
  65. City getCity(int index)
  66. {
  67. return (City)destinationCities.at(index);
  68. }
  69.  
  70. //get the number of destination city
  71. // получить номер города назначения
  72. int numberOfCities()
  73. {
  74. return (int)destinationCities.size();
  75. }
  76. };
  77.  
  78. class Tour
  79. {
  80. private:
  81. //holds our tour of cities
  82. // проводит тур по городам
  83. vector<City> tour;
  84. double fitness = 0;
  85. int distance = 0;
  86. TourManager tourManager;
  87.  
  88. public:
  89. //constructs a blank tour
  90. //создает пустой тур
  91. Tour()
  92. {
  93. City *city = new City(0, 0);
  94. for (int i = 0; i < tourManager.numberOfCities(); ++i)
  95. {
  96. tour.push_back(*city);
  97. }
  98. }
  99.  
  100. Tour(vector<City> tour)
  101. {
  102. this->tour = tour;
  103. }
  104.  
  105. //generates a random individual
  106. // генерирует случайную особь
  107. void generateIndividual()
  108. {
  109. //loop through all our destinations cities and add them to our tour
  110. // цикл через все наши города назначения и добавить их в наш тур
  111. for (int cityIndex = 0; cityIndex < tourManager.numberOfCities(); ++cityIndex)
  112. {
  113. setCity(cityIndex, tourManager.getCity(cityIndex));
  114. }
  115. //randomly reorder the tour
  116. // случайным образом изменить порядок тура
  117. random_shuffle(tour.begin(), tour.end(), tour);
  118. }
  119.  
  120. City getCity(int tourPosition)
  121. {
  122. return (City)tour.at(tourPosition);
  123. }
  124.  
  125. void setCity(int tourPosition, City city)
  126. {
  127. //CAUTION: not sure if the line below will work!
  128. // Внимание: не уверен, что строка ниже будет работать!
  129. tour.insert(tour.begin() + tourPosition, city);
  130.  
  131. //if the tour has been altered we need to reset fitness and distance
  132. //если тур был изменен, нам нужно сбросить Фитнес и расстояние
  133. fitness = 0;
  134. distance = 0;
  135. }
  136.  
  137. //gets the tours fitness (fitness = cost?)
  138. //получает туры фитнес (фитнес = стоимость?)
  139. double getFitness()
  140. {
  141. if (fitness == 0)
  142. {
  143. fitness = 1 / (double)getDistance();
  144. }
  145.  
  146. return fitness;
  147. }
  148.  
  149. // Gets the total distance of the tour
  150. // Получает общее расстояние тураw
  151. int getDistance()
  152. {
  153. if (distance == 0)
  154. {
  155. int tourDistance = 0;
  156.  
  157. // Loop through our tour's cities
  158. // цикл по городам нашего тура
  159. for (int cityIndex = 0; cityIndex < tourSize(); cityIndex++)
  160. {
  161. // Get city we're travelling from
  162. // Получить город, из которого мы едем
  163. City fromCity = getCity(cityIndex);
  164.  
  165. // City we're travelling to
  166. // Город, в который мы едем
  167. City *destinationCity = new City(0, 0);
  168.  
  169. // Check we're not on our tour's last city, if we are set our
  170. // tour's final destination city to our starting city
  171. // Проверьте, что мы не в последнем городе нашего тура, если мы установили
  172. //конечный город нашего тура в наш стартовый город
  173. if (cityIndex + 1 < tourSize())
  174. {
  175. *destinationCity = getCity(cityIndex + 1);
  176. }
  177. else
  178. {
  179. *destinationCity = getCity(0);
  180. }
  181.  
  182. // Get the distance between the two cities
  183. // Получить расстояние между двумя городами
  184. tourDistance += fromCity.distanceTo(*destinationCity);
  185. }
  186. distance = tourDistance;
  187. }
  188. return distance;
  189. }
  190.  
  191. //get the number of cities on our tour
  192. // получить количество городов в нашем туре
  193. int tourSize()
  194. {
  195. return (int)tour.size();
  196. }
  197.  
  198. // Check if the tour contains a city
  199. // Проверьте, содержит ли тур город
  200. bool containsCity(City city)
  201. {
  202. for (int i = 0; i < tourSize(); ++i)
  203. {
  204. if ((tour[i].getX() == city.getX()) && (tour[i].getY() == city.getY()))
  205. return true;
  206. }
  207.  
  208. return false;
  209. }
  210. };
  211.  
  212. class Population
  213. {
  214. private:
  215. //hold population of tours
  216. // держать население туров
  217. vector<Tour> tours;
  218.  
  219. public:
  220. //contructs a population
  221. //построить популяцию
  222. Population(int populationSize, bool initialize)
  223. {
  224. tours.resize(populationSize);
  225.  
  226. //if we need to initialize a population then do so
  227. //если нам нужно инициализировать популяцию, сделайте это
  228. if (initialize)
  229. {
  230. for (int i = 0; i < populationSize; ++i)
  231. {
  232. Tour *newTour = new Tour();
  233. newTour->generateIndividual();
  234. saveTour(i, *newTour);
  235. }
  236. }
  237. }
  238.  
  239. // Saves a tour
  240. // Сохранение тура
  241. void saveTour(int index, Tour tour)
  242. {
  243. tours[index] = tour;
  244. }
  245.  
  246. // Gets a tour from population
  247. // Получает тур от популяции
  248. Tour getTour(int index)
  249. {
  250. return tours[index];
  251. }
  252.  
  253. // Gets the best tour in the population
  254. //Получает лучший тур из популяции
  255. Tour getFittest()
  256. {
  257. Tour fittest = tours[0];
  258.  
  259. // Loop through individuals to find fittest
  260. // цикл по особям, чтобы найти наиболее приспособленных
  261. for (int i = 1; i < populationSize(); i++)
  262. {
  263. if (fittest.getFitness() <= getTour(i).getFitness())
  264. {
  265. fittest = getTour(i);
  266. }
  267. }
  268. return fittest;
  269. }
  270.  
  271. // Gets population size
  272. //Получает размер популяции
  273. int populationSize()
  274. {
  275. return (int)tours.size();
  276. }
  277. };
  278.  
  279. class GA
  280. {
  281. private:
  282.  
  283. /* GA parameters */
  284. double mutationRate = 0.015;
  285. int tournamentSize = 5;
  286. bool elitism = true;
  287.  
  288. public:
  289.  
  290. //Evolves a population over one generation
  291. // Эволюция популяции в течение одного поколения
  292. Population evolvePopulation(Population pop)
  293. {
  294. Population* newPopulation = new Population(pop.populationSize(), false);
  295.  
  296. //keep our best individual if elitism is enabled
  297. // получаем наш лучшую особь, если элитарность включена
  298. int elitismOffset = 0;
  299. if (elitism)
  300. {
  301. newPopulation->saveTour(0, pop.getFittest());
  302. elitismOffset = 1;
  303. }
  304.  
  305. // Crossover population
  306. // Loop over the new population's size and create individuals from
  307. // Current population
  308. // Кроссовер популяции
  309. // Цикл над новой численностью популяции и создание особей
  310. // Нынешняя популяция
  311. for (int i = 0; i < newPopulation->populationSize(); ++i)
  312. {
  313. //select parents
  314. //выбор родителей
  315. Tour parent1 = tournamentSelection(pop);
  316. Tour parent2 = tournamentSelection(pop);
  317.  
  318. //crossover parents
  319. //кроссовер родителей
  320. Tour child = crossover(parent1, parent2);
  321.  
  322. //add child to new population
  323. //добавление детей в новую популяцию
  324. newPopulation->saveTour(i, child);
  325. }
  326.  
  327. //mutate the new population a bit to add some new genetic material
  328. // мутация новой популяции, чтобы добавить новый генетический материал
  329. for (int i = elitismOffset; i < newPopulation->populationSize(); ++i)
  330. {
  331. mutate(newPopulation->getTour(i));
  332. }
  333.  
  334. return *newPopulation;
  335. }
  336.  
  337. //applies crossover to a set of parents and creates offspring
  338. // применяет кроссовер к набору родителей и создает потомство
  339. Tour crossover(Tour parent1, Tour parent2)
  340. {
  341. //create the new child
  342. //создание нового ребенка
  343. Tour* child = new Tour();
  344. City* cityBlank = new City(0, 0);
  345.  
  346. //get start and end sub tour positions for parents1's tour
  347. // начало и конец sub ваши позиции для родителей 1-х тур
  348. int startPos = (int)(rand() * parent1.tourSize());
  349. int endPos = (int)(rand() * parent1.tourSize());
  350.  
  351. // Loop and add the sub tour from parent1 to our child
  352. // Loop и добавить суб тур от parent1 к нашему ребенку
  353. for (int i = 0; i < child->tourSize(); i++)
  354. {
  355. // if our start position is less than the end position
  356. // если наша стартовая позиция-это меньше, чем конечное положение
  357. if (startPos < endPos && i > startPos && i < endPos)
  358. {
  359. child->setCity(i, parent1.getCity(i));
  360. }
  361. // If our start position is larger
  362. // Если наша стартовая позиция больше
  363. else if (startPos > endPos)
  364. {
  365. if (!(i < startPos && i > endPos))
  366. {
  367. child->setCity(i, parent1.getCity(i));
  368. }
  369. }
  370. }
  371.  
  372. // Loop through parent2's city tour
  373. // Цикл по городам тура родителя 2
  374. for (int i = 0; i < parent2.tourSize(); i++)
  375. {
  376. // If child doesn't have the city add it
  377. //Если у ребенка нет города, добавьте его
  378. if (!child->containsCity(parent2.getCity(i)))
  379. {
  380. // Loop to find a spare position in the child's tour
  381. //Цикл, чтобы найти запасную позицию в детском туре
  382. for (int ii = 0; ii < child->tourSize(); ii++)
  383. {
  384. // Spare position found, add city
  385. // CHECK HERE!
  386. //Запасная позиция найдена, добавить город
  387.  
  388. // ПРОВЕРЬТЕ ЗДЕСЬ!
  389. if (child->getCity(ii).getX() == cityBlank->getX() && child->getCity(ii).getY() == cityBlank->getY())
  390. {
  391. child->setCity(ii, parent2.getCity(i));
  392. break;
  393. }
  394. }
  395. }
  396. }
  397. return *child;
  398. }
  399.  
  400. // Mutate a tour using swap mutation
  401. //Мутировать тур с помощью swap mutation
  402. void mutate(Tour tour)
  403. {
  404. // Loop through tour cities
  405. //Цикл по городам тура
  406. for (int tourPos1 = 0; tourPos1 < tour.tourSize(); tourPos1++)
  407. {
  408. // Apply mutation rate
  409. //Применить скорость мутации
  410. if (rand() < mutationRate)
  411. {
  412. // Get a second random position in the tour
  413. // Получить вторую случайную позицию в туре
  414. int tourPos2 = (int)(tour.tourSize() * rand());
  415.  
  416. // Get the cities at target position in tour
  417. // Получить города в целевом положении в туре
  418. City city1 = tour.getCity(tourPos1);
  419. City city2 = tour.getCity(tourPos2);
  420.  
  421. // Swap them around
  422. // Поменять их местами
  423. tour.setCity(tourPos2, city1);
  424. tour.setCity(tourPos1, city2);
  425. }
  426. }
  427. }
  428.  
  429. // Selects candidate tour for crossover
  430. // Выбор тура-кандидата для кроссовера
  431. Tour tournamentSelection(Population pop)
  432. {
  433. // Create a tournament population
  434. // Создание популяции турнира
  435. Population* tournament = new Population(tournamentSize, false);
  436.  
  437. // For each place in the tournament get a random candidate tour and add it
  438. // Для каждого места в турнире получите случайный тур кандидата и добавьте его
  439. for (int i = 0; i < tournamentSize; i++)
  440. {
  441. //int randomId = (int)(rand() * pop.populationSize());
  442. int randomId = (int)(rand() % pop.populationSize());
  443. tournament->saveTour(i, pop.getTour(randomId));
  444. }
  445.  
  446. // Get the fittest tour
  447. // Получите самый подходящий тур
  448. Tour fittest = tournament->getFittest();
  449.  
  450. return fittest;
  451. }
  452. };
  453.  
  454. int main()
  455. {
  456. TourManager tourmanager;
  457. GA ga;
  458.  
  459. City *city1 = new City(60, 200);
  460. tourmanager.addCity(*city1);
  461.  
  462. City *city2 = new City(180, 200);
  463. tourmanager.addCity(*city2);
  464.  
  465. City *city3 = new City(80, 180);
  466. tourmanager.addCity(*city3);
  467.  
  468. City *city4 = new City(140, 180);
  469. tourmanager.addCity(*city4);
  470.  
  471. City *city5 = new City(20, 160);
  472. tourmanager.addCity(*city5);
  473.  
  474. //initialize population
  475. //инициализация популяции
  476. Population *pop = new Population(50, true);
  477. cout << "Initial distance: " << pop->getFittest().getDistance() << endl;
  478.  
  479. // Evolve population for 50 generations
  480. // Эволюция населения в течение 50 поколений
  481. *pop = ga.evolvePopulation(*pop);
  482. for (int i = 0; i < 10; i++)
  483. {
  484. *pop = ga.evolvePopulation(*pop);
  485. }
  486.  
  487. // Print final results
  488. // Печать окончательных результатов
  489.  
  490. cout << "Finished" << endl;
  491. cout << "Final distance: " << pop->getFittest().getDistance() << endl;
  492. // std:ostream& operator<<(std::ostream&, const Tour&);
  493. // Tour t = pop->getFittest();
  494. // cout << "Solution: Distance = " << t.getDistance()<<". Fitness = "<<t.getFitness() << endl;
  495. system("pause");
  496.  
  497. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement