Advertisement
Guest User

GA_TASK3_II

a guest
Dec 14th, 2019
125
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.05 KB | None | 0 0
  1. #include <iostream>
  2. #include <bitset>
  3. #include <vector>
  4. #include <fstream>
  5. #include <math.h>
  6. #include <intrin.h>
  7. #include <random>
  8. #include <time.h>
  9.  
  10. std::ofstream fout("data.out");
  11. std::ifstream fin("data.in");
  12. /*
  13. std::default_random_engine gen01;
  14. std::uniform_real_distribution<double> rand01(0.0, 1.0);
  15.  
  16. std::default_random_engine gen05;
  17. std::uniform_real_distribution<double> rand05(0.0, 0.5);
  18. */
  19. unsigned int graphDistances[2000][2000];
  20. unsigned int cityCount;
  21. int popSize = 100;
  22.  
  23. double fRand(double fMin, double fMax)
  24. {
  25.     double f = (double)rand() / RAND_MAX;
  26.     return fMin + f * (fMax - fMin);
  27. }
  28. struct Tour
  29. {
  30.     std::bitset<10000> bits;
  31.     std::vector<unsigned int> values; //vectors are assigned at element creation in order to not repeat memory assignment at every modification
  32.     std::vector<unsigned int> orderedValues; //same as above
  33.     std::vector<unsigned int> tourOrder; //same as above
  34.     unsigned int cityLen; //amount of bits assigned per city; value should always be ceil(log2(cityCount))
  35.     unsigned int cityCount;
  36.     unsigned int tourDistance;
  37.     bool modified; //false if the tourOrder and tourDistance correspond to the current bitset; should be turned to true every time the bitset is modified (for example, at mutation)
  38.     double pcx;
  39.     double fitness;
  40.  
  41.  
  42.     Tour(int cityNumber) //constructor; count is the number of cities
  43.     {
  44.         cityCount = cityNumber;
  45.         cityLen = (int)ceil(log2(cityCount));
  46.         tourDistance = 0;
  47.         for (int i = 0; i < cityCount; i++)
  48.             values.push_back(-1), orderedValues.push_back(-1), tourOrder.push_back(-1);
  49.         modified = false;
  50.  
  51.         randomize();
  52.         calculateValues();
  53.         calculatePath();
  54.         calculateDistance();
  55.  
  56.         pcx = fRand(0, 1);
  57.     }
  58.  
  59.     Tour(const Tour& t2) //copy contructor
  60.     {
  61.         cityCount = t2.cityCount;
  62.         cityLen = t2.cityLen;
  63.         bits = t2.bits;
  64.         fitness = t2.fitness;
  65.         for (int i = 0; i < cityCount; i++)
  66.             values.push_back(t2.values[i]), orderedValues.push_back(t2.orderedValues[i]), tourOrder.push_back(t2.tourOrder[i]);
  67.  
  68.         tourDistance = t2.tourDistance;
  69.         modified = t2.modified; //ideally, this should ALWAYS be false 
  70.         pcx = fRand(0, 1);
  71.     }
  72.  
  73.     void randomize()
  74.     {
  75.         for (int i = 0; i < 10000; i++)
  76.             bits[i] = rand() % 2;
  77.     }
  78.  
  79.     void generatePCX()
  80.     {
  81.         pcx = fRand(0, 1);
  82.     }
  83.  
  84.     void showBits()
  85.     {
  86.         for (int i = 0; i < cityCount; i++)
  87.         {
  88.             for (int j = 0; j < cityLen; j++)
  89.                 fout << bits[i * cityLen + j];
  90.             fout << " ";
  91.         }
  92.  
  93.         fout << std::endl;
  94.     }
  95.  
  96.     void showPath()
  97.     {
  98.         for (int i = 0; i < cityCount; i++)
  99.             fout << tourOrder[i] << " ";
  100.         fout << std::endl;
  101.     }
  102.  
  103.     void recalculate()
  104.     {
  105.         calculateValues();
  106.         calculatePath();
  107.         calculateDistance();
  108.         modified = false;
  109.     }
  110.  
  111.     void calculateValues()
  112.     {
  113.         int p2, tValue;
  114.  
  115.         for (int i = 0; i < cityCount; i++)
  116.         {
  117.             p2 = (int)pow(2, cityLen - 1);
  118.             tValue = 0;
  119.             for (int j = 0; j < cityLen; j++)
  120.             {
  121.                 tValue += p2 * bits[i * cityLen + j];
  122.                 p2 /= 2;
  123.             }
  124.             values[i] = tValue;
  125.             orderedValues[i] = tValue;
  126.         }
  127.  
  128.         std::sort(orderedValues.begin(), orderedValues.end());
  129.     }
  130.  
  131.     void calculatePath()
  132.     {
  133.         for (int i = 0; i < cityCount; i++)
  134.             for (int j = 0; j < cityCount; j++)
  135.                 if (values[i] == orderedValues[j])
  136.                 {
  137.                     tourOrder[i] = j;
  138.                     orderedValues[j] = -1;
  139.                     j = cityCount + 1;
  140.                 }
  141.  
  142.         //for (int i = 1; i < cityCount; i++)
  143.             //tourDistance += graphDistances[tourOrder[i - 1]][tourOrder[i]]; //NOTE: MIGHT CHANGE ONCE I LEARN HOW TO USE TSPLIB
  144.     }
  145.  
  146.     void calculateDistance()
  147.     {
  148.         tourDistance = graphDistances[tourOrder[0]][tourOrder[cityCount-1]];
  149.         for (int i = 1; i < cityCount; i++)
  150.         {
  151.             tourDistance += graphDistances[tourOrder[i - 1]][tourOrder[i]];
  152.         }
  153.     }
  154.  
  155.     void mutate(double pm)
  156.     {
  157.        
  158.         for (int i = 0; i < cityCount * cityLen; i++)
  159.             if (fRand(0, 1) < pm) {
  160.                 bits[i] = !bits[i];
  161.                 modified = true;
  162.             }
  163.     }
  164. };
  165.  
  166. //std::vector<Tour*> pop;
  167.  
  168. void showEntirePopulation(std::vector<Tour> population)
  169. {
  170.     for (unsigned int i = 0; i < population.size(); i++)
  171.     {
  172.         //population[i].showBits();
  173.         population[i].showPath();
  174.         fout << population[i].tourDistance << " " << population[i].fitness << "\n";
  175.     }
  176. }
  177.  
  178. void readGraph()
  179. {
  180.     fin >> cityCount;
  181.     for (int i = 0; i < cityCount; i++)
  182.         for (int j = 0; j < cityCount; j++)
  183.             fin >> graphDistances[i][j];
  184. }
  185.  
  186.  
  187. void mutation(double pm, std::vector<Tour>& pop)
  188. {
  189.     for (int i = 0; i < pop.size(); i++) {
  190.         pop[i].mutate(pm);
  191.     }
  192. }
  193.  
  194. bool cmp(const Tour& t1, const Tour& t2) {
  195.     return (t1.pcx < t2.pcx);
  196. }
  197.  
  198. /*
  199. void crossover(double pcx, std::vector<Tour>& pop) {
  200.     int crossoverCount = 0;
  201.     std::sort(pop.begin(), pop.end(), cmp);
  202.  
  203.     const int L = pop[0].cityLen * pop[0].cityCount;
  204.  
  205.     std::default_random_engine genint;
  206.     std::uniform_int_distribution<int> randint(1, L - 2);
  207.  
  208.     for (int i = 0; i < pop.size(); i++)
  209.     {
  210.         pop[i].generatePCX();
  211.     }
  212.  
  213.     int i;
  214.     for (i = 0; i < popSize - 1; i += 2) {
  215.         if (pop[i + 1].pcx < pcx && pop[i].pcx < pcx)
  216.         {
  217.             crossoverCount += 2;
  218.  
  219.             int pos = (int)fRand(1,L-2);
  220.             //fout << "pos=" << pos << '\n';
  221.             Tour c1(pop[i]);
  222.             Tour c2(pop[i + 1]);
  223.  
  224.             for (int j = pos; j < L - 1; j++) {
  225.                 c1.bits[j] = pop[i + 1].bits[j];
  226.                 c2.bits[j] = pop[i].bits[j];
  227.             }
  228.             pop.push_back(c1);
  229.             pop.push_back(c2);
  230.  
  231.             fout << std::endl << pos << std::endl;
  232.             pop[i].showBits();
  233.             pop[i + 1].showBits();
  234.             c1.showBits();
  235.             c2.showBits();
  236.         }
  237.         else break;
  238.     }
  239.    
  240.     double newpcx = fRand(0, 1);
  241.     if (pop[i].pcx < pcx && newpcx < 0.5) {
  242.  
  243.         crossoverCount += 2;
  244.  
  245.         int pos = randint(genint);
  246.         //fout << "pos=" << pos << '\n';
  247.         Tour c1(pop[i]);
  248.         Tour c2(pop[i + 1]);
  249.  
  250.         for (int j = pos; j < L - 1; j++) {
  251.             c1.bits[j] = pop[i + 1].bits[j];
  252.             c2.bits[j] = pop[i].bits[j];
  253.         }
  254.         pop.push_back(c1);
  255.         pop.push_back(c2);
  256.     }
  257.     std::cout << "CROSSOVER ENDED WITH " << crossoverCount << " TOTAL CROSSOVERS \n";
  258. }
  259. */
  260.  
  261.  
  262. Tour CrossoverF(Tour& parent1, Tour& parent2, int k)
  263. {
  264.     Tour child(parent1);
  265.     for (int i = 0; i < child.cityLen * child.cityCount; i++)
  266.     {
  267.         (i < k) ? (child.bits[i] = parent1.bits[i]) : (child.bits[i] = parent2.bits[i]);
  268.     }
  269.     child.recalculate();
  270.     //fout << std::endl << k << std::endl;
  271.     //parent1.showBits();
  272.     //parent2.showBits();
  273.     //child.showBits();
  274.    
  275.     return child;
  276. }
  277.  
  278.  
  279. void crossover(double crossoverP, std::vector<Tour> pop)
  280. {
  281.     //std::cout << "STARTING CROSSOVER \n";
  282.     int c = -1, caux = -1, crossoverCount = 0;
  283.     const int L = pop[0].cityLen * pop[0].cityCount;
  284.     for (int i = 0; i < popSize; i++)
  285.     {
  286.         if (pop[i].pcx < crossoverP)
  287.         {
  288.             if (c == -1) c = i;
  289.             else
  290.             {
  291.                 crossoverCount += 2;
  292.                 int k = fRand(1, L-1);
  293.  
  294.                 pop.push_back(CrossoverF(pop[c], pop[i], k));
  295.                 pop.push_back(CrossoverF(pop[i], pop[c], k));
  296.                 //std::cout << "Crossed chromosomes " << c << " and " << i << " at crossing point " << k <<"; \n";
  297.                 c = -1;
  298.             }
  299.         }
  300.         else caux = i;
  301.     }
  302.     if ((c != -1) && (fRand(0, 1) < 0.5))
  303.     {
  304.         crossoverCount += 2;
  305.         int k = fRand(1, L - 1);
  306.         pop.push_back(CrossoverF(pop[c], pop[caux], k));
  307.         pop.push_back(CrossoverF(pop[caux], pop[c], k));
  308.         //std::cout << "Crossed chromosomes " << c << " and " << caux << " at crossing point " << k << "; \n";
  309.     }
  310.     //std::cout << "CROSSOVER ENDED WITH " <<crossoverCount<< " TOTAL CROSSOVERS \n";
  311. }
  312.  
  313.  
  314.  
  315.  
  316. std::vector<Tour> selection(std::vector<Tour>& population,int eliteCount)
  317. {
  318.     std::vector<Tour> newPopulation;
  319.     std::vector<double> sectorFitness;
  320.     double worst = -1;
  321.     //int populationSize = population.size();
  322.  
  323.     for (int i = 0; i < population.size(); i++)
  324.     {
  325.         if (worst < population[i].tourDistance) worst = population[i].tourDistance;
  326.     }
  327.  
  328.  
  329.     for (int i = 0; i < population.size(); i++)
  330.     {
  331.         //population[i].fitness = 1.1 * worst - population[i].tourDistance;
  332.         population[i].fitness = -1*population[i].tourDistance;
  333.     }
  334.  
  335.     std::sort(population.begin(), population.end(), [](Tour t1, Tour t2) {return t1.fitness > t2.fitness; });
  336.  
  337.     sectorFitness.push_back(population[0].fitness);
  338.     for (int i = 1; i < population.size(); i++)
  339.         sectorFitness.push_back(sectorFitness[i - 1] + population[i].fitness);
  340.  
  341.    
  342.     for (int i = 0; i < sectorFitness.size(); i++)
  343.     {
  344.         //std::cout << i << " " << sectorFitness[i] << " ";
  345.     }
  346.    
  347.     for (int i = 0; i < eliteCount; i++)
  348.         newPopulation.push_back(population[i]); //Elitism keeps the first eliteCount individuals unchanged
  349.  
  350.     for (int i = 0; i < popSize - eliteCount; i++)
  351.     {
  352.         double prob = fRand(0, 1) * sectorFitness[sectorFitness.size() - 1];
  353.         for (int j = 0; j < population.size(); j++)
  354.         {
  355.             if (prob <= sectorFitness[j])
  356.             {
  357.                 newPopulation.push_back(population[j]);
  358.                 j = population.size() + 1; //organic break
  359.             }
  360.         }
  361.     }
  362.  
  363.     return newPopulation;
  364. }
  365.  
  366.  
  367. int main() {
  368.  
  369.     //srand(__rdtsc());
  370.     srand(time(NULL));
  371.     //double pm = 0.1;
  372.     //double pcx = 0.3;
  373.  
  374.     std::vector<Tour> pop;
  375.    
  376.     readGraph();
  377.    
  378.     for (int i = 0; i < popSize; i++)
  379.     {
  380.         Tour newtour(cityCount);
  381.         pop.push_back(newtour);
  382.     }
  383.  
  384.     //mutation(0.1, pop);
  385.     //crossover(0.99, pop);
  386.  
  387.    
  388.     int g = 0;
  389.     int shortest = 100000000;
  390.     int shortestIndex = 0;
  391.    
  392.     while (g < 1500)
  393.     {
  394.  
  395.         std::cout << "GENERATION "<< g <<std::endl;
  396.         pop = selection(pop, 5);
  397.         //showEntirePopulation(pop);
  398.         mutation(0.02, pop);
  399.         crossover(0.3, pop);
  400.  
  401.         shortestIndex = 0;
  402.        
  403.         for (int i = 0; i < pop.size(); i++)
  404.         {
  405.             if (pop[i].modified) pop[i].recalculate();
  406.             if (pop[i].tourDistance <= shortest)
  407.             {
  408.                 //std::cout << shortest << " ";
  409.                 shortestIndex = i;
  410.                 shortest = pop[i].tourDistance;
  411.                 //std::cout << shortest << " ";
  412.             }
  413.         }
  414.        
  415.         std::cout << shortest << std::endl;
  416.         pop[shortestIndex].showPath();
  417.         fout << pop[shortestIndex].tourDistance<<" "<<pop[shortestIndex].fitness<<std::endl;
  418.         fout << "--------------------------------------------------------------\n";
  419.         g++;
  420.     }
  421.    
  422.  
  423.     //for (int i = 0; i < pop.size(); i++)
  424.         //fout << pop[i].tourDistance << " " << divFit(&pop[i]) << std::endl;
  425.  
  426.     Tour test(29);
  427.     test.tourOrder = { 0,27,5,11,8,4,25,28,2,1,19,9,3,14,17,16,13,21,10,18,24,6,22,26,7,23,15,12,20 };
  428.     test.calculateDistance();
  429.     std::cout << std::endl << test.tourDistance;
  430.     fout.close();
  431.     return 0;
  432. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement