evol_game_simu 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/evol_game_simu/version.rb +1 -1
- data/lib/evol_game_simu.rb +111 -89
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 03c47726493c14799f0496b0ab9f134ef1860d63c0d03d1fb443bd5da2d54e5e
|
4
|
+
data.tar.gz: 9f02d4c6bd3290f60323f586f53973741cc86d445522cee8a813b24a9b992bcc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d0430da58d375e8827f643075d1513e0bef90e1f7bcf119c492f4068fc1cc959416e149a756d99b9a80500372ccd9a6c5dfd7e411c750a5b88138e2cc86e634
|
7
|
+
data.tar.gz: 2e19d179aeeaea1174cfe1a2ec54619fb900722a2a9e4c4bff9c3cf388d7107873e480e4883b78a9416a93b15b4302a1f290575d57677c686576f30cbcc4ec92
|
data/Gemfile.lock
CHANGED
data/lib/evol_game_simu.rb
CHANGED
@@ -1,19 +1,27 @@
|
|
1
1
|
require "evol_game_simu/version"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
# now i say again
|
4
|
+
# this time, it was also very tempting to do mutation
|
5
|
+
# but then please remember this bug
|
6
|
+
# you mutate at posn x, somehow it mutates also at posn y
|
7
|
+
# it breaks your simulation
|
8
|
+
# you cannot even manually set the value in posn y back
|
9
|
+
# wow
|
10
|
+
|
11
|
+
$Cooperator = [0, [[0, [0, 0]]]].freeze
|
12
|
+
$Defector = [0, [[1, [0, 0]]]].freeze
|
13
|
+
$Titfortat = [0, [[0, [0, 1]],
|
14
|
+
[1, [0, 1]]]].freeze
|
7
15
|
def Cooperator()
|
8
|
-
$Cooperator
|
16
|
+
$Cooperator.clone
|
9
17
|
end
|
10
18
|
def Defector()
|
11
|
-
$Defector
|
19
|
+
$Defector.clone
|
12
20
|
end
|
13
21
|
def Titfortat()
|
14
|
-
$Titfortat
|
22
|
+
$Titfortat.clone
|
15
23
|
end
|
16
|
-
$PAY = [[[3,3],[0,4]],[[4,0],[1,1]]]
|
24
|
+
$PAY = [[[3,3],[0,4]],[[4,0],[1,1]]].freeze
|
17
25
|
$ACTION = 2
|
18
26
|
$DELTA = 0.9
|
19
27
|
$ROUNDS = 400
|
@@ -21,39 +29,37 @@ def generate_deltas(delta, rounds)
|
|
21
29
|
result = (0..rounds-1).to_a
|
22
30
|
result.map { |round| delta ** round }
|
23
31
|
end
|
24
|
-
$DELTAS = generate_deltas($DELTA, $ROUNDS)
|
32
|
+
$DELTAS = generate_deltas($DELTA, $ROUNDS).freeze
|
25
33
|
|
26
34
|
def sum(arr)
|
27
35
|
arr.reduce() { | total, n | total += n }
|
28
36
|
end
|
29
37
|
def interact(machine1,machine2,rounds)
|
30
38
|
result = []
|
31
|
-
|
32
|
-
|
33
|
-
states1, states2 = machine1[
|
39
|
+
current1, current2 = machine1[0],machine2[0]
|
40
|
+
(1..rounds).reduce(result) do | result |
|
41
|
+
states1, states2 = machine1[1], machine2[1]
|
34
42
|
cstate1, cstate2 = states1[current1], states2[current2]
|
35
43
|
action1,action2 = cstate1[0], cstate2[0]
|
36
44
|
dispatch1,dispatch2 = cstate1[1], cstate2[1]
|
37
|
-
|
45
|
+
current1, current2 = dispatch1[action2], dispatch2[action1]
|
38
46
|
result << $PAY[action1][action2]
|
39
47
|
end
|
40
|
-
machine1[1],machine2[1]=machine1[0],machine2[0]
|
41
48
|
result
|
42
49
|
end
|
43
50
|
def match_machines(machine1,machine2,rounds, deltas)
|
44
51
|
pay1, pay2 = 0, 0
|
52
|
+
current1, current2 = machine1[0], machine2[0]
|
45
53
|
for i in 0..rounds-1 do
|
46
|
-
|
47
|
-
states1, states2 = machine1[2], machine2[2]
|
54
|
+
states1, states2 = machine1[1], machine2[1]
|
48
55
|
cstate1, cstate2 = states1[current1], states2[current2]
|
49
56
|
action1,action2 = cstate1[0], cstate2[0]
|
50
57
|
dispatch1,dispatch2 = cstate1[1], cstate2[1]
|
51
|
-
|
58
|
+
current1,current2 = dispatch1[action2], dispatch2[action1]
|
52
59
|
p1,p2 = $PAY[action1][action2]
|
53
60
|
pay1 += p1*deltas[i]
|
54
61
|
pay2 += p2*deltas[i]
|
55
62
|
end
|
56
|
-
machine1[1], machine2[1] = machine1[0] , machine2[0]
|
57
63
|
return pay1.round(2), pay2.round(2)
|
58
64
|
end
|
59
65
|
def generate_dispatch(states)
|
@@ -65,96 +71,116 @@ end
|
|
65
71
|
def generate_machine(states)
|
66
72
|
init = rand(states)
|
67
73
|
m = Array.new(states) { generate_state(states) }
|
68
|
-
[init
|
69
|
-
|
70
|
-
|
71
|
-
def reset_machine(machine)
|
72
|
-
machine[1] = machine[0]
|
74
|
+
m = [init]+[m]
|
75
|
+
m.freeze
|
73
76
|
end
|
74
|
-
|
75
77
|
def mutate_init(machine)
|
76
|
-
|
77
|
-
newinit = rand(
|
78
|
+
init, ss = machine
|
79
|
+
newinit = rand(ss.length)
|
78
80
|
puts "initial state: #{machine[0]} -> #{newinit}"
|
79
|
-
|
80
|
-
|
81
|
+
new = [newinit] + [ss]
|
82
|
+
new.freeze
|
81
83
|
end
|
82
84
|
|
83
85
|
def mutate_action(machine)
|
84
|
-
states = machine
|
85
|
-
|
86
|
-
|
87
|
-
puts "state #{state}: change action #{machine[2][state][0]} -> #{newact}"
|
88
|
-
machine[2][state][0] = newact
|
89
|
-
return
|
90
|
-
end
|
91
|
-
|
92
|
-
def mutate_dispatch!(machine)
|
93
|
-
states = machine[2].length
|
94
|
-
state = rand(states)
|
95
|
-
reactto = rand($ACTION)
|
86
|
+
init, states = machine
|
87
|
+
ss = states.length
|
88
|
+
s = rand(ss)
|
96
89
|
newact = rand($ACTION)
|
97
|
-
puts "state #{
|
98
|
-
|
99
|
-
|
90
|
+
puts "state #{s}: change action #{machine[1][s][0]} -> #{newact}"
|
91
|
+
newss = []
|
92
|
+
for i in 0..ss-1 do
|
93
|
+
if i == s
|
94
|
+
newss << [newact, states[i][1].clone]
|
95
|
+
else
|
96
|
+
newss << states[i].clone
|
97
|
+
end
|
98
|
+
end
|
99
|
+
newss = [init] + [newss]
|
100
|
+
newss.freeze
|
100
101
|
end
|
101
102
|
|
102
103
|
def mutate_dispatch(machine)
|
103
|
-
|
104
|
-
|
104
|
+
init, states = machine
|
105
|
+
ss = states.length
|
106
|
+
s = rand(states.length)
|
105
107
|
reactto = rand($ACTION)
|
106
|
-
|
107
|
-
puts "state #{s}: change reaction to #{reactto} from #{machine[
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
act, disp = ss.dup[index].dup
|
108
|
+
newdispatch=rand(ss)
|
109
|
+
puts "state #{s}: change reaction to #{reactto} from #{machine[1][s][1][reactto]} -> #{newdispatch}"
|
110
|
+
newss = []
|
111
|
+
for i in 0..ss-1 do
|
112
|
+
if i == s
|
113
|
+
act, disp = states[i].clone
|
113
114
|
toc, tod = disp
|
114
115
|
if reactto == 0
|
115
|
-
toc =
|
116
|
+
toc = newdispatch
|
116
117
|
else
|
117
|
-
tod =
|
118
|
+
tod = newdispatch
|
118
119
|
end
|
119
|
-
|
120
|
+
newss << [act, [toc, tod]]
|
120
121
|
else
|
121
|
-
|
122
|
+
newss << states[i].clone
|
122
123
|
end
|
123
124
|
end
|
124
|
-
|
125
|
-
|
126
|
-
return
|
125
|
+
newss = [init] + [newss]
|
126
|
+
newss.freeze
|
127
127
|
end
|
128
128
|
|
129
|
-
|
130
129
|
def add_state(machine)
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
130
|
+
init, states = machine
|
131
|
+
ss = states.length
|
132
|
+
newss = ss + 1
|
133
|
+
newstate = generate_state(newss)
|
134
|
+
|
135
|
+
newstates = []
|
136
|
+
s = rand(ss)
|
135
137
|
moveendof = rand($ACTION)
|
136
|
-
puts "add new state at the end: state #{
|
137
|
-
|
138
|
-
|
138
|
+
puts "add new state at the end: state #{s}: reaction to #{moveendof} goes to the new state"
|
139
|
+
|
140
|
+
for i in 0..ss-1 do
|
141
|
+
if i == s
|
142
|
+
act, disp = states[i].clone
|
143
|
+
toc, tod = disp
|
144
|
+
if moveendof == 0
|
145
|
+
toc = newss - 1
|
146
|
+
else
|
147
|
+
tod = newss - 1
|
148
|
+
end
|
149
|
+
newstates << [act, [toc, tod]]
|
150
|
+
else
|
151
|
+
newstates << states[i].clone
|
152
|
+
end
|
153
|
+
end
|
154
|
+
newstates << newstate
|
155
|
+
newstates = [init] + [newstates]
|
156
|
+
newstates.freeze
|
139
157
|
end
|
140
158
|
def random_member(arr)
|
141
159
|
arr[rand(arr.length)]
|
142
160
|
end
|
143
161
|
def del_state(machine)
|
144
|
-
states = machine
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
for i in 0..states-1 do
|
150
|
-
dispatch = machine[2][i][1]
|
151
|
-
dispatch[0] = random_member(pos) if dispatch[0] == state
|
152
|
-
dispatch[1] = random_member(pos) if dispatch[1] == state
|
162
|
+
init, states = machine
|
163
|
+
ss = states.length
|
164
|
+
if ss == 1
|
165
|
+
puts "\n"
|
166
|
+
return machine.clone
|
153
167
|
end
|
154
|
-
|
168
|
+
pos = (0..ss-1).to_a
|
169
|
+
s = rand(ss)
|
170
|
+
pos.delete_at(s)
|
171
|
+
newss = []
|
172
|
+
for i in 0..ss-1 do
|
173
|
+
act, dispatch = states[i]
|
174
|
+
toc, tod = dispatch
|
175
|
+
toc = random_member(pos) if toc == s
|
176
|
+
tod = random_member(pos) if tod == s
|
177
|
+
newss << [act, [toc, tod]]
|
178
|
+
end
|
179
|
+
puts "delete state #{s}"
|
180
|
+
newss = [init] + [newss]
|
181
|
+
newss.freeze
|
155
182
|
end
|
156
|
-
def mutate_machine(machine
|
157
|
-
print("machine #{i}: ")
|
183
|
+
def mutate_machine(machine)
|
158
184
|
r = rand(5)
|
159
185
|
case r
|
160
186
|
when 0
|
@@ -172,7 +198,6 @@ end
|
|
172
198
|
def generate_population(n)
|
173
199
|
Array.new(n) { generate_machine(1) }
|
174
200
|
end
|
175
|
-
|
176
201
|
def match_population(p,n,rounds,deltas)
|
177
202
|
res = []
|
178
203
|
for i in (0..n-2).step(2) do
|
@@ -221,22 +246,19 @@ def throws(arr,s)
|
|
221
246
|
res
|
222
247
|
end
|
223
248
|
|
224
|
-
def regenerate(p,arr)
|
249
|
+
def regenerate!(p,arr)
|
225
250
|
subs = arr.map{|e| p[e]}
|
226
251
|
for i in 0..subs.length-1 do
|
227
252
|
p[i] = subs[i]
|
228
253
|
end
|
229
254
|
end
|
230
255
|
|
231
|
-
def mutate(p,n)
|
256
|
+
def mutate!(p,n)
|
232
257
|
for i in 0..n-1 do
|
233
|
-
mutate_machine(p[i]
|
258
|
+
p[i] = mutate_machine(p[i])
|
234
259
|
end
|
235
260
|
end
|
236
261
|
|
237
|
-
def reset(population)
|
238
|
-
population.map{ |machine| reset_machine(machine) }
|
239
|
-
end
|
240
262
|
$N = 100
|
241
263
|
$P = generate_population $N
|
242
264
|
def evolve(p,n,cycles,speed,mutation,rounds,deltas)
|
@@ -252,10 +274,10 @@ def evolve(p,n,cycles,speed,mutation,rounds,deltas)
|
|
252
274
|
a = accumulate(res)
|
253
275
|
t = throws(a, speed)
|
254
276
|
|
255
|
-
regenerate(p,t)
|
277
|
+
regenerate!(p,t)
|
256
278
|
p.shuffle!
|
257
|
-
mutate(p,mutation)
|
258
|
-
|
279
|
+
mutate!(p,mutation)
|
280
|
+
|
259
281
|
end
|
260
282
|
avg
|
261
283
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: evol_game_simu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- chi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|