Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAINT: Add graceful handling of invalid initial brackets to elementwise bracket finding functions #20685

Merged
merged 9 commits into from May 13, 2024

Conversation

steppi
Copy link
Contributor

@steppi steppi commented May 9, 2024

Reference issue

What does this implement/fix?

This PR updates the private _bracket_minimum and _bracket_root functions from scipy.optimize._bracket to gracefully handle cases where the initial bracket is invalid. Previously a ValueError was raised if any invalid initial brackets appear among the set of input initial brackets (these are vectorized functions which can takes arrays for bracket endpoints and other parameters). These functions have been updated to terminate in the cases where the initial bracket is invalid with an exit status indicating a failure due to an invalid initial bracket. All other cases proceed as usual.

Additional information

In scipy.optimize.tests.test_bracket, I moved all of the relevant test cases from the test_input_validation test methods into the corresponding test_flags test methods. This might be overkill, so I'm happy to remove some of these if you think that's fine @mdhaber; right now a majority of test_flags test cases are due to invalid initial brackets.

I called the error code _EINPUTERR, but would be open to suggestions. I didn't put much thought into this name. The way I implemented this is pretty clean for _bracket_minimum but gets a little convoluted with _bracket_root due to having to work with trickery involved to get the left and right searches to proceed together.

@steppi steppi requested a review from mdhaber May 9, 2024 23:16
@steppi steppi requested a review from andyfaff as a code owner May 9, 2024 23:16
@steppi steppi removed the request for review from andyfaff May 9, 2024 23:16
@github-actions github-actions bot added scipy.optimize scipy._lib maintenance Items related to regular maintenance tasks labels May 9, 2024
scipy/optimize/_bracket.py Outdated Show resolved Hide resolved
@mdhaber
Copy link
Contributor

mdhaber commented May 9, 2024

gets a little convoluted with _bracket_root due to having to work with trickery involved to get the left and right searches to proceed together

For the sake of simplicity (future maintenance, array API conversion) I've wondered whether we should restrict _bracket_root to search downhill. If you agree, I'd like to get a few more informed opinions before we remove the uphill search, though.

scipy/optimize/_bracket.py Outdated Show resolved Hide resolved
scipy/optimize/_bracket.py Outdated Show resolved Hide resolved
@@ -246,11 +255,13 @@ def post_func_eval(x, f, work):

def check_termination(work):
stop = np.zeros_like(work.x, dtype=bool)
# Condition 0: initial bracket is invalid
stop[work.status == eim._EINPUTERR] = True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A special case that I don't really want to deal with is xl0 == xr0 == true_root : ( Maybe we should just add a note about it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't addressed this yet. I'd rather not deal with that case either. It looks like the documentation currently doesn't even mention that xmin <= xl0 < xm0 < xr0 <= xmax is needed. I think just adding a note about that should be enough; the behavior will be exactly as documented.

Copy link
Contributor Author

@steppi steppi May 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just put things like this

 - ``-5`` : The initial bracket does not satisfy
              `xmin <= xl0 < xm0 < xr0 <= xmax`.

when documenting the error codes. Do you think that's sufficient, or should this go somewhere else as well? I was thinking of putting it in the Parameters documentation, but wasn't sure where to include it, since it pertains to every one of these bracket parameters. I guess it could go in the xm0 section, stating that the parameters are defined below; or in the xmin, xmax section.

scipy/optimize/_bracket.py Outdated Show resolved Hide resolved
Comment on lines 160 to 161
lambda x: x,
lambda x: x]
Copy link
Contributor

@mdhaber mdhaber May 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we only need to have one example of each status code here; I'd prefer that rather than having one example of the first few code and many examples of the last code. My intent when writing this test was to show that the codes could all be different; it really is elementwise. There could be a separate function to test the logic for generating this status code with many different cases, if desired (i.e. all possible invalid orderings). But maybe the most natural example here would be to have everything in reverse order, xmin > xl0 > xr0 > xmax.

Copy link
Contributor

@mdhaber mdhaber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I think I have a simplification. Hopefully I'm not hallucinating!

@mdhaber
Copy link
Contributor

mdhaber commented May 13, 2024

Thanks @steppi!

@mdhaber mdhaber merged commit 1c0bdc4 into scipy:main May 13, 2024
29 of 31 checks passed
@tylerjereddy tylerjereddy modified the milestone: 1.14.0 May 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
maintenance Items related to regular maintenance tasks scipy._lib scipy.optimize
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants