Skip to content

Commit cd8824d

Browse files
committed
Scipy: fixed bounds, if there is not bounds It will pass Py_None
added verbose output, to check parameters passed to the minimizer and output returned
1 parent 1b4bb60 commit cd8824d

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

math/scipy/src/ScipyMinimizer.cxx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ ScipyMinimizer::ScipyMinimizer() : BasicMinimizer()
7474
fOptions.SetMinimizerType("Scipy");
7575
fOptions.SetMinimizerAlgorithm("L-BFGS-B");
7676
PyInitialize();
77-
fHessianFunc = [](const std::vector<double> &, double *) -> bool { return false; };
77+
fHessianFunc = nullptr;
7878
// set extra options
7979
SetAlgoExtraOptions();
8080
fConstraintsList = PyList_New(0);
@@ -88,7 +88,7 @@ ScipyMinimizer::ScipyMinimizer(const char *type)
8888
fOptions.SetMinimizerType("Scipy");
8989
fOptions.SetMinimizerAlgorithm(type);
9090
PyInitialize();
91-
fHessianFunc = [](const std::vector<double> &, double *) -> bool { return false; };
91+
fHessianFunc = nullptr;
9292
// set extra options
9393
SetAlgoExtraOptions();
9494
fConstraintsList = PyList_New(0);
@@ -98,7 +98,6 @@ ScipyMinimizer::ScipyMinimizer(const char *type)
9898
//_______________________________________________________________________
9999
void ScipyMinimizer::SetAlgoExtraOptions()
100100
{
101-
std::string type = fOptions.MinimizerAlgorithm();
102101
SetExtraOptions(fExtraOpts);
103102
}
104103

@@ -201,7 +200,7 @@ bool ScipyMinimizer::Minimize()
201200
if (gGradFunction == nullptr) {
202201
fJacobian = Py_None;
203202
}
204-
if (!gfHessianFunction) {
203+
if (gfHessianFunction == nullptr) {
205204
fHessian = Py_None;
206205
}
207206
auto method = fOptions.MinimizerAlgorithm();
@@ -234,16 +233,19 @@ bool ScipyMinimizer::Minimize()
234233
PyObject *pybounds_args = PyTuple_New(2);
235234
PyObject *pylimits_lower = PyList_New(NDim());
236235
PyObject *pylimits_upper = PyList_New(NDim());
236+
bool foundBounds = false;
237237
for (unsigned int i = 0; i < NDim(); i++) {
238238
ParameterSettings varsettings;
239239

240240
if (GetVariableSettings(i, varsettings)) {
241241
if (varsettings.HasLowerLimit()) {
242+
foundBounds=true;
242243
PyList_SetItem(pylimits_lower, i, PyFloat_FromDouble(varsettings.LowerLimit()));
243244
} else {
244245
PyList_SetItem(pylimits_lower, i, PyFloat_FromDouble(-NPY_INFINITY));
245246
}
246247
if (varsettings.HasUpperLimit()) {
248+
foundBounds=true;
247249
PyList_SetItem(pylimits_upper, i, PyFloat_FromDouble(varsettings.UpperLimit()));
248250
} else {
249251
PyList_SetItem(pylimits_upper, i, PyFloat_FromDouble(NPY_INFINITY));
@@ -252,24 +254,37 @@ bool ScipyMinimizer::Minimize()
252254
MATH_ERROR_MSG("ScipyMinimizer::Minimize", Form("Variable index = %d not found", i));
253255
}
254256
}
255-
PyTuple_SetItem(pybounds_args, 0, pylimits_lower);
256-
PyTuple_SetItem(pybounds_args, 1, pylimits_upper);
257-
258-
PyObject *pybounds = PyObject_CallObject(fBoundsMod, pybounds_args);
259-
257+
PyObject *pybounds = Py_None;
258+
if(foundBounds)
259+
{
260+
PyTuple_SetItem(pybounds_args, 0, pylimits_lower);
261+
PyTuple_SetItem(pybounds_args, 1, pylimits_upper);
262+
pybounds = PyObject_CallObject(fBoundsMod, pybounds_args);
263+
}
264+
260265
// minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None,
261266
// callback=None, options=None)
262267
PyObject *args = Py_BuildValue("(OO)", fTarget, x0);
263268
PyObject *kw = Py_BuildValue("{s:s,s:O,,s:O,s:O,s:O,s:d,s:O}", "method", method.c_str(), "jac", fJacobian, "hess",
264269
fHessian, "bounds", pybounds,"constraints",fConstraintsList, "tol", Tolerance(),
265270
"options", pyoptions);
266-
271+
if(PrintLevel()>0)
272+
{
273+
std::cout<<"========Minimizer Parameters========\n";
274+
PyPrint(kw);
275+
std::cout<<"====================================\n";
276+
}
267277
PyObject *result = PyObject_Call(fMinimize, args, kw);
268278
if (result == NULL) {
269279
PyErr_Print();
270280
return false;
271281
}
272-
// PyPrint(result);
282+
if(PrintLevel()>0)
283+
{
284+
std::cout<<"========Minimizer Results========\n";
285+
PyPrint(result);
286+
std::cout<<"=================================\n";
287+
}
273288
Py_DECREF(pybounds);
274289
Py_DECREF(args);
275290
Py_DECREF(kw);
@@ -304,12 +319,14 @@ bool ScipyMinimizer::Minimize()
304319
auto obj_value = (*gFunction)(x);
305320
SetMinValue(obj_value);
306321
fCalls = nfev; // number of function evaluations
307-
308322
std::cout << "=== Success: " << success << std::endl;
309323
std::cout << "=== Status: " << status << std::endl;
310324
std::cout << "=== Message: " << message << std::endl;
311325
std::cout << "=== Function calls: " << nfev << std::endl;
312326
if(success) fStatus=0;
327+
else fStatus = status; //suggested by Lorenzo.
328+
329+
Py_DECREF(result);
313330
return success;
314331
}
315332

0 commit comments

Comments
 (0)