Browse Source

Add subparser and image generator

Yann Weber 6 years ago
parent
commit
b5369a9a41
2 changed files with 120 additions and 99 deletions
  1. 112
    92
      gte/__main__.py
  2. 8
    7
      gte/world.py

+ 112
- 92
gte/__main__.py View File

@@ -1,124 +1,144 @@
1
+import os
2
+import os.path
1 3
 import argparse
2 4
 import logging
3 5
 import time
4 6
 import numpy as np
5 7
 from random import randint
6
-import os.path
8
+from multiprocessing import Pool
7 9
 
8 10
 logging.basicConfig(level=logging.INFO,
9 11
                     format="%(created)d %(asctime)s:%(module)s(%(lineno)d):%(levelname)s:%(message)s")
10
-logger = logging.getLogger(__name__)
12
+logger = logging.getLogger()
11 13
 logger.debug('Logger started')
12 14
 
13 15
 from . import turmit, rpnlib
14 16
 from .turmit import Turmit
15
-from .world import World, LivingTurmit
17
+from .world import World, LivingTurmit, eval_prog
16 18
 from .mutator import mutate
17 19
 
18 20
 parser = argparse.ArgumentParser(description='Genetic Turmit Evolver')
19 21
 
20
-parser.add_argument('--list-op', action='store_const', default=False,
21
-                    const=True)
22
-parser.add_argument('--list-var', action='store_const', default=False,
23
-                    const=True)
24
-parser.add_argument('--rand-sym', '-r', action='store_const', default=False,
25
-                    const=True)
22
+subparsers = parser.add_subparsers(help='sub-commands help')
23
+
24
+parser_evolve = subparsers.add_parser('evolve', help='evolving help')
26 25
 
27
-parser.add_argument('--steps', '-s', type=int, metavar='N', default=1024,
26
+parser_evolve.add_argument('--steps', '-s', type=int, metavar='N', default=1024,
28 27
                     help="Number of steps")
29 28
 
30
-parser.add_argument('--try', type=int, metavar='N', default=5)
29
+parser_evolve.add_argument('--repeat-eval', type=int, metavar='N', default=5)
30
+
31
+parser_evolve.add_argument('--world-height', '-y', type=int, metavar='HEIGHT',
32
+                           default=256)
33
+parser_evolve.add_argument('--world-width', '-x', type=int, metavar='WIDTH',
34
+                           default=256)
35
+
36
+parser_evolve.add_argument('--turmit-count', '-T', type=int, metavar='N',
37
+                           default=10)
38
+
39
+parser_evolve.add_argument('--pool-size', '-p', type=int, metavar='N',
40
+                           default=10)
31 41
 
32
-parser.add_argument('--world-height', '-y', type=int, metavar='HEIGHT',
33
-                    default=256)
34
-parser.add_argument('--world-width', '-x', type=int, metavar='WIDTH',
35
-                    default=256)
42
+parser_evolve.add_argument('--prog-size', type=int, metavar='SIZE',
43
+                           default=10)
36 44
 
37
-parser.add_argument('--turmit-count', '-T', type=int, metavar='N',
38
-                    default=10)
45
+parser_evolve.add_argument('--prog', '-P', type=str, metavar='EXPR',
46
+                           default=None)
39 47
 
40
-parser.add_argument('--pool-size', '-p', type=int, metavar='N',
41
-                    default=20)
48
+parser_evolve.add_argument('--threads', type=int, metavar='N',
49
+                           default=os.cpu_count())
42 50
 
43
-parser.add_argument('--prog-size', type=int, metavar='SIZE',
44
-                    default=10)
51
+parser_evolve.add_argument('--max-generation', '-G', type=int, metavar='N',
52
+                           default=0)
45 53
 
46
-parser.add_argument('--output-dir', '-O', type=str, metavar='PATH',
47
-                    default=None)
54
+parser_gen = subparsers.add_parser('generate', help='evolving help')
48 55
 
49
-parser.add_argument('--prog', '-P', type=str, metavar='EXPR',
50
-                    default=None)
56
+parser_gen.add_argument('--prog', '-P', type=str, default=None)
57
+parser_gen.add_argument('--output', '-o', type=str, default='gte.png')
58
+parser_gen.add_argument('--world-height', '-y', type=int, metavar='HEIGHT',
59
+                        default=256)
60
+parser_gen.add_argument('--world-width', '-x', type=int, metavar='WIDTH',
61
+                        default=256)
62
+parser_gen.add_argument('--turmit-count', '-T', type=int, metavar='N',
63
+                        default=10)
64
+parser_gen.add_argument('--steps', '-s', type=int, metavar='N',
65
+                        default=1024)
51 66
 
52
-parser.add_argument('--threads', type=int, metavar='N',
53
-                    default=4)
54 67
 
55 68
 args = parser.parse_args()
56 69
 
57
-if args.list_op:
58
-    for i,(op, desc) in enumerate(rpnlib._op_list.items()):
59
-        print('#%02X %7s%s' % (i, op.upper(), desc[0].__doc__))
60
-    exit(0)
61
-elif args.list_var:
62
-    print([op.upper() for op in rpnlib._op_list.keys()])
63
-    exit(0)
64
-elif args.rand_sym:
65
-    for _ in range(10):
66
-        print(rpnlib.RpnSymbol.random())
67
-    exit(0)
68
-
69
-w = World(args.world_height, args.world_width)
70
-
71
-if args.prog is None:
72
-    progs = [rpnlib.RpnExpr.random(args.prog_size)
73
-             for _ in range(args.pool_size)]
70
+if 'pool_size' in args:
71
+    # Evolver
72
+    if args.prog is None:
73
+        progs = [rpnlib.RpnExpr.random(args.prog_size)
74
+                 for _ in range(args.pool_size)]
75
+    else:
76
+        progs = [rpnlib.RpnExpr.from_string(args.prog)]
77
+        progs = [mutate(progs[0], force=True) for _ in range(args.pool_size-1)]
78
+
79
+    generation = 0
80
+
81
+    pool = Pool(args.threads)
82
+
83
+    while True:
84
+        if args.max_generation > 0 and generation >= args.max_generation:
85
+            exit(0)
86
+        scores = []
87
+        for i, prog in enumerate(progs):
88
+            logger.info('Gen#%d P%d: %s' % (generation, i, str(prog)))
89
+        genstart = time.time()
90
+        msg = 'Gen#%d Running %d eval with %d turmits and %d steps for each %d progs'
91
+        logger.info(msg % (generation, args.repeat_eval, args.turmit_count,
92
+                           args.steps, args.pool_size))
93
+
94
+        works = []
95
+        for pid, prog in enumerate(progs):
96
+            for i in range(args.repeat_eval):
97
+                works.append((pid, prog, i, args))
98
+        res = pool.map(eval_prog, works)
99
+        scores = [0 for _ in range(len(progs))]
100
+        for pid, score in res:
101
+            scores[pid] += score
102
+        scores = [(scores[i] / args.repeat_eval, progs[i])
103
+                  for i in range(len(progs))]
104
+
105
+        genstop = time.time()
106
+        logger.info('Generation evaluating ended in %.2fs' % (genstop - genstart))
107
+
108
+        scores = sorted(scores, key=lambda x: x[0], reverse=True)
109
+        for i, (score, prog) in enumerate(scores):
110
+            logger.debug('P%d %.3f : %s' % (i, score, str(prog)))
111
+
112
+        for score, prog in scores[:len(scores)//2]:
113
+            logger.info('Keeping %.3f : %s' % (score, str(prog)))
114
+
115
+        progs = [ prog for _, prog in scores[:len(scores)//2]]
116
+        for prog in list(progs):
117
+            progs.append(mutate(prog, force=True))
118
+            if len(progs) >= args.pool_size:
119
+                break
120
+        generation += 1
74 121
 else:
75
-    progs = [rpnlib.RpnExpr.from_string(args.prog)
76
-             for _ in range(args.pool_size)]
77
-
78
-generation = 0
79
-
80
-while True:
81
-    scores = []
82
-    logger.info('Generation %d' % generation)
83
-    genstart = time.time()
84
-    for i, prog in enumerate(progs):
85
-        
86
-        logger.debug('Running %s' % prog)
87
-        w.raz()
88
-        turmits = [LivingTurmit(world=w, prog=prog)
89
-                   for _ in range(args.turmit_count)]
90
-
91
-        start = time.time()
92
-        for step in range(args.steps):
93
-            for turmit in turmits:
94
-                turmit()
95
-        stop = time.time()
96
-
97
-        score = w.fractdim()
98
-        scores.append((score, prog))
99
-        msg = 'Prog %d/%d scores %.3f in %.2fs (%dus per step)'
100
-        msg %= (i, len(progs), score,
101
-                stop - start,
102
-                ((stop - start)*1000000)//args.steps)
103
-        logger.info(msg)
104
-        
105
-        if args.output_dir is not None:
106
-            filename = 'gte_G%04X_%02d.png' % (generation, i)
107
-            w.save(os.path.join(args.output_dir,filename))
108
-            logger.debug('Saved in %s' % filename)
109
-
110
-    genstop = time.time()
111
-    logger.info('Generation evaluating ended in %.2fs' % (genstop - genstart))
112
-
113
-    scores = sorted(scores, key=lambda x: x[0], reverse=True)
114
-    for score, prog in scores[:len(scores)//2]:
115
-        logger.info('Keeping %.3f : %s' % (score, str(prog)))
116
-
117
-    progs = [ prog for _, prog in scores[:len(scores)//2]]
118
-    for prog in list(progs):
119
-        progs.append(mutate(prog, force=True))
120
-        if len(progs) >= args.pool_size:
121
-            break
122
-    generation += 1
122
+    # Generate
123
+    w = World(args.world_height, args.world_width)
124
+    prog = rpnlib.RpnExpr.from_string(args.prog)
125
+    turmits = [LivingTurmit(world=w, prog=prog)
126
+               for _ in range(args.turmit_count)]
127
+    msg = 'Generating image for program %s with %d steps and %d turmits'
128
+    logger.info(msg % (str(prog), args.steps, args.turmit_count))
129
+    start = time.time()
130
+    for step in range(args.steps):
131
+        for turmit in turmits:
132
+            turmit()
133
+    stop = time.time()
134
+
135
+    msg = 'Fractdim %.3f after %d steps in %.2fs (%dus per step)'
136
+    msg %= (w.fractdim(), args.steps,
137
+            stop - start,
138
+            ((stop - start)*1000000)//args.steps)
139
+    logger.info(msg)
140
+
141
+    w.save(args.output)
142
+    logger.info('Image saved in %s' % args.output)
123 143
 
124 144
 exit(0)

+ 8
- 7
gte/world.py View File

@@ -3,19 +3,21 @@
3 3
 import colorsys
4 4
 import scipy.misc
5 5
 import logging
6
+import time
6 7
 import numpy as np
7 8
 from random import randint
8 9
 
9 10
 from .turmit import Turmit
10 11
 
11
-logger = logging.getLogger(__name__)
12
+logger = logging.getLogger()
12 13
 
13
-def eval_prog(prog, args):
14
+def eval_prog(args):
14 15
     ''' @brief Return an array of fractdim
15 16
         @param args : dirty argparser returned arguments
16 17
     '''
18
+    progid, prog, trynum, args = args
17 19
     w = World(args.world_height, args.world_width)
18
-    logger.debug('Running %s' % prog)
20
+    logger.debug('Running P%d run#%d %s' % (progid, trynum, prog))
19 21
     w.raz()
20 22
     turmits = [LivingTurmit(world=w, prog=prog)
21 23
                for _ in range(args.turmit_count)]
@@ -27,13 +29,12 @@ def eval_prog(prog, args):
27 29
     stop = time.time()
28 30
 
29 31
     score = w.fractdim()
30
-    scores.append(score)
31
-    msg = 'Prog %d/%d scores %.3f in %.2fs (%dus per step)'
32
-    msg %= (i, len(progs), score,
32
+    msg = 'P%d run#%d scores %.3f in %.2fs (%dus per step)'
33
+    msg %= (progid, trynum, score,
33 34
             stop - start,
34 35
             ((stop - start)*1000000)//args.steps)
35 36
     logger.info(msg)
36
-    return scores
37
+    return progid, score
37 38
 
38 39
 class World(object):
39 40
     ''' @brief A Turmit world. An array of dim == 2 with tuple(R,G,B) '''

Loading…
Cancel
Save