Use a genetic algorithm to evolve populations of bit strings.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

286 lines
4.3 KiB

  1. //
  2. #include "BitEvolver/Chromosome.h"
  3. #include "BitEvolver/Random.h"
  4. //
  5. #include <memory>
  6. #include <string>
  7. #include <sstream>
  8. #include <vector>
  9. #include <mutex>
  10. //
  11. namespace BitEvolver
  12. {
  13. //
  14. using std::string;
  15. using std::to_string;
  16. using std::stringstream;
  17. //
  18. Chromosome::Chromosome(std::shared_ptr<Random> _random, int _bits)
  19. {
  20. //
  21. this->random = _random;
  22. //
  23. this->generation_number = 1;
  24. //
  25. this->SetBitCount(_bits);
  26. //
  27. this->Reset();
  28. }
  29. //
  30. void Chromosome::Reset()
  31. {
  32. //
  33. this->Randomize();
  34. }
  35. //
  36. void Chromosome::Randomize()
  37. {
  38. //
  39. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  40. int i;
  41. //
  42. this->bits.clear();
  43. //
  44. for ( i=0; i<this->bits_count_desired; i++ ) {
  45. this->bits.push_back(this->random->GetInt(0, 1));
  46. }
  47. }
  48. //
  49. void Chromosome::SetGenerationNumber(int g)
  50. {
  51. //
  52. this->generation_number = g;
  53. }
  54. //
  55. void Chromosome::IncrementGenerationNumber()
  56. {
  57. //
  58. this->generation_number++;
  59. }
  60. //
  61. int Chromosome::GetGenerationNumber()
  62. {
  63. //
  64. return this->generation_number;
  65. }
  66. //
  67. void Chromosome::SetBitCount(int count)
  68. {
  69. //
  70. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  71. //
  72. this->bits_count_desired = count;
  73. this->Randomize();
  74. }
  75. //
  76. int Chromosome::GetBitCount()
  77. {
  78. return (int)this->bits.size();
  79. }
  80. //
  81. void Chromosome::FlipBit(int index)
  82. {
  83. //
  84. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  85. //
  86. if ( index >= (int)this->bits.size() ) {
  87. throw std::runtime_error("Chromosome::FlipBit() - Tried to flip out of range bit index: " + to_string(index));
  88. }
  89. //
  90. if ( this->bits[index] ) {
  91. this->bits[index] = false;
  92. }
  93. else{
  94. this->bits[index] = true;
  95. }
  96. }
  97. //
  98. bool Chromosome::GetBit(int index)
  99. {
  100. //
  101. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  102. //
  103. if ( index >= (int)this->bits.size() ) {
  104. throw std::runtime_error("Chromosome::GetBit() - Tried to access out of bounds bit");
  105. }
  106. //
  107. return this->bits[index];
  108. }
  109. //
  110. void Chromosome::SetBit(int index, bool b)
  111. {
  112. //
  113. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  114. //
  115. if ( index >= (int)this->bits.size() ) {
  116. throw std::runtime_error("Chromosome::GetBit() - Tried to access out of bounds bit");
  117. }
  118. //
  119. this->bits[index] = b;
  120. }
  121. //
  122. void Chromosome::SetBits(string s)
  123. {
  124. //
  125. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  126. size_t i;
  127. char c;
  128. //
  129. this->SetBitCount( (int) s.size() );
  130. //
  131. for ( i=0; i<s.size(); i++ ) {
  132. //
  133. c = s[i];
  134. if ( c == '1' ) {
  135. this->bits[i] = true;
  136. }
  137. else if ( c == '0' ) {
  138. this->bits[i] = false;
  139. }
  140. else{
  141. stringstream ss;
  142. ss << "Chromosome::SetBits() - Invalid character '" << c << "' (" << (int)c << ") in bit string input";
  143. throw std::runtime_error( ss.str() );
  144. }
  145. }
  146. }
  147. //
  148. void Chromosome::ResetFitness()
  149. {
  150. //
  151. this->SetFitness(0.0);
  152. }
  153. //
  154. void Chromosome::SetFitness(double d)
  155. {
  156. //
  157. this->fitness = d;
  158. }
  159. //
  160. void Chromosome::AdjustFitness(double d)
  161. {
  162. //
  163. this->fitness += d;
  164. }
  165. //
  166. double Chromosome::GetFitness()
  167. {
  168. //
  169. return this->fitness;
  170. }
  171. //
  172. void Chromosome::ResetError()
  173. {
  174. //
  175. this->ResetFitness();
  176. }
  177. //
  178. void Chromosome::SetError(double e)
  179. {
  180. //
  181. this->SetFitness(-e);
  182. }
  183. //
  184. void Chromosome::AdjustError(double e)
  185. {
  186. //
  187. this->AdjustFitness(-e);
  188. }
  189. //
  190. double Chromosome::GetError()
  191. {
  192. //
  193. return -this->GetFitness();
  194. }
  195. //
  196. string Chromosome::ToString()
  197. {
  198. //
  199. std::unique_lock<std::recursive_mutex> lock(this->modification_mutex);
  200. stringstream s;
  201. //
  202. for ( bool b : this->bits ) {
  203. //
  204. if ( b ) {
  205. s << "1";
  206. }
  207. else{
  208. s << "0";
  209. }
  210. }
  211. //
  212. return s.str();
  213. }
  214. //
  215. const Chromosome& Chromosome::operator=(const Chromosome& other)
  216. {
  217. //
  218. std::unique_lock<std::recursive_mutex> lock1(this->modification_mutex);
  219. int i;
  220. //
  221. this->random = other.random;
  222. this->generation_number = other.generation_number;
  223. this->bits = other.bits;
  224. this->bits_count_desired = other.bits_count_desired;
  225. this->fitness = other.fitness;
  226. // Copy the bits!
  227. this->bits.clear();
  228. for ( i=0; i<(int)other.bits.size(); i++ ) {
  229. this->bits.push_back(other.bits[i]);
  230. }
  231. return *this;
  232. }
  233. };