-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
This fixes a problem which appeared when using constraints and fixed parameters at the same time.It was caused due to constriants not being provided the fixed parameters in the same way that the objective function was. * Constraints are partialed with data before being passed to the minimizer, since minimizers don't know about data. * Partial constraints with fixed parameters. * Updated resize_jac to facilitate Constraint.eval_jacobian * Introduce ScipyConstrainedMinimize. This brings constraints on the same footing as jacobians by bringing the conversion to scipy constraints to a seperate subclass. Inherites from ScipyGradientMinimize because we need this to wrap the jacobian of the constraints in order to feed them to SLSQP, but this might be factored out because scipy's COBYLA does not accept a jacobian for it's constraints. * Made sure we cannot np.squeeze down to 0-dimensional * Cleaned up the inheretence tree. Now only SLSQP adds jacobians to constraints. Also, a COBYLA method has been added for gradient-less constrained optimization. * Use numpy masking to slice the jacobian to the right shape. * Added a wrapper to scipys COBYLA * Use @wraps on decorators * SLSQP has to pass the wrapped_jacobian explicitely. * Added very complete tests on the basis of #165. * Renamed wrap_func to a more descriptive list2kwargs * Added basic docstring to all objects in minimze.py * Fixed py27 issue by using functools32.wraps * Added a repeatable partial function for python versions older than 3.5 * Added tests for repeatable_partial * Made key2str use the type of the input Mapping * Prevent potential future namespace conflicts by renaming partial derivatives * Fixed minor autodoc indentation problem. * Removed a rogue print statement * Fixed some typos in the docstring * Changed the name of the file containg repeatable_partial to _repeatable_partial.py, and added comments.
- Loading branch information
Showing
8 changed files
with
293 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ numpy >= 1.12 | |
scipy >= 1.0 | ||
sympy <= 1.1.1 | ||
funcsigs; python_version < '3.0' | ||
functools32; python_version < '3.0' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
from functools import partial | ||
|
||
class repeatable_partial(partial): | ||
""" | ||
In python < 3.5, stacked partials on the same function do not add more args | ||
and kwargs to the function being partialed, but rather partial the | ||
partial. | ||
This is unlogical behavior, which has been corrected in py35. This objects | ||
rectifies this behavior in earlier python versions as well. | ||
""" | ||
def __new__(*args, **keywords): | ||
""" | ||
This is essentially just a copy-paste of python 3.5's __new__ method, | ||
but made python 2.7 friendly. | ||
:param args: | ||
:param keywords: | ||
:return: | ||
""" | ||
if not args: | ||
raise TypeError("descriptor '__new__' of partial needs an argument") | ||
if len(args) < 2: | ||
raise TypeError("type 'partial' takes at least one argument") | ||
cls = args[0] | ||
func = args[1] | ||
args = args[2:] | ||
if not callable(func): | ||
raise TypeError("the first argument must be callable") | ||
args = tuple(args) | ||
# I would prefer isinstance(func, partial), but the standard lib does | ||
# this so best copy that for now. | ||
if hasattr(func, "func"): | ||
args = func.args + args | ||
tmpkw = func.keywords.copy() | ||
tmpkw.update(keywords) | ||
keywords = tmpkw | ||
del tmpkw | ||
func = func.func | ||
|
||
return super(repeatable_partial, cls).__new__(cls, func, *args, **keywords) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.