Advertisement
mamamaria

Untitled

Apr 17th, 2022 (edited)
832
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.44 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <ctime>
  4. #include <random>
  5. #include <chrono>
  6. #include <fstream>
  7. #include <string>
  8. #include "Neighbours.h"
  9. string mainstr = "C:\\Users\\asus\\Desktop\\petya\\Coursework\\Coursework\\graphs\\";
  10. int N;
  11. using namespace std;
  12. using namespace chrono;
  13. default_random_engine eng(time(0));
  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. void NeuronUpdater(NN& nn, double A, double B, double C, double D, int index, const Graph& graph) {
  62.     double NET = 0;
  63.     for (int endex = 0; endex < nn.size(); endex++) {
  64.         if (endex == index) continue;
  65.         NET += -C * nn[endex];
  66.     }
  67.     int x = index / N;
  68.     int i = index % N;
  69.     for (int j = 0; j < N; j++) {
  70.         if (j == i)continue;
  71.         int y = x;
  72.         int endex = y * N + j;
  73.         NET += -A * nn[endex];
  74.     }
  75.     for (int y = 0; y < N; y++) {
  76.         if (x == y)continue;
  77.         int j = i;
  78.         int endex = y * N + j;
  79.         NET += -B * nn[endex];
  80.     }
  81.     for (int y = 0; y < N; y++) {
  82.         int j = i + 1;
  83.         if (j == N) j = 0;
  84.         int endex = y * N + j;
  85.         NET += -D * graph[x][y] * nn[endex];
  86.  
  87.         j = i - 1;
  88.         if (j == -1) j = N - 1;
  89.         endex = y * N + j;
  90.         NET += -D * graph[x][y] * nn[endex];
  91.     }
  92.  
  93.     double w_0_j = C * (N - 0.5);
  94.     NET += w_0_j;
  95.     double u_0 = 5;
  96.     /*if (NET > 0)
  97.         nn[j] = 1;
  98.     if (NET < 0)
  99.         nn[j] = 0;*/
  100.         /*nn[j] = 0.5 * (1 + tanh(NET / u_0));*/
  101.     nn[index] = 0.5 * (1 + tanh(NET / u_0));
  102.     /*nn[index] = 1.0 / (1 + exp(-NET * u_0));*/
  103. }
  104.  
  105. double EnegryChecker(const NN& nn, double A, double B, double C, double D, const Graph& graph) {
  106.     double E = 0;
  107.     double w_0_j = C * (N - 0.5);
  108.     for (int index = 0; index < nn.size(); index++) {
  109.         double NET = 0;
  110.         for (int endex = 0; endex < nn.size(); endex++) {
  111.             if (endex == index) continue;
  112.             NET += -C * nn[endex];
  113.         }
  114.         int x = index / N;
  115.         int i = index % N;
  116.         for (int j = 0; j < N; j++) {
  117.             if (j == i)continue;
  118.             int y = x;
  119.             int endex = y * N + j;
  120.             NET += -A * nn[endex];
  121.         }
  122.         for (int y = 0; y < N; y++) {
  123.             if (x == y)continue;
  124.             int j = i;
  125.             int endex = y * N + j;
  126.             NET += -B * nn[endex];
  127.         }
  128.         for (int y = 0; y < N; y++) {
  129.             int j = i + 1;
  130.             if (j == N) j = 0;
  131.             int endex = y * N + j;
  132.             NET += -D * graph[x][y] * nn[endex];
  133.  
  134.             j = i - 1;
  135.             if (j == -1) j = N - 1;
  136.             endex = y * N + j;
  137.             NET += -D * graph[x][y] * nn[endex];
  138.         }
  139.         E += nn[index] * NET;
  140.     }
  141.     E *= -0.5;
  142.  
  143.     for (int j = 0; j < nn.size(); j++)
  144.         E -= (w_0_j * nn[j]);
  145.     return E;
  146. }
  147.  
  148. bool OkayNNChecker(NN nn, Ways& ways) {
  149.     ways.resize(N);
  150.     int counter1 = 0, counter2 = 0;
  151.     for (int i = 0; i < N; i++) {
  152.         int counter1 = 0;
  153.         for (int j = 0; j < N; j++) {
  154.             int index = i * N + j;
  155.             if (nn[index] >= 0.5) {
  156.                 counter1++;
  157.                 ways[j] = i;
  158.             }
  159.         }
  160.         counter2 = 0;
  161.         for (int k = 0; k < N; k++) {
  162.             if (nn[i + k * N] >= 0.5)
  163.                 counter2++;
  164.         }
  165.         if (counter1 != 1 || counter2 != 1) return false;
  166.     }
  167.     return true;
  168. }
  169. double LengthCounter(Ways ways, Graph graph) {
  170.     double length = 0;
  171.     for (int i = 0; i < N - 1; i++)
  172.         length += graph[ways[i]][ways[i + 1]];
  173.     length += graph[ways[0]][ways[N - 1]];
  174.     return length;
  175.  
  176. }
  177. void NNFilling(NN& nn) {
  178.     for (int i = 0; i < N; i++)
  179.         nn[i] = rand() % 2;
  180. }
  181. //нужно сделать чтобы в каждом городе ровно 1 единица матрицы nn и в кадждый момент времени был только один город
  182. // найти длину пути
  183. bool NarayanaPermutation(Ways& ways) {
  184.  
  185.     int index = -1;
  186.     for (int i = (N - 2); i >= 0; i--) {
  187.         if (ways[i] < ways[i + 1]) {
  188.             index = i;
  189.             break;
  190.         }
  191.     }
  192.     if (index == -1)
  193.         return false;
  194.     for (int j = (N - 1); j > index; j--) {
  195.         if (ways[index] < ways[j]) {
  196.             swap(ways[index], ways[j]);
  197.             break;
  198.         }
  199.     }
  200.     reverse(ways.begin() + (index + 1), ways.end());
  201.     return true;
  202. }
  203.  
  204. Ways OrdinaryTravelingSalesman(Graph graph) {
  205.     Ways ways(N); Ways minimalWays(N);
  206.     for (int i = 0; i < N; i++)
  207.         ways[i] = i;
  208.     double min = INFINITY;
  209.     while (true) {
  210.         double newMinimum = LengthCounter(ways, graph);
  211.         if (newMinimum < min) {
  212.             min = newMinimum;
  213.             minimalWays = ways;
  214.         }
  215.         if (!NarayanaPermutation(ways)) break;
  216.     }
  217.     return minimalWays;
  218. }
  219. Ways WorstOrdinaryTravelingSalesman(Graph graph) {
  220.     Ways ways(N); Ways maximumWays(N);
  221.     for (int i = 0; i < N; i++)
  222.         ways[i] = i;
  223.     double max = -INFINITY;
  224.     while (true) {
  225.         double newMinimum = LengthCounter(ways, graph);
  226.         if (newMinimum > max) {
  227.             max = newMinimum;
  228.             maximumWays = ways;
  229.         }
  230.         if (!NarayanaPermutation(ways)) break;
  231.     }
  232.     return maximumWays;
  233. }
  234.  
  235.  
  236. void GraphReader(Graph& graph, int& N, const string strr) {
  237.     ifstream gin(strr);
  238.     gin >> N;
  239.     graph.resize(N);
  240.     for (int i = 0; i < N; i++) {
  241.         graph[i].resize(N);
  242.     }
  243.     double dub;
  244.     for (int i = 0; i < N; i++) {
  245.         for (int j = 0; j < N; j++) {
  246.             gin >> graph[i][j];
  247.             //if (i == j) dub = INFINITY;
  248.             //graph[i][j] = dub;
  249.         }
  250.     }
  251.     gin.close();
  252. }
  253. int main()
  254. {
  255.  
  256.    
  257.     srand(time(0));
  258.     int TEST = 10;
  259.     int EPOCH = 50;
  260.     int FINALEPOCH = EPOCH - 1;
  261.     ofstream filetime("time-N.txt");
  262.     ofstream filelongway("longway-N.txt");
  263.     for (int NUMBER = 5; NUMBER <= 100; NUMBER+=5) {
  264.        
  265.         double bests_Hopefield = 0, bests_NNS = 0, bests_BNNS = 0;
  266.         double timeHopfield = 0,  timeBNNS = 0, timeNNS = 0;
  267.         //Хопфилд
  268.         for (int graphforN = 0; graphforN < 20; graphforN++) {
  269.            
  270.             cout << "\nGraph " << graphforN + 1 << endl;
  271.             //Graph graph = GraphGenerator();
  272.             //GraphPrinter(graph);
  273.             //cout << endl;
  274.             string strr = mainstr + to_string(NUMBER) + "_" + to_string(graphforN) + ".txt";
  275.             Graph graph;
  276.             GraphReader(graph, N, strr);
  277.             Ways ways(N, 0);
  278.             double sum = 0;
  279.             double best = INFINITY;
  280.             int count = 0;
  281.             auto tH1 = high_resolution_clock::now();
  282.             for (int test = 0; test < TEST; test++) {
  283.                 //auto t1 = high_resolution_clock::now();
  284.                 //cout << "test: " << test << endl;
  285.                 NN nn(N * N);
  286.                 NNFilling(nn);
  287.                 for (int i = 0; i < EPOCH; i++) {
  288.                     if (i < EPOCH - 5) {
  289.                         for (int j = 0; j < N * N; j++)
  290.                             NeuronUpdater(nn, 5, 5, 5, 1, rand() % (N * N), graph);
  291.                         for (int j = 0; j < N * N; j++)
  292.                             NeuronUpdater(nn, 5, 5, 5, 1, j, graph);
  293.                     }
  294.                     for (int j = 0; j < N * N; j++)
  295.                         NeuronUpdater(nn, 20, 20, 10, 0.2, rand() % (N * N), graph);
  296.                     for (int j = 0; j < N * N; j++)
  297.                         NeuronUpdater(nn, 20, 20, 10, 0.2, j, graph);
  298.  
  299.                     double E1 = EnegryChecker(nn, 5, 5, 5, 1, graph);
  300.                     double E2 = EnegryChecker(nn, 20, 20, 20, 0.2, graph);
  301.                     //file << i << "\t" << E1 << "\t" << E2 << endl;
  302.                     ways.clear();
  303.  
  304.                     bool NNCheck = OkayNNChecker(nn, ways);
  305.                    
  306.                     if (NNCheck) {
  307.                         double l = LengthCounter(ways, graph);
  308.  
  309.                         if (l < best) best = l;
  310.                         if (i == FINALEPOCH) {
  311.                             sum += l;
  312.                             count++;
  313.                             /*cout << "BEST NOW: " << best << endl;*/
  314.  
  315.                         }
  316.                     }
  317.                 }
  318.                 //auto t2 = high_resolution_clock::now();
  319.                 //cout << duration_cast<milliseconds>(t2 - t1).count() << endl;
  320.                 //cout << endl;
  321.                 //file << endl;
  322.             }
  323.             auto tH2 = high_resolution_clock::now();
  324.             timeHopfield += duration_cast<milliseconds>(tH2 - tH1).count();
  325.             //file << endl;
  326.             cout << "Average Hopfield: " << sum / count << endl;
  327.             cout << "Best Hopfield: " << best << endl;
  328.  
  329.             //Модифицированный Ближайший сосед
  330.             auto tBNNS1 = high_resolution_clock::now();
  331.             Visit BNNSvisit = BNNSVisitGenerator();
  332.             double BNNS = BNNSFinder(graph, BNNSvisit);
  333.             auto tBNNS2 = high_resolution_clock::now();
  334.             timeBNNS += duration_cast<milliseconds>(tBNNS2 - tBNNS1).count();
  335.             cout << "BNNS: " << BNNS << endl;
  336.             bests_BNNS += BNNS;
  337.             //Ближайший сосед
  338.             auto tNNS1 = high_resolution_clock::now();
  339.             Visit NNSvisit = NNSVisitGenerator();
  340.             double NNS = NNSTravelingSalesmanNeighbour(graph, NNSvisit);
  341.             auto tNNS2 = high_resolution_clock::now();
  342.             timeNNS += duration_cast<milliseconds>(tNNS2 - tNNS1).count();
  343.             cout << "NNS: " << NNS << endl;
  344.             bests_NNS += NNS;
  345.  
  346.             bests_Hopefield += best; // Хопфилд
  347.             cout << "Hopfield: " << best << endl;
  348.         }
  349.         filelongway << "\nAverages on N=" << N << ": \nHopefield " << bests_Hopefield / 20 << "\nNeighbour " << bests_NNS / 20 << "\nSuper-Neighbour " << bests_BNNS / 20 << endl;
  350.         filetime << "\nAverages on N=" << N << ": \nHopefield " << timeHopfield / 20 << "\nNeighbour " << timeNNS / 20 << "\nSuper-Neighbour " << timeBNNS / 20 << endl;
  351.         filetime << endl;
  352.        
  353.     }
  354.     filelongway.close();
  355.     filetime.close();
  356. }
  357.  
  358.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement