Advertisement
mamamaria

СломанныйКоммивояжер

Oct 31st, 2021
1,068
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.50 KB | None | 0 0
  1. // TravellingSalesman.cpp : Этот файл содержит функцию "main". Здесь начинается и заканчивается выполнение программы.
  2. //
  3.  
  4. #include <iostream>
  5. #include <vector>
  6. #include <ctime>
  7. #include <random>
  8.  
  9. const int N = 500;
  10.  
  11.  
  12. using namespace std;
  13. default_random_engine eng;
  14.  
  15. using Graph = vector<vector<double>>;
  16. using NN = vector<double>;//сеть с нейронами, где нейрон - это double
  17. using Weights = vector<vector<double>>;
  18. using Ways = vector<int>;
  19.  
  20. void GraphPrinter(Graph graph) {
  21.     for (int i = 0; i < graph.size(); i++) {
  22.         for (int j = 0; j < graph.size(); j++)
  23.             cout << graph[i][j] << " ";
  24.         cout << endl;
  25.     }
  26. }
  27. void WaysPrinter(Ways ways) {
  28.     for (int i = 0; i < ways.size(); i++)
  29.         cout << ways[i] << " ";
  30.     cout << endl;
  31. }
  32.  
  33. void NNPrinter(NN nn) {
  34.     for (int i = 0; i < N; i++) {
  35.         for (int j = 0; j < N; j++)
  36.             cout << round(nn[i * N + j]) << " ";
  37.         cout << endl;
  38.     }
  39. }
  40. Graph GraphGenerator() {
  41.     Graph graph(N);
  42.     for (int i = 0; i < graph.size(); i++) {
  43.         graph[i].resize(N);
  44.     }
  45.     uniform_real_distribution<double> distr(1, 10);
  46.     for (int i = 0; i < graph.size(); i++) {
  47.         for (int j = 0; j < i; j++) {
  48.             double dist = distr(eng);
  49.             graph[i][j] = dist;
  50.             graph[j][i] = graph[i][j];
  51.         }
  52.     }
  53.     return graph;
  54. }
  55.  
  56. /*Weights WeightsCalculator(Graph graph, double A = 20, double B = 20, double C = 10, double D = 0.14) {*/
  57. Weights WeightsCalculator(Graph graph, double A, double B, double C, double D) {
  58.     Weights weights(N * N);
  59.     for (int i = 0; i < weights.size(); i++) {
  60.         weights[i].resize(N * N);
  61.     }
  62.     for (int index = 0; index < N * N; index++) {
  63.         int x = index / N;
  64.         int i = index % N;
  65.         for (int endex = 0; endex < N * N; endex++) {
  66.             int y = endex / N;
  67.             int j = endex % N;
  68.             double w = 0;
  69.             if (x == y && i != j)
  70.                 w -= A;
  71.             if (x != y && i == j)
  72.                 w -= B;
  73.             w -= C;
  74.             if (j == i + 1 || j == i - 1)
  75.                 w -= (D * graph[x][y]);
  76.             if ((j == 0 && i == N - 1)  || (j == N - 1 && i == 0))
  77.                 w -= (D * graph[x][y]);
  78.             if (index == endex) w = 0;
  79.             weights[index][endex] = w;
  80.         }
  81.     }
  82.     return weights;
  83. }
  84.  
  85. void NeuronUpdater(NN& nn, Weights weights, double C, int j) {
  86.     double NET = 0;
  87.     for (int i = 0; i < nn.size(); i++)
  88.         NET += weights[i][j] * nn[i];
  89.     double w_0_j = C * (N - 0.5);
  90.     NET += w_0_j;
  91.     double u_0 = 1;
  92.     /*if (NET > 0)
  93.         nn[j] = 1;
  94.     if (NET < 0)
  95.         nn[j] = 0;*/
  96.     nn[j] = 0.5 * (1 + tanh(NET / u_0));
  97. }
  98.  
  99. double EnegryChecker(NN nn, Weights weights, double C) {
  100.     double E = 0;
  101.     double w_0_j = C * (N - 0.5);
  102.     for (int i = 0; i < nn.size(); i++)
  103.         for (int j = 0; j < nn.size(); j++)
  104.             E += weights[i][j] * nn[i] * nn[j];
  105.     E *= -0.5;
  106.  
  107.     for (int j = 0; j < nn.size(); j++)
  108.         E -= (w_0_j * nn[j]);
  109.     return E;
  110. }
  111.  
  112. bool OkayNNChecker(NN nn, Ways& ways) {
  113.     ways.resize(N);
  114.     int counter1 = 0, counter2 = 0;
  115.     for (int i = 0; i < N; i++) {
  116.         int counter1 = 0;
  117.         for (int j = 0; j < N; j++) {
  118.             int index = i * N + j;
  119.             if (nn[index] >= 0.5) {
  120.                 counter1++;
  121.                 ways[j] = i;
  122.             }
  123.         }
  124.         counter2 = 0;
  125.         for (int k = 0; k < N; k++) {
  126.             if (nn[i + k * N] >=0.5)
  127.                 counter2++;
  128.         }
  129.         if (counter1 != 1 || counter2 != 1) return false;
  130.     }
  131.     return true;
  132. }
  133. double LengthCounter(Ways ways, Graph graph) {
  134.     double length = 0;
  135.     for (int i = 0; i < N - 1; i++)
  136.         length += graph[ways[i]][ways[i + 1]];
  137.     length += graph[ways[0]][ways[N - 1]];
  138.     return length;
  139.    
  140. }
  141. void NNFilling(NN& nn) {
  142.     for (int i = 0; i < N; i++)
  143.         nn[i] = rand() % 2;
  144. }
  145. //нужно сделать чтобы в каждом городе ровно 1 единица матрицы nn и в кадждый момент времени был только один город
  146. // найти длину пути
  147. bool NarayanaPermutation(Ways &ways) {
  148.    
  149.     int index=-1;
  150.     for (int i = (N - 2); i >= 0; i--) {
  151.         if (ways[i] < ways[i + 1]) {
  152.             index = i;
  153.             break;
  154.         }
  155.     }
  156.     if (index == -1)
  157.         return false;
  158.     for (int j = (N - 1); j > index; j--) {
  159.         if (ways[index] < ways[j]) {
  160.             swap(ways[index], ways[j]);
  161.             break;
  162.         }
  163.     }
  164.     reverse(ways.begin() + (index + 1), ways.end());
  165.     return true;
  166. }
  167.  
  168. Ways OrdinaryTravelingSalesman(Graph graph) {
  169.     Ways ways(N); Ways minimalWays(N);
  170.     for (int i = 0; i < N; i++)
  171.         ways[i] = i;
  172.     double min = INFINITY;
  173.     while (true) {
  174.         double newMinimum = LengthCounter(ways, graph);
  175.         if (newMinimum < min) {
  176.             min = newMinimum;
  177.             minimalWays = ways;
  178.         }
  179.         if (!NarayanaPermutation(ways)) break;
  180.     }
  181.     return minimalWays;
  182. }
  183. Ways WorstOrdinaryTravelingSalesman(Graph graph) {
  184.     Ways ways(N); Ways maximumWays(N);
  185.     for (int i = 0; i < N; i++)
  186.         ways[i] = i;
  187.     double max = -INFINITY;
  188.     while (true) {
  189.         double newMinimum = LengthCounter(ways, graph);
  190.         if (newMinimum > max) {
  191.             max = newMinimum;
  192.             maximumWays = ways;
  193.         }
  194.         if (!NarayanaPermutation(ways)) break;
  195.     }
  196.     return maximumWays;
  197. }
  198. int main()
  199. {
  200.  
  201.     Graph graph = GraphGenerator();
  202.     srand(time(0));
  203.     //GraphPrinter(graph);
  204.     cout << endl;
  205.     Weights weights1 = WeightsCalculator(graph,20,20,10,0.14);
  206.     Weights weights2 = WeightsCalculator(graph, 5, 5, 5, 0.5);
  207.    
  208.     Ways ways(N, 0);
  209.     /*Ways ordindaryWays = OrdinaryTravelingSalesman(graph);
  210.     WaysPrinter(ordindaryWays);
  211.     cout << LengthCounter(ordindaryWays, graph) << endl;
  212.     Ways WorstordindaryWays = WorstOrdinaryTravelingSalesman(graph);
  213.     WaysPrinter(WorstordindaryWays);
  214.     cout << LengthCounter(WorstordindaryWays, graph) << endl;*/
  215.  
  216.     double sum = 0;
  217.     double best = INFINITY;
  218.     for (int test = 0; test < 10; test++) {
  219.         NN nn(N * N);
  220.         NNFilling(nn);
  221.         for (int i = 0; i < 40; i++) {
  222.             for (int j = 0; j < 100; j++)
  223.                 NeuronUpdater(nn, weights2, 5, rand() % (N * N));
  224.             for (int j = 0; j < 100; j++)
  225.                 NeuronUpdater(nn, weights2, 5, j);
  226.             for (int j = 0; j < 100; j++)
  227.                 NeuronUpdater(nn, weights1, 10, rand() % (N * N));
  228.             for (int j = 0; j < 100; j++)
  229.                 NeuronUpdater(nn, weights1, 10, j);
  230.             double E = EnegryChecker(nn, weights1, 10);
  231.  
  232.             //if (i % 200 == 0) {
  233.             ways.clear();
  234.             bool NNCheck = OkayNNChecker(nn, ways);
  235.             if (NNCheck) {
  236.                 cout << "Count 1 in NN: " << NNCheck << endl;
  237.                 WaysPrinter(ways);
  238.                 cout << LengthCounter(ways, graph) << endl;
  239.                 cout << endl;
  240.  
  241.             }
  242.             else
  243.                 cout << "Fail\n";
  244.             //NNPrinter(nn);
  245.             cout << endl;
  246.             cout << "E: " << E << endl;
  247.             //}
  248.  
  249.             if (i == 39 && NNCheck) {
  250.                 double l = LengthCounter(ways, graph);
  251.                 sum += l;
  252.                 if (l < best) best = l;
  253.             }
  254.         }
  255.        
  256.     }
  257.     cout << "Average: " << sum / 10 << endl;
  258.     cout << "Best: " << best << endl;
  259. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement