Skip to content

Commit

Permalink
Fix pypesto.profile.parameter_profile incorrectly assuming symmetric …
Browse files Browse the repository at this point in the history
…bounds (#1166)

Use the correct bounds for checking whether we are done computing the profile.

Add test.

Closes #1165
  • Loading branch information
dweindl authored Oct 30, 2023
1 parent 8d3986d commit 2ca056c
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 7 deletions.
15 changes: 8 additions & 7 deletions pypesto/profile/walk_along_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,15 @@ def walk_along_profile(
x_now = current_profile.x_path[:, -1]

# check if the next profile point needs to be computed
if options.whole_path:
stop_profile = (
x_now[i_par] * par_direction >= problem.ub_full[[i_par]]
)
# ... check bounds
if par_direction == -1:
stop_profile = x_now[i_par] <= problem.lb_full[[i_par]]
elif par_direction == 1:
stop_profile = x_now[i_par] >= problem.ub_full[[i_par]]
else:
stop_profile = (
x_now[i_par] * par_direction >= problem.ub_full[[i_par]]
) or (current_profile.ratio_path[-1] < options.ratio_min)
raise AssertionError("par_direction must be -1 or 1")
if not options.whole_path:
stop_profile |= current_profile.ratio_path[-1] < options.ratio_min

if stop_profile:
break
Expand Down
48 changes: 48 additions & 0 deletions test/profile/test_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,51 @@ def test_options_valid():
min_step_size=2,
max_step_size=1,
)


@pytest.mark.parametrize(
"lb,ub",
[(6 * np.ones(5), 10 * np.ones(5)), (-4 * np.ones(5), 1 * np.ones(5))],
)
def test_gh1165(lb, ub):
"""Regression test for https://github.com/ICB-DCM/pyPESTO/issues/1165
Check profiles with non-symmetric bounds and whole_path=True span the full parameter domain.
"""
obj = rosen_for_sensi(max_sensi_order=1)['obj']

problem = pypesto.Problem(
objective=obj,
lb=lb,
ub=ub,
)

optimizer = optimize.ScipyOptimizer(options={'maxiter': 10})
result = optimize.minimize(
problem=problem,
optimizer=optimizer,
n_starts=2,
progress_bar=False,
)
# just any parameter
par_idx = 1
profile.parameter_profile(
problem=problem,
result=result,
optimizer=optimizer,
next_guess_method='fixed_step',
profile_index=[par_idx],
progress_bar=False,
profile_options=profile.ProfileOptions(
min_step_size=0.1,
delta_ratio_max=0.05,
default_step_size=0.5,
ratio_min=0.01,
whole_path=True,
),
)
# parameter value of the profiled parameter
x_path = result.profile_result.list[0][par_idx]['x_path'][par_idx, :]
# ensure we cover lb..ub
assert x_path[0] == lb[par_idx], (x_path.min(), lb[par_idx])
assert x_path[-1] == ub[par_idx], (x_path.max(), ub[par_idx])

0 comments on commit 2ca056c

Please sign in to comment.