Advertisement
sergiosvieira1978

Untitled

May 22nd, 2018
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.53 KB | None | 0 0
  1. //
  2. // main.cpp
  3. // tsp
  4. //
  5.  
  6. #include <iostream>
  7. #include <vector>
  8. #include <map>
  9. #include <math.h>
  10. #include <cmath>
  11. #include <set>
  12. #include <limits>
  13. #include <random>
  14. #include <fstream>
  15. #include <sstream>
  16. #include <algorithm>
  17. #include <iterator>
  18. #include <ctime>
  19.  
  20. // Genetic Algorithm
  21. static std::random_device rdev{};
  22. static std::default_random_engine eng{rdev()};
  23. static const int PopulationSize = 10;
  24. static const double MutationRate = 0.35; // 0..1
  25. static const int Generations = 2;
  26.  
  27.  
  28. using City = struct
  29. {
  30. int id;
  31. int x;
  32. int y;
  33. };
  34.  
  35. using Data = std::vector<City>;
  36. using Cromossome = std::vector<int>;
  37. using Solution = struct
  38. {
  39. Cromossome cromossome;
  40. int cost = 0.0;
  41. double fitness = 0.0;
  42. };
  43. using Population = std::vector<Solution>;
  44. using Distances = std::map<int, std::map<int, int>>;
  45. using CrossSolution = std::pair<Cromossome, Cromossome>;
  46.  
  47. int distance(const City& src, const City& dst)
  48. {
  49. double d1 = src.x - dst.x;
  50. double d2 = src.y - dst.y;
  51. double d = sqrt(pow(d1, 2.0) + pow(d2, 2.0));
  52. return (int)std::round(d);
  53. }
  54.  
  55. void print(Distances& dist)
  56. {
  57. for (auto src: dist)
  58. {
  59. std::cout << src.first << "\n";
  60. for (auto dst: src.second)
  61. {
  62. std::cout << "\t" << dst.first << " = " << dst.second << "\n";
  63. }
  64. }
  65. }
  66.  
  67. std::string str(const Cromossome& r)
  68. {
  69. std::string result = "[";
  70. for (int i = 0; i < r.size(); ++i)
  71. {
  72. result += std::to_string(r[i]);
  73. if (i < r.size() - 1) result += ",";
  74. }
  75. result += "]";
  76. return result;
  77. }
  78.  
  79. bool isValidSolution(const Cromossome& cromossome, const Data& data)
  80. {
  81. std::set<int> cityIndexes;
  82. if (cromossome.size() != data.size())
  83. {
  84. return false;
  85. }
  86. for (int i = 0; i < cromossome.size(); ++i)
  87. {
  88. cityIndexes.insert(cromossome[i]);
  89. }
  90. if (cityIndexes.size() != cromossome.size())
  91. {
  92. return false;
  93. }
  94. return true;
  95. }
  96.  
  97. int calcCost(const Cromossome& cromossome, Distances& dist, const Data& data, bool debug = false)
  98. {
  99. if (!isValidSolution(cromossome, data)) return std::numeric_limits<int>::max() / 2.0;
  100. int totalCost = 0.0;
  101. for (int i = 0; i < cromossome.size(); ++i)
  102. {
  103. int src;
  104. int dst;
  105. if (i == 0)
  106. {
  107. //totalCost += dist[0][cromossome[cromossome.size() - 1]];
  108. dst = cromossome[cromossome.size() - 1];
  109. src = cromossome[0];
  110. }
  111. else
  112. {
  113. dst = cromossome[i - 1];
  114. src = cromossome[i];
  115. }
  116. if (debug)
  117. {
  118. std::cout << i
  119. << " "
  120. << src
  121. << " "
  122. << dst
  123. << " "
  124. << dist[src][dst]
  125. << " "
  126. << totalCost
  127. << "\n";
  128. }
  129. int d = dist[src][dst];
  130. totalCost += d;
  131. }
  132. return totalCost;
  133. }
  134.  
  135. int rndMinMax(int min, int max)
  136. {
  137. std::uniform_real_distribution<double> urd(min, max);
  138. return urd(eng);
  139. }
  140.  
  141. Population initialPopulation(Distances& dist, int popSize, const Data& data)
  142. {
  143. Population result;
  144. for (int i = 0; i < popSize; ++i)
  145. {
  146. Cromossome v(dist.size());
  147. std::iota(v.begin(), v.end(), 0);
  148. std::shuffle(v.begin(), v.end(), eng);
  149. Solution s;
  150. s.cromossome = v;
  151. s.cost = calcCost(v, dist, data);
  152. s.fitness = 0.0;
  153. result.push_back(s);
  154. }
  155. return result;
  156. }
  157.  
  158. int findBest(const Population& pop)
  159. {
  160. double bestFitness = pop[0].fitness;
  161. int index = 0;
  162. for (int i = 1; i < pop.size(); ++i)
  163. {
  164. double fitness = pop[i].fitness;
  165. if (fitness < bestFitness)
  166. {
  167. bestFitness = fitness;
  168. index = i;
  169. }
  170. }
  171. return index;
  172. }
  173.  
  174. int pickOne(const Population& pop)
  175. {
  176. std::uniform_real_distribution<double> urd(0, 1);
  177. double r = urd(eng);
  178. int index = 0;
  179. double offset = 0.0;
  180. for (int i = 0; i < pop.size(); ++i)
  181. {
  182. offset += pop[i].fitness;
  183. if (r < offset)
  184. {
  185. return i;
  186. }
  187. }
  188. return index;
  189. }
  190.  
  191. void mutation(Cromossome& cromossome)
  192. {
  193. int p1 = rndMinMax(0, cromossome.size() - 1);
  194. int p2 = rndMinMax(0, cromossome.size() - 1);
  195. int aux = cromossome[p1];
  196. cromossome[p1] = cromossome[p2];
  197. cromossome[p2] = aux;
  198. }
  199.  
  200. CrossSolution crossover(const Cromossome& c1, const Cromossome& c2)
  201. {
  202. Cromossome s1(c1);
  203. Cromossome s2(c2);
  204. int randPos1 = rndMinMax(0, c1.size() - 1);
  205. std::shuffle(s1.begin() + randPos1, s1.end(), eng);
  206. int randPos2 = rndMinMax(0, c2.size() - 1);
  207. std::shuffle(s2.begin() + randPos2, s2.end(), eng);
  208. return std::make_pair(s1, s2);
  209. }
  210.  
  211. void printPop(Population& pop)
  212. {
  213. for (int i = 0; i < pop.size(); ++i)
  214. {
  215. std::cout << str(pop[i].cromossome)
  216. << " = " << pop[i].cost
  217. << ", " << pop[i].fitness
  218. << "\n";
  219. }
  220. std::cout << "\n";
  221. }
  222.  
  223. std::vector<std::string> split(const std::string text)
  224. {
  225. std::stringstream ss(text);
  226. std::istream_iterator<std::string> begin(ss);
  227. std::istream_iterator<std::string> end;
  228. std::vector<std::string> result(begin, end);
  229. return result;
  230. }
  231.  
  232. void calcFitness(Solution& s, double total)
  233. {
  234. s.fitness = s.cost / (total + 1.0);
  235. }
  236.  
  237. void calculatePopFitness(Population& pop)
  238. {
  239. double total = 0.0;
  240. for (int i = 0; i < pop.size(); ++i)
  241. {
  242. total += pop[i].cost;
  243. }
  244. for (int i = 0; i < pop.size(); ++i)
  245. {
  246. calcFitness(pop[i], total);
  247. }
  248. }
  249.  
  250. Data readData(const char* filename)
  251. {
  252. Data data;
  253. std::ifstream input(filename);
  254. if (!input.is_open()) return data;
  255. while (input.good())
  256. {
  257. City c;
  258. std::string line;
  259. std::getline(input, line);
  260. if (line.size() == 0) continue;
  261. std::vector<std::string> tokens = split(line);
  262. if (tokens.size() != 3) continue;
  263. int id = std::atoi(tokens[0].c_str());
  264. double x = std::atof(tokens[1].c_str());
  265. double y = std::atof(tokens[2].c_str());
  266. c.id = id;
  267. c.x = x;
  268. c.y = y;
  269. data.push_back(c);
  270. std::cout << id;
  271. }
  272. return data;
  273. }
  274.  
  275. Distances calcDistances(const Data& data)
  276. {
  277. Distances result;
  278. int src, dst, d = 0;
  279. for (int i = 0; i < data.size(); ++i)
  280. {
  281. src = i;
  282. for (int j = 0; j < data.size(); ++j)
  283. {
  284. dst = j;
  285. if (src == dst)
  286. {
  287. d = std::numeric_limits<int>::max() / 2.0;
  288. result[src][dst] = d;
  289. }
  290. else
  291. {
  292. auto row = result.find(src);
  293. if (row == result.end())
  294. {
  295. d = distance(data[src], data[dst]);
  296. result[src][dst] = d;
  297. result[dst][src] = d;
  298. std::cout << "[" << d << "]";
  299. }
  300. }
  301. }
  302. }
  303. return result;
  304. }
  305.  
  306. int main(int argc, const char * argv[])
  307. {
  308. if (argc < 2)
  309. {
  310. std::cerr << "Usage: " << argv[0] << " <input file name>\n";
  311. return 1;
  312. }
  313. Data data = readData(argv[1]);
  314. if (data.size() == 0) return 0;
  315. Distances dist = calcDistances(data);
  316. Population pop = initialPopulation(dist, PopulationSize, data);
  317. //printPop(pop);
  318. for (int i = 0; i < Generations; ++i)
  319. {
  320. std::cout << "Generation #" << i << "\n";
  321. calculatePopFitness(pop);
  322. int best = findBest(pop);
  323. Population newPop;
  324. Solution s = pop[best];
  325. newPop.push_back(s);
  326. for (int j = 1; j < pop.size(); ++j)
  327. {
  328. int s1 = pickOne(pop);
  329. int s2 = pickOne(pop);
  330. CrossSolution cs = crossover(pop[s1].cromossome, pop[s2].cromossome);
  331. double cost1 = calcCost(cs.first, dist, data);
  332. double cost2 = calcCost(cs.second, dist, data);
  333. Cromossome best = cost1 < cost2 ? cs.first : cs.second;
  334. double bestCost = cost1 < cost2 ? cost1 : cost2;
  335. auto it = std::find_if(pop.begin(), pop.end(), [&](const Solution& s){
  336. return s.cost == bestCost;
  337. });
  338. if (it != pop.end())
  339. {
  340. std::shuffle(best.begin(), best.end(), eng);
  341. if (!isValidSolution(best, data))
  342. {
  343. std::cerr << "Invalid solution.\n";
  344. }
  345. bestCost = calcCost(best, dist, data);
  346. }
  347. if (rndMinMax(0, 100) < MutationRate * 100.)
  348. {
  349. mutation(best);
  350. if (!isValidSolution(best, data))
  351. {
  352. std::cerr << "Invalid solution.\n";
  353. }
  354. bestCost = calcCost(best, dist, data);
  355. }
  356. if (bestCost > pop[j].cost)
  357. {
  358. newPop.push_back(pop[j]);
  359. }
  360. else
  361. {
  362. Solution newSolution;
  363. newSolution.cromossome = best;
  364. newSolution.cost = bestCost;
  365. if (!isValidSolution(best, data))
  366. {
  367. std::cerr << "Invalid solution.\n";
  368. }
  369. newPop.push_back(newSolution);
  370. }
  371. }
  372. pop = newPop;
  373. }
  374. calculatePopFitness(pop);
  375. int bestSolution = findBest(pop);
  376. if (!isValidSolution(pop[bestSolution].cromossome, data))
  377. {
  378. std::cerr << "Invalid solution.\n";
  379. }
  380. std::string result = "";
  381. std::string outputFilename = std::string(argv[1]) + ".tour";
  382. std::ofstream output(outputFilename.c_str(), std::ofstream::out);
  383. //result += std::to_string((int)pop[bestSolution].cost) + "\n";
  384. output << std::to_string((int)pop[bestSolution].cost) + "\n";
  385. for (auto c: pop[bestSolution].cromossome)
  386. {
  387. //result += std::to_string(c) + "\n";
  388. output << std::to_string(c) + "\n";
  389. }
  390. //output << result;
  391. output.close();
  392. //calcCost(pop[bestSolution].cromossome, dist, data, true);
  393. /*
  394. std::cout << str(pop[bestSolution].cromossome)
  395. << " = " << pop[bestSolution].cost
  396. << " = " << pop[bestSolution].fitness
  397. << "\n";
  398. printPop(pop);
  399. */
  400. return 0;
  401. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement