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

Changed return of prob.run_driver() from a bool to an object containing information about the Driver execution. #3214

Merged
merged 29 commits into from
May 20, 2024

Conversation

robfalck
Copy link
Contributor

@robfalck robfalck commented May 1, 2024

Summary

This is the first of several implementation changes in support of POEM 094.

Users were finding the fact that run_driver returned True if something had failed to be confusing.

To address this, a new DriverResult object has been added, containing the information previously stored in driver.opt_result.
This DriverResult object exists for all drivers, including non-optimization ones, so it is now stored in Driver.result.
Previously, ScipyOptimizeDriver stored scipy's OptimizeResult object as driver.result, but this is now changed to scipy_optimize_result.

DOEDriver now successfully populates the attributes of DriverResult.
Hooks have been added, though not yet implemented, to allow drivers to add driver/optimizer-specific attributes to the DriverResults object.

DriverResult currently overrides __bool__ with a deprecation warning to retain existing behavior.

Related Issues

Backwards incompatibilities

ScipyOptimizeDriver.result is now a DriverResults object. Scipy-specific OptimizeResult objects are now stored in ScipyOptimizeDriver._scipy_optimize_result, though some of this information will be added to the DriverResult object.

New Dependencies

None

…success" which is the inverse of the previous return value of

prob.run_driver.

Inidividual driver .run() methods should still return fail, this minimizes breaking backwards compatibility.

Drivers may now override _update_results to populate driver results with additional data.
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@robfalck robfalck marked this pull request as draft May 1, 2024 18:50
@coveralls
Copy link

coveralls commented May 1, 2024

Coverage Status

coverage: 86.997%. first build
when pulling 18033e7 on robfalck:i3206_2
into 5eb923f on OpenMDAO:master.

@robfalck robfalck marked this pull request as ready for review May 3, 2024 19:45
self.iter_count = 0
self.obj_calls = 0
self.deriv_calls = 0
self.exit_status = 'NOT_RUN'
Copy link
Member

Choose a reason for hiding this comment

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

In Aviary and MBSE, we have been using python enums for things like this. It makes it easer for someone coding a new driver, so that they can just import the enum and select one of the exit statuses instead of accidentally making up a new string. (Of course, if they really do have a new kind of status, they can add that to the enum.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, this isn't a new addition though. This is someothing that's alread existent that the optimization report relies upon.

Copy link
Member

@Kenneth-T-Moore Kenneth-T-Moore left a comment

Choose a reason for hiding this comment

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

Approve, but make sure to look at my comment. That can be a future consideration if you want.

"""
self.runtime = 0.0
self.iter_count = 0
self.obj_calls = 0
Copy link
Member

Choose a reason for hiding this comment

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

What do you think about maybe keeping track of runtime for obj_calls and deriv_calls separately? Might be nice to know where the time is being spent.

@@ -87,8 +158,8 @@ class Driver(object):
Cached total jacobian handling object.
_total_jac_linear : _TotalJacInfo or None
Cached linear total jacobian handling object.
opt_result : dict
Dictionary containing information for use in the optimization report.
result : dict
Copy link
Contributor

Choose a reason for hiding this comment

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

type is DriverResult vs dict..

@robfalck robfalck requested a review from naylor-b May 15, 2024 19:28
Parameters
----------
kind : str
One of 'obj' or 'deriv', specifying which statistics should be accumulated.
Copy link
Member

Choose a reason for hiding this comment

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

maybe pedantic, but i don't know about this being called 'obj', since you don't always have an objective (and, when you do want an objective, you want the constraints too, which also come along for free.) I know that I can't just say this without offering some alternatives ...

"compute" , "compute_totals"
"function", "gradient" (note, this allows for our future "hessian")
"eval", "deriv_eval"

@staticmethod
def track_stats(kind):
"""
Decorate methods to tracks either the objective the deriv time and call count for a Driver.
Copy link
Member

Choose a reason for hiding this comment

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

should be 'to track' instead of 'to tracks'

Decorate methods to tracks either the objective the deriv time and call count for a Driver.

This decorator should be applied to the _objfunc or _gradfunc (or equivalent) methods
of drivers. It will either accumulated the elapsed time in driver.result.obj_time or
Copy link
Member

Choose a reason for hiding this comment

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

acumulated --> acumulate

@@ -183,7 +183,7 @@
"metadata": {},
"outputs": [],
"source": [
"fail = prob.run_driver()"
Copy link
Contributor

Choose a reason for hiding this comment

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

as future work, we may want to add a __repr__ so that this displays as e.g. a dict in notebooks

@@ -73,6 +77,8 @@ def __init__(self, generator=None, **kwargs):
self._name = ''
self._problem_comm = None
self._color = None
self._num_model_evals = 0
self._num_deriv_evals = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see where these attributes are consumed, they seem redundant with the decorator.. am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Bah you're right.

@@ -723,7 +877,7 @@ def get_driver_objective_calls(self):
int
Number of objective evaluations made during a driver run.
"""
return 0
return self.result.model_evals
Copy link
Contributor

@swryan swryan May 17, 2024

Choose a reason for hiding this comment

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

The change in terminology makes me wonder if these method names should be deprecated in favor of get_driver_model_evals and get_driver_deriv_evals.

But then I'm not sure why these public methods need to exist... they were only used to populate the opt_result, which is no longer the case. They are not documented anywhere for the user (outside of source docs)...

So maybe these methods should be deprecated entirely in favor of just using the result object.

Also I see that differential_evolution driver overrides the get_objective_calls method, but this doesn't end up affecting the result object now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Changed them to being deprecated and removed their override in DifferentialEvolutionDriver.

@swryan swryan merged commit 60cce99 into OpenMDAO:master May 20, 2024
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

POEM 094 Part I: DriverResults
5 participants