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.

__main__.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env python3
  2. import copy
  3. import random
  4. import multiprocessing
  5. try:
  6. import pyrpn
  7. except (ImportError, NameError) as e:
  8. print("Error importing pyrpn. Try to run make.",
  9. file=sys.stderr)
  10. raise e
  11. from PIL import Image
  12. from PIL.PngImagePlugin import PngImageFile, PngInfo
  13. import numpy as np
  14. from tqdm import tqdm
  15. from .ifs1 import IFS1
  16. from .ifs2 import IFS2
  17. from .ifs3 import IFS3
  18. from .ifs4 import IFS4
  19. from .ifs5 import IFS5
  20. from .shape_score import ShapeScore
  21. #steps = 1024**2
  22. steps=512**2
  23. #steps=1024**2
  24. #steps*=4
  25. #steps*=10
  26. #pool_sz = 30
  27. #best_sz = 6
  28. pool_sz = 32
  29. best_sz = 8
  30. n_mutation = 10
  31. outfile='/tmp/rpnifs2_%02d.png'
  32. outfile_grp='/tmp/rpnifs2_%02d_grp.png'
  33. #world = IFS1.get_world()
  34. #pool = [IFS1(init_sz=3, world=world) for _ in range(pool_sz)]
  35. #world = IFS2.get_world()
  36. #pool = [IFS2(init_sz=3, world=world) for _ in range(pool_sz)]
  37. #world = IFS3.get_world()
  38. #pool = [IFS3(init_sz=3, world=world) for _ in range(pool_sz)]
  39. #world = IFS4.get_world()
  40. #pool = [IFS4(init_sz=3, world=world) for _ in range(pool_sz)]
  41. world = IFS5.get_world()
  42. #pool = [IFS5(init_sz=3, world=world) for _ in range(pool_sz)]
  43. pool = [IFS5(init_sz=6, world=world) for _ in range(pool_sz)]
  44. print('POOL ready')
  45. def stepper(ifs):
  46. for _ in range(steps):
  47. ifs.step()
  48. return ifs
  49. def get_score(world):
  50. shapescore = ShapeScore(world, jobs=1)
  51. score = shapescore.score()
  52. return score, shapescore
  53. generation=0
  54. mp_pool = multiprocessing.Pool(2)
  55. while True:
  56. generation+=1
  57. print('='*78)
  58. print(' '*10 + 'GENERATION #%d' % generation)
  59. print('='*78)
  60. scores = []
  61. i=0
  62. #for ifs in pool:
  63. #for ifs in tqdm(pool, unit='ifs'):
  64. # ifs.raz_world()
  65. # #for _ in tqdm(range(steps), total=steps, unit_scale=True):
  66. # for _ in range(steps):
  67. # ifs.step()
  68. pool = [ifs for ifs in tqdm(mp_pool.imap(stepper, pool),
  69. total=len(pool),
  70. unit='ifs')]
  71. for i, (score,shapescore) in tqdm(enumerate(mp_pool.imap(get_score,
  72. [ifs._world for ifs in pool])),
  73. unit='ifs', total=len(pool)):
  74. ifs = pool[i]
  75. #score = ifs.score()
  76. scores.append((ifs, score))
  77. #print('%02d) %5.3f %s' % (i, score, ifs))
  78. print('%02d) %5.3f' % (i, score))
  79. im = Image.fromarray(ifs.get_image())
  80. im.save(outfile % i)
  81. shapescore.result_image(outfile_grp % i)
  82. im_png = PngImageFile(outfile % i)
  83. metadata = PngInfo()
  84. metadata.add_text('Score', '%5.3f' % score)
  85. metadata.add_text('Generation', '%04d' % generation)
  86. metadata.add_text('Pool_position', '%02d' % i)
  87. for key, text in ifs.expr_dict().items():
  88. metadata.add_text(key, text)
  89. im_png.save(outfile % i, pnginfo=metadata)
  90. # Selecting best
  91. scores = sorted(scores, key=lambda v: 0 if v[1] == np.nan else v[1],
  92. reverse=True)
  93. best = scores[:best_sz]
  94. for i, (ifs, score) in enumerate(best):
  95. print('%02d) %5.3f %s' % (i, score, ifs))
  96. # Saving best
  97. im = Image.fromarray(best[0][0].get_image())
  98. outfile_gen = '/tmp/gen_%03d.png'
  99. im.save(outfile_gen % generation)
  100. im_png = PngImageFile(outfile_gen % generation)
  101. metadata = PngInfo()
  102. metadata.add_text('Score', '%5.3f' % score)
  103. metadata.add_text('Generation', '%04d' % generation)
  104. metadata.add_text('Pool_position', '%02d' % 1)
  105. for key, text in ifs.expr_dict().items():
  106. metadata.add_text(key, text)
  107. im_png.save(outfile_gen % generation, pnginfo=metadata)
  108. # Mutating best
  109. pool = [b for b, _ in best]
  110. for ifs, _ in best:
  111. nmut_max = (pool_sz//best_sz)-1
  112. for nmut in range(nmut_max):
  113. # needs >= IFS5
  114. again = 0
  115. while True:
  116. # half random mutation and half mutation by adding two IFS
  117. if again > 5 or nmut < nmut_max / 2:
  118. new = copy.copy(ifs)
  119. new.mutation(n_mutation)
  120. else:
  121. new = ifs + random.choice(best)[0]
  122. for cur in pool:
  123. if cur - new == 0:
  124. break
  125. else:
  126. pool.append(new)
  127. break
  128. again += 1
  129. ###
  130. #new = copy.copy(ifs)
  131. #new.mutation(n_mutation)
  132. #pool.append(new)