evol_game_simu 0.1.0
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 +7 -0
- data/.gitignore +8 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +20 -0
- data/README.md +35 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/evol_game_simu.gemspec +38 -0
- data/lib/evol_game_simu/version.rb +3 -0
- data/lib/evol_game_simu.rb +261 -0
- metadata +83 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 2588ec65c185be992aa36f34b67a060441ea49f4bd9023f83dc62bc05426b49b
|
4
|
+
data.tar.gz: 7a032f2253c89cffdafbaba31119c7c62c480126892395b515b070bdea939c17
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '09c7ee65d021ccafb802df63f1ebf09c01fcba453f5415cb52e84874dd5d168b39af5ab9fda7bbb5db25c4ef3bf5452f513832ee851322df9fd0947e90cdfeee'
|
7
|
+
data.tar.gz: 664c4cb115a68560da1adce559da9a1cd20e3f978ca3dc1aca22062540bb377da2f208c6796f82315d88af8f9d8fcc39c092b83eebd617819391bc59f5a6b92e
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
evol_game_simu (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
rake (10.5.0)
|
10
|
+
|
11
|
+
PLATFORMS
|
12
|
+
ruby
|
13
|
+
|
14
|
+
DEPENDENCIES
|
15
|
+
bundler (~> 1.17)
|
16
|
+
evol_game_simu!
|
17
|
+
rake (~> 10.0)
|
18
|
+
|
19
|
+
BUNDLED WITH
|
20
|
+
1.17.3
|
data/README.md
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# EvolGameSimu
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/evol_game_simu`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'evol_game_simu'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install evol_game_simu
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/evol_game_simu.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "evol_game_simu"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "evol_game_simu/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "evol_game_simu"
|
8
|
+
spec.version = EvolGameSimu::VERSION
|
9
|
+
spec.authors = ["chi"]
|
10
|
+
spec.email = ["nguyenlinhchi09@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Simulation populations of agents playing games under evolutionary algorithm.}
|
13
|
+
spec.description = %q{.}
|
14
|
+
spec.homepage = "https://gitlab.com/ayaderaghul/simulation"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
20
|
+
|
21
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
22
|
+
else
|
23
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
24
|
+
"public gem pushes."
|
25
|
+
end
|
26
|
+
|
27
|
+
# Specify which files should be added to the gem when it is released.
|
28
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
29
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
30
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
31
|
+
end
|
32
|
+
spec.bindir = "exe"
|
33
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
34
|
+
spec.require_paths = ["lib"]
|
35
|
+
|
36
|
+
spec.add_development_dependency "bundler", "~> 1.17"
|
37
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
38
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
require "evol_game_simu/version"
|
2
|
+
|
3
|
+
$Cooperator = [0,0, [[0, [0, 0]]]]
|
4
|
+
$Defector = [0,0, [[1, [0, 0]]]]
|
5
|
+
$Titfortat = [0,0, [[0, [0, 1]],
|
6
|
+
[1, [0, 1]]]]
|
7
|
+
def Cooperator()
|
8
|
+
$Cooperator
|
9
|
+
end
|
10
|
+
def Defector()
|
11
|
+
$Defector
|
12
|
+
end
|
13
|
+
def Titfortat()
|
14
|
+
$Titfortat
|
15
|
+
end
|
16
|
+
$PAY = [[[3,3],[0,4]],[[4,0],[1,1]]]
|
17
|
+
$ACTION = 2
|
18
|
+
$DELTA = 0.9
|
19
|
+
$ROUNDS = 400
|
20
|
+
def generate_deltas(delta, rounds)
|
21
|
+
result = (0..rounds-1).to_a
|
22
|
+
result.map { |round| delta ** round }
|
23
|
+
end
|
24
|
+
$DELTAS = generate_deltas($DELTA, $ROUNDS)
|
25
|
+
|
26
|
+
def sum(arr)
|
27
|
+
arr.reduce() { | total, n | total += n }
|
28
|
+
end
|
29
|
+
def interact(machine1,machine2,rounds)
|
30
|
+
result = []
|
31
|
+
(1..rounds).reduce(result) do | result |
|
32
|
+
current1,current2 = machine1[1],machine2[1]
|
33
|
+
states1, states2 = machine1[2], machine2[2]
|
34
|
+
cstate1, cstate2 = states1[current1], states2[current2]
|
35
|
+
action1,action2 = cstate1[0], cstate2[0]
|
36
|
+
dispatch1,dispatch2 = cstate1[1], cstate2[1]
|
37
|
+
machine1[1],machine2[1] = dispatch1[action2], dispatch2[action1]
|
38
|
+
result << $PAY[action1][action2]
|
39
|
+
end
|
40
|
+
machine1[1],machine2[1]=machine1[0],machine2[0]
|
41
|
+
result
|
42
|
+
end
|
43
|
+
def match_machines(machine1,machine2,rounds, deltas)
|
44
|
+
pay1, pay2 = 0, 0
|
45
|
+
for i in 0..rounds-1 do
|
46
|
+
current1,current2 = machine1[1],machine2[1]
|
47
|
+
states1, states2 = machine1[2], machine2[2]
|
48
|
+
cstate1, cstate2 = states1[current1], states2[current2]
|
49
|
+
action1,action2 = cstate1[0], cstate2[0]
|
50
|
+
dispatch1,dispatch2 = cstate1[1], cstate2[1]
|
51
|
+
machine1[1],machine2[1] = dispatch1[action2], dispatch2[action1]
|
52
|
+
p1,p2 = $PAY[action1][action2]
|
53
|
+
pay1 += p1*deltas[i]
|
54
|
+
pay2 += p2*deltas[i]
|
55
|
+
end
|
56
|
+
machine1[1], machine2[1] = machine1[0] , machine2[0]
|
57
|
+
return pay1.round(2), pay2.round(2)
|
58
|
+
end
|
59
|
+
def generate_dispatch(states)
|
60
|
+
(0..$ACTION-1).map {|e| rand(states)}
|
61
|
+
end
|
62
|
+
def generate_state(states)
|
63
|
+
[] << rand($ACTION) << generate_dispatch(states)
|
64
|
+
end
|
65
|
+
def generate_machine(states)
|
66
|
+
init = rand(states)
|
67
|
+
m = Array.new(states) { generate_state(states) }
|
68
|
+
[init,init]+[m]
|
69
|
+
end
|
70
|
+
|
71
|
+
def reset_machine(machine)
|
72
|
+
machine[1] = machine[0]
|
73
|
+
end
|
74
|
+
|
75
|
+
def mutate_init(machine)
|
76
|
+
states = machine[2].length
|
77
|
+
newinit = rand(states)
|
78
|
+
puts "initial state: #{machine[0]} -> #{newinit}"
|
79
|
+
machine[0], machine[1] = newinit, newinit
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
def mutate_action(machine)
|
84
|
+
states = machine[2].length
|
85
|
+
state = rand(states)
|
86
|
+
newact = rand($ACTION)
|
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)
|
96
|
+
newact = rand($ACTION)
|
97
|
+
puts "state #{state}: change reaction to #{reactto} from #{machine[2][state][1][reactto]} -> #{newact}"
|
98
|
+
machine[2][state][1][reactto] = newact
|
99
|
+
return
|
100
|
+
end
|
101
|
+
|
102
|
+
def mutate_dispatch(machine)
|
103
|
+
i, c, ss = machine
|
104
|
+
s = rand(ss.length)
|
105
|
+
reactto = rand($ACTION)
|
106
|
+
newact=rand($ACTION)
|
107
|
+
puts "state #{s}: change reaction to #{reactto} from #{machine[2][s][1][reactto]} -> #{newact}"
|
108
|
+
|
109
|
+
b = []
|
110
|
+
for index in 0..ss.length-1 do
|
111
|
+
if index == s
|
112
|
+
act, disp = ss.dup[index].dup
|
113
|
+
toc, tod = disp
|
114
|
+
if reactto == 0
|
115
|
+
toc = newact
|
116
|
+
else
|
117
|
+
tod = newact
|
118
|
+
end
|
119
|
+
b << [act, [toc, tod]]
|
120
|
+
else
|
121
|
+
b << ss.dup[index].dup
|
122
|
+
end
|
123
|
+
end
|
124
|
+
b = [i,c]+[b]
|
125
|
+
machine = b
|
126
|
+
return
|
127
|
+
end
|
128
|
+
|
129
|
+
|
130
|
+
def add_state(machine)
|
131
|
+
newstates = machine[2].length + 1
|
132
|
+
newstate = generate_state(newstates)
|
133
|
+
machine[2] << newstate
|
134
|
+
oldstate = rand(newstates - 1)
|
135
|
+
moveendof = rand($ACTION)
|
136
|
+
puts "add new state at the end: state #{oldstate}: reaction to #{moveendof} goes to the new state"
|
137
|
+
machine[2][oldstate][1][rand($ACTION)] = machine[2].length - 1
|
138
|
+
return
|
139
|
+
end
|
140
|
+
def random_member(arr)
|
141
|
+
arr[rand(arr.length)]
|
142
|
+
end
|
143
|
+
def del_state(machine)
|
144
|
+
states = machine[2].length
|
145
|
+
return puts "\n" if states == 1
|
146
|
+
pos = (0..states-1).to_a
|
147
|
+
state = rand(states)
|
148
|
+
pos.delete_at(state)
|
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
|
153
|
+
end
|
154
|
+
puts "delete state #{state}"
|
155
|
+
end
|
156
|
+
def mutate_machine(machine,i)
|
157
|
+
print("machine #{i}: ")
|
158
|
+
r = rand(5)
|
159
|
+
case r
|
160
|
+
when 0
|
161
|
+
mutate_init(machine)
|
162
|
+
when 1
|
163
|
+
mutate_action(machine)
|
164
|
+
when 2
|
165
|
+
mutate_dispatch(machine)
|
166
|
+
when 3
|
167
|
+
add_state(machine)
|
168
|
+
when 4
|
169
|
+
del_state(machine)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
def generate_population(n)
|
173
|
+
Array.new(n) { generate_machine(1) }
|
174
|
+
end
|
175
|
+
|
176
|
+
def match_population(p,n,rounds,deltas)
|
177
|
+
res = []
|
178
|
+
for i in (0..n-2).step(2) do
|
179
|
+
a,b = p[i],p[i+1]
|
180
|
+
p1,p2 = match_machines(a,b,rounds,deltas)
|
181
|
+
res << p1 << p2
|
182
|
+
end
|
183
|
+
res
|
184
|
+
end
|
185
|
+
def accumulate(arr)
|
186
|
+
sofar = 0
|
187
|
+
arr.reduce([]) do | res, n |
|
188
|
+
sofar += n
|
189
|
+
res << sofar
|
190
|
+
res
|
191
|
+
end
|
192
|
+
end
|
193
|
+
def throw(arr)
|
194
|
+
m = arr.last
|
195
|
+
r = rand(m)
|
196
|
+
l = arr.length
|
197
|
+
for i in 0..l-1 do
|
198
|
+
e = arr[i]
|
199
|
+
if r < e
|
200
|
+
return i
|
201
|
+
end
|
202
|
+
end
|
203
|
+
rand(l)
|
204
|
+
end
|
205
|
+
|
206
|
+
def throws(arr,s)
|
207
|
+
m = arr.last
|
208
|
+
l = arr.length
|
209
|
+
res = []
|
210
|
+
for i in 0..s-1 do
|
211
|
+
r = rand(m)
|
212
|
+
for j in 0..l-1 do
|
213
|
+
e = arr[j]
|
214
|
+
if r < e
|
215
|
+
res << j
|
216
|
+
break
|
217
|
+
end
|
218
|
+
end
|
219
|
+
res << rand(l) if j == l-1
|
220
|
+
end
|
221
|
+
res
|
222
|
+
end
|
223
|
+
|
224
|
+
def regenerate(p,arr)
|
225
|
+
subs = arr.map{|e| p[e]}
|
226
|
+
for i in 0..subs.length-1 do
|
227
|
+
p[i] = subs[i]
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def mutate(p,n)
|
232
|
+
for i in 0..n-1 do
|
233
|
+
mutate_machine(p[i],i)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
def reset(population)
|
238
|
+
population.map{ |machine| reset_machine(machine) }
|
239
|
+
end
|
240
|
+
$N = 100
|
241
|
+
$P = generate_population $N
|
242
|
+
def evolve(p,n,cycles,speed,mutation,rounds,deltas)
|
243
|
+
avg = []
|
244
|
+
|
245
|
+
for i in 1..cycles do
|
246
|
+
|
247
|
+
puts "before match"
|
248
|
+
res = match_population p,n,rounds,deltas
|
249
|
+
|
250
|
+
avg << sum(res)/n
|
251
|
+
|
252
|
+
a = accumulate(res)
|
253
|
+
t = throws(a, speed)
|
254
|
+
|
255
|
+
regenerate(p,t)
|
256
|
+
p.shuffle!
|
257
|
+
mutate(p,mutation)
|
258
|
+
reset(p)
|
259
|
+
end
|
260
|
+
avg
|
261
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evol_game_simu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- chi
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-01-01 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.17'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.17'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
description: "."
|
42
|
+
email:
|
43
|
+
- nguyenlinhchi09@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- ".gitignore"
|
49
|
+
- Gemfile
|
50
|
+
- Gemfile.lock
|
51
|
+
- README.md
|
52
|
+
- Rakefile
|
53
|
+
- bin/console
|
54
|
+
- bin/setup
|
55
|
+
- evol_game_simu.gemspec
|
56
|
+
- lib/evol_game_simu.rb
|
57
|
+
- lib/evol_game_simu/version.rb
|
58
|
+
homepage: https://gitlab.com/ayaderaghul/simulation
|
59
|
+
licenses: []
|
60
|
+
metadata:
|
61
|
+
allowed_push_host: https://rubygems.org
|
62
|
+
homepage_uri: https://gitlab.com/ayaderaghul/simulation
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 2.7.6
|
80
|
+
signing_key:
|
81
|
+
specification_version: 4
|
82
|
+
summary: Simulation populations of agents playing games under evolutionary algorithm.
|
83
|
+
test_files: []
|