class Gen(): func = 0 param = () def __init__(self): super().__init__() self.func = random.randint(0,7) self.param = round(random.random()*2-1,2) def calc(self, value, mem): if self.func == 0: # push mem.append(value + self.param) return (None, 1) elif self.func == 1: # pop return (mem.pop() + self.param, 0) elif self.func == 2: # dup mem.append(mem[-1] + self.param) return (None, 0) elif self.func == 3: # add mem.append(mem.pop() + value + self.param) return (None, 1) elif self.func == 4: # del mem.append(mem.pop() - (value + self.param)) return (None, 1) elif self.func == 5: # mul mem.append(mem.pop() * (value + self.param)) return (None, 1) elif self.func == 6: # div mem.append(mem.pop() / (value + self.param)) return (None, 1) return (self.params, 0) def funcName(self, func): if self.func >= 0 and self.func <= 7: return [ 'push', 'pop', 'dup', 'add', 'del', 'mul', 'div', 'const'][func] return str(func) def __str__(self): return "%s:%s" % (self.funcName(self.func), str(self.param))
class Gen(): func = 0 param = () def __init__(self): super().__init__() self.func = random.randint(0,7) self.param = round(random.random()*2-1,2) def calc(self, values, mem): if self.func == 0: # pop return mem.pop() + self.param elif self.func == 1: # push mem.append(values.pop() + self.param) return None elif self.func == 2: # dup mem.append(mem[-1] + self.param) return None elif self.func == 3: # add mem.append(mem.pop() + values.pop() + self.param) return None elif self.func == 4: # del mem.append(mem.pop() - (values.pop() + self.param)) return None elif self.func == 5: # mul mem.append(mem.pop() * (values.pop() + self.param)) return None elif self.func == 6: # div mem.append(mem.pop() / (values.pop() + self.param)) return None return self.param def funcName(self, func): if self.func >= 0 and self.func <= 7: return [ 'pop', 'push', 'dup', 'add', 'del', 'mul', 'div', 'const'][func] return str(func) def __str__(self): return "%s:%s" % (self.funcName(self.func), str(self.param))
class Gen(): func = 0 param = () def __init__(self, func=None): super().__init__() if func is None: funcMap = [0,1,2,3,4,5,6,7,8,9,10,11] i = random.randint(0,len(funcMap)-1) func = funcMap[i] self.func = func self.param = round((random.random()-0.5)*10,2) def calc(self, values, mem): def getVal(): v = values[0] values[0:1]=[] return v if self.func == 0: # pop return mem.pop() elif self.func == 1: # push mem.append(getVal()) return None elif self.func == 2: # dup mem.append(mem[-1] + self.param) return None elif self.func == 3: # addVal mem.append(getVal() + self.param) return None elif self.func == 4: # delVal mem.append(getVal() + self.param) return None elif self.func == 5: # mulVal mem.append(getVal() * self.param) return None elif self.func == 6: # divVal mem.append(getVal() / self.param) return None elif self.func == 7: # addMem mem.append(self.param + mem.pop()) return None elif self.func == 8: # delMem mem.append(self.param - mem.pop()) return None elif self.func == 9: # mulMem mem.append(self.param * mem.pop()) return None elif self.func == 10: # divMem mem.append(self.param / mem.pop()) return None mem.append(self.param) return None def funcName(self, func): funcNames = ( 'pop', 'push', 'dup', 'addVal', 'delVal', 'mulVal', 'divVal', 'addMem', 'delMem', 'mulMem', 'divMem', 'const') if self.func >= 0 and self.func < len(funcNames): return funcNames[func] return str(func) def __str__(self): return "%s:%s" % (self.funcName(self.func), str(round(self.param,4)))
class Dnk: gen = [] level = 0 def __init__(self, genlen=10): super().__init__() self.gen = [ Gen(1), Gen(1) ] + [ Gen() for i in range(genlen-2) ] def copy(self, src): self.gen = src.gen def __mul__(self, other): divider = 2 def sel(): v = random.random()*(self.level + other.level) return v <=self.level mode = random.randint(0,3) minLen = min(len(self.gen), len(other.gen)) maxLen = max(len(self.gen), len(other.gen)) n = Dnk() if mode == 0: n.gen = [ self.gen[i] if sel() else other.gen[i] for i in range(minLen) ] elif mode == 1: n.gen = [ Gen() for i in range(minLen) ] for g in n.gen: g.param += round((random.random()-0.5)/divider,3) elif mode == 2: n.gen = [ self.gen[i-1] if i % 2 == 1 else other.gen[i] for i in range(minLen) ] for g in n.gen: g.param += round((random.random()-0.5)/divider,3) else: v = random.randint(0,1) n.gen = [ self.gen[i] if i % 2 == v else other.gen[-1-i] for i in range(minLen) ] for g in n.gen: g.param += round((random.random()-0.5)/divider,3) n.gen = n.gen + [ Gen() for i in range(minLen,maxLen) ] return n def calc(self, values): res = [] mem = [] varr = values.copy() i = 0 for g in self.gen: try: r = g.calc(varr, mem) i = i + 1 except: self.gen = self.gen[0:i] #raise break; if not r is None: res.append(r) return res def __str__(self): return '(' + ', '.join([ str(g) for g in self.gen ]) + '):'+str(round(self.level,2))
def calc(self, values): res = [] mem = [] varr = values.copy() i = 0 for g in self.gen: try: r = g.calc(varr, mem) i = i + 1 except: self.gen = self.gen[0:i] #raise break; if not r is None: res.append(r) return res
>>> a = Dnk() >>> b = Dnk() >>> c = a * b >>> print(a) (push:4.061, push:1.79, dup:-4.32, mulMem:3.6, push:-3.752, addVal:2.4, delVal:-1.863, delMem:4.06, delVal:-3.692, addMem:0.48):0 >>> print(b) (push:0.356, push:-4.8, pop:2.865, delVal:1.53, addMem:-2.853, mulVal:-1.6, const:-2.451, delVal:-2.53, divVal:4.424, delMem:-0.6):0 >>> print(c) (push:4.061, divVal:4.424, dup:-4.32, const:-2.451, push:-3.752, addMem:-2.853, delVal:-1.863, pop:2.865, delVal:-3.692, push:0.356):0 >>>
# def mixIts(its, needCount): half = needCount // 2 its[half:needCount] = [] nIts = [] l = min(len(its), half) ll = l // 2 for ii in range(half,needCount): i0 = random.randint(0,l-1) i1 = random.randint(0,l-1) d0 = its[i0] d1 = its[i1] nd = d0 * d1 mutate(nd) its.append(nd) # def mixIts2(its, needCount): half = needCount // 2 its[half:needCount] = [] nIts = [] l = min(len(its), half) ll = l // 2 for ii in range(half,needCount): i0 = random.randint(0,ll-1) i1 = random.randint(ll,l-1) d0 = its[i0] d1 = its[i1] nd = d0 * d1 mutate(nd) its.append(nd) # def mixIts3(its, needCount): half = needCount // 2 its[half:needCount] = [] nIts = [] l = min(len(its), half) ll = l // 4 for ii in range(half,needCount): i0 = random.randint(0,ll-1) i1 = random.randint(ll,ll*2-1) d0 = its[i0] d1 = its[i1] nd = d0 * d1 mutate(nd) its.append(nd)
def mutate(it): # listMix = [ (random.randint(0,len(it.gen)-1), random.randint(0,len(it.gen)-1)) for i in range(3) ] for i in listMix: it.gen[i[0]], it.gen[i[1]] = (it.gen[i[1]], it.gen[i[0]]) # , for i in [ random.randint(0,len(it.gen)-1) for i in range(3) ]: it.gen[i] = Gen() # for i in [ random.randint(0,len(it.gen)-1) for i in range(1) ]: it.gen[i].param = it.gen[i].param + (random.random()-0.5)*2
# dataLen = 6 # itCount = 100 # genLen = 80 # epochCount = 100 srcData = [ i+1 for i in range(dataLen) ] def getIts(dest = 0): its = [ Dnk(genLen) for i in range(itCount) ] res = [] for epoch in range(epochCount): nIts = [] maxAchiev = 0 for it in its: try: res = it.calc(srcData) achiev = len(res) if achiev == 0: it = None continue maxAchiev = max(maxAchiev, achiev) it.level = achiev nIts.append(it) except: # print('Died',it[0],sys.exc_info()[1]) it = None its = nIts l = len(its) if l<2: print("Low it's count:",l) break; # , its.sort(key = lambda it: -it.level) if maxAchiev >= dataLen: break; mixIts(its, itCount) for it in its[:]: if it.level<dest: its.remove(it) return its
def diffData(resData, srcData): # , if len(resData) != len(srcData): return None d = 0 for i in range(len(resData)): d = d + abs((len(resData)*30 - i) * (resData[i] - srcData[i])) return d
# bestCount = 30 # globCount = 30000 # , seekValue = 8000 its = [] while len(its)<bestCount: its = its + getIts(len(destData)) print('Its len', len(its)) # , printIts(its[0:1], srcData) its[bestCount:len(its)]=[] for glob in range(globCount): minD = None for it in its[:]: resData = it.calc(srcData) d = diffData(resData, destData) # , . if d is None: its.remove(it) continue # it.level = 100000 - d minD = d if minD is None else min(d, minD) its.sort(key = lambda it: -it.level) if glob % 100 == 0 or glob == globCount - 1: # , 100- print('glob', glob, ':', round(minD,3) if minD else 'None', len(its)) #, resData) if minD < seekValue: print('Break') break mixIts2(its, bestCount) # printIts(its[0:3], srcData)
... glob 2900 : 7067.129 18 glob 3000 : 4789.967 15 glob 3100 : 6791.239 17 glob 3200 : 6809.478 15 Break 16 0 (const:24.7735, addMem:1.7929, dup:39.1318, dup:-15.2363, mulVal:24.952, mulVal:4.7857, pop:14.4176, pop:19.8343, dup:-19.4728, pop:2.6658, dup:-14.8237, pop:6.7005, pop:1.3567, pop:-2.7399):97009.88 => [9.571, 24.952, 30.989, 35.638, 50.462, 65.698] 1 (const:24.7735, dup:-4.8988, dup:39.1318, dup:-4.3082, mulVal:24.952, mulVal:6.1096, pop:14.4176, pop:19.8343, dup:-19.4728, pop:2.6658, dup:-14.8237, pop:6.7005, pop:1.3567, pop:-2.7128):96761.03 => [12.219, 24.952, 35.226, 39.875, 54.698, 59.007] 2 (const:24.7735, addMem:1.7929, dup:39.1318, dup:-15.2363, mulVal:24.952, delVal:3.4959, pop:14.4176, pop:19.8343, dup:-19.4728, pop:2.6658, dup:-14.8237, pop:6.7005, pop:1.3567, pop:-2.7399):96276.27 => [5.496, 24.952, 30.989, 35.638, 50.462, 65.698] >>>
Source: https://habr.com/ru/post/346134/
All Articles