ga 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/Gemfile +1 -0
- data/examples/01bag.rb +3 -1
- data/examples/Makefile +17 -0
- data/examples/robot.rb +52 -163
- data/examples/robot_tester.cpp +150 -0
- data/examples/robot_tester.h +36 -0
- data/examples/test.cpp +35 -0
- data/lib/ga/version.rb +1 -1
- data/lib/ga/zoo.rb +32 -9
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2831b4e765ee161b47cbfd96efa977e635443047
|
4
|
+
data.tar.gz: '09022f90fcf17f9892e576534648b48f49703ab1'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5a0c7db9d6a018b65816060a1da1d9544da8fe3dbc44ef06174797abec42e50e407ecfa1ba115b0763b0cb95ac6812df91ac34d2ecd7ae5a2562db539e4bc34
|
7
|
+
data.tar.gz: 335144415a50aef9a3afa65dfc5e71dbc3e67d0a4bc69592940c43357be95470f60c03706eb985f6dec145c07dc49b546761ca0cc6fd7a2a787170ca26326a46
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/examples/01bag.rb
CHANGED
@@ -82,7 +82,9 @@ Benchmark.bm do |x|
|
|
82
82
|
x.report('a') do
|
83
83
|
puts 'start'
|
84
84
|
100.times do
|
85
|
-
|
85
|
+
ga = Unit.new_ga_zoo
|
86
|
+
ga.elite_policy!
|
87
|
+
units = ga.evolve(20, 100, 0.8, 0.15)
|
86
88
|
unit = units.max
|
87
89
|
print unit.inspect + "\r"
|
88
90
|
r[unit.fitness] ||= 0
|
data/examples/Makefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
test: clean test.o robot_tester.o
|
3
|
+
g++ -o test test.o robot_tester.o
|
4
|
+
./test
|
5
|
+
|
6
|
+
sharedlib: clean robot_tester.o
|
7
|
+
g++ -shared -Wall -o librt.so robot_tester.o
|
8
|
+
|
9
|
+
clean:
|
10
|
+
rm -f *.o *.so test
|
11
|
+
|
12
|
+
robot_tester.o: robot_tester.cpp
|
13
|
+
g++ -Wall -c robot_tester.cpp
|
14
|
+
|
15
|
+
test.o: test.cpp
|
16
|
+
g++ -c test.cpp
|
17
|
+
|
data/examples/robot.rb
CHANGED
@@ -1,81 +1,35 @@
|
|
1
|
-
require 'bundler/setup'
|
2
1
|
require 'ga'
|
3
|
-
|
2
|
+
require 'pry'
|
4
3
|
require 'parallel'
|
4
|
+
require 'ffi'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
# 0 empty 1 dust 2 wall
|
10
|
-
# [x][y]
|
11
|
-
def new_map
|
12
|
-
MAP_SIZE.times.map { [0] * MAP_SIZE }
|
13
|
-
end
|
14
|
-
|
15
|
-
def rand_map(map, dust_rate = 0.5)
|
16
|
-
map.each do |cols|
|
17
|
-
cols.length.times {|i| cols[i] = rand() <= dust_rate ? 1 : 0 }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def show_map(map, bx = nil, by = nil)
|
22
|
-
puts('-' * 20)
|
23
|
-
MAP_SIZE.times do |y|
|
24
|
-
MAP_SIZE.times do |x|
|
25
|
-
if bx == x and by == y then
|
26
|
-
print(map[x][y], '* ')
|
27
|
-
else
|
28
|
-
print(map[x][y], ' ')
|
29
|
-
end
|
30
|
-
end
|
31
|
-
print("\n")
|
32
|
-
end
|
33
|
-
puts('-' * 20)
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
# 0 random move
|
38
|
-
# 9 clear
|
39
|
-
# 1 2 3
|
40
|
-
# 4 5
|
41
|
-
# 6 7 8
|
42
|
-
ACTIONS_DATA = {
|
43
|
-
0 => nil,
|
44
|
-
9 => nil,
|
45
|
-
|
46
|
-
# 1 => [-1, -1],
|
47
|
-
2 => [0, -1],
|
48
|
-
# 3 => [1, -1],
|
49
|
-
|
50
|
-
4 => [-1, 0],
|
51
|
-
# 5 => [1, 0],
|
6
|
+
system 'make sharedlib'
|
52
7
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
8
|
+
# env:
|
9
|
+
# '12001'
|
10
|
+
# 1
|
11
|
+
# 2 3 4
|
12
|
+
# 5
|
57
13
|
|
58
|
-
|
59
|
-
|
14
|
+
# actions:
|
15
|
+
# 1
|
16
|
+
# 2 3
|
17
|
+
# 4
|
18
|
+
# 1 2 3 4 move
|
19
|
+
# 0 rand move
|
20
|
+
# 5 clean
|
21
|
+
ACTIONS = [0, 1, 2, 3, 4, 5]
|
60
22
|
|
61
23
|
class Robot
|
62
24
|
include GA
|
63
25
|
|
64
|
-
# genome
|
65
|
-
#
|
66
26
|
# {env => action}
|
67
|
-
#
|
68
|
-
# env: '10122'
|
69
|
-
# 1
|
70
|
-
# 2 3 4
|
71
|
-
# 5
|
72
|
-
# action:
|
73
|
-
|
74
27
|
attr_accessor :genome, :fitness
|
75
|
-
|
28
|
+
TOTAL_TEST_TIMES = 100
|
76
29
|
|
77
30
|
def self.random_new
|
78
|
-
|
31
|
+
genome = {}
|
32
|
+
self.new(genome)
|
79
33
|
end
|
80
34
|
|
81
35
|
def initialize(genome)
|
@@ -83,37 +37,22 @@ class Robot
|
|
83
37
|
end
|
84
38
|
|
85
39
|
def fitness
|
86
|
-
|
87
|
-
@fitness ||= TOTAL_VALUE_TEST.times.map { tester.test }.reduce(&:+) / TOTAL_VALUE_TEST
|
88
|
-
end
|
89
|
-
|
90
|
-
def <=>(target)
|
91
|
-
fitness <=> target.fitness
|
40
|
+
@fitness ||= RobotTester.test(TOTAL_TEST_TIMES, 200, self)
|
92
41
|
end
|
93
42
|
|
94
43
|
def analyse_env(env)
|
95
|
-
@genome[env] ||=
|
96
|
-
9
|
97
|
-
elsif env == '00000' then
|
98
|
-
0
|
99
|
-
else
|
100
|
-
MOVE_ACTIONS.sample
|
101
|
-
end
|
44
|
+
@genome[env] ||= ACTIONS.sample
|
102
45
|
end
|
103
46
|
|
104
47
|
def cross!(target)
|
105
48
|
all_genome = (genome.keys + target.genome.keys).uniq
|
106
49
|
len = all_genome.length
|
107
|
-
min_robot = [self, target].min
|
108
50
|
|
109
|
-
rand(len).times do
|
51
|
+
(len / 4 + rand(len / 4)).times do
|
110
52
|
gene = all_genome[rand(len)]
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
else
|
115
|
-
genome[gene], target.genome[gene] = target.genome[gene], genome[gene]
|
116
|
-
end
|
53
|
+
genome[gene] ||= ACTIONS.sample
|
54
|
+
target.genome[gene] ||= ACTIONS.sample
|
55
|
+
genome[gene], target.genome[gene] = target.genome[gene], genome[gene]
|
117
56
|
end
|
118
57
|
end
|
119
58
|
|
@@ -121,94 +60,43 @@ class Robot
|
|
121
60
|
all_genome = genome.keys
|
122
61
|
len = all_genome.length
|
123
62
|
|
124
|
-
(rand(len
|
63
|
+
(len / 4 + rand(len / 2)).times do
|
125
64
|
gene = all_genome[rand(len)]
|
126
|
-
genome[gene] = ACTIONS.sample
|
65
|
+
genome[gene] = (ACTIONS - [genome[gene]]).sample
|
127
66
|
end
|
128
67
|
end
|
129
68
|
end
|
130
69
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
def initialize(robot)
|
135
|
-
@map = new_map
|
136
|
-
@robot = robot
|
137
|
-
end
|
70
|
+
module RobotTester
|
71
|
+
extend FFI::Library
|
138
72
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
y = rand(map.length)
|
143
|
-
@total_value = 0
|
144
|
-
|
145
|
-
step.times do
|
146
|
-
env = scan_env(x, y)
|
147
|
-
action = robot.analyse_env(env)
|
148
|
-
rx, ry = execute_action(x, y, action)
|
149
|
-
|
150
|
-
x += rx
|
151
|
-
y += ry
|
152
|
-
|
153
|
-
if x < 0 or y < 0 or x >= MAP_SIZE or y >= MAP_SIZE then
|
154
|
-
x -= rx
|
155
|
-
y -= ry
|
156
|
-
@total_value -= 10
|
157
|
-
elsif map[x][y] == 1
|
158
|
-
@total_value += 1
|
159
|
-
end
|
160
|
-
|
161
|
-
if show then
|
162
|
-
show_map(map, x, y)
|
163
|
-
sleep 0.2
|
164
|
-
end
|
165
|
-
end
|
73
|
+
ffi_lib File.expand_path('../librt.so', __FILE__)
|
74
|
+
callback :analyse_cb, [:string], :int
|
75
|
+
attach_function :robot_test, [:int, :int, :pointer, :pointer, :int, :analyse_cb], :int
|
166
76
|
|
167
|
-
|
168
|
-
|
77
|
+
def self.test(times, step, robot)
|
78
|
+
genome = robot.genome
|
79
|
+
len = genome.length
|
80
|
+
env_pointer = FFI::MemoryPointer.new(:pointer, len)
|
81
|
+
action_pointer = FFI::MemoryPointer.new(:int, len)
|
169
82
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
if map[x][y] == 1 then
|
174
|
-
map[x][y] = 0
|
175
|
-
@total_value += 10
|
176
|
-
else
|
177
|
-
@total_value -= 10
|
178
|
-
end
|
179
|
-
|
180
|
-
[0, 0]
|
181
|
-
when 0 then
|
182
|
-
@total_value -= 1
|
183
|
-
ACTIONS_DATA[MOVE_ACTIONS.sample]
|
184
|
-
else
|
185
|
-
@total_value -= 1
|
186
|
-
ACTIONS_DATA[action]
|
187
|
-
end
|
188
|
-
end
|
83
|
+
eps = genome.keys.map {|k| FFI::MemoryPointer.from_string(k) }
|
84
|
+
env_pointer.write_array_of_pointer eps
|
85
|
+
action_pointer.write_array_of_int genome.values
|
189
86
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
rx = x + sx
|
196
|
-
ry = y + sy
|
197
|
-
|
198
|
-
if rx < 0 || ry < 0 || rx >= MAP_SIZE || ry >= MAP_SIZE then
|
199
|
-
2
|
200
|
-
else
|
201
|
-
map[rx][ry]
|
202
|
-
end
|
203
|
-
end.join
|
87
|
+
robot_test(
|
88
|
+
times, step,
|
89
|
+
env_pointer, action_pointer, len,
|
90
|
+
robot.method(:analyse_env)
|
91
|
+
)
|
204
92
|
end
|
205
93
|
end
|
206
94
|
|
207
|
-
|
208
95
|
ga_zoo = Robot.new_ga_zoo
|
209
96
|
ga_zoo.debug!
|
97
|
+
# ga_zoo.cataclysm(10, 1)
|
210
98
|
|
211
|
-
ga_zoo.before_init_fitness do |units|
|
99
|
+
ga_zoo.before_init_fitness do |units, generation|
|
212
100
|
vs = Parallel.map(units, in_processes: 8) do |unit|
|
213
101
|
[unit.fitness, unit.genome]
|
214
102
|
end
|
@@ -217,13 +105,14 @@ ga_zoo.before_init_fitness do |units|
|
|
217
105
|
end
|
218
106
|
end
|
219
107
|
|
220
|
-
|
108
|
+
srand(Time.now.to_i)
|
109
|
+
robots = ga_zoo.evolve(200, 1000, 0.9, 0.2)
|
221
110
|
robot = robots.max
|
222
111
|
|
223
|
-
RobotTester.new(robot).test(100, true)
|
224
|
-
|
225
112
|
puts "========= result ============="
|
226
113
|
puts "fitness: #{robot.fitness}"
|
227
114
|
puts robot.genome
|
228
|
-
|
115
|
+
puts "score: %i" % RobotTester.test(1, 200, robot)
|
116
|
+
binding.pry
|
117
|
+
puts 'end'
|
229
118
|
|
@@ -0,0 +1,150 @@
|
|
1
|
+
#include "robot_tester.h"
|
2
|
+
|
3
|
+
#include <cstdio>
|
4
|
+
#include <cstdlib>
|
5
|
+
#include <ctime>
|
6
|
+
#include <unistd.h>
|
7
|
+
|
8
|
+
RobotTester::RobotTester(int map_size, env_map* p_em) {
|
9
|
+
size = map_size;
|
10
|
+
p_env_action = p_em;
|
11
|
+
map = new int*[size];
|
12
|
+
x = 0; y = 0;
|
13
|
+
for (int i = 0; i < size; i++) {
|
14
|
+
map[i] = new int[size];
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
RobotTester::~RobotTester() {
|
19
|
+
for (int i = 0; i < size; i++) {
|
20
|
+
delete map[i];
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
int RobotTester::test(int step, analyse_callback cb, bool play = false) {
|
25
|
+
int score = 0;
|
26
|
+
char env[6] = {0, 0, 0, 0, 0, 0};
|
27
|
+
int action;
|
28
|
+
env_map::iterator em_itor;
|
29
|
+
x = 0; y = 0;
|
30
|
+
|
31
|
+
rand_map();
|
32
|
+
|
33
|
+
for (int i = 0; i < step; i++) {
|
34
|
+
scan_env(env);
|
35
|
+
em_itor = p_env_action->find(env);
|
36
|
+
if (em_itor != p_env_action->end()) {
|
37
|
+
action = em_itor->second;
|
38
|
+
} else {
|
39
|
+
action = cb(env);
|
40
|
+
p_env_action->insert(env_map::value_type(env, action));
|
41
|
+
}
|
42
|
+
|
43
|
+
score = score + execute_action(action == 0 ? (rand() % 4 + 1) : action);
|
44
|
+
if (play) {
|
45
|
+
show_map();
|
46
|
+
usleep(100 * 1000);
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
return score;
|
51
|
+
}
|
52
|
+
|
53
|
+
void RobotTester::rand_map() {
|
54
|
+
for (int i = 0; i < size; i++) {
|
55
|
+
for (int j = 0; j < size; j++) {
|
56
|
+
map[i][j] = rand() % 2;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
const int scan_len = 5;
|
62
|
+
const int scan_points[scan_len][2] = {
|
63
|
+
{0, -1},
|
64
|
+
{-1, 0}, {0, 0}, {1, 0},
|
65
|
+
{0, 1}
|
66
|
+
};
|
67
|
+
void RobotTester::scan_env(char* env) {
|
68
|
+
int sx, sy;
|
69
|
+
for (int i = 0; i < scan_len; i++) {
|
70
|
+
sx = x + scan_points[i][0];
|
71
|
+
sy = y + scan_points[i][1];
|
72
|
+
|
73
|
+
if (sx < 0 || sx >= size || sy < 0 || sy >= size) {
|
74
|
+
env[i] = '2';
|
75
|
+
continue;
|
76
|
+
}
|
77
|
+
env[i] = char(map[sx][sy] + 48);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
void RobotTester::show_map() {
|
82
|
+
for (int i = 0; i < size; i++) {
|
83
|
+
for (int j = 0; j < size; j++) {
|
84
|
+
printf(" %i%c", map[j][i], (x == j and y == i) ? '*' : ' ');
|
85
|
+
}
|
86
|
+
printf("\n");
|
87
|
+
}
|
88
|
+
printf("\n");
|
89
|
+
}
|
90
|
+
|
91
|
+
// 1 2 3 4 move
|
92
|
+
// 5 take
|
93
|
+
// 1
|
94
|
+
// 2 5 3
|
95
|
+
// 4
|
96
|
+
const int actions[5][2] = {
|
97
|
+
{0, 0}, {0, -1}, {-1, 0}, {1, 0}, {0, 1}
|
98
|
+
};
|
99
|
+
int RobotTester::execute_action(int action) {
|
100
|
+
switch(action) {
|
101
|
+
case 5: {
|
102
|
+
if (map[x][y] == 1) {
|
103
|
+
map[x][y] = 0;
|
104
|
+
return 10;
|
105
|
+
} else {
|
106
|
+
return -1;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
case 1:
|
110
|
+
case 2:
|
111
|
+
case 3:
|
112
|
+
case 4: {
|
113
|
+
int mx = x + actions[action][0];
|
114
|
+
int my = y + actions[action][1];
|
115
|
+
if (mx < 0 || mx >= size || my < 0 || my >= size) {
|
116
|
+
return -5;
|
117
|
+
} else {
|
118
|
+
x = mx; y = my;
|
119
|
+
return 0;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
default:
|
123
|
+
printf("Invalid action %i\n", action);
|
124
|
+
throw("Invalid action\n");
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
typedef std::unordered_map<std::string, short> env_map;
|
129
|
+
|
130
|
+
|
131
|
+
extern "C" {
|
132
|
+
int robot_test(int times, int step, char** envs, short* actions, int elen, analyse_callback cb) {
|
133
|
+
srand(time(0));
|
134
|
+
|
135
|
+
env_map emap;
|
136
|
+
for (int i = 0; i < elen; i++) {
|
137
|
+
emap.insert(env_map::value_type(envs[i], actions[i]));
|
138
|
+
}
|
139
|
+
|
140
|
+
RobotTester rt = RobotTester(10, &emap);
|
141
|
+
int total_score = 0;
|
142
|
+
|
143
|
+
for (int i = 0; i < times; i++) {
|
144
|
+
total_score = total_score + rt.test(step, cb, times == 1);
|
145
|
+
}
|
146
|
+
|
147
|
+
return total_score / times;
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#ifndef ROBOT_TESTER_H
|
2
|
+
#define ROBOT_TESTER_H
|
3
|
+
|
4
|
+
#include <unordered_map>
|
5
|
+
#include <string>
|
6
|
+
|
7
|
+
typedef int(*analyse_callback)(const char* const);
|
8
|
+
typedef std::unordered_map<std::string, short> env_map;
|
9
|
+
|
10
|
+
class RobotTester {
|
11
|
+
public:
|
12
|
+
RobotTester(int, env_map*);
|
13
|
+
~RobotTester();
|
14
|
+
int test(int, analyse_callback, bool play);
|
15
|
+
|
16
|
+
void rand_map();
|
17
|
+
void show_map();
|
18
|
+
|
19
|
+
private:
|
20
|
+
env_map* p_env_action;
|
21
|
+
int size;
|
22
|
+
int **map;
|
23
|
+
int x;
|
24
|
+
int y;
|
25
|
+
|
26
|
+
void scan_env(char[5]);
|
27
|
+
int execute_action(int);
|
28
|
+
};
|
29
|
+
|
30
|
+
|
31
|
+
extern "C" {
|
32
|
+
int robot_test(int times, int step, char** envs, short* action, int elen, analyse_callback);
|
33
|
+
}
|
34
|
+
|
35
|
+
#endif
|
36
|
+
|
data/examples/test.cpp
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#include "robot_tester.h"
|
2
|
+
|
3
|
+
#include <cstdio>
|
4
|
+
#include <cstdlib>
|
5
|
+
|
6
|
+
#include <unordered_map>
|
7
|
+
#include <string>
|
8
|
+
|
9
|
+
int analyse_env(const char* const env) {
|
10
|
+
return rand() % 6;
|
11
|
+
}
|
12
|
+
|
13
|
+
typedef std::unordered_map<std::string, short> env_hash;
|
14
|
+
|
15
|
+
int main() {
|
16
|
+
env_hash eh;
|
17
|
+
int step = 200;
|
18
|
+
int times = 200;
|
19
|
+
|
20
|
+
printf("'robot_test' avg score: %i\n", robot_test(times, step, NULL, NULL, 0, analyse_env));
|
21
|
+
|
22
|
+
RobotTester rt = RobotTester(10, &eh);
|
23
|
+
int total_score = 0;
|
24
|
+
printf("env_hash size: %i\n", (int)eh.size());
|
25
|
+
|
26
|
+
for (int i = 0; i < times; i++) {
|
27
|
+
total_score = total_score + rt.test(step, analyse_env, false);
|
28
|
+
}
|
29
|
+
|
30
|
+
printf("env_hash size: %i\n", (int)eh.size());
|
31
|
+
printf("'RobotTester#test' avg score: %i\n", total_score / times);
|
32
|
+
|
33
|
+
return 0;
|
34
|
+
}
|
35
|
+
|
data/lib/ga/version.rb
CHANGED
data/lib/ga/zoo.rb
CHANGED
@@ -1,21 +1,27 @@
|
|
1
1
|
module GA
|
2
2
|
class Zoo
|
3
|
-
attr_reader :unit_cls
|
3
|
+
attr_reader :unit_cls, :before_fitness_callback, :after_select_callback
|
4
4
|
|
5
5
|
def initialize(unit_cls)
|
6
6
|
@unit_cls = unit_cls
|
7
7
|
@debug = false
|
8
8
|
@before_fitness_callback = nil
|
9
|
+
@after_select_callback = nil
|
10
|
+
@elite_policy = false
|
11
|
+
@select_sample = 2
|
9
12
|
end
|
10
13
|
|
11
14
|
def evolve(units = 32, generations = 100, crossover_rate = 0.8, mutation_rate = 0.15)
|
12
15
|
units = units.times.map { unit_cls.random_new } if units.is_a?(Fixnum)
|
16
|
+
@start_at = Time.now
|
13
17
|
|
14
18
|
generations.times do |i|
|
15
19
|
@before_fitness_callback.call(units, i + 1) if @before_fitness_callback
|
16
20
|
output_debug_info(units, generations, i + 1) if @debug
|
17
21
|
|
18
22
|
units = select_units(units)
|
23
|
+
@after_select_callback.call(units, i + 1) if @after_select_callback
|
24
|
+
|
19
25
|
cross(units, crossover_rate)
|
20
26
|
mutate(units, mutation_rate)
|
21
27
|
end
|
@@ -27,25 +33,40 @@ module GA
|
|
27
33
|
@debug = true
|
28
34
|
end
|
29
35
|
|
36
|
+
def set_select_sample(val)
|
37
|
+
@select_sample = val
|
38
|
+
end
|
39
|
+
|
40
|
+
def elite_policy!
|
41
|
+
@elite_policy = true
|
42
|
+
end
|
43
|
+
|
30
44
|
def before_init_fitness(&block)
|
31
45
|
@before_fitness_callback = block
|
32
46
|
end
|
33
47
|
|
48
|
+
def after_select(&block)
|
49
|
+
@after_select_callback = block
|
50
|
+
end
|
51
|
+
|
34
52
|
|
35
53
|
private
|
36
54
|
|
37
55
|
def select_units(units)
|
38
56
|
new_units = units.map do
|
39
|
-
ou = units.sample(
|
57
|
+
ou = units.sample(@select_sample).max
|
40
58
|
unit_cls.new(ou.genome).tap {|u| u.fitness = ou.fitness }
|
41
59
|
end
|
42
60
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
61
|
+
if @elite_policy
|
62
|
+
min_index = new_units.index(new_units.min)
|
63
|
+
if min_index != 0 then
|
64
|
+
new_units[min_index], new_units[0] = new_units[0], new_units[min_index]
|
65
|
+
end
|
66
|
+
max_unit = units.max
|
67
|
+
new_units[0] = unit_cls.new(max_unit.genome)
|
47
68
|
end
|
48
|
-
|
69
|
+
|
49
70
|
new_units
|
50
71
|
end
|
51
72
|
|
@@ -53,7 +74,7 @@ module GA
|
|
53
74
|
last_index = nil
|
54
75
|
|
55
76
|
units.each_with_index do |unit, index|
|
56
|
-
next if index == 0
|
77
|
+
next if @elite_policy && index == 0
|
57
78
|
next if rand() >= rate
|
58
79
|
|
59
80
|
if last_index
|
@@ -69,7 +90,7 @@ module GA
|
|
69
90
|
|
70
91
|
def mutate(units, rate)
|
71
92
|
units.each_with_index do |unit, index|
|
72
|
-
next if index == 0
|
93
|
+
next if @elite_policy && index == 0
|
73
94
|
next if rand() >= rate
|
74
95
|
unit.mutate!
|
75
96
|
# recalculate fitness
|
@@ -80,6 +101,7 @@ module GA
|
|
80
101
|
def output_debug_info(units, generations, generation)
|
81
102
|
units.sort!
|
82
103
|
info = [
|
104
|
+
"[#{(Time.now - @start_at).to_f}]",
|
83
105
|
"GA-#{generation}/#{generations} #{units.count}-#{units[-1].genome.length}",
|
84
106
|
' fitness: '
|
85
107
|
]
|
@@ -88,6 +110,7 @@ module GA
|
|
88
110
|
info << units.map(&:fitness).join(', ')
|
89
111
|
else
|
90
112
|
info << "#{units[0..2].map(&:fitness).join(', ')}"
|
113
|
+
info << " ... #{units[units.length / 2].fitness}"
|
91
114
|
info << " ... #{units[-5..-1].map(&:fitness).join(', ')}"
|
92
115
|
end
|
93
116
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ga
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- jiangzhi.xie
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -83,7 +83,11 @@ files:
|
|
83
83
|
- bin/console
|
84
84
|
- bin/setup
|
85
85
|
- examples/01bag.rb
|
86
|
+
- examples/Makefile
|
86
87
|
- examples/robot.rb
|
88
|
+
- examples/robot_tester.cpp
|
89
|
+
- examples/robot_tester.h
|
90
|
+
- examples/test.cpp
|
87
91
|
- ga.gemspec
|
88
92
|
- lib/ga.rb
|
89
93
|
- lib/ga/version.rb
|