Skip to content

Commit f46f88d

Browse files
feat: modified global options; added 1d optimization tests (#56)
* feat: modified global options; added 1d optimization tests * fix: dev environment dependencies install. --------- Co-authored-by: GurjeetSinghSangra <gurjeet.singh.sangra@gmail.com>
1 parent e008c16 commit f46f88d

File tree

6 files changed

+78
-21
lines changed

6 files changed

+78
-21
lines changed

environment.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# run: conda env create --file environment.yml
22
name: pybads-dev
3+
34
dependencies:
4-
- python>=3.8
5+
- python>=3.9
56
- pip
67
- pip:
7-
- -r requirements.txt
8+
- -e ".[dev]"

examples/pybads_example_1_basic_usage.ipynb

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
"Formally, the goal of BADS is to *minimize* a target (or objective) function $f(\\mathbf{x}): \\mathbb{R}^D \\rightarrow \\mathbb{R}$, for $\\mathbf{x} \\in \\mathbb{R}^D$,\n",
6060
"\n",
6161
"$$\n",
62-
"\\mathbf{x}^\\star = \\arg\\min_\\mathbf{x} f(\\mathbf{x}) \\qquad \\text{with} \\; \\text{lower_bounds}_d \\le x_d \\le \\text{upper_bounds}_d \\; \\text{ for } 1\\le d \\le D,\n",
62+
"\\mathbf{x}^\\star = \\arg\\min_\\mathbf{x} f(\\mathbf{x}) \\qquad \\text{with} \\quad \\text{lower\\_bounds}_d \\le x_d \\le \\text{upper\\_bounds}_d \\; \\text{ for } 1\\le d \\le D,\n",
6363
"$$\n",
6464
"where $D$ is the dimensionality of the problem and `lower_bounds`, `upper_bounds` are arrays representing lower/upper bound constraints, which can be set to infinite for unbounded parameters."
6565
]
@@ -131,18 +131,23 @@
131131
" 0 6 1 1 Initial mesh Initial points\n",
132132
" 0 10 1 0.5 Refine grid Train\n",
133133
" 1 18 1 0.25 Refine grid Train\n",
134-
" 2 22 0.250428 0.25 Successful search (ES-wcm) \n",
135-
" 2 24 0.0851394 0.25 Successful search (ES-ell) \n",
136-
" 2 26 0.00997961 0.25 Incremental search (ES-ell) \n",
137-
" 2 27 0.000224117 0.25 Incremental search (ES-ell) \n",
138-
" 2 34 0.000224117 0.125 Refine grid \n",
139-
" 3 42 0.000224117 0.0625 Refine grid Train\n",
140-
" 4 44 7.97867e-05 0.0625 Incremental search (ES-wcm) \n",
141-
" 4 50 7.97867e-05 0.03125 Refine grid \n",
142-
" 5 58 7.97867e-05 0.0078125 Refine grid \n",
143-
" 6 66 7.97867e-05 0.00195312 Refine grid Train\n",
134+
" 2 20 0.608156 0.25 Successful search (ES-ell) \n",
135+
" 2 21 0.408646 0.25 Successful search (ES-ell) \n",
136+
" 2 23 0.303906 0.25 Incremental search (ES-wcm) \n",
137+
" 2 25 0.212582 0.25 Incremental search (ES-ell) \n",
138+
" 2 30 0.212582 0.125 Refine grid Train\n",
139+
" 3 32 0.127714 0.125 Successful search (ES-wcm) \n",
140+
" 3 33 0.0139198 0.125 Successful search (ES-wcm) \n",
141+
" 3 34 0.000681342 0.125 Incremental search (ES-wcm) \n",
142+
" 3 42 0.000681342 0.0625 Refine grid Train\n",
143+
" 4 44 0.000120297 0.0625 Incremental search (ES-ell) \n",
144+
" 4 50 0.000120297 0.03125 Refine grid Train\n",
145+
" 5 58 0.000120297 0.015625 Refine grid Train\n",
146+
" 6 66 0.000120297 0.00390625 Refine grid Train\n",
147+
" 7 69 2.70979e-05 0.00390625 Incremental search (ES-wcm) \n",
148+
" 7 74 2.70979e-05 0.000976562 Refine grid Train\n",
144149
"Optimization terminated: change in the function value less than options['tol_fun'].\n",
145-
"Function value at minimum: 7.97867122044391e-05\n",
150+
"Function value at minimum: 2.7097907605695835e-05\n",
146151
"\n"
147152
]
148153
}
@@ -173,8 +178,8 @@
173178
"name": "stdout",
174179
"output_type": "stream",
175180
"text": [
176-
"BADS minimum at: x_min = [1.00744247 1.01543427], fval = 7.979e-05\n",
177-
"total f-count: 67, time: 1.34 s\n"
181+
"BADS minimum at: x_min = [0.99709786 0.993772 ], fval = 2.71e-05\n",
182+
"total f-count: 75, time: 1.13 s\n"
178183
]
179184
}
180185
],
@@ -216,7 +221,7 @@
216221
"name": "python",
217222
"nbconvert_exporter": "python",
218223
"pygments_lexer": "ipython3",
219-
"version": "3.9.16"
224+
"version": "3.13.1"
220225
},
221226
"vscode": {
222227
"interpreter": {

pybads/bads/options.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ def load_options_file(
108108

109109
# evaluation_parameters
110110
for key, val in evaluation_parameters.items():
111-
exec(key + "=val")
111+
global_scope = globals()
112+
exec(f"{key} = {val}", global_scope)
112113

113114
options_list = _read_config_file(options_path)
114115
for (key, value, description) in options_list:

pybads/testing/bads/test_bads_optimization.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,37 @@ def test_univariate_input_and_opt():
6262
opt = BADS(rfn, x0, plausible_lower_bounds=plb, plausible_upper_bounds=pub)
6363
opt.optimize()
6464

65-
def test_1D_opt():
66-
D, x0, LB, UB, PLB, PUB, tol_errs = get_test_opt_conf(D=1)
67-
fun = lambda x: np.sum((np.atleast_2d(x) / np.arange(1, len(x) + 1) ** 2) ** 2)
65+
def test_1D_opt_ndarray():
66+
"""Test optimization with 1D inputs and nd arrays"""
67+
fun = lambda x: np.atleast_2d(x)**2
68+
x0 = np.array([[2.0]])
69+
LB = np.array([[-10.0]])
70+
UB = np.array([[10.0]])
71+
PLB = np.array([[-5.0]])
72+
PUB = np.array([[5.0]])
73+
tol_errs = np.array([0.1])
74+
run_bads(fun, x0, LB, UB, PLB, PUB, tol_errs, f_min=0.0, assert_flag=True)
75+
76+
def test_1D_opt_1darray():
77+
"""Test optimization with 1D inputs and 1D arrays"""
78+
fun = lambda x: np.atleast_2d(x)**2
79+
x0 = np.array([2.0])
80+
LB = np.array([-10.0])
81+
UB = np.array([10.0])
82+
PLB = np.array([-5.0])
83+
PUB = np.array([5.0])
84+
tol_errs = np.array([0.1])
85+
run_bads(fun, x0, LB, UB, PLB, PUB, tol_errs, f_min=0.0, assert_flag=True)
86+
87+
def test_1D_opt_scalar():
88+
"""Test optimization with scalar inputs"""
89+
fun = lambda x: np.atleast_2d(x)**2
90+
x0 = 2.0
91+
LB = -10.0
92+
UB = 10.0
93+
PLB = -5.0
94+
PUB = 5.0
95+
tol_errs = np.array([0.1])
6896
run_bads(fun, x0, LB, UB, PLB, PUB, tol_errs, f_min=0.0, assert_flag=True)
6997

7098
def test_high_dim_opt():

pybads/testing/decorators/test_handle_0D_1D_input_decorator.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@ def bar(self, x):
4949

5050
x = np.ones(10)
5151
assert np.ndim(Foo().bar(x)) == 0
52+
53+
# Test single value array
54+
x = np.array([1.0])
55+
assert np.ndim(Foo().bar(x)) == 0
56+
assert isinstance(Foo().bar(x), float)
57+
58+
# Test scalar input
59+
x = 1.0
60+
assert np.ndim(Foo().bar(x)) == 0
61+
assert isinstance(Foo().bar(x), float)
5262

5363

5464
def test_1D_return_multiple_returns():

pybads/testing/variable_transformer/test_variable_transformer.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,18 @@ def test_inverse_on_boundaries():
136136
X2 = np.ones((10, D)) * -10.
137137
assert np.all(np.isclose(X, X2))
138138

139+
def test_1D_transform():
140+
"""Test 1D variable transformation"""
141+
parameter_transformer = VariableTransformer(
142+
D=1,
143+
lower_bounds=np.array([[-10]]),
144+
upper_bounds=np.array([[10]]),
145+
)
146+
X = np.array([[3]])
147+
Y = parameter_transformer(X)
148+
Y2 = np.array([[0.3]])
149+
assert np.all(np.isclose(Y, Y2, atol=1e-04))
150+
139151
def test_inverse_min_space():
140152
parameter_transformer = VariableTransformer(
141153
D=D,

0 commit comments

Comments
 (0)