mamamaria

коми

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