@@ -14,13 +14,12 @@ using namespace ROOT::Math;
1414using namespace ROOT ::Math::Experimental;
1515using namespace ROOT ::Fit;
1616
17-
1817// / function wrapper for the function to be minimized
1918const ROOT::Math::IMultiGenFunction *gFunction ;
2019// / function wrapper for the gradient of the function to be minimized
2120const ROOT::Math::IMultiGradFunction *gGradFunction ;
2221
23- PyObject * target_function (PyObject */*self*/, PyObject *args)
22+ PyObject *target_function (PyObject * /* self*/ , PyObject *args)
2423{
2524 PyArrayObject *arr = (PyArrayObject *)PyTuple_GetItem (args, 0 );
2625
@@ -30,7 +29,6 @@ PyObject * target_function(PyObject */*self*/, PyObject *args)
3029 return PyFloat_FromDouble (r);
3130};
3231
33-
3432// _______________________________________________________________________
3533ScipyMinimizer::ScipyMinimizer () : BasicMinimizer()
3634{
@@ -39,11 +37,8 @@ ScipyMinimizer::ScipyMinimizer() : BasicMinimizer()
3937 if (!PyIsInitialized ()) {
4038 PyInitialize ();
4139 }
42-
4340}
4441
45-
46-
4742// _______________________________________________________________________
4843ScipyMinimizer::ScipyMinimizer (const char *type)
4944{
@@ -59,22 +54,17 @@ void ScipyMinimizer::PyInitialize()
5954{
6055 static PyObject *ParamsError;
6156 static PyMethodDef ParamsMethods[] = {
62- {" target_function" , target_function, METH_VARARGS,
63- " Target function to minimize." },
64- {NULL , NULL , 0 , NULL } /* Sentinel */
57+ {" target_function" , target_function, METH_VARARGS, " Target function to minimize." },
58+ {NULL , NULL , 0 , NULL } /* Sentinel */
6559 };
6660
67- static struct PyModuleDef paramsmodule = {
68- PyModuleDef_HEAD_INIT,
69- " params" , /* name of module */
70- " ROOT Scipy parameters" , /* module documentation, may be NULL */
71- -1 , /* size of per-interpreter state of the module,
72- or -1 if the module keeps state in global variables. */
73- ParamsMethods
74- };
61+ static struct PyModuleDef paramsmodule = {PyModuleDef_HEAD_INIT, " params" , /* name of module */
62+ " ROOT Scipy parameters" , /* module documentation, may be NULL */
63+ -1 , /* size of per-interpreter state of the module,
64+ or -1 if the module keeps state in global variables. */
65+ ParamsMethods};
7566
76- auto PyInit_params = [](void )->PyObject *
77- {
67+ auto PyInit_params = [](void ) -> PyObject * {
7868 PyObject *m;
7969
8070 m = PyModule_Create (¶msmodule);
@@ -99,15 +89,15 @@ void ScipyMinimizer::PyInitialize()
9989
10090 bool pyIsInitialized = PyIsInitialized ();
10191 if (!pyIsInitialized) {
102- Py_Initialize (); // Python initialization
92+ Py_Initialize (); // Python initialization
10393 }
10494 fLocalNS = PyDict_New ();
10595 fGlobalNS = PyDict_New ();
10696
10797 if (!pyIsInitialized) {
10898 _import_array (); // Numpy initialization
10999 }
110- // Scipy initialization
100+ // Scipy initialization
111101 PyRunString (" from scipy.optimize import minimize" );
112102 fMinimize = PyDict_GetItemString (fLocalNS , " minimize" );
113103 PyRunString (" from params import target_function" );
@@ -118,76 +108,87 @@ void ScipyMinimizer::PyInitialize()
118108// Finalize Python interpreter
119109void ScipyMinimizer::PyFinalize ()
120110{
121- if (fMinimize ) Py_DECREF (fMinimize );
111+ if (fMinimize )
112+ Py_DECREF (fMinimize );
122113 Py_Finalize ();
123114}
124115
125116// _______________________________________________________________________
126117int ScipyMinimizer::PyIsInitialized ()
127118{
128- if (!Py_IsInitialized ()) return kFALSE ;
119+ if (!Py_IsInitialized ())
120+ return kFALSE ;
129121 return kTRUE ;
130122}
131123
132124// _______________________________________________________________________
133- ScipyMinimizer::~ScipyMinimizer ()
134- {
135- }
125+ ScipyMinimizer::~ScipyMinimizer () {}
136126
137127// _______________________________________________________________________
138128bool ScipyMinimizer::Minimize ()
139129{
140- (gFunction )= ObjFunction ();
130+ (gFunction ) = ObjFunction ();
141131 (gGradFunction ) = GradObjFunction ();
142132 auto method = fOptions .MinimizerAlgorithm ();
143133
144- std::cout<<" === Scipy Minimization" <<std::endl;
145- std::cout<<" === Method: " <<method<<std::endl;
146- std::cout<<" === Initial value: (" ;
147- for (uint i=0 ;i<NDim ();i++ )
148- {
149- std::cout<<X ()[i];
150- if (i<NDim ()-1 )
151- std::cout<<" ," ;
134+ std::cout << " === Scipy Minimization" << std::endl;
135+ std::cout << " === Method: " << method << std::endl;
136+ std::cout << " === Initial value: (" ;
137+ for (uint i = 0 ; i < NDim (); i++) {
138+ std::cout << X ()[i];
139+ if (i < NDim () - 1 )
140+ std::cout << " ," ;
152141 }
153- std::cout<< " )" << std::endl;
142+ std::cout << " )" << std::endl;
154143
155- double *values = const_cast <double *>(X ());
156- npy_intp dims[1 ] = { NDim ()};
157- PyObject *py_array= PyArray_SimpleNewFromData (1 , dims, NPY_DOUBLE, values);
144+ double *values = const_cast <double *>(X ());
145+ npy_intp dims[1 ] = {NDim ()};
146+ PyObject *py_array = PyArray_SimpleNewFromData (1 , dims, NPY_DOUBLE, values);
158147
159- PyObject *pargs= PyTuple_New (0 );
148+ PyObject *pargs = PyTuple_New (0 );
160149
161- auto pyvalues = Py_BuildValue (" (OOOs)" ,fTarget ,py_array,pargs,method.c_str ());
150+ auto pyvalues = Py_BuildValue (" (OOOs)" , fTarget , py_array, pargs, method.c_str ());
162151
163- PyObject *result = PyObject_CallObject (fMinimize ,pyvalues);
152+ PyObject *result = PyObject_CallObject (fMinimize , pyvalues);
164153 Py_DECREF (pyvalues);
165154 Py_DECREF (py_array);
166155
167-
168- // if the minimization works
169- PyObject *pstatus = PyObject_GetAttrString (result," status" );
170- bool status = PyBool_Check (pstatus );
156+ // if the minimization works
157+ PyObject *pstatus = PyObject_GetAttrString (result, " status" );
158+ bool status = PyBool_Check (pstatus);
171159 Py_DECREF (pstatus);
172160
173- // the x values for the minimum
174- PyArrayObject *pyx = (PyArrayObject *)PyObject_GetAttrString (result," x" );
175- const double *x =(const double *)PyArray_DATA (pyx);
161+ // the x values for the minimum
162+ PyArrayObject *pyx = (PyArrayObject *)PyObject_GetAttrString (result, " x" );
163+ const double *x = (const double *)PyArray_DATA (pyx);
176164 Py_DECREF (pyx);
177165
166+ // number of function evaluations
167+ PyObject *pynfev = PyObject_GetAttrString (result, " nfev" );
168+ long nfev = PyLong_AsLong (pynfev);
169+ Py_DECREF (pynfev);
170+
171+ PyObject *pymessage = PyObject_GetAttrString (result, " message" );
172+ const char *message = (const char *)PyUnicode_DATA (pymessage);
173+ Py_DECREF (pymessage);
174+
178175 SetFinalValues (x);
179176 auto obj_value = (*gFunction )(x);
180177 SetMinValue (obj_value);
181178
179+ std::cout << " === Status: " << status << std::endl;
180+ std::cout << " === Message: " << message << std::endl;
181+ std::cout << " === Function calls: " << nfev << std::endl;
182182 return status;
183183}
184184
185185// _______________________________________________________________________
186- void ScipyMinimizer::PyRunString (TString code, TString errorMessage, int start) {
186+ void ScipyMinimizer::PyRunString (TString code, TString errorMessage, int start)
187+ {
187188 auto fPyReturn = PyRun_String (code, start, fGlobalNS , fLocalNS );
188189 if (!fPyReturn ) {
189- auto msg = errorMessage + Form (" \n code = \" %s\" " ,code.Data ());
190- MATH_ERROR_MSG (" ScipyMinimizer::PyRunString" , msg.Data () );
190+ auto msg = errorMessage + Form (" \n code = \" %s\" " , code.Data ());
191+ MATH_ERROR_MSG (" ScipyMinimizer::PyRunString" , msg.Data ());
191192 PyErr_Print ();
192193 exit (1 );
193194 }
0 commit comments