-
Notifications
You must be signed in to change notification settings - Fork 0
/
evolve.py
121 lines (96 loc) · 3.32 KB
/
evolve.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import random
class VM:
def __init__(self, program):
self.program = program
self.slots = {"A": 0, "B": 0, "C": 0, "D": 0, "E": 0, "F": 0}
def clear_memory(self):
self.slots = {"A": 0, "B": 0, "C": 0, "D": 0, "E": 0, "F": 0}
def execute_instruction(self, instr):
if instr.name == 'INC':
self.slots[instr.args[0]] += 1
elif instr.name == 'DEC':
self.slots[instr.args[0]] -= 1
elif instr.name == 'MUL':
self.slots[instr.args[0]] = int(self.slots[instr.args[0]]) * int(instr.args[1])
def run(self):
for e in self.program:
self.execute_instruction(e)
def mutate_program(self, argrange):
self.program[random.randrange(len(self.program))] = random_instruction(argrange)
class Instruction:
def __init__(self, instr, *instr_args):
self.name = instr
self.args = instr_args
def generate_random(self):
pass
# workfile = list(open("example.evm").readlines())
# workfile = [line.rstrip('\n') for line in workfile]
# workfile = [Instruction(instr.split(" ")[0], *instr.split(" ")[1:]) for instr in workfile]
# for instr in workfile:
# print(instr.name, instr.args)
# my_vm = VM(workfile)
# for instr in my_vm.program:
# my_vm.execute_instruction(instr)
# print(my_vm.slots)
# alright, so that works. let's evolve a program then.
# argrange is the limit of what an argument for an instruction can be
# we'll keep it low for now, eventually I suppose it'll be 255??
def random_instruction(argrange):
p = random.choice(['INC', 'DEC', 'MUL'])
r = random.choice(['A', 'B', 'C', 'D', 'E', 'F'])
if p == 'INC':
return Instruction('INC', r)
elif p == 'DEC':
return Instruction('DEC', r)
elif p == 'MUL':
return Instruction('MUL', r, random.randint(0, argrange))
def random_instructions(maxlength, argrange):
res = []
for _i in range(0, maxlength):
res.append(random_instruction(argrange))
return res
goal = {'A': 10, 'B': 20, 'C': 30, 'D': 40, 'E': 50, 'F': 60}
def old_fitness(goal, current):
keys = ['A', 'B', 'C', 'D', 'E', 'F']
return [goal[key] == current[key] for key in keys].count(True)
def fitness(goal, current):
keys = ['A', 'B', 'C', 'D', 'E', 'F']
return sum([abs(goal[key] - current[key]) for key in keys])
# adam = random_instructions(20, 20)
# my_vm = VM(adam)
# print(my_vm.slots)
# my_vm.run()
# print(my_vm.slots)
# print(fitness(goal, my_vm.slots))
# my_vm.mutate_program(20)
# my_vm.clear_memory()
# my_vm.run()
# print(my_vm.slots)
# my_vm.slots['A'] = 10
# print(my_vm.slots)
# print(fitness(goal, my_vm.slots))
def mutate_loop(n = 1_000_000, mutations = 1):
aux = VM(random_instructions(100,2))
aux.run()
res = VM(random_instructions(100,2))
for ns in range(n):
for ms in range(random.randrange(1,mutations + 1)):
res.mutate_program(10)
aux.program = res.program
aux.clear_memory()
aux.run()
aux_fit = fitness(goal, aux.slots)
res_fit = fitness(goal, res.slots)
#print(aux_fit, res_fit)
if fitness(goal, res.slots) == 0:
return fitness(goal, res.slots), res.slots
elif aux_fit < res_fit:
print(f"new fitness is {aux_fit}")
res.program = aux.program
res.clear_memory()
res.run()
elif aux_fit > res_fit:
pass
#print("fitness was worse")
return fitness(goal, res.slots), res.slots
print(mutate_loop(n = 50_000_000, mutations = 5))