permutation.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "permutation.h"
  2. #include <algorithm> // swap, advance
  3. #include <cstdlib> // rand
  4. #include <cassert>
  5. #include <set>
  6. using namespace std;
  7. permutation::permutation(int size) : size(size), sigma(size) {
  8. assert(size > 0);
  9. for(int i = 0; i < size; i++)
  10. sigma[i] = i;
  11. }
  12. void permutation::transpose(int i, int j) {
  13. assert(0 < i && i < size);
  14. assert(0 < j && j < size);
  15. std::swap(sigma[i], sigma[j]);
  16. }
  17. // TODO rapport : dire qu'on garde l'invariant pi[0] = 0
  18. void permutation::random() {
  19. // Knuth shuffle
  20. // there is a bias due to the use of rand()%_
  21. for(int i = 1; i < size; i++)
  22. transpose(i, 1+rand()%i);
  23. }
  24. int permutation::operator[](int i) {
  25. assert(0 <= i && i < size);
  26. return sigma[i];
  27. }
  28. bool permutation::check() {
  29. if(size != (int)sigma.size() || sigma[0] != 0)
  30. return false;
  31. vector<bool> seen(size);
  32. for(int i = 0; i < size; i++)
  33. seen[sigma[i]] = true;
  34. for(int i = 0; i < size; i++)
  35. if(!seen[i])
  36. return false;
  37. return true;
  38. }
  39. int permutation::get_size() {
  40. return size;
  41. }
  42. // Algorithm:
  43. // for each i (randomly : we use a permutation :P (it always starts with 0 but
  44. // it's OK since a[0]=b[0]=0 and also we want ret[0]=0))
  45. // we choose either a[i] or b[i]
  46. // if one value was already choosen, we choose the other
  47. // if both were, we choose a value we have seen but not choose (in the set disp)
  48. permutation permutation_crossover(permutation &a, permutation &b) {
  49. assert(a.size == b.size);
  50. permutation ret(a.size);
  51. permutation ord(a.size); // order in which we consider elements of permutations a and b
  52. vector<bool> seen(a.size);
  53. set<int> disp;
  54. ord.random();
  55. for(int i = 0; i < a.size; i++) {
  56. int j = ord[i];
  57. bool seen_a = seen[a[j]], seen_b = seen[b[j]];
  58. if(seen_a && seen_b) {
  59. // take a random value in disp
  60. assert(disp.size()>0);
  61. auto it = disp.begin();
  62. advance(it, rand()%disp.size());
  63. ret.sigma[i] = *it;
  64. }
  65. else if(seen_a) {
  66. // take value in b
  67. ret.sigma[i] = b[j];
  68. }
  69. else if(seen_b) {
  70. // take value in a
  71. ret.sigma[i] = a[j];
  72. }
  73. else if(rand()%2) {
  74. // take value in b
  75. ret.sigma[i] = b[j];
  76. disp.insert(a[j]);
  77. }
  78. else {
  79. // take value in a
  80. ret.sigma[i] = a[j];
  81. disp.insert(b[j]);
  82. }
  83. seen[ret[i]] = true;
  84. disp.erase(ret[i]);
  85. }
  86. assert(ret.check());
  87. return ret;
  88. }