Browse Source

Add a score to evaluate the use of variable in direction calculation

Yann Weber 5 years ago
parent
commit
6f004245f3
3 changed files with 82 additions and 48 deletions
  1. 15
    3
      gte/rpnlib.py
  2. 57
    42
      gte/turmit.py
  3. 10
    3
      gte/world.py

+ 15
- 3
gte/rpnlib.py View File

@@ -24,7 +24,10 @@ _var_list['r'] = 0
24 24
 _var_list['g'] = 0
25 25
 _var_list['b'] = 0
26 26
 
27
-def RpnOp(method):
27
+def RpnOpNoMod(method):
28
+    return RpnOp(method, True)
29
+
30
+def RpnOp(method, nomod = False):
28 31
     ''' @brief Decorator for RPN operation that autodetect argument count
29 32
         
30 33
         Autodetect argument count and pop them from the stack. Then attempt
@@ -36,13 +39,19 @@ def RpnOp(method):
36 39
     narg = len(inspect.signature(method).parameters)-1
37 40
     def wrapped(self):
38 41
         args = [ self._pop() for _ in range(narg) ]
42
+        determinist = True
43
+        if not nomod:
44
+            for arg in args:
45
+                if isinstance(arg, IntVar):
46
+                    determinist = False
47
+                    break
39 48
         args.reverse()
40 49
         try:
41 50
             res = method(self, *args)
42 51
         except ZeroDivisionError:
43 52
             res = None
44 53
         if res is None:
45
-            return None
54
+            return determinist
46 55
         try:
47 56
             for topush in res:
48 57
                 if not isinstance(topush, int):
@@ -55,7 +64,7 @@ def RpnOp(method):
55 64
                 raise ValueError('Turmit.%s() returned a list containing a\
56 65
 %s : %s' % (method.__name__, type(res), res))
57 66
             self._push(res)
58
-        return res
67
+        return determinist
59 68
     _op_list[method.__name__] = (method, wrapped)
60 69
     return wrapped
61 70
 
@@ -219,3 +228,6 @@ class RpnSymbol(object):
219 228
         ''' @return Random value '''
220 229
         return cls.random(cls.VALUE)
221 230
 
231
+
232
+class IntVar(int):
233
+    pass

+ 57
- 42
gte/turmit.py View File

@@ -74,20 +74,27 @@ class Turmit(object):
74 74
         if self._prog is None:
75 75
             self._prog = RpnExpr.random(self._prog_sz)
76 76
 
77
-        self.__expr_fun = lambda *args, **kwargs: (0,)
77
+        self._determin_score = 5
78
+
79
+        self.__expr_fun = lambda *args, **kwargs: (0, True, None)
78 80
 
79 81
     def __call__(self, **context):
80 82
         ''' @brief Exec the RPN expression and return the stack head
81 83
             @param context dict : dict with variable values (see @ref rpnlib._var_list)
82 84
             @return stack head after RPN
83 85
         '''
84
-        context = {k:int(context[k]) % self._max_int for k in context}
86
+        context = {k:IntVar(context[k]) % self._max_int for k in context}
85 87
 
86 88
         if self.__expr_fun is None:
87 89
             self._compile()
88 90
         ret = self.__expr_fun(self, **context)
89
-        if isinstance(ret, int):
91
+
92
+        determinist = ret[1]
93
+
94
+        if len(ret) == 2:
95
+            ret = ret[0]
90 96
             return ret
97
+        #if len(ret) == 3 -> returned a continuation address in RPN expr
91 98
 
92 99
         #self.__ip = 0
93 100
         self.__ip = ret[0]
@@ -97,14 +104,29 @@ class Turmit(object):
97 104
             if sym.optype == RpnSymbol.VALUE:
98 105
                 self._push(sym.value)
99 106
             elif sym.optype == RpnSymbol.VARIABLE:
100
-                self._push(context[sym.value.lower()])
107
+                self._push(IntVar(context[sym.value.lower()]))
101 108
             elif sym.optype == RpnSymbol.OPERATION:
102
-                getattr(self, sym.value.lower())()
109
+                op = getattr(self, sym.value.lower())
110
+                if determinist:
111
+                    if not op():
112
+                        determinist = False
113
+                else:
114
+                    op()
103 115
             self.__ip += 1
116
+
117
+        self._determin_score += 0 if determinist else 1
104 118
         return self.shead
105 119
 
106 120
     def _compile(self):
107
-        code = 'def expr_fun(self, x, y, r, g, b):\n'
121
+        code = '''def expr_fun(self, x, y, r, g, b):
122
+
123
+    determinist = True'''
124
+
125
+        op2_head = '''a = self._stack[self._cur]
126
+    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
127
+    if isinstance(a, IntVar) or isinstance(self._stack[self._cur], IntVar):
128
+        determinist = False
129
+'''
108 130
         for ip, sym in enumerate(self._prog):
109 131
             if sym.optype == RpnSymbol.VALUE:
110 132
                 code += '''
@@ -120,73 +142,65 @@ class Turmit(object):
120 142
 ''' % sym.value.lower()
121 143
             elif sym.value == 'add':
122 144
                 code += '''
123
-    a = self._stack[self._cur]
124
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
145
+    %s
125 146
     self._stack[self._cur] += a
126 147
     self._stack[self._cur] %= self._max_int
127
-'''
148
+''' % op2_head
128 149
             elif sym.value == 'sub':
129 150
                 code += '''
130
-    a = self._stack[self._cur]
131
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
151
+    %s
132 152
     self._stack[self._cur] = self._stack[self._cur] - a
133 153
     if self._stack[self._cur] < 0:
134 154
         self._stack[self._cur] += self._max_int
135
-'''
155
+''' % op2_head
136 156
             elif sym.value == 'mul':
137 157
                 code += '''
138
-    a = self._stack[self._cur]
139
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
158
+    %s
140 159
     self._stack[self._cur] *= a
141 160
     self._stack[self._cur] %= self._max_int
142
-'''
161
+''' % op2_head
143 162
             elif sym.value == 'div':
144 163
                 code += '''
145
-    a = self._stack[self._cur]
146
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
164
+    %s
147 165
     if a != 0:
148 166
         self._stack[self._cur] = self._stack[self._cur] // a
149
-'''
167
+''' % op2_head
150 168
             elif sym.value == 'mod':
151 169
                 code += '''
152
-    a = self._stack[self._cur]
153
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
170
+    %s
154 171
     if a != 0:
155 172
         self._stack[self._cur] = self._stack[self._cur] % a
156
-'''
173
+''' % op2_head
157 174
             elif sym.value == 'bin_and':
158 175
                 code += '''
159
-    a = self._stack[self._cur]
160
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
176
+    %s
161 177
     self._stack[self._cur] &= a
162
-'''
178
+''' % op2_head
163 179
             elif sym.value == 'bin_or':
164 180
                 code += '''
165
-    a = self._stack[self._cur]
166
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
181
+    %s
167 182
     self._stack[self._cur] |= a
168
-'''
183
+''' % op2_head
169 184
             elif sym.value == 'bin_xor':
170 185
                 code += '''
171
-    a = self._stack[self._cur]
172
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
186
+    %s
173 187
     self._stack[self._cur] ^= a
174
-'''
188
+''' % op2_head
175 189
             elif sym.value == 'lshift':
176 190
                 code += '''
177
-    a = self._stack[self._cur]
178
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
191
+    %s
179 192
     self._stack[self._cur] = (self._stack[self._cur] << a) % self._max_int
180
-'''
193
+''' % op2_head
181 194
             elif sym.value == 'rshift':
182 195
                 code += '''
183
-    a = self._stack[self._cur]
184
-    self._cur = (self._cur - 1) if self._cur > 0 else (len(self._stack) - 1)
196
+    %s
185 197
     self._stack[self._cur] = self._stack[self._cur] >> a
186
-'''
198
+''' % op2_head
187 199
             elif sym.value == 'dup':
188 200
                 code += '''
189 201
     a = self._stack[self._cur]
202
+    if isinstance(a, IntVar):
203
+        determinist = False
190 204
     self._cur += 1
191 205
     self._cur %= len(self._stack)
192 206
     self._stack[self._cur] = a
@@ -197,10 +211,10 @@ class Turmit(object):
197 211
 '''
198 212
             else:
199 213
                 code += '''
200
-    return (%d,)
214
+    return (%d,determinist, None)
201 215
 ''' % ip
202 216
         code += '''
203
-    return self._stack[self._cur]
217
+    return (self._stack[self._cur], determinist)
204 218
 '''
205 219
         g = {}
206 220
         l = {}
@@ -245,12 +259,13 @@ class Turmit(object):
245 259
             @param val int : integer to transform
246 260
             @return integer
247 261
         '''
262
+        intvar = isinstance(val, IntVar)
248 263
         val = int(val)
249 264
         if self._max_int is not None:
250 265
             val %= self._max_int
251 266
             if not self._signed_int and val < 0:
252 267
                 val = self._max_int - val
253
-        return val
268
+        return IntVar(val) if intvar else val
254 269
 
255 270
     @RpnOp
256 271
     def mem_sz(self, new_sz):
@@ -295,7 +310,7 @@ class Turmit(object):
295 310
         '''
296 311
         return a & b
297 312
 
298
-    @RpnOp
313
+    @RpnOpNoMod
299 314
     def dup(self, a):
300 315
         ''' @brief Duplicates stack head
301 316
             @param a int : value
@@ -359,14 +374,14 @@ class Turmit(object):
359 374
         '''
360 375
         return a ^ b
361 376
 
362
-    @RpnOp
377
+    @RpnOpNoMod
363 378
     def pop(self, a):
364 379
         ''' @brief Pops a, head of the stack
365 380
             @param a int : value
366 381
         '''
367 382
         pass
368 383
 
369
-    @RpnOp
384
+    @RpnOpNoMod
370 385
     def swp(self, a, b):
371 386
         ''' @brief Swap the two values on top of the stack
372 387
             @param a int : v1

+ 10
- 3
gte/world.py View File

@@ -39,15 +39,16 @@ def eval_prog(args):
39 39
     stop = time.time()
40 40
 
41 41
     score_dir = sum([t.dirvar() for t in turmits]) / len(turmits)
42
+    score_deter = sum([t.determinist() for t in turmits]) / len(turmits)
42 43
     score_fract = w.fractdim()
43
-    score = score_dir * score_fract
44
+    score = (score_dir * score_fract) * (score_deter * 0.2 + 0.8)
44 45
     sinfo = {'F':score_fract, 'D':score_dir}
45 46
     #score = sum([score_fract] + [score_dir] * 4) / 5
46 47
     if not args.quiet:
47 48
         tall = time.time() - startall
48
-        msg = 'G%d P%d R%d: %d steps scores %.3f:(D:%.3f,F:%.3f) in %.3fs (%dus per step)\t%s'
49
+        msg = 'G%d P%d R%d: %d steps scores %.3f:(D:%.3f,F:%.3f,Dtr:%.3f) in %.3fs (%dus per step)\t%s'
49 50
         msg %= (generation, progid, trynum, steps, score, score_dir,
50
-                score_fract, tall,
51
+                score_fract, score_deter, tall,
51 52
                 ((stop - start)*1000000)//steps//len(turmits),
52 53
                 str(prog))
53 54
         logger.info(msg)
@@ -243,6 +244,12 @@ class LivingTurmit(Turmit):
243 244
         self._dirvar_cnt -= 1
244 245
         self._steps += 1
245 246
 
247
+    def determinist(self):
248
+        ''' @brief Process a determinit score : determinist_expr / total expr
249
+            @return float in [0.0..1.0]
250
+        '''
251
+        return (self._determin_score + 1) / self._steps
252
+
246 253
     def dirvar(self):
247 254
         ''' @brief Process @ref _dirvar to return a direction variation
248 255
             score

Loading…
Cancel
Save