Skip to content

Commit 8e45317

Browse files
add pytest
1 parent 148a16e commit 8e45317

File tree

10 files changed

+230
-17
lines changed

10 files changed

+230
-17
lines changed

.circleci/config.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
machine:
2+
python:
3+
version: 3.5.0
4+
5+
dependencies:
6+
pre:
7+
- pip install -r ./requirements.txt
8+
9+
test:
10+
override:
11+
- pytest

crfmnes/alg.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ def sort_indices_by(evals, z):
3232
return sorted_indices
3333

3434

35-
def calc_constraint_violation(x, lamb):
36-
constraint_violation = np.zeros(lamb)
37-
for i in range(lamb):
38-
for j in range(x[:, i].size):
39-
constraint_violation[i] += (-min(0.0, x[:, i][j]) + max(0.0, x[:, i][j] - 1.0)) * 1e5
40-
return constraint_violation
41-
42-
4335
class CRFMNES:
4436
def __init__(self, dim, f, m, sigma, lamb, **kwargs):
4537

@@ -55,7 +47,7 @@ def __init__(self, dim, f, m, sigma, lamb, **kwargs):
5547
self.D = np.ones([dim, 1])
5648
self.constraint = kwargs.get('constraint', [[- np.inf, np.inf] for _ in range(dim)])
5749
self.penalty_coef = kwargs.get('penalty_coef', 1e5)
58-
self.use_constraint_violation = True
50+
self.use_constraint_violation = kwargs.get('use_constraint_violation', True)
5951

6052
self.w_rank_hat = (np.log(self.lamb / 2 + 1) - np.log(np.arange(1, self.lamb + 1))).reshape(self.lamb, 1)
6153
self.w_rank_hat[np.where(self.w_rank_hat < 0)] = 0
@@ -95,12 +87,12 @@ def calc_violations(self, x):
9587
violations = np.zeros(self.lamb)
9688
for i in range(self.lamb):
9789
for j in range(self.dim):
98-
violations[i] += (- min(0, x[j][i] - self.constraint[j][0]) + max(0, x[j][i] - self.constraint[j][
99-
1])) * self.penalty_coef
90+
violations[i] += (- min(0, x[j][i] - self.constraint[j][0]) + max(0, x[j][i] - self.constraint[j][1])) * self.penalty_coef
10091
return violations
10192

10293
def optimize(self, iterations):
10394
for _ in range(iterations):
95+
# print("f_best:{}".format(self.f_best))
10496
_ = self.one_iteration()
10597
return self.x_best, self.f_best
10698

@@ -120,7 +112,7 @@ def one_iteration(self):
120112

121113
violations = np.zeros(lamb)
122114
if self.use_constraint_violation:
123-
violations = calc_constraint_violation(x, self.lamb)
115+
violations = self.calc_violations(x)
124116
sorted_indices = sort_indices_by(evals_no_sort + violations, self.z)
125117
else:
126118
sorted_indices = sort_indices_by(evals_no_sort, self.z)
@@ -172,7 +164,7 @@ def one_iteration(self):
172164
b = -(1 - alphavd ** 2) * normv4 / gammav + 2 * alphavd ** 2
173165
H = np.ones([self.dim, 1]) * 2 - (b + 2 * alphavd ** 2) * vbarbar # dim x 1
174166
invH = H ** (-1)
175-
s_step1 = yy - normv2 / gammav * (yvbar * ip_yvbar) + np.ones([self.dim, self.lamb + 1]) # dim x lamb+1
167+
s_step1 = yy - normv2 / gammav * (yvbar * ip_yvbar) - np.ones([self.dim, self.lamb + 1]) # dim x lamb+1
176168
ip_vbart = vbar.T @ t # 1 x lamb+1
177169
s_step2 = s_step1 - alphavd / gammav * ((2 + normv2) * (t * vbar) - normv2 * vbarbar @ ip_vbart) # dim x lamb+1
178170
invHvbarbar = invH * vbarbar
@@ -194,7 +186,7 @@ def one_iteration(self):
194186
# update s, D
195187
G_s = np.sum((self.z * self.z - np.ones([self.dim, self.lamb])) @ weights) / self.dim
196188
l_s = 1.0 if ps_norm >= self.chiN and G_s < 0 else 0.0
197-
self.sigma = self.sigma * np.exp((1 - l_s) * eta_sigma / 2 * G_s) * nthrootdetAold
189+
self.sigma = self.sigma * np.exp((1 - l_s) * eta_sigma / 2 * G_s) * nthrootdetA / nthrootdetAold
198190
self.D = self.D / nthrootdetA
199191

200192
return xs_no_sort, evals_no_sort, violations

examples/demo_sphere.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66

77

88
def sphere(x):
9+
x = x.reshape(-1)
910
return np.sum(x**2)
1011

1112

1213
def main():
13-
dim = 3
14+
dim = 40
1415
mean = np.ones([dim, 1]) * 2
1516
sigma = 0.5
16-
lamb = 6 # note that lamb (sample size) should be even number
17-
iteration_number = 100
17+
lamb = 16 # note that lamb (sample size) should be even number
18+
iteration_number = 500
1819

1920
cr = CRFMNES(dim, sphere, mean, sigma, lamb)
2021
x_best, f_best = cr.optimize(iteration_number)

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
numpy==1.15.2
2+
pytest==3.9.1

tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import crfmnes

tests/test_constraint_sphere.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import numpy as np
5+
from crfmnes import CRFMNES
6+
7+
8+
def const_sphere(x):
9+
x = x.reshape(-1)
10+
if np.sum(x < 0) > 0:
11+
return np.inf
12+
return np.sum(x**2)
13+
14+
15+
def test_run_d40_const_sphere():
16+
print("test_run_d40:")
17+
dim = 40
18+
mean = np.ones([dim, 1]) * 10
19+
sigma = 2.0
20+
lamb = 16 # note that lamb (sample size) should be even number
21+
allowable_evals = (19.4 + 1.1*3) * 1e3 # 2 sigma
22+
iteration_number = int(allowable_evals / lamb) + 1
23+
24+
cr = CRFMNES(dim, const_sphere, mean, sigma, lamb)
25+
x_best, f_best = cr.optimize(iteration_number)
26+
print("f_best:{}".format(f_best))
27+
assert f_best < 1e-12
28+
29+
30+
def test_run_d80_const_sphere():
31+
print("test_run_d80:")
32+
dim = 80
33+
mean = np.ones([dim, 1]) * 10
34+
sigma = 2.0
35+
lamb = 32 # note that lamb (sample size) should be even number
36+
allowable_evals = (48.8 + 1.4*3) * 1e3 # 2 sigma
37+
iteration_number = int(allowable_evals / lamb) + 1
38+
39+
cr = CRFMNES(dim, const_sphere, mean, sigma, lamb)
40+
x_best, f_best = cr.optimize(iteration_number)
41+
print("f_best:{}".format(f_best))
42+
assert f_best < 1e-12

tests/test_ellipsoid.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import numpy as np
5+
from crfmnes import CRFMNES
6+
7+
8+
def ellipsoid(x):
9+
x = x.reshape(-1)
10+
dim = len(x)
11+
return np.sum([(1000**(i / (dim-1)) * x[i])**2 for i in range(dim)])
12+
13+
14+
def test_run_d40_ellipsoid():
15+
print("test_run_d40:")
16+
dim = 40
17+
mean = np.ones([dim, 1]) * 3
18+
sigma = 2.0
19+
lamb = 16 # note that lamb (sample size) should be even number
20+
allowable_evals = (8.8 + 0.5*3) * 1e3 # 2 sigma
21+
iteration_number = int(allowable_evals / lamb) + 1
22+
23+
cr = CRFMNES(dim, ellipsoid, mean, sigma, lamb, use_constraint_violation=False)
24+
x_best, f_best = cr.optimize(iteration_number)
25+
print("f_best:{}".format(f_best))
26+
assert f_best < 1e-12
27+
28+
29+
def test_run_d80_ellipsoid():
30+
print("test_run_d80:")
31+
dim = 80
32+
mean = np.ones([dim, 1]) * 3
33+
sigma = 2.0
34+
lamb = 16 # note that lamb (sample size) should be even number
35+
allowable_evals = (17.5 + 0.6*3) * 1e3 # 2 sigma
36+
iteration_number = int(allowable_evals / lamb) + 1
37+
38+
cr = CRFMNES(dim, ellipsoid, mean, sigma, lamb, use_constraint_violation=False)
39+
x_best, f_best = cr.optimize(iteration_number)
40+
print("f_best:{}".format(f_best))
41+
assert f_best < 1e-12

tests/test_ktablet.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import numpy as np
5+
from crfmnes import CRFMNES
6+
7+
8+
def ktablet(x):
9+
x = x.reshape(-1)
10+
dim = len(x)
11+
k = int(dim / 4)
12+
return np.sum(x[0:k]**2) + np.sum((100*x[k:dim])**2)
13+
14+
15+
def test_run_d40_ktablet():
16+
print("test_run_d40:")
17+
dim = 40
18+
mean = np.ones([dim, 1]) * 3
19+
sigma = 2.0
20+
lamb = 16 # note that lamb (sample size) should be even number
21+
allowable_evals = (9.1 + 0.6*3) * 1e3 # 2 sigma
22+
iteration_number = int(allowable_evals / lamb) + 1
23+
24+
cr = CRFMNES(dim, ktablet, mean, sigma, lamb)
25+
x_best, f_best = cr.optimize(iteration_number)
26+
print("f_best:{}".format(f_best))
27+
assert f_best < 1e-12
28+
29+
30+
def test_run_d80_ktablet():
31+
print("test_run_d80:")
32+
dim = 80
33+
mean = np.ones([dim, 1]) * 3
34+
sigma = 2.0
35+
lamb = 16 # note that lamb (sample size) should be even number
36+
allowable_evals = (18.6 + 0.8*3) * 1e3 # 2 sigma
37+
iteration_number = int(allowable_evals / lamb) + 1
38+
39+
cr = CRFMNES(dim, ktablet, mean, sigma, lamb)
40+
x_best, f_best = cr.optimize(iteration_number)
41+
print("f_best:{}".format(f_best))
42+
assert f_best < 1e-12

tests/test_rastrigin.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import numpy as np
5+
from crfmnes import CRFMNES
6+
import math
7+
8+
9+
def rastrigin(x):
10+
x = x.reshape(-1)
11+
dim = len(x)
12+
return 10.0 * dim + np.sum([x[i] ** 2 - 10.0 * math.cos(2.0 * math.pi * x[i]) for i in range(dim)])
13+
14+
15+
def test_run_d40_rastrigin():
16+
print("test_run_d40:")
17+
dim = 40
18+
mean = np.ones([dim, 1]) * 3
19+
sigma = 2.0
20+
lamb = 1130 # note that lamb (sample size) should be even number
21+
allowable_evals = (148 + 8.8*3) * 1e3 # 2 sigma
22+
iteration_number = int(allowable_evals / lamb) + 1
23+
24+
cr = CRFMNES(dim, rastrigin, mean, sigma, lamb, use_constraint_violation=False)
25+
x_best, f_best = cr.optimize(iteration_number)
26+
print("f_best:{}".format(f_best))
27+
assert f_best < 1e-12
28+
29+
30+
def test_run_d80_rastrigin():
31+
print("test_run_d80:")
32+
dim = 80
33+
mean = np.ones([dim, 1]) * 3
34+
sigma = 2.0
35+
lamb = 1600 # note that lamb (sample size) should be even number
36+
allowable_evals = (296 + 8.0*3) * 1e3 # 2 sigma
37+
iteration_number = int(allowable_evals / lamb) + 1
38+
39+
cr = CRFMNES(dim, rastrigin, mean, sigma, lamb, use_constraint_violation=False)
40+
x_best, f_best = cr.optimize(iteration_number)
41+
print("f_best:{}".format(f_best))
42+
assert f_best < 1e-12

tests/test_rosenbrock_chain.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
4+
import numpy as np
5+
from crfmnes import CRFMNES
6+
7+
8+
def rosenbrock_chain(x):
9+
x = x.reshape(-1)
10+
return np.sum(100.0*(x[1:] - x[:-1]**2)**2 + (1-x[:-1])**2)
11+
12+
def test_run_d40_rosen():
13+
print("test_run_d40:")
14+
dim = 40
15+
mean = np.zeros([dim, 1])
16+
sigma = 2.0
17+
lamb = 40 # note that lamb (sample size) should be even number
18+
allowable_evals = (52.2 + 1.5*3) * 1e3 # 2 sigma
19+
iteration_number = int(allowable_evals / lamb) + 1
20+
21+
cr = CRFMNES(dim, rosenbrock_chain, mean, sigma, lamb)
22+
x_best, f_best = cr.optimize(iteration_number)
23+
print("f_best:{}".format(f_best))
24+
assert f_best < 1e-12
25+
26+
27+
def test_run_d80_rosen():
28+
print("test_run_d80:")
29+
dim = 80
30+
mean = np.zeros([dim, 1])
31+
sigma = 2.0
32+
lamb = 64 # note that lamb (sample size) should be even number
33+
allowable_evals = (192 + 2.0*3) * 1e3 # 2 sigma
34+
iteration_number = int(allowable_evals / lamb) + 1
35+
36+
cr = CRFMNES(dim, rosenbrock_chain, mean, sigma, lamb)
37+
x_best, f_best = cr.optimize(iteration_number)
38+
print("f_best:{}".format(f_best))
39+
assert f_best < 1e-12

0 commit comments

Comments
 (0)