GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Update find_eqpt to find_operating_point, adding root_method + better docs by murrayrm · Pull Request #1054 · python-control/python-control Conversation
Member
This PR is motivated by discussion #1053 in which a situation the current implementation of In addition, while looking through this (fairly old) code, it seemed worth making some additional changes:
In the context of #1053, a solution to the issue there can be obtained by calling
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
|
There was an error while loading. Please reload this page.
|
coverage: 94.692% (-0.002%) from 94.694% |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Good improvements! I made several comments to consider before merging.
I ran the example that originally motivated this pull request, and I confirmed the result is as expected after adding the new argument root_method='lm'.
Note that other files in examples/ besides cruise-control.py use find_eqpt(). However, it is now an alias for find_operating_point() without any indication of being deprecated, so OK to leave the other examples for now.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| np.testing.assert_allclose(linsys_orig.C, linsys_oppt.C) | ||
| np.testing.assert_allclose(linsys_orig.D, linsys_oppt.D) | ||
|
|
||
| # Call find_operating point with method and keyword arguments |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| # Call find_operating point with method and keyword arguments | |
| # Call find_operating_point with method and keyword arguments |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| params : dict, optional | ||
| Parameter values for the system. Passed to the evaluation functions | ||
| Parameter values for the system. Passed to the evaluation functions |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
The indentation step size is 4 spaces, but this change is to 3 spaces. Was this an accident?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
| """ | ||
| def __init__( | ||
| self, states, inputs=None, outputs=None, result=None, |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| self, states, inputs=None, outputs=None, result=None, | |
| self, states, inputs, outputs=None, result=None, |
inputs parameter is not optional.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
|
||
|
|
||
| # Test out new operating point version of find_eqpt | ||
| # TODO: add return_)y tests |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
There is a test below (function test_operating_point) that uses return_y. Is something else intended with this TODO?
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| return_y : bool, optional | ||
| If True, return the value of output at the equilibrium point. | ||
| fixed at `dx0` in searching for an operating point. | ||
| root_method : str, optonal |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| root_method : str, optonal | |
| root_method : str, optional |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| def find_operating_point( | ||
| sys, x0, u0=None, y0=None, t=0, params=None, iu=None, iy=None, | ||
| ix=None, idx=None, dx0=None, root_method=None, root_kwargs=None, | ||
| return_outputs=None, return_result=None, **kwargs): |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| return_outputs=None, return_result=None, **kwargs): | |
| return_outputs=False, return_result=False, **kwargs): |
return_outputs and return_result are not used in a way where the distinction between None and False matters. I recommend to write the default value in the expected type, i.e., False, because the docstring shows these as bool, optional without explicitly stating the default value, so users will look at the function signature and may be confused if it is None.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
This needs to be None in order for the legacy keyword handling to work: if both return_y and return_outputs are specified, _process_legacy_keyword will raise an exception. Thus with this change, setting the default value of return_outputs to False would mean that if you call find_operating_point with return_y, you get an exception instead of a warning.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| iu=None, iy=None, ix=None, idx=None, dx0=None, | ||
| return_y=False, return_result=False): | ||
| """Find the equilibrium point for an input/output system. | ||
| class OperatingPoint(object): |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Python 3 has classes inherit from object by default, so writing explicitly is not required: https://docs.python.org/3/reference/compound_stmts.html#class-definitions
However, I am not aware of a style recommendation. black does not add (object) and does not remove it, but the standard Python tutorial gives examples without explicit object: https://docs.python.org/3/tutorial/classes.html#class-objects
I forgot to make this comment on a recent pull request that I reviewed where a new class was defined. Anyway, we can keep explicit object inheritance for consistency with existing code and consider removing it later to be more concise.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Since we are using Python 3 and that only supports new classes, I think we should move to not inheriting from object (which is how things are done in the official documentation).
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| self.inputs = inputs | ||
|
|
||
| if outputs is None and return_outputs and not return_result: | ||
| raise SystemError("return_outputs specified by no y0 value") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| raise SystemError("return_outputs specified by no y0 value") | |
| raise SystemError("return_outputs specified but no y0 value") |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Here and below are both non-standard uses of SystemError, which normally is for "when the [Python] interpreter finds an internal error". I recommend ValueError instead, which is also used elsewhere in this module for inconsistent arguments.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| self.return_outputs = return_outputs | ||
|
|
||
| if result is None and return_result: | ||
| raise SystemError("return_result specified by no result value") |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| raise SystemError("return_result specified by no result value") | |
| raise SystemError("return_result specified but no result value") |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| X0, U0, Y0 = ct.find_eqpt( | ||
| X0, U0, Y0 = ct.find_operating_point( | ||
| cruise_pi, [vref[0], 0], [vref[0], gear[0], theta0[0]], | ||
| y0=[0, vref[0]], iu=[1, 2], iy=[1], return_y=True) |
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
| y0=[0, vref[0]], iu=[1, 2], iy=[1], return_y=True) | |
| y0=[0, vref[0]], iu=[1, 2], iy=[1], return_outputs=True) |
Update the argument to avoid a FutureWarning being raised in the example.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Similarly, return_y=True in examples/cruise.ipynb should be updated, too.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.