Advertisement
Guest User

Untitled

a guest
Nov 19th, 2019
460
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.80 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <random>
  4. #include <algorithm>
  5. #include <set>
  6. #include <iomanip>
  7. #include <climits>
  8.  
  9. typedef double ftyp;
  10. constexpr ftyp EPSILON = std::numeric_limits<ftyp>::epsilon();
  11.  
  12. typedef const ftyp cftyp;
  13. typedef std::mt19937_64 Trnd;
  14. typedef std::uniform_int_distribution<int> TIntDist;
  15. typedef std::uniform_real_distribution<ftyp> TFltDist;
  16.  
  17. class MyException : public std::exception {
  18. private:
  19.     const std::string swhat;
  20.  
  21. public:
  22.     MyException( const char *const swhat ) : swhat(swhat) {
  23.     }
  24.  
  25.     virtual const char* what() const throw(){
  26.         return swhat.c_str();
  27.     }
  28. };
  29.  
  30. struct Spec {
  31.     std::vector<int> genotype;
  32.     std::vector<int> cgenotype; // copy genotype
  33.     ftyp eval;
  34.     ftyp ceval;                 // copy eval
  35.     ftyp weight;
  36.     bool repeat;
  37. };
  38.  
  39. static std::ostream& operator<<( std::ostream& dest, const Spec &spec ) {
  40.     dest << std::setprecision(14) << spec.ceval << ", " << std::setprecision(14) << spec.weight << " [";
  41.     for( size_t i=0 ; i<spec.genotype.size() ; i++ ) {
  42.         std::cout << spec.cgenotype[i];
  43.         if( i < spec.genotype.size() - 1 ) {
  44.             std::cout << ",";
  45.         }
  46.     }
  47.     dest << "]";
  48.     return dest;
  49. }
  50.  
  51. struct BpItem {
  52.     ftyp weight;
  53.     ftyp value;
  54. };
  55.  
  56. static std::ostream& operator<<( std::ostream& dest, const BpItem &item ) {
  57.     dest << std::setprecision(14) << item.value << " / " << std::setprecision(14) << item.weight << " == " << item.value / item.weight;
  58.     return dest;
  59. }
  60.  
  61. static bool cmpItem( const BpItem &a , const BpItem &b ) {
  62.     return a.value / a.weight > b.value / b.weight;
  63. }
  64.  
  65. static int getSeed() {
  66.     std::cout << "Please input random seed (zero to random): ";
  67.     int n;
  68.     std::cin >> n;
  69.     if( std::cin.fail() ) {
  70.         throw MyException("invalid random seed");
  71.     }
  72.     if( n < 1 ) {
  73.         n = (int)time(NULL);
  74.     }
  75.     return n;
  76. }
  77.  
  78. static int getLoops() {
  79.     std::cout << "Please input max loops (zero to inifinite): ";
  80.     int n;
  81.     std::cin >> n;
  82.     if( std::cin.fail() || n < 0 ) {
  83.         throw MyException("invalid max loops");
  84.     }
  85.     return n;
  86. }
  87.  
  88. static int getSize() {
  89.     std::cout << "Please input population's size: ";
  90.     int n;
  91.     std::cin >> n;
  92.     if( std::cin.fail() || n < 1) {
  93.         throw MyException("invalid populations size");
  94.     }
  95.     return n;
  96. }
  97.  
  98. static std::vector<ftyp> getBackpacks() {
  99.     std::vector<ftyp> backpacks;
  100.     std::cout << "Please input number of backpacks: ";
  101.     int n;
  102.     std::cin >> n;
  103.     if( std::cin.fail() || n < 1 ) {
  104.         throw MyException("invalid number of backpacks");
  105.     }
  106.     for( int i=0 ; i<n ; i++ ) {
  107.         std::cout << (i+1) << " please input capacity of backpack: ";
  108.         ftyp c;
  109.         std::cin >> c;
  110.         if( std::cin.fail() || c <= 0 ) {
  111.             throw MyException("invalid capacity of backpack");
  112.         }
  113.         backpacks.push_back( c );
  114.     }
  115.     return backpacks;
  116. }
  117.  
  118. static float getMutation() {
  119.     std::cout << "Please input probability of mutations <0.000,1.000>: ";
  120.     ftyp n;
  121.     std::cin >> n;
  122.     if( std::cin.fail() || n > 1 || n < 0 ) {
  123.         throw MyException("invalid probability of mutation");
  124.     }
  125.     return n;
  126. }
  127.  
  128. static ftyp getBack() {
  129.     std::cout << "Please input probability of back <0.000,1.000>: ";
  130.     ftyp n;
  131.     std::cin >> n;
  132.     if( std::cin.fail() || n < 0 || n > 1 ) {
  133.         throw MyException("invalid probability of back");
  134.     }
  135.     return n;
  136. }
  137.  
  138. static ftyp getPenal() {
  139.     std::cout << "Please input penal: ";
  140.     ftyp n;
  141.     std::cin >> n;
  142.     if( std::cin.fail() || n < 0 ) {
  143.         throw MyException("invalid penal");
  144.     }
  145.     return n;
  146. }
  147.  
  148. static std::vector<BpItem> getItems() {
  149.     std::vector<BpItem> items;
  150.     std::cout << "Please insert number of items:";
  151.     int n;
  152.     std::cin >> n;
  153.     if( std::cin.fail() || n < 1 ) {
  154.         throw MyException("invalid number of items");
  155.     }
  156.     items.resize( n );
  157.  
  158.     for( int i=0 ; i<n ; i++ ) {
  159.         BpItem bpItem;
  160.         std::cout << "insert " << (i+1) << " weight: ";
  161.         std::cin >> bpItem.weight;
  162.         if( std::cin.fail() || bpItem.weight <= 0 ) {
  163.             throw MyException("invalid weight");
  164.         }
  165.         std::cout << "insert " << (i+1) << " value: ";
  166.         std::cin >> bpItem.value;
  167.         if( std::cin.fail() || bpItem.value <= 0 ) {
  168.             throw MyException("invalid value");
  169.         }
  170.         items[i] =  bpItem ;
  171.     }
  172.     std::sort(items.begin(),items.end(),cmpItem);
  173.     for( size_t i=0 ; i<items.size() ; i++ ) {
  174.         std::cout << (i+1) << " " << items[i] << std::endl;
  175.     }
  176.     std::cout << "Readed " << items.size() << " elements" << std::endl;
  177.     return items;
  178. }
  179.  
  180. static void evalSpec(
  181.     Spec                      &spec,
  182.     const std::vector<ftyp>   &backpacks ,
  183.     const std::vector<BpItem> &items ,
  184.     cftyp                     penal
  185. ) {
  186.     spec.eval   = 0;
  187.     spec.weight = 0;
  188.     std::vector<ftyp> weights( backpacks.size() , 0 );
  189.     for( size_t i=0 ; i<spec.genotype.size() ; i++ ) {
  190.         if( spec.genotype[i] == 0 ) {
  191.             continue;
  192.         }
  193.         const int nr = spec.genotype[i] - 1;
  194.         if( weights[nr] + items[i].weight > backpacks[nr] ) {
  195.             spec.eval -= penal;
  196.             continue;
  197.         }
  198.         weights[nr] += items[i].weight;
  199.         spec.weight += items[i].weight;
  200.         spec.eval += items[i].value;
  201.     }
  202. }
  203.  
  204. static void randSpec(
  205.     Spec      &spec ,
  206.     Trnd      &rnd ,
  207.     const std::vector<BpItem> &items,
  208.     const std::vector<ftyp> backpacks
  209. ) {
  210.     spec.genotype.resize( items.size() );
  211.     for( size_t i=0 ; i<items.size() ; i++ ) {
  212.         spec.genotype[i] = ( rnd() % ( backpacks.size() + 1 ) );
  213.     }
  214. }
  215.  
  216. static void mutationSpec(
  217.     Spec                    &spec,
  218.     Trnd                    &rnd ,
  219.     const std::vector<ftyp> &backpacks
  220. ) {
  221.     size_t gen;
  222.     int    value;
  223.     do {
  224.         gen = rnd() % spec.genotype.size();
  225.         value = rnd() % (backpacks.size() + 1);
  226.     } while( spec.genotype[ gen ] == value );
  227.     spec.genotype[ gen ] = value;
  228. }
  229.  
  230. static void cross2(
  231.     const Spec &a,
  232.     const Spec &b,
  233.     Spec       &out,
  234.     Trnd       &rnd
  235. ) {
  236.     for( size_t i=0 ; i<a.genotype.size() ; i++ ) {
  237.         if( rnd() & 1 ) {
  238.             out.genotype[i] = a.genotype[i];
  239.         } else {
  240.             out.genotype[i] = b.genotype[i];
  241.         }
  242.     }
  243. }
  244.  
  245. static void cross1(
  246.     const Spec &a,
  247.     const Spec &b,
  248.     Spec       &out,
  249.     Trnd       &rnd
  250. ) {
  251.     size_t x = rnd() % (a.genotype.size()-1) + 1;
  252.     for( size_t i=0 ; i<x ; i++ ) {
  253.         out.genotype[i] = a.genotype[i];
  254.     }
  255.     for( size_t i=x ; i<a.genotype.size() ; i++ ) {
  256.         out.genotype[i] = b.genotype[i];
  257.     }
  258. }
  259.  
  260. static ftyp mkAvg( const std::vector<Spec> &specs ) {
  261.     ftyp sum = 0;
  262.     for( size_t i=0 ; i<specs.size() ; i++ ) {
  263.         sum += specs[i].ceval;
  264.     }
  265.     return sum / specs.size();
  266. }
  267.  
  268. static ftyp mkStDev( const std::vector<Spec> &specs ) {
  269.     std::vector<ftyp> stdev( specs[0].cgenotype.size() , 0 );
  270.     std::vector<ftyp> avgs( specs[0].cgenotype.size() , 0 );
  271.  
  272.     for( size_t i=0 ; i<specs.size() ; i++ ) {
  273.         for( size_t j=0 ; j<specs[i].cgenotype.size() ; j++ ) {
  274.             avgs[j] += specs[i].cgenotype[j];
  275.         }
  276.     }
  277.     for( size_t i=0 ; i<avgs.size() ; i++ ) {
  278.         avgs[i] /= specs.size();
  279.     }
  280.     for( size_t i=0 ; i<specs.size() ; i++ ) {
  281.         for( size_t j=0 ; j<specs[i].cgenotype.size() ; j++ ) {
  282.             cftyp tmp = avgs[j] - specs[i].cgenotype[j];
  283.             stdev[j] += tmp * tmp;
  284.         }
  285.     }
  286.     ftyp sum = 0;
  287.     for( size_t i=0 ; i<avgs.size() ; i++ ) {
  288.         sum += sqrt( stdev[i] / specs.size() );
  289.     }
  290.     return sum / specs[0].cgenotype.size();
  291. }
  292.  
  293.  
  294. int main(int argc, char *argv[]) {
  295.     (void)argc;
  296.     (void)argv;
  297.     try {
  298.         const int seed     = getSeed();
  299.         std::cout << "seed = " << seed << std::endl;
  300.         const int loops    = getLoops();
  301.         const int size     = getSize();
  302.         cftyp mutation     = getMutation();
  303.         cftyp back         = getBack();
  304.         cftyp     penal     = getPenal();
  305.         const std::vector<ftyp> backpacks = getBackpacks();
  306.         const std::vector<BpItem> items = getItems();
  307.  
  308.         Trnd rnd( seed );
  309.         TIntDist pDist(0 , size-1 );
  310.         TFltDist fDist( 0.0 , 1.0 );
  311.  
  312.         const time_t start = time(NULL);
  313.         time_t showTime    = start;
  314.  
  315.         std::vector<Spec> specs( size );
  316.  
  317.         int best = 0;
  318.         long long improveStat[2] = {0,0};
  319.         long long sumStat[2]     = {0,0};
  320.  
  321.         for( size_t i=0 ; i<specs.size() ; i++ ) {
  322.             randSpec( specs[i] , rnd , items , backpacks );
  323.             evalSpec( specs[i] , backpacks , items , penal );
  324.             specs[i].ceval = specs[i].eval;
  325.             specs[i].cgenotype = specs[i].genotype;
  326.             if( specs[best].eval < specs[i].eval ) {
  327.                 best = i;
  328.             }
  329.         }
  330.  
  331.         std::cout << (time(NULL)-start) << "s; best[0]: " << specs[ best ] << std::endl;
  332.         std::cout << "avg: " << std::setprecision(14) << mkAvg(specs) << std::endl;
  333.  
  334.         for( int loop=1 ; loops == 0 || loop <= loops ; loop++ ) {
  335.  
  336.             for( int child=0 ; child<size ; child++ ) {
  337.                 int improveIdx;
  338.                 if( fDist(rnd) < mutation ) {
  339.                     improveIdx = 0;
  340.                     mutationSpec( specs[child] , rnd , backpacks );
  341.                 } else {
  342.                     improveIdx = 1;
  343.                     int parent1, parent2;
  344.                     do {
  345.                         parent1 = pDist(rnd);
  346.                         parent2 = pDist(rnd);
  347.                     } while(parent1 == parent2 || parent1 == child || parent2 == child);
  348.                     cross1( specs[parent1], specs[parent2], specs[child], rnd );
  349.                 }
  350.                 evalSpec( specs[child] , backpacks , items , penal );
  351.                 sumStat[improveIdx] ++ ;
  352.                 if( specs[child].eval < specs[child].ceval ) {
  353.                     if( fDist(rnd) < back ) {
  354.                         specs[child].genotype = specs[child].cgenotype;
  355.                         specs[child].eval     = specs[child].ceval;
  356.                     }
  357.                 } else {
  358.                     if( specs[child].eval > specs[child].ceval ) {
  359.                         improveStat[improveIdx] ++ ;
  360.                         if( specs[child].eval > specs[best].ceval ) {
  361.                             best = child;
  362.                             showTime = 0;
  363.                         }
  364.                     }
  365.                     specs[child].cgenotype = specs[child].genotype;
  366.                     specs[child].ceval     = specs[child].eval;
  367.                 }
  368.             }
  369.  
  370.             if(
  371.                 showTime == 0
  372.                     ||
  373.                 ( !(loop & 1023) && time(NULL) - showTime >= 300 )
  374.                     ||
  375.                 loop == loops
  376.             ) {
  377.                 std::cout << (time(NULL)-start) << "s; best[" << loop << "]: " << specs[best] << std::endl;
  378.                 std::cout << "avg:   " << mkAvg(specs) << std::endl;
  379.                 std::cout << "stdev: " << mkStDev(specs) << std::endl;
  380.                 std::cout << "mutation inc:" << std::setw(13) << std::setprecision(7) << (100.0 * improveStat[0] / (sumStat[0]+EPSILON)) << "% all: " << std::setw(11) << sumStat[0] << std::endl;
  381.                 std::cout << "cross:   inc:" << std::setw(13) << std::setprecision(7) << (100.0 * improveStat[1] / (sumStat[1]+EPSILON)) << "% all: " << std::setw(11) << sumStat[1] << std::endl;
  382.                 showTime = time(NULL);
  383.             }
  384.         }
  385.     }
  386.     catch( std::exception &e ) {
  387.         std::cout << "We have a problem: " << e.what() << std::endl;
  388.     }
  389.     return 0;
  390. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement