Skip to content

Commit bc06082

Browse files
0.14.62
generate random point if point cannot be evaluated
1 parent c5644d2 commit bc06082

4 files changed

Lines changed: 149 additions & 84 deletions

File tree

notebooks/00_spotPython_tests.ipynb

Lines changed: 55 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4538,78 +4538,9 @@
45384538
},
45394539
{
45404540
"cell_type": "code",
4541-
"execution_count": 5,
4541+
"execution_count": null,
45424542
"metadata": {},
4543-
"outputs": [
4544-
{
4545-
"name": "stdout",
4546-
"output_type": "stream",
4547-
"text": [
4548-
"Selected messreihen: ['MR001A', 'MR001H', 'MR001aH', 'MR001bH', 'MR001cH', 'MR001dH', 'MR001eH', 'MR001vH', 'MR001wH', 'MR002aH', 'MR002bH', 'MR002cH', 'MR002dH', 'MR002eH', 'MR003aH', 'MR003bH', 'MR003cH', 'MR003dH', 'MR003eH', 'MR003fH', 'MR003gH', 'MR02H', 'MR02bH', 'MR02cH', 'MR02dH', 'MR02zA', 'MR02zH', 'MR03A', 'MR03H', 'MR03aH', 'MR03bH', 'MR03cH', 'MR03dH', 'MR04A', 'MR04H', 'MR04aH', 'MR04cH', 'MR04dH', 'MR04eH', 'MR05A', 'MR05H', 'MR05aH', 'MR05bH', 'MR05cH', 'MR05dH', 'MR05eH']\n",
4549-
"Loading data for ['C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'N', 'U', 'V', 'W', 'X', 'Y', 'AS', 'AT', 'AV', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BC', 'BD', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BP', 'BQ', 'BR', 'BS', 'BU', 'BV', 'BW', 'BX', 'BY', 'BZ', 'CA', 'CB', 'CD', 'CE', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CP', 'CQ', 'CR', 'CS', 'CT', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DA', 'DB', 'DC', 'DD', 'DE', 'DG', 'DH', 'DI', 'DJ', 'DK', 'DL', 'DM', 'DN', 'DP', 'DQ', 'DR', 'DS', 'DT', 'DU', 'DV']\n",
4550-
"Loaded df.columns: Index(['AS Drossel Drucks.', 'AT Drossel Saugs.', 'AV Drehzahl Verd', 'AW u2',\n",
4551-
" 'AX Drehzahl Motor', 'AZ p U', 'BA Umgebungsdruck Kontrolle',\n",
4552-
" 'BB p tot vV', 'BC p tot nV', 'BD Pi tot V', 'BF p Blende',\n",
4553-
" 'BG p_Blende B Kontrolle', 'BH p Blende BW', 'BI p_Blende BW Kontrolle',\n",
4554-
" 'BJ T Selbstlaufblende', 'BL V tot V red', 'BM m V red',\n",
4555-
" 'BN Reaktionsgrad V', 'BP rho vV', 'BQ rho nV', 'BR rel. Luftfeuchte',\n",
4556-
" 'BS T-Luftfeuchte', 'BU TvV_1', 'BV TvV_2', 'BW TvV_3', 'BX TvV_4',\n",
4557-
" 'BY TvV_5', 'BZ TvV_6', 'C Messreihe ', 'CA TvV_7', 'CB TvV_8',\n",
4558-
" 'CD TnV_1', 'CE TnV_2', 'CF TnV_3', 'CG TnV_4', 'CH TnV_5', 'CI TnV_6',\n",
4559-
" 'CK p Radseitenraum Verdichter', 'CL p_stat_SEALING-COVER_01',\n",
4560-
" 'CM p_stat_SEALING-COVER_02', 'CN p_stat_SEALING-COVER_03',\n",
4561-
" 'CO p_stat_SEALING-COVER_04', 'CP p_stat_SEALING-COVER_05',\n",
4562-
" 'CQ p_stat_SEALING-COVER_06', 'CR p_stat_SEALING-COVER_07',\n",
4563-
" 'CS p_stat_SEALING-COVER_08', 'CT p_stat_SEALING-COVER_09',\n",
4564-
" 'CU p_stat_SEALING-COVER_10', 'CV p_stat_SEALING-COVER_11',\n",
4565-
" 'CW p_stat_SEALING-COVER_12', 'CX p_stat_SEALING-COVER_13',\n",
4566-
" 'CY p_stat_SEALING-COVER_14', 'CZ p_stat_SEALING-COVER_15',\n",
4567-
" 'D Flächenverhältnis ', 'DA p_stat_SEALING-COVER_16',\n",
4568-
" 'DB p_stat_SEALING-COVER_17', 'DC p_stat_SEALING-COVER_18',\n",
4569-
" 'DD p_stat_SEALING-COVER_19', 'DE p_stat_SEALING-COVER_20', 'DG p Öl',\n",
4570-
" 'DH p Öl PLAG', 'DI p Öl TBOG', 'DJ T Öl ein', 'DK T Öl aus PLAG',\n",
4571-
" 'DL T Öl aus TBOG', 'DM T Öl aus VERD', 'DN Töl nach Tank',\n",
4572-
" 'DP T_Axiallager 1', 'DQ T_Axiallager 2', 'DR T_Axiallager 3',\n",
4573-
" 'DS T_Lager_3_Turbogetriebe_1', 'DT T_Lager_4_Turbogetriebe_1',\n",
4574-
" 'DU T_Lager_3_Turbogetriebe_2', 'DV T_Lager_4_Turbogetriebe_2',\n",
4575-
" 'E Drosselstellung ', 'F DMS ', 'G Zeit [s]', 'H Drehzahl [1/min]',\n",
4576-
" 'I Ordnung []', 'J Frequenz [Hz]', 'K Knotendurchmesser []',\n",
4577-
" 'L Mode []', 'N AufgewAmplitudeNom [MPa]', 'U Sensitivität []',\n",
4578-
" 'V Güteklasse []', 'W ex_ey []', 'X Sx_ex_E []', 'Y Krümmung []'],\n",
4579-
" dtype='object')\n",
4580-
"non_numerical_columns before encoding: C Messreihe F DMS \n",
4581-
"0 MR001A HS5-M3S\n",
4582-
"1 MR001A HS5-M2D\n",
4583-
"2 MR001A HS9-M3S\n",
4584-
"3 MR05A HS5-M3S\n",
4585-
"4 MR05A HS5-M2D\n",
4586-
"... ... ...\n",
4587-
"27855 MR02zH HS5-M2D\n",
4588-
"27856 MR02zH HS5-M2D\n",
4589-
"27857 MR02zH HS9-M3S\n",
4590-
"27858 MR02zH HS5-M2D\n",
4591-
"27859 MR02zH HS5-M2D\n",
4592-
"\n",
4593-
"[27857 rows x 2 columns]\n",
4594-
"non_numerical_columns after encoding: C Messreihe F DMS \n",
4595-
"0 0.0 1.0\n",
4596-
"1 0.0 0.0\n",
4597-
"2 0.0 4.0\n",
4598-
"3 39.0 1.0\n",
4599-
"4 39.0 0.0\n",
4600-
"... ... ...\n",
4601-
"27855 26.0 0.0\n",
4602-
"27856 26.0 0.0\n",
4603-
"27857 26.0 4.0\n",
4604-
"27858 26.0 0.0\n",
4605-
"27859 26.0 0.0\n",
4606-
"\n",
4607-
"[27857 rows x 2 columns]\n",
4608-
"<class 'torch.utils.data.dataset.TensorDataset'>\n",
4609-
"27857\n"
4610-
]
4611-
}
4612-
],
4543+
"outputs": [],
46134544
"source": [
46144545
"from pyhcf.utils.io import load_hcf_dataframe, hcf_df2tensor\n",
46154546
"from pyhcf.utils.names import load_all_features_N_regression_list\n",
@@ -4637,24 +4568,65 @@
46374568
},
46384569
{
46394570
"cell_type": "code",
4640-
"execution_count": 27,
4571+
"execution_count": null,
4572+
"metadata": {},
4573+
"outputs": [],
4574+
"source": [
4575+
"dataset.__getitem__(0)\n",
4576+
"# get the dimensions of the first sample\n",
4577+
"dataset.__getitem__(0)[0].shape[0]"
4578+
]
4579+
},
4580+
{
4581+
"cell_type": "markdown",
4582+
"metadata": {},
4583+
"source": [
4584+
"# Generate Random Point"
4585+
]
4586+
},
4587+
{
4588+
"cell_type": "code",
4589+
"execution_count": 1,
46414590
"metadata": {},
46424591
"outputs": [
46434592
{
4644-
"data": {
4645-
"text/plain": [
4646-
"86"
4647-
]
4648-
},
4649-
"execution_count": 27,
4650-
"metadata": {},
4651-
"output_type": "execute_result"
4593+
"name": "stderr",
4594+
"output_type": "stream",
4595+
"text": [
4596+
"Seed set to 123\n",
4597+
"Seed set to 123\n"
4598+
]
4599+
},
4600+
{
4601+
"name": "stdout",
4602+
"output_type": "stream",
4603+
"text": [
4604+
"X0: [[-0.36470373 0.89235796]]\n",
4605+
"y0: [0.92931154]\n"
4606+
]
46524607
}
46534608
],
46544609
"source": [
4655-
"dataset.__getitem__(0)\n",
4656-
"# get the dimensions of the first sample\n",
4657-
"dataset.__getitem__(0)[0].shape[0]"
4610+
"import numpy as np\n",
4611+
"from spotPython.fun.objectivefunctions import analytical\n",
4612+
"from spotPython.spot import spot\n",
4613+
"from spotPython.utils.init import fun_control_init\n",
4614+
"fun = analytical().fun_sphere\n",
4615+
"fun_control = fun_control_init(\n",
4616+
" lower = np.array([-1, -1]),\n",
4617+
" upper = np.array([1, 1])\n",
4618+
" )\n",
4619+
"S = spot.Spot(fun=fun,\n",
4620+
" fun_control=fun_control,\n",
4621+
" )\n",
4622+
"X0, y0 = S.generate_random_point()\n",
4623+
"print(f\"X0: {X0}\")\n",
4624+
"print(f\"y0: {y0}\")\n",
4625+
"assert X0.size == 2\n",
4626+
"assert y0.size == 1\n",
4627+
"assert np.all(X0 >= S.lower)\n",
4628+
"assert np.all(X0 <= S.upper)\n",
4629+
"assert y0 >= 0"
46584630
]
46594631
},
46604632
{

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.14.61"
10+
version = "0.14.62"
1111
authors = [
1212
{ name="T. Bartz-Beielstein", email="tbb@bartzundbartz.de" }
1313
]

src/spotPython/spot/spot.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,53 @@ def initialize_design(self, X_start=None) -> None:
947947
def should_continue(self, timeout_start) -> bool:
948948
return (self.counter < self.fun_evals) and (time.time() < timeout_start + self.max_time * 60)
949949

950+
def generate_random_point(self):
951+
"""Generate a random point in the design space.
952+
953+
Returns:
954+
(tuple): tuple containing:
955+
X0 (numpy.ndarray): random point in the design space
956+
y0 (numpy.ndarray): function value at X
957+
958+
Notes:
959+
If the evaluation fails, the function returns arrays of shape[0] == 0.
960+
961+
Examples:
962+
>>> import numpy as np
963+
from spotPython.fun.objectivefunctions import analytical
964+
from spotPython.spot import spot
965+
from spotPython.utils.init import fun_control_init
966+
fun = analytical().fun_sphere
967+
fun_control = fun_control_init(
968+
lower = np.array([-1, -1]),
969+
upper = np.array([1, 1])
970+
)
971+
S = spot.Spot(fun=fun,
972+
fun_control=fun_control,
973+
)
974+
X0, y0 = S.generate_random_point()
975+
print(f"X0: {X0}")
976+
print(f"y0: {y0}")
977+
assert X0.size == 2
978+
assert y0.size == 1
979+
assert np.all(X0 >= S.lower)
980+
assert np.all(X0 <= S.upper)
981+
assert y0 >= 0
982+
"""
983+
X0 = self.generate_design(
984+
size=1,
985+
repeats=1,
986+
lower=self.lower,
987+
upper=self.upper,
988+
)
989+
X0 = repair_non_numeric(X0, self.var_type)
990+
X_all = self.to_all_dim_if_needed(X0)
991+
logger.debug("In Spot() generate_random_point(), before calling self.fun: X_all: %s", X_all)
992+
logger.debug("In Spot() generate_random_point(), before calling self.fun: fun_control: %s", self.fun_control)
993+
y0 = self.fun(X=X_all, fun_control=self.fun_control)
994+
X0, y0 = remove_nan(X0, y0, stop_on_zero_return=False)
995+
return X0, y0
996+
950997
def update_design(self) -> None:
951998
"""
952999
Update design. Generate and evaluate new design points.
@@ -1076,6 +1123,11 @@ def update_design(self) -> None:
10761123
if y0.shape[0] > 0:
10771124
self.X = np.append(self.X, X0, axis=0)
10781125
self.y = np.append(self.y, y0)
1126+
else:
1127+
# otherwise, generate a random point and append it to the design
1128+
Xr, yr = self.generate_random_point()
1129+
self.X = np.append(self.X, Xr, axis=0)
1130+
self.y = np.append(self.y, yr)
10791131

10801132
def fit_surrogate(self) -> None:
10811133
"""

test/test_generate_random_point.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import pytest
2+
import numpy as np
3+
from unittest.mock import Mock
4+
from spotPython.spot import spot
5+
from spotPython.utils.init import fun_control_init
6+
7+
8+
@pytest.fixture
9+
def setup_spot():
10+
fun_control = fun_control_init(
11+
lower=np.array([-1, -1]),
12+
upper=np.array([1, 1])
13+
)
14+
return fun_control
15+
16+
17+
def test_generate_random_point(setup_spot):
18+
fun = Mock(return_value=np.array([0])) # Replace with valid function
19+
S = spot.Spot(fun=fun, fun_control=setup_spot)
20+
X0, y0 = S.generate_random_point()
21+
22+
print(f"X0: {X0}")
23+
print(f"y0: {y0}")
24+
25+
assert X0.size == 2, "X0 does not have a size of 2"
26+
assert y0.size == 1, "y0 does not have a size of 1"
27+
assert np.all(X0 >= S.lower), "X0 has values less than lower bounds"
28+
assert np.all(X0 <= S.upper), "X0 has values greater than upper bounds"
29+
assert y0 >= 0, "y0 is not greater than or equal to 0"
30+
31+
32+
def test_generate_random_point_with_nan(setup_spot):
33+
fun = Mock(return_value=np.array([np.nan])) # Function that returns NaN
34+
S = spot.Spot(fun=fun, fun_control=setup_spot)
35+
X0, y0 = S.generate_random_point()
36+
37+
print(f"X0 with NaN: {X0}")
38+
print(f"y0 with NaN: {y0}")
39+
40+
assert X0.shape[0] == 0, "X0 should have shape[0] == 0 when fun returns NaN"
41+
assert y0.shape[0] == 0, "y0 should have shape[0] == 0 when fun returns NaN"

0 commit comments

Comments
 (0)