Skip to content

Commit e381296

Browse files
v0.8.11
1 parent ccd8ac4 commit e381296

6 files changed

Lines changed: 697 additions & 58 deletions

File tree

notebooks/testKriging.ipynb

Lines changed: 392 additions & 43 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
77

88
[project]
99
name = "spotPython"
10-
version = "0.8.10"
10+
version = "0.8.11"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotPython/spot/spot.py

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,10 @@ def append_X_ocba(self, X_ocba, X0) -> np.array:
479479
def run(self, X_start=None) -> Spot:
480480
self.initialize_design(X_start)
481481
# New: self.update_stats() moved here:
482-
# self.update_stats()
482+
# changed in 0.5.9:
483+
self.update_stats()
484+
# (S-4): Imputation:
485+
# Not implemented yet.
483486
# (S-11) Surrogate Fit:
484487
self.fit_surrogate()
485488
# (S-5) Calling the spotLoop Function
@@ -504,18 +507,69 @@ def run(self, X_start=None) -> Spot:
504507
return self
505508

506509
def initialize_design(self, X_start=None) -> None:
507-
# (S-2) Initial Design:
508-
X0 = self.generate_design(
509-
size=self.design_control["init_size"],
510-
repeats=self.design_control["repeats"],
511-
lower=self.lower,
512-
upper=self.upper,
513-
)
510+
"""
511+
Initialize design. Generate and evaluate initial design.
512+
If `X_start` is not `None`, append it to the initial design.
513+
Therefore, the design size is `init_size` + `X_start.shape[0]`.
514+
515+
Args:
516+
self (object): Spot object
517+
X_start (numpy.ndarray, optional): initial design. Defaults to None.
518+
519+
Returns:
520+
(NoneType): None
521+
522+
Attributes:
523+
self.X (numpy.ndarray): initial design
524+
self.y (numpy.ndarray): initial design values
525+
526+
Note:
527+
* If `X_start` is has the wrong shape, it is ignored.
528+
529+
Examples:
530+
>>> import numpy as np
531+
from spotPython.fun.objectivefunctions import analytical
532+
from spotPython.spot import spot
533+
# number of initial points:
534+
ni = 7
535+
# start point X_0
536+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
537+
538+
539+
fun = analytical().fun_sphere
540+
lower = np.array([-1, -1])
541+
upper = np.array([1, 1])
542+
design_control={"init_size": ni}
543+
544+
S = spot.Spot(fun=fun,
545+
lower = lower,
546+
upper= upper,
547+
show_progress=True,
548+
design_control=design_control,)
549+
S.initialize_design(X_start=X_start)
550+
print(f"S.X: {S.X}")
551+
print(f"S.y: {S.y}")
552+
"""
553+
if self.design_control["init_size"] > 0:
554+
X0 = self.generate_design(
555+
size=self.design_control["init_size"],
556+
repeats=self.design_control["repeats"],
557+
lower=self.lower,
558+
upper=self.upper,
559+
)
514560
if X_start is not None:
561+
if not isinstance(X_start, np.ndarray):
562+
X_start = np.array(X_start)
563+
X_start = np.atleast_2d(X_start)
515564
try:
516-
X0 = append(X_start, X0, axis=0)
565+
if self.design_control["init_size"] > 0:
566+
X0 = append(X_start, X0, axis=0)
567+
else:
568+
X0 = X_start
517569
except ValueError:
518570
logger.warning("X_start has wrong shape. Ignoring it.")
571+
if X0.shape[0] == 0:
572+
raise Exception("X0 has zero rows. Check design_control['init_size'] or X_start.")
519573
X0 = repair_non_numeric(X0, self.var_type)
520574
self.X = X0
521575
# (S-3): Eval initial design:
@@ -538,11 +592,6 @@ def initialize_design(self, X_start=None) -> None:
538592
writer.flush()
539593
#
540594
self.X, self.y = remove_nan(self.X, self.y)
541-
# self.update_stats() moved to run()!
542-
# changed in 0.5.9:
543-
self.update_stats()
544-
# (S-4): Imputation:
545-
# Not implemented yet.
546595

547596
def should_continue(self, timeout_start) -> bool:
548597
return (self.counter < self.fun_evals) and (time.time() < timeout_start + self.max_time * 60)
@@ -594,6 +643,16 @@ def update_stats(self) -> None:
594643
Returns:
595644
(NoneType): None
596645
646+
Attributes:
647+
self.min_y (float): minimum y value
648+
self.min_X (numpy.ndarray): X value of the minimum y value
649+
self.counter (int): number of function evaluations
650+
self.mean_X (numpy.ndarray): mean X values
651+
self.mean_y (numpy.ndarray): mean y values
652+
self.var_y (numpy.ndarray): variance of y values
653+
self.min_mean_y (float): minimum mean y value
654+
self.min_mean_X (numpy.ndarray): X value of the minimum mean y value
655+
597656
"""
598657
self.min_y = min(self.y)
599658
self.min_X = self.X[argmin(self.y)]

test/test_fit_surrogate.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import numpy as np
2+
from spotPython.fun.objectivefunctions import analytical
3+
from spotPython.spot import spot
4+
5+
def test_fit_surrogate():
6+
# number of initial points:
7+
ni = 0
8+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1], [1, 1]])
9+
fun = analytical().fun_sphere
10+
lower = np.array([-1, -1])
11+
upper = np.array([1, 1])
12+
design_control={"init_size": ni}
13+
S = spot.Spot(fun=fun,
14+
noise=False,
15+
lower = lower,
16+
upper= upper,
17+
show_progress=True,
18+
design_control=design_control,)
19+
S.initialize_design(X_start=X_start)
20+
S.update_stats()
21+
S.fit_surrogate()
22+
# correlation matrix should be square and the same size as the number of points
23+
assert S.surrogate.Psi.shape[0] == S.X.shape[0]

test/test_initialize_design.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import numpy as np
2+
from spotPython.fun.objectivefunctions import analytical
3+
from spotPython.spot import spot
4+
5+
def test_initialize_design():
6+
# number of initial points:
7+
ni = 7
8+
fun = analytical().fun_sphere
9+
lower = np.array([-1])
10+
upper = np.array([1])
11+
design_control={"init_size": ni}
12+
S = spot.Spot(fun=fun,
13+
lower = lower,
14+
upper= upper,
15+
show_progress=False,
16+
design_control=design_control,)
17+
S.initialize_design()
18+
assert S.X.shape[0] == ni
19+
assert S.X.shape[1] == lower.size
20+
21+
def test_initialize_design_2():
22+
# number of initial points:
23+
ni = 7
24+
# start point
25+
X_start = np.array([0, 0.5])
26+
fun = analytical().fun_sphere
27+
lower = np.array([-1, -1])
28+
upper = np.array([1, 2])
29+
design_control={"init_size": ni}
30+
31+
S = spot.Spot(fun=fun,
32+
lower = lower,
33+
upper= upper,
34+
show_progress=True,
35+
design_control=design_control,)
36+
S.initialize_design()
37+
assert S.X.shape[0] == ni
38+
assert S.X.shape[1] == lower.size
39+
40+
def test_initialize_design_3():
41+
# number of initial points:
42+
ni = 7
43+
# start point
44+
X_start = np.array([0, 0]).reshape(1, -1)
45+
fun = analytical().fun_sphere
46+
lower = np.array([-1, -1])
47+
upper = np.array([1, 1])
48+
design_control={"init_size": ni}
49+
S = spot.Spot(fun=fun,
50+
lower = lower,
51+
upper= upper,
52+
show_progress=True,
53+
design_control=design_control,)
54+
S.initialize_design(X_start=X_start)
55+
assert S.X.shape[0] == ni + np.atleast_2d(X_start).shape[0]
56+
assert S.X.shape[1] == lower.size
57+
58+
def test_initialize_design_4():
59+
# number of initial points:
60+
ni = 7
61+
# start point
62+
X_start = np.array([0, 0])
63+
fun = analytical().fun_sphere
64+
lower = np.array([-1, -1])
65+
upper = np.array([1, 1])
66+
design_control={"init_size": ni}
67+
S = spot.Spot(fun=fun,
68+
lower = lower,
69+
upper= upper,
70+
show_progress=True,
71+
design_control=design_control,)
72+
S.initialize_design(X_start=X_start)
73+
assert S.X.shape[0] == ni + np.atleast_2d(X_start).shape[0]
74+
assert S.X.shape[1] == lower.size
75+
76+
def test_initialize_design_5():
77+
# number of initial points:
78+
ni = 7
79+
# start point
80+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
81+
fun = analytical().fun_sphere
82+
lower = np.array([-1, -1])
83+
upper = np.array([1, 1])
84+
design_control={"init_size": ni}
85+
S = spot.Spot(fun=fun,
86+
lower = lower,
87+
upper= upper,
88+
show_progress=True,
89+
design_control=design_control,)
90+
S.initialize_design(X_start=X_start)
91+
assert S.X.shape[0] == ni + np.atleast_2d(X_start).shape[0]
92+
assert S.X.shape[1] == lower.size
93+
94+
def test_initialize_design_noX0():
95+
# number of initial points is zero, but a start point is given
96+
ni = 0
97+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
98+
fun = analytical().fun_sphere
99+
lower = np.array([-1, -1])
100+
upper = np.array([1, 1])
101+
design_control={"init_size": ni}
102+
103+
S = spot.Spot(fun=fun,
104+
lower = lower,
105+
upper= upper,
106+
show_progress=True,
107+
design_control=design_control,)
108+
S.initialize_design(X_start=X_start)
109+
assert S.X.shape[0] == ni + np.atleast_2d(X_start).shape[0]
110+
assert S.X.shape[1] == lower.size

test/test_update_stats.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import numpy as np
2+
from spotPython.fun.objectivefunctions import analytical
3+
from spotPython.spot import spot
4+
5+
def update_stats_no_duplicates():
6+
# number of initial points:
7+
ni = 0
8+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
9+
fun = analytical().fun_sphere
10+
lower = np.array([-1, -1])
11+
upper = np.array([1, 1])
12+
design_control={"init_size": ni}
13+
S = spot.Spot(fun=fun,
14+
lower = lower,
15+
upper= upper,
16+
show_progress=True,
17+
design_control=design_control,)
18+
S.initialize_design(X_start=X_start)
19+
S.update_stats()
20+
assert np.equal(S.min_X, X_start[0]).all()
21+
assert S.min_y == fun(X_start[0])
22+
assert S.counter == X_start.shape[0]
23+
# Since noise is False, the following statics should be None:
24+
assert S.mean_X is None
25+
assert S.mean_y is None
26+
assert S.var_y is None
27+
assert S.min_mean_X is None
28+
assert S.min_mean_y is None
29+
30+
def test_update_stats_duplicates_and_noise():
31+
# number of initial points:
32+
ni = 0
33+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1], [1, 1]])
34+
35+
fun = analytical().fun_sphere
36+
lower = np.array([-1, -1])
37+
upper = np.array([1, 1])
38+
design_control={"init_size": ni}
39+
40+
S = spot.Spot(fun=fun,
41+
noise=True,
42+
lower = lower,
43+
upper= upper,
44+
show_progress=True,
45+
design_control=design_control,)
46+
S.initialize_design(X_start=X_start)
47+
print(f"S.X: {S.X}")
48+
print(f"S.y: {S.y}")
49+
S.update_stats()
50+
assert np.equal(S.min_X, X_start[0]).all()
51+
assert S.min_y == fun(X_start[0])
52+
assert S.counter == X_start.shape[0]
53+
# the X values are aggregated, the last two rows are equal,
54+
# so the mean_X should have only 4 rows
55+
assert np.equal(S.mean_X,
56+
np.array([[0., 0.],
57+
[0., 1.],
58+
[1., 0.],
59+
[1., 1.]])).all()
60+
# the y values are also aggregated, there are only 4 values
61+
assert np.equal(S.mean_y, np.array([0., 1., 1., 2.])).all()
62+
63+
def test_update_stats_duplicates_nonoise():
64+
# number of initial points:
65+
ni = 0
66+
X_start = np.array([[0, 0], [0, 1], [1, 0], [1, 1], [1, 1]])
67+
68+
fun = analytical().fun_sphere
69+
lower = np.array([-1, -1])
70+
upper = np.array([1, 1])
71+
design_control={"init_size": ni}
72+
73+
S = spot.Spot(fun=fun,
74+
noise=False,
75+
lower = lower,
76+
upper= upper,
77+
show_progress=True,
78+
design_control=design_control,)
79+
S.initialize_design(X_start=X_start)
80+
print(f"S.X: {S.X}")
81+
print(f"S.y: {S.y}")
82+
S.update_stats()
83+
assert np.equal(S.min_X, X_start[0]).all()
84+
assert S.min_y == fun(X_start[0])
85+
assert S.counter == X_start.shape[0]
86+
# Since noise is False, the following statics should be None:
87+
assert S.mean_X is None
88+
assert S.mean_y is None
89+
assert S.var_y is None
90+
assert S.min_mean_X is None
91+
assert S.min_mean_y is None
92+
# the X values are not aggregated, the last two equal rows ae not modified:
93+
assert np.equal(S.X,
94+
np.array([[0., 0.],
95+
[0., 1.],
96+
[1., 0.],
97+
[1., 1.],
98+
[1., 1.]])).all()

0 commit comments

Comments
 (0)