Fast IFS using RPN notation
python
c
x86-64
nasm
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.

rpn_mutate.c 7.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include "rpn_mutate.h"
  2. const rnd_t rnd_t_max = -1;
  3. rpn_mutation_params_t rpn_mutation_params_default = {
  4. .min_len = 3,
  5. .w_add = 1.25,
  6. .w_del = 1.0,
  7. .w_mut = 2.0,
  8. .w_mut_soft = 4.0,
  9. .w_add_elt = {1,1,1},
  10. .w_mut_elt={1,1,1},
  11. };
  12. int rpn_mutation_init_params(rpn_mutation_params_t *params)
  13. {
  14. float mut_weights[4] = {params->w_add, params->w_del,
  15. params->w_mut, params->w_mut_soft};
  16. if(rpnifs_fast_rnd_weights(4, mut_weights, params->_weights)<0)
  17. {
  18. return -1;
  19. }
  20. /*
  21. #ifdef DEBUG
  22. dprintf(2, "summed weights : %d %d %d %d\n",
  23. params->_weights[0],
  24. params->_weights[1],
  25. params->_weights[2],
  26. params->_weights[3]);
  27. #endif
  28. */
  29. /**@todo test this */
  30. if(rpnifs_fast_rnd_weights(3, params->w_add_elt,
  31. &(params->_weights[4])) < 0)
  32. {
  33. return -1;
  34. }
  35. if(rpnifs_fast_rnd_weights(3, params->w_mut_elt,
  36. &(params->_weights[7])) < 0)
  37. {
  38. return -1;
  39. }
  40. return 0;
  41. }
  42. int rpn_mutation(rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  43. {
  44. //_print_params(2, params);
  45. assert(toks->argc < rnd_t_max);
  46. if(toks->tokens_sz <= params->min_len)
  47. {
  48. return rpn_mutation_add(toks, params);
  49. }
  50. size_t choice;
  51. if(_rpn_random_choice(4, params->_weights, &choice) < 0)
  52. {
  53. return -1;
  54. }
  55. switch(choice)
  56. {
  57. case 0:
  58. return rpn_mutation_add(toks, params);
  59. case 1:
  60. return rpn_mutation_del(toks, params);
  61. case 2:
  62. return rpn_mutation_mut(toks, params);
  63. case 3:
  64. return rpn_mutation_mut_soft(toks, params);
  65. default:
  66. dprintf(2, "Random error that should never occurs");
  67. return -1;
  68. }
  69. }
  70. int rpn_mutation_add(rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  71. {
  72. rpn_token_t *new_toks, new_token;
  73. size_t position;
  74. if(toks->tokens_sz == 0)
  75. {
  76. position = 0;
  77. }
  78. else if(rpn_rand_limit(toks->tokens_sz, &position) < 0)
  79. {
  80. return -1;
  81. }
  82. if(rpn_random_token_type(&(new_token.type), &params->_weights[4]) < 0)
  83. {
  84. return -1;
  85. }
  86. if(rpn_mutation_random_token(&new_token, toks, params) < 0)
  87. {
  88. return -1;
  89. }
  90. toks->tokens_sz++;
  91. new_toks = realloc(toks->tokens, sizeof(rpn_token_t) * toks->tokens_sz);
  92. if(!new_toks)
  93. {
  94. toks->tokens_sz--;
  95. return -1;
  96. }
  97. toks->tokens = new_toks;
  98. if(position < toks->tokens_sz - 1)
  99. {
  100. memmove(&(toks->tokens[position+1]), &(toks->tokens[position]),
  101. sizeof(rpn_token_t) * ((toks->tokens_sz-1) - position));
  102. }
  103. memcpy(&toks->tokens[position], &new_token, sizeof(rpn_token_t));
  104. return 0;
  105. }
  106. int rpn_mutation_del(rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  107. {
  108. rpn_token_t *new_toks;
  109. size_t position;
  110. if(rpn_rand_limit(toks->tokens_sz-1, &position) < 0)
  111. {
  112. return -1;
  113. }
  114. if(position != toks->tokens_sz - 1)
  115. {
  116. memmove(&(toks->tokens[position]), &(toks->tokens[position+1]),
  117. sizeof(rpn_token_t) * ((toks->tokens_sz - 1) - position));
  118. }
  119. toks->tokens_sz--;
  120. new_toks = realloc(toks->tokens, sizeof(rpn_token_t) * toks->tokens_sz);
  121. if(!new_toks)
  122. {
  123. toks->tokens_sz = 0;
  124. toks->tokens = NULL;
  125. return -1;
  126. }
  127. toks->tokens = new_toks;
  128. return 0;
  129. }
  130. int rpn_mutation_mut(rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  131. {
  132. rpn_token_t *tok;
  133. size_t position;
  134. if(rpn_rand_limit(toks->tokens_sz-1, &position) < 0)
  135. {
  136. return -1;
  137. }
  138. tok = &toks->tokens[position];
  139. if(rpn_random_token_type(&(tok->type), &(params->_weights[7])) < 0)
  140. {
  141. return -1;
  142. }
  143. if(rpn_mutation_random_token(tok, toks, params) < 0)
  144. {
  145. return -1;
  146. }
  147. return 0;
  148. }
  149. int rpn_mutation_mut_soft(rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  150. {
  151. rpn_token_t *tok;
  152. size_t position;
  153. if(rpn_rand_limit(toks->tokens_sz-1, &position) < 0)
  154. {
  155. return -1;
  156. }
  157. tok = &(toks->tokens[position]);
  158. if(rpn_mutation_random_token(tok, toks, params) < 0)
  159. {
  160. return -1;
  161. }
  162. return 0;
  163. }
  164. int rpn_mutation_random_token(rpn_token_t *tok,
  165. rpn_tokenized_t *toks, rpn_mutation_params_t *params)
  166. {
  167. rnd_t rand;
  168. if(rpn_getrandom(&rand) < 0)
  169. {
  170. return -1;
  171. }
  172. unsigned char op_n;
  173. unsigned char *val;
  174. size_t left;
  175. switch(tok->type)
  176. {
  177. case RPN_op:
  178. op_n = rand / (rnd_t_max/RPN_OP_SZ);
  179. op_n %= RPN_OP_SZ;
  180. tok->op_n = op_n;
  181. tok->op = &(rpn_ops[op_n]);
  182. break;
  183. case RPN_arg:
  184. tok->arg_n = rand / (rnd_t_max/toks->argc);
  185. tok->arg_n %= toks->argc;
  186. break;
  187. case RPN_val:
  188. val =(unsigned char*)&(tok->value);
  189. left = sizeof(tok->value);
  190. do
  191. {
  192. ssize_t ret = getrandom(val, left, GRND_NONBLOCK);
  193. if(ret == -1)
  194. {
  195. if(errno == EAGAIN || errno == EINTR)
  196. {
  197. continue;
  198. }
  199. return -1;
  200. }
  201. left -= ret;
  202. val += ret;
  203. }while(left);
  204. break;
  205. default:
  206. dprintf(2, "Another random error that shouldn't occur\n");
  207. return -1;
  208. }
  209. return 0;
  210. }
  211. int rpn_random_token_type(rpn_token_type_t *type, rnd_t *weights)
  212. {
  213. const rpn_token_type_t types[3] = { RPN_op, RPN_arg, RPN_val };
  214. size_t choice;
  215. if(_rpn_random_choice(3, weights, &choice) < 0)
  216. {
  217. return -1;
  218. }
  219. *type = types[choice];
  220. return 0;
  221. }
  222. int rpn_getrandom(rnd_t *rand)
  223. {
  224. rnd_t seed;
  225. char *seed_ptr = (char*)&seed;
  226. size_t buflen = sizeof(seed);
  227. do
  228. {
  229. ssize_t ret = getrandom(seed_ptr, buflen, GRND_NONBLOCK);
  230. if(ret == -1)
  231. {
  232. if(errno == EAGAIN || errno == EINTR)
  233. {
  234. continue;
  235. }
  236. return -1;
  237. }
  238. buflen -= ret;
  239. seed_ptr += ret;
  240. }while(buflen);
  241. *rand = seed;
  242. return 0;
  243. }
  244. int rpnifs_fast_rnd_weights(size_t sz, const float *weights,
  245. rnd_t *fast_weights)
  246. {
  247. long double total = 0;
  248. for(size_t i=0; i<sz; i++)
  249. {
  250. if(weights[i] < 0)
  251. {
  252. errno = EDOM;
  253. return -1;
  254. }
  255. total += weights[i];
  256. }
  257. for(size_t i=0; i<sz; i++)
  258. {
  259. rnd_t w;
  260. if(total == 0)
  261. {
  262. w = (rnd_t)((rnd_t_max / sz)*(i+1));
  263. }
  264. else
  265. {
  266. w = ((((long double)weights[i]) * rnd_t_max)/total);
  267. if(i>0)
  268. {
  269. w += fast_weights[i-1];
  270. }
  271. }
  272. fast_weights[i] = w;
  273. }
  274. return 0;
  275. }
  276. int rpnifs_rnd_float(float range[2], float *res)
  277. {
  278. #if DEBUG
  279. if(range[0] >= range[1])
  280. {
  281. errno = EINVAL;
  282. return -1;
  283. }
  284. #endif
  285. const rnd_t mid = rnd_t_max / 2;
  286. rnd_t rand;
  287. short neg;
  288. if(rpn_getrandom(&rand) < 0) { return -1; }
  289. if(rand >= mid)
  290. {
  291. neg = 1;
  292. rand -= mid;
  293. }
  294. else
  295. {
  296. neg = 0;
  297. }
  298. *res = ((rand*(range[1]-range[0]))/mid) + range[0];
  299. *res *= neg?-1:1;
  300. return 0;
  301. }
  302. int _rpn_random_choice(size_t sz, rnd_t *weights, size_t *res)
  303. {
  304. if(weights)
  305. {
  306. rnd_t rand;
  307. if(rpn_getrandom(&rand) < 0) { return -1; }
  308. __rpn_random_choice(sz, weights, rand, res);
  309. return 0;
  310. }
  311. // unweighted choice
  312. rnd_t rand;
  313. unsigned long long div = rnd_t_max;
  314. div++;
  315. div /= sz;
  316. if(rpn_getrandom(&rand) < 0) { return -1; }
  317. *res = (rnd_t)(((unsigned long long)rand)/div);
  318. return 0;
  319. }
  320. void __rpn_random_choice(size_t sz, rnd_t *weights, rnd_t rand, size_t *res)
  321. {
  322. for(*res=0; *res<sz; (*res)++)
  323. {
  324. if(weights[*res] >= rand)
  325. {
  326. return;
  327. }
  328. }
  329. *res = sz-1;
  330. }
  331. int rpn_rand_limit(size_t max, size_t *res)
  332. {
  333. unsigned long int step = rnd_t_max / max;
  334. rnd_t rnd;
  335. if(rpn_getrandom(&rnd) < 0)
  336. {
  337. return -1;
  338. }
  339. for(*res=0; *res<max; (*res)++)
  340. {
  341. if(*res * step >= rnd)
  342. {
  343. return 0;
  344. }
  345. }
  346. //*res = max - 1;
  347. return 0;
  348. }
  349. void _print_params(int fd, rpn_mutation_params_t *params)
  350. {
  351. dprintf(fd, "Minlen = %ld w[add=%.2f del=%.2f mut=%.2f msf=%.2f]\n",
  352. params->min_len, params->w_add, params->w_del,
  353. params->w_mut, params->w_mut_soft);
  354. dprintf(fd, "w_add_elt [op=%.2f const=%.2f var=%.2f]\n",
  355. params->w_add_elt[0], params->w_add_elt[1],
  356. params->w_add_elt[2]);
  357. dprintf(fd, "w_mut_elt [op=%.2f const=%.2f var=%.2f]\n",
  358. params->w_mut_elt[0], params->w_mut_elt[1],
  359. params->w_mut_elt[2]);
  360. }