travelsalesman.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <opencv2/core.hpp>
  2. #include <opencv2/imgproc.hpp>
  3. #include <opencv2/highgui.hpp>
  4. #include <opencv2/ml.hpp>
  5. using namespace cv;
  6. class TravelSalesman
  7. {
  8. private :
  9. const std::vector<Point>& posCity;
  10. std::vector<int>& next;
  11. RNG rng;
  12. int d0,d1,d2,d3;
  13. public:
  14. TravelSalesman(std::vector<Point> &p, std::vector<int> &n) :
  15. posCity(p), next(n)
  16. {
  17. rng = theRNG();
  18. }
  19. /** Give energy value for a state of system.*/
  20. double energy() const;
  21. /** Function which change the state of system (random perturbation).*/
  22. void changeState();
  23. /** Function to reverse to the previous state.*/
  24. void reverseState();
  25. };
  26. void TravelSalesman::changeState()
  27. {
  28. d0 = rng.uniform(0,static_cast<int>(posCity.size()));
  29. d1 = next[d0];
  30. d2 = next[d1];
  31. d3 = next[d2];
  32. next[d0] = d2;
  33. next[d2] = d1;
  34. next[d1] = d3;
  35. }
  36. void TravelSalesman::reverseState()
  37. {
  38. next[d0] = d1;
  39. next[d1] = d2;
  40. next[d2] = d3;
  41. }
  42. double TravelSalesman::energy() const
  43. {
  44. double e = 0;
  45. for (size_t i = 0; i < next.size(); i++)
  46. {
  47. e += norm(posCity[i]-posCity[next[i]]);
  48. }
  49. return e;
  50. }
  51. static void DrawTravelMap(Mat &img, std::vector<Point> &p, std::vector<int> &n)
  52. {
  53. for (size_t i = 0; i < n.size(); i++)
  54. {
  55. circle(img,p[i],5,Scalar(0,0,255),2);
  56. line(img,p[i],p[n[i]],Scalar(0,255,0),2);
  57. }
  58. }
  59. int main(void)
  60. {
  61. int nbCity=40;
  62. Mat img(500,500,CV_8UC3,Scalar::all(0));
  63. RNG rng(123456);
  64. int radius=static_cast<int>(img.cols*0.45);
  65. Point center(img.cols/2,img.rows/2);
  66. std::vector<Point> posCity(nbCity);
  67. std::vector<int> next(nbCity);
  68. for (size_t i = 0; i < posCity.size(); i++)
  69. {
  70. double theta = rng.uniform(0., 2 * CV_PI);
  71. posCity[i].x = static_cast<int>(radius*cos(theta)) + center.x;
  72. posCity[i].y = static_cast<int>(radius*sin(theta)) + center.y;
  73. next[i]=(i+1)%nbCity;
  74. }
  75. TravelSalesman ts_system(posCity, next);
  76. DrawTravelMap(img,posCity,next);
  77. imshow("Map",img);
  78. waitKey(10);
  79. double currentTemperature = 100.0;
  80. for (int i = 0, zeroChanges = 0; zeroChanges < 10; i++)
  81. {
  82. int changesApplied = ml::simulatedAnnealingSolver(ts_system, currentTemperature, currentTemperature*0.97, 0.99, 10000*nbCity, &currentTemperature, rng);
  83. img.setTo(Scalar::all(0));
  84. DrawTravelMap(img, posCity, next);
  85. imshow("Map", img);
  86. int k = waitKey(10);
  87. std::cout << "i=" << i << " changesApplied=" << changesApplied << " temp=" << currentTemperature << " result=" << ts_system.energy() << std::endl;
  88. if (k == 27 || k == 'q' || k == 'Q')
  89. return 0;
  90. if (changesApplied == 0)
  91. zeroChanges++;
  92. }
  93. std::cout << "Done" << std::endl;
  94. waitKey(0);
  95. return 0;
  96. }