OptimizerEvolutionary.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. #include <iostream>
  2. #include "OptimizerBase.h"
  3. namespace mdd {
  4. class OptimizerEvolutionary : public OptimizerBase {
  5. public:
  6. struct Individual {
  7. public:
  8. std::vector<std::vector<double>> dna;
  9. double fitness = 0;
  10. bool operator== (const Individual& ind) {
  11. return (dna == ind.dna) && (fitness == ind.fitness);
  12. };
  13. };
  14. protected:
  15. static int random_num(double min, double max, double inc = 1.0)
  16. {
  17. int range = (max - min) / inc + 1;
  18. return min + inc * (std::rand() % range);
  19. }
  20. Individual generateIndividual();
  21. Individual combine(Individual par1, Individual par2);
  22. std::vector<Individual> _children;
  23. Individual _best;
  24. int _min_generations;
  25. double _max_fitness;
  26. size_t _grow_generation;
  27. size_t _converges;
  28. void evolve(std::vector<Individual> parents);
  29. void evaluate(size_t ignore_len = 0);
  30. std::vector<double> mutateGene(std::shared_ptr<IInput> input, std::vector<double> seed = std::vector<double>());
  31. public:
  32. OptimizerEvolutionary();
  33. /*
  34. std::shared_ptr<IModule> module,
  35. size_t converges = 0,
  36. size_t grow_generation = 20,
  37. double max_fitness = 0.0,
  38. int min_generations = -1
  39. */
  40. std::vector<std::vector<double>> update() override;
  41. Individual getBest();
  42. double evaluateFitness(const Individual& ind);
  43. };
  44. void OptimizerEvolutionary::evaluate(size_t ignore_len)
  45. {
  46. //calculate fitness
  47. for (auto it = _children.begin() + ignore_len; it != _children.end(); ++it)
  48. {
  49. for (size_t j = 0; j < _inputs.size(); j++)
  50. {
  51. //std::cout << "set: " << j << ": " << it->dna[j] << std::endl;
  52. _inputs[j]->setValue() = it->dna[j];
  53. }
  54. auto opt = updateOutputs();
  55. if (opt.module_state == state::STATE_ERROR) {
  56. _children.erase(it);
  57. }
  58. else {
  59. it->fitness = opt.opt_value;
  60. }
  61. }
  62. //find fitest
  63. double min = _children[0].fitness;
  64. for (size_t i = 1; i < _children.size(); i++)
  65. {
  66. if (min > _children[i].fitness) {
  67. min = _children[i].fitness;
  68. _best = _children[i];
  69. }
  70. }
  71. }
  72. OptimizerEvolutionary::OptimizerEvolutionary()
  73. :OptimizerBase(R"JSON(
  74. [{
  75. "name":"converges",
  76. "value": 0
  77. },{
  78. "name":"grow_generation",
  79. "value": 20
  80. },{
  81. "name":"max_fitness",
  82. "value": 0.0
  83. },{
  84. "name":"min_generations",
  85. "value": -1
  86. }])JSON")
  87. {
  88. //_module = module;
  89. _grow_generation = 0;
  90. _min_generations = 20;
  91. _max_fitness = 0.0;
  92. _converges = -1;
  93. }
  94. std::vector<std::vector<double>> OptimizerEvolutionary::update()
  95. {
  96. int gen = -1;
  97. bool check;
  98. Individual old_best;
  99. size_t same_counter = 0;
  100. if (_inputs.size() == 0)
  101. {
  102. std::cout << "ERROR: No optimizable inputs detected!" << std::endl;
  103. return std::vector<std::vector<double>>();
  104. }
  105. do
  106. {
  107. std::cout << _children.size() << " | " << gen << std::endl;
  108. if (_children.empty())
  109. {
  110. for (size_t i = 0; i < _grow_generation*2; i++)
  111. {
  112. _children.push_back(generateIndividual());
  113. }
  114. evaluate();
  115. }
  116. else {
  117. if (gen != -1)
  118. {
  119. evolve(_children);
  120. }
  121. else {
  122. evaluate();
  123. }
  124. }
  125. ++gen;
  126. check = gen < _min_generations || _best.fitness > _max_fitness;
  127. if (!check && _converges > 0)
  128. {
  129. if (_best == old_best)
  130. {
  131. ++same_counter;
  132. }
  133. else
  134. {
  135. old_best = _best;
  136. same_counter = 0;
  137. }
  138. if (same_counter < _converges)
  139. {
  140. check = true;
  141. }
  142. }
  143. } while (check);
  144. return _best.dna;
  145. }
  146. std::vector<double> OptimizerEvolutionary::mutateGene(std::shared_ptr<IInput> input, std::vector<double> seed)
  147. {
  148. limits limit = input->getLimits();
  149. auto ret = seed;
  150. if (!limit.elements.empty())
  151. {
  152. int i = (int)random_num(0, limit.elements.size() - 1);
  153. ret = limit.elements[i];
  154. return ret;
  155. }
  156. if (!limit.min.empty() && !limit.max.empty()) {
  157. bool check = true;
  158. do {
  159. if (!ret.empty())
  160. {
  161. int i = (int)random_num(0, limit.min.size() - 1);
  162. if (!limit.step.empty()) {
  163. //randomly generate step dx in [min, max]
  164. /*std::cout << limit["min"][i].get<double>() << " | ";
  165. std::cout << limit["max"][i].dump() << " | ";
  166. std::cout << limit["step"][i].dump() << " | ";*/
  167. ret[i] = random_num(limit.min[i], limit.max[i], limit.step[i]);
  168. }
  169. else {
  170. int m = (int)random_num(0, 1);
  171. if (m == 0)
  172. {
  173. ret[i] = limit.min[i];
  174. }
  175. else {
  176. ret[i] = limit.max[i];
  177. }
  178. }
  179. }
  180. else
  181. {
  182. for (size_t i = 0; i < limit.min.size(); i++)
  183. {
  184. if (!limit.step.empty()) {
  185. //randomly generate step dx in [min, max]
  186. ret.push_back(random_num(limit.min[i], limit.max[i], limit.step[i]));
  187. }
  188. else {
  189. int m = (int)random_num(0, 1);
  190. if (m == 0)
  191. {
  192. ret.push_back(limit.min[i]);
  193. }
  194. else {
  195. ret.push_back(limit.max[i]);
  196. }
  197. }
  198. }
  199. }
  200. if (!limit.rule.empty()) {
  201. //use rule to check
  202. exprtk::symbol_table<double> symbol_table;
  203. symbol_table.add_vector("val", ret);
  204. symbol_table.add_constants();
  205. exprtk::expression<double> func_expr;
  206. func_expr.register_symbol_table(symbol_table);
  207. exprtk::parser<double> parser;
  208. parser.compile(limit.rule, func_expr);
  209. check = (bool)func_expr.value();
  210. }
  211. } while (!check);
  212. return ret;
  213. }
  214. std::cout << "ERROR in GENE elements! (END)" << std::endl;
  215. return input->getValue();//ERROR
  216. }
  217. void OptimizerEvolutionary::evolve(std::vector<Individual> parents)
  218. {
  219. ////fittest should breed more
  220. //detect lower border
  221. double max = parents[0].fitness;
  222. for (size_t i = 1; i < parents.size(); i++)
  223. {
  224. if (max < parents[i].fitness) {
  225. max = parents[i].fitness;
  226. }
  227. }
  228. //detect lower border
  229. double sum = 0;
  230. for (size_t i = 0; i < parents.size(); i++)
  231. {
  232. sum += max - parents[i].fitness;
  233. }
  234. if (sum == 0)
  235. {
  236. sum = 1.0;
  237. }
  238. //multiply fitter parents
  239. std::vector<Individual> gen_pool = parents;
  240. for (size_t i = 0; i < parents.size(); i++)
  241. {
  242. int additional = std::round((max - parents[i].fitness) / sum * 20);
  243. //std::cout << additional << std::endl;
  244. for (size_t j = 1; j < additional; j++)
  245. {
  246. gen_pool.push_back(parents[i]);
  247. }
  248. }
  249. //fittest parents will also be new childrens
  250. _children.clear();
  251. double min = parents[0].fitness;
  252. for (size_t i = 1; i < parents.size(); i++)
  253. {
  254. if (max > parents[i].fitness) {
  255. min = parents[i].fitness;
  256. }
  257. }
  258. for (size_t i = 0; i < parents.size(); i++)
  259. {
  260. if (max == parents[i].fitness) {
  261. bool exist = false;
  262. for (size_t j = 0; j < _children.size(); j++)
  263. {
  264. if (_children[j].dna == parents[i].dna) {
  265. exist = true;
  266. break;
  267. }
  268. }
  269. if (!exist) {
  270. _children.push_back(parents[i]);
  271. }
  272. }
  273. }
  274. //breed
  275. size_t init_len = _children.size();
  276. for (size_t i = 0; i < _grow_generation; i++)
  277. {
  278. int p1 = (int)random_num(0, gen_pool.size() - 1);
  279. int p2 = (int)random_num(0, gen_pool.size() - 1);
  280. _children.push_back(combine(gen_pool[p1], gen_pool[p2]));
  281. }
  282. evaluate(init_len);
  283. }
  284. OptimizerEvolutionary::Individual OptimizerEvolutionary::combine(Individual par1, Individual par2)
  285. {
  286. size_t len = par1.dna.size();
  287. Individual child;
  288. for (size_t i = 0; i < len; i++)
  289. {
  290. double p = random_num(0.0, 100.0, 1.0);
  291. if (p<45.0)
  292. {
  293. child.dna.push_back(par1.dna[i]);
  294. }
  295. else if(p<90.0){
  296. child.dna.push_back(par2.dna[i]);
  297. }
  298. else
  299. {
  300. child.dna.push_back(mutateGene(_inputs[i]));
  301. }
  302. }
  303. return child;
  304. }
  305. OptimizerEvolutionary::Individual OptimizerEvolutionary::generateIndividual()
  306. {
  307. Individual ret;
  308. for (size_t i = 0; i < _inputs.size(); i++)
  309. {
  310. ret.dna.push_back(mutateGene(_inputs[i]));
  311. }
  312. return ret;
  313. }
  314. OptimizerEvolutionary::Individual OptimizerEvolutionary::getBest() {
  315. return _best;
  316. }
  317. double OptimizerEvolutionary::evaluateFitness(const Individual& ind) {
  318. for (size_t j = 0; j < _inputs.size(); j++)
  319. {
  320. _inputs[j]->setValue() = ind.dna[j];
  321. }
  322. auto opt = updateOutputs();
  323. return opt.opt_value;
  324. }
  325. }