8000 MAINT: optimize.bracket: don't fail silently by mdhaber · Pull Request #17704 · scipy/scipy · GitHub
[go: up one dir, main page]

Skip to content

MAINT: optimize.bracket: don't fail silently #17704

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

Merged
merged 17 commits into from
May 13, 2023
Merged

Conversation

mdhaber
Copy link
Contributor
@mdhaber mdhaber commented Jan 2, 2023

Reference issue

Closes gh-14858

What does this implement/fix?

gh-14858 reported that scipy.optimize.bracket may silently return an invalid bracket, causing scalar minimization functions to fail. This PR resolves the issue by checking for failure before returning. It also begins to improve the function documentation and tests.

Update: bracket is used in brent, golden, and minimize_scalar with methods 'brent' and 'golden'. It's probably appropriate for brent and golden to raise errors when bracket fails, but minimize_scalar should terminate gracefully with success=False. This requires plumbing the status information from bracket through the optimizers, which could this PR quite a bit more complex than intended - see a6aa40d. I ended up refactoring it that makes it much simpler, albeit a bit unorthodox.

Additional information

In main, bracket is not tested outside of minimize_scalar, and the documentation is not explicit about the function's behavior. This is intended to be an improvement, but more work is certainly needed in followup PRs. For instance, this function still needs:

  • A reference
  • A description of what the function does and how to select the initial points. Besides expanding the bracket by the golden ratio, I don't really know the other things it tries.
  • Unit tests (separate from minimize_scalar)
  • (Possibly) Improvements to mitigate difficulties caused be erroneous documentation (minimize_scalar -- strange behaviour #5899 (comment))

For this PR, let's stick within the existing scope of fixing gh-14858 and these doc improvements so as not to delay progress.

@mdhaber mdhaber added scipy.optimize maintenance Items related to regular maintenance tasks labels Jan 2, 2023
@mdhaber mdhaber requested a review from andyfaff as a code owner January 2, 2023 22:46
@mdhaber mdhaber marked this pull request as draft January 3, 2023 08:01
@mdhaber mdhaber marked this pull request as ready for review January 5, 2023 21:53
@mdhaber mdhaber marked this pull request as draft January 5, 2023 23:18
Copy link
Contributor Author
@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.

Some self-review to aid the reviewer.

@mdhaber mdhaber marked this pull request as ready for review January 20, 2023 23:28
args : tuple, optional
Additional arguments (if present), passed to `func`.
grow_limit : float, optional
Maximum grow limit. Defaults to 110.0
maxiter : int, optional
Maximum number of iterations to perform. Defaults to 1000.

Raises
Copy link
Member

Choose a reason for hiding this comment

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

Think this should be between returns and notes as per https://numpydoc.readthedocs.io/en/latest/format.html#sections

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ugh I even looked at the standards to confirm; then I went and put it in the wrong place. I'll fix it.

if np.any(np.isnan([xs, fs])):
x, fun = np.nan, np.nan
else:
imin = np.argmin(xs)
Copy link
Member

Choose a reason for hiding this comment

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

Possible mistake?

Suggested change
imin = np.argmin(xs)
imin = np.argmin(fs)

Copy link
Contributor Author
@mdhaber mdhaber May 12, 2023

Choose a reason for hiding this comment

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

Unfortunately, I'm having trouble coming up with a realistic test case that exercises this with minimize_scalar. Sure, we could simulate calling _recover_from_backet_error with an artificial solve argument that raises a BracketError with out-of-order xs and fs and show that this picks the right one, but I don't think it's worth it.

@j-bowhay j-bowhay added this to the 1.11.0 milestone May 13, 2023
Copy link
Member
@j-bowhay j-bowhay left a comment

Choose a reason for hiding this comment

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

LGTM, thanks @mdhaber

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.optimize
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BUG: scipy.optimize.bracket sometimes fails silently
2 participants
0