From c31be04f6ac79ca934e904c12e7d68a3c308063c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filipe=20Brand=C3=A3o?= Date: Tue, 6 Jul 2021 16:14:26 +0100 Subject: [PATCH] Return PyDict in getSolutionDict (workaround for #2) --- python/common-python-extensions.i | 22 +++++---- python/cplex/amplpy_cplex/patch.py | 10 ---- .../swig/amplpy_cplex_swig_wrap.cxx | 46 ++++++++++--------- python/gurobi/amplpy_gurobi/patch.py | 10 ---- .../swig/amplpy_gurobi_swig_wrap.cxx | 46 ++++++++++--------- 5 files changed, 60 insertions(+), 74 deletions(-) diff --git a/python/common-python-extensions.i b/python/common-python-extensions.i index 4b5c01a..c79b3a9 100644 --- a/python/common-python-extensions.i +++ b/python/common-python-extensions.i @@ -1,25 +1,27 @@ -%extend ampls::AMPLModel{ - std::map _getSolutionDict() { + +%extend ampls::AMPLModel{ + PyObject* getSolutionDict() { + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } } %extend ampls::impl::BaseCallback{ - - std::map _getSolutionDict() { + PyObject* getSolutionDict() { + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } } \ No newline at end of file diff --git a/python/cplex/amplpy_cplex/patch.py b/python/cplex/amplpy_cplex/patch.py index 8bc928b..504e3fb 100644 --- a/python/cplex/amplpy_cplex/patch.py +++ b/python/cplex/amplpy_cplex/patch.py @@ -1,10 +1,6 @@ import types -def getSolutionDict(self): - return dict(self._getSolutionDict()) - - def setCallback(self, cb): def run(self): try: @@ -15,8 +11,6 @@ def run(self): cb._run = cb.run cb.run = types.MethodType(run, cb) - # Workaround for issue #2 - cb.getSolutionDict = types.MethodType(getSolutionDict, cb) super(type(cb), cb).__init__() self._setCallback(cb) @@ -42,8 +36,6 @@ def exportCplexModel(self, options=None): os.remove(fname + '.nl') model._setCallback = model.setCallback model.setCallback = types.MethodType(setCallback, model) - # Workaround for issue #2 - model.getSolutionDict = types.MethodType(getSolutionDict, model) return model except: shutil.rmtree(tmp) @@ -76,8 +68,6 @@ def exportGurobiModel(self, options=None): os.remove(fname + '.nl') model._setCallback = model.setCallback model.setCallback = types.MethodType(setCallback, model) - # Workaround for issue #2 - model.getSolutionDict = types.MethodType(getSolutionDict, model) return model except: shutil.rmtree(tmp) diff --git a/python/cplex/amplpy_cplex/swig/amplpy_cplex_swig_wrap.cxx b/python/cplex/amplpy_cplex/swig/amplpy_cplex_swig_wrap.cxx index 8b9800d..9d367cf 100644 --- a/python/cplex/amplpy_cplex/swig/amplpy_cplex_swig_wrap.cxx +++ b/python/cplex/amplpy_cplex/swig/amplpy_cplex_swig_wrap.cxx @@ -7158,13 +7158,14 @@ SWIG_FromCharPtr(const char *cptr) return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); } -SWIGINTERN std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > ampls_impl_BaseCallback__getSolutionDict(ampls::impl::BaseCallback *self){ +SWIGINTERN PyObject *ampls_impl_BaseCallback_getSolutionDict(ampls::impl::BaseCallback *self){ + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } @@ -7181,13 +7182,14 @@ SWIG_AsVal_bool (PyObject *obj, bool *val) return SWIG_OK; } -SWIGINTERN std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > ampls_AMPLModel__getSolutionDict(ampls::AMPLModel *self){ +SWIGINTERN PyObject *ampls_AMPLModel_getSolutionDict(ampls::AMPLModel *self){ + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } @@ -20159,23 +20161,23 @@ SWIGINTERN PyObject *_wrap_BaseCallback_getValue(PyObject *self, PyObject *args) } -SWIGINTERN PyObject *_wrap_BaseCallback__getSolutionDict(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_BaseCallback_getSolutionDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; ampls::impl::BaseCallback *arg1 = (ampls::impl::BaseCallback *) 0 ; void *argp1 = 0 ; int res1 = 0 ; PyObject *swig_obj[1] ; - std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > result; + PyObject *result = 0 ; - if (!SWIG_Python_UnpackTuple(args, "BaseCallback__getSolutionDict", 0, 0, 0)) SWIG_fail; + if (!SWIG_Python_UnpackTuple(args, "BaseCallback_getSolutionDict", 0, 0, 0)) SWIG_fail; res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ampls__impl__BaseCallback, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BaseCallback__getSolutionDict" "', argument " "1"" of type '" "ampls::impl::BaseCallback *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BaseCallback_getSolutionDict" "', argument " "1"" of type '" "ampls::impl::BaseCallback *""'"); } arg1 = reinterpret_cast< ampls::impl::BaseCallback * >(argp1); { try { - result = ampls_impl_BaseCallback__getSolutionDict(arg1); + result = (PyObject *)ampls_impl_BaseCallback_getSolutionDict(arg1); } catch(const ampls::AMPLSolverException &e) { SWIG_exception(SWIG_RuntimeError, e.what()); } @@ -20183,7 +20185,7 @@ SWIGINTERN PyObject *_wrap_BaseCallback__getSolutionDict(PyObject *self, PyObjec SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } - resultobj = swig::from(static_cast< std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > >(result)); + resultobj = result; return resultobj; fail: return NULL; @@ -21531,23 +21533,23 @@ SWIGINTERN PyObject *_wrap_AMPLModel_getAMPLsDoubleParameter(PyObject *self, PyO } -SWIGINTERN PyObject *_wrap_AMPLModel__getSolutionDict(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_AMPLModel_getSolutionDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; ampls::AMPLModel *arg1 = (ampls::AMPLModel *) 0 ; void *argp1 = 0 ; int res1 = 0 ; PyObject *swig_obj[1] ; - std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > result; + PyObject *result = 0 ; - if (!SWIG_Python_UnpackTuple(args, "AMPLModel__getSolutionDict", 0, 0, 0)) SWIG_fail; + if (!SWIG_Python_UnpackTuple(args, "AMPLModel_getSolutionDict", 0, 0, 0)) SWIG_fail; res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ampls__AMPLModel, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AMPLModel__getSolutionDict" "', argument " "1"" of type '" "ampls::AMPLModel *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AMPLModel_getSolutionDict" "', argument " "1"" of type '" "ampls::AMPLModel *""'"); } arg1 = reinterpret_cast< ampls::AMPLModel * >(argp1); { try { - result = ampls_AMPLModel__getSolutionDict(arg1); + result = (PyObject *)ampls_AMPLModel_getSolutionDict(arg1); } catch(const ampls::AMPLSolverException &e) { SWIG_exception(SWIG_RuntimeError, e.what()); } @@ -21555,7 +21557,7 @@ SWIGINTERN PyObject *_wrap_AMPLModel__getSolutionDict(PyObject *self, PyObject * SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } - resultobj = swig::from(static_cast< std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > >(result)); + resultobj = result; return resultobj; fail: return NULL; @@ -66659,7 +66661,7 @@ SWIGINTERN PyMethodDef SwigPyBuiltin__ampls__impl__BaseCallback_methods[] = { { "getMessage", _wrap_BaseCallback_getMessage, METH_NOARGS, "" }, { "getAMPLWhere", _wrap_BaseCallback_getAMPLWhere, METH_NOARGS, "" }, { "getValue", _wrap_BaseCallback_getValue, METH_O, "" }, - { "_getSolutionDict", _wrap_BaseCallback__getSolutionDict, METH_NOARGS, "" }, + { "getSolutionDict", _wrap_BaseCallback_getSolutionDict, METH_NOARGS, "" }, { NULL, NULL, 0, NULL } /* Sentinel */ }; @@ -67109,7 +67111,7 @@ SWIGINTERN PyMethodDef SwigPyBuiltin__ampls__AMPLModel_methods[] = { { "setAMPLsParameter", _wrap_AMPLModel_setAMPLsParameter, METH_VARARGS, "" }, { "getAMPLsIntParameter", _wrap_AMPLModel_getAMPLsIntParameter, METH_O, "" }, { "getAMPLsDoubleParameter", _wrap_AMPLModel_getAMPLsDoubleParameter, METH_O, "" }, - { "_getSolutionDict", _wrap_AMPLModel__getSolutionDict, METH_NOARGS, "" }, + { "getSolutionDict", _wrap_AMPLModel_getSolutionDict, METH_NOARGS, "" }, { NULL, NULL, 0, NULL } /* Sentinel */ }; diff --git a/python/gurobi/amplpy_gurobi/patch.py b/python/gurobi/amplpy_gurobi/patch.py index 8bc928b..504e3fb 100644 --- a/python/gurobi/amplpy_gurobi/patch.py +++ b/python/gurobi/amplpy_gurobi/patch.py @@ -1,10 +1,6 @@ import types -def getSolutionDict(self): - return dict(self._getSolutionDict()) - - def setCallback(self, cb): def run(self): try: @@ -15,8 +11,6 @@ def run(self): cb._run = cb.run cb.run = types.MethodType(run, cb) - # Workaround for issue #2 - cb.getSolutionDict = types.MethodType(getSolutionDict, cb) super(type(cb), cb).__init__() self._setCallback(cb) @@ -42,8 +36,6 @@ def exportCplexModel(self, options=None): os.remove(fname + '.nl') model._setCallback = model.setCallback model.setCallback = types.MethodType(setCallback, model) - # Workaround for issue #2 - model.getSolutionDict = types.MethodType(getSolutionDict, model) return model except: shutil.rmtree(tmp) @@ -76,8 +68,6 @@ def exportGurobiModel(self, options=None): os.remove(fname + '.nl') model._setCallback = model.setCallback model.setCallback = types.MethodType(setCallback, model) - # Workaround for issue #2 - model.getSolutionDict = types.MethodType(getSolutionDict, model) return model except: shutil.rmtree(tmp) diff --git a/python/gurobi/amplpy_gurobi/swig/amplpy_gurobi_swig_wrap.cxx b/python/gurobi/amplpy_gurobi/swig/amplpy_gurobi_swig_wrap.cxx index ff1f673..1597d6d 100644 --- a/python/gurobi/amplpy_gurobi/swig/amplpy_gurobi_swig_wrap.cxx +++ b/python/gurobi/amplpy_gurobi/swig/amplpy_gurobi_swig_wrap.cxx @@ -7050,13 +7050,14 @@ SWIG_FromCharPtr(const char *cptr) return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); } -SWIGINTERN std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > ampls_impl_BaseCallback__getSolutionDict(ampls::impl::BaseCallback *self){ +SWIGINTERN PyObject *ampls_impl_BaseCallback_getSolutionDict(ampls::impl::BaseCallback *self){ + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } @@ -7073,13 +7074,14 @@ SWIG_AsVal_bool (PyObject *obj, bool *val) return SWIG_OK; } -SWIGINTERN std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > ampls_AMPLModel__getSolutionDict(ampls::AMPLModel *self){ +SWIGINTERN PyObject *ampls_AMPLModel_getSolutionDict(ampls::AMPLModel *self){ + PyObject* res = PyDict_New(); std::vector sol = self->getSolutionVector(); std::map map = self->getVarMapInverse(); - std::map res; std::map::const_iterator it; - for (it = map.begin(); it != map.end(); it++) - res[it->second] = sol[it->first]; + for (it = map.begin(); it != map.end(); ++it) { + PyDict_SetItem(res, PyString_FromString(it->second.c_str()), PyFloat_FromDouble(sol[it->first])); + } return res; } @@ -20095,23 +20097,23 @@ SWIGINTERN PyObject *_wrap_BaseCallback_getValue(PyObject *self, PyObject *args) } -SWIGINTERN PyObject *_wrap_BaseCallback__getSolutionDict(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_BaseCallback_getSolutionDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; ampls::impl::BaseCallback *arg1 = (ampls::impl::BaseCallback *) 0 ; void *argp1 = 0 ; int res1 = 0 ; PyObject *swig_obj[1] ; - std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > result; + PyObject *result = 0 ; - if (!SWIG_Python_UnpackTuple(args, "BaseCallback__getSolutionDict", 0, 0, 0)) SWIG_fail; + if (!SWIG_Python_UnpackTuple(args, "BaseCallback_getSolutionDict", 0, 0, 0)) SWIG_fail; res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ampls__impl__BaseCallback, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BaseCallback__getSolutionDict" "', argument " "1"" of type '" "ampls::impl::BaseCallback *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "BaseCallback_getSolutionDict" "', argument " "1"" of type '" "ampls::impl::BaseCallback *""'"); } arg1 = reinterpret_cast< ampls::impl::BaseCallback * >(argp1); { try { - result = ampls_impl_BaseCallback__getSolutionDict(arg1); + result = (PyObject *)ampls_impl_BaseCallback_getSolutionDict(arg1); } catch(const ampls::AMPLSolverException &e) { SWIG_exception(SWIG_RuntimeError, e.what()); } @@ -20119,7 +20121,7 @@ SWIGINTERN PyObject *_wrap_BaseCallback__getSolutionDict(PyObject *self, PyObjec SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } - resultobj = swig::from(static_cast< std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > >(result)); + resultobj = result; return resultobj; fail: return NULL; @@ -21467,23 +21469,23 @@ SWIGINTERN PyObject *_wrap_AMPLModel_getAMPLsDoubleParameter(PyObject *self, PyO } -SWIGINTERN PyObject *_wrap_AMPLModel__getSolutionDict(PyObject *self, PyObject *args) { +SWIGINTERN PyObject *_wrap_AMPLModel_getSolutionDict(PyObject *self, PyObject *args) { PyObject *resultobj = 0; ampls::AMPLModel *arg1 = (ampls::AMPLModel *) 0 ; void *argp1 = 0 ; int res1 = 0 ; PyObject *swig_obj[1] ; - std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > result; + PyObject *result = 0 ; - if (!SWIG_Python_UnpackTuple(args, "AMPLModel__getSolutionDict", 0, 0, 0)) SWIG_fail; + if (!SWIG_Python_UnpackTuple(args, "AMPLModel_getSolutionDict", 0, 0, 0)) SWIG_fail; res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ampls__AMPLModel, 0 | 0 ); if (!SWIG_IsOK(res1)) { - SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AMPLModel__getSolutionDict" "', argument " "1"" of type '" "ampls::AMPLModel *""'"); + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "AMPLModel_getSolutionDict" "', argument " "1"" of type '" "ampls::AMPLModel *""'"); } arg1 = reinterpret_cast< ampls::AMPLModel * >(argp1); { try { - result = ampls_AMPLModel__getSolutionDict(arg1); + result = (PyObject *)ampls_AMPLModel_getSolutionDict(arg1); } catch(const ampls::AMPLSolverException &e) { SWIG_exception(SWIG_RuntimeError, e.what()); } @@ -21491,7 +21493,7 @@ SWIGINTERN PyObject *_wrap_AMPLModel__getSolutionDict(PyObject *self, PyObject * SWIG_exception(SWIG_RuntimeError, "Unknown exception"); } } - resultobj = swig::from(static_cast< std::map< std::string,double,std::less< std::string >,std::allocator< std::pair< std::string const,double > > > >(result)); + resultobj = result; return resultobj; fail: return NULL; @@ -41240,7 +41242,7 @@ SWIGINTERN PyMethodDef SwigPyBuiltin__ampls__impl__BaseCallback_methods[] = { { "getMessage", _wrap_BaseCallback_getMessage, METH_NOARGS, "" }, { "getAMPLWhere", _wrap_BaseCallback_getAMPLWhere, METH_NOARGS, "" }, { "getValue", _wrap_BaseCallback_getValue, METH_O, "" }, - { "_getSolutionDict", _wrap_BaseCallback__getSolutionDict, METH_NOARGS, "" }, + { "getSolutionDict", _wrap_BaseCallback_getSolutionDict, METH_NOARGS, "" }, { NULL, NULL, 0, NULL } /* Sentinel */ }; @@ -41690,7 +41692,7 @@ SWIGINTERN PyMethodDef SwigPyBuiltin__ampls__AMPLModel_methods[] = { { "setAMPLsParameter", _wrap_AMPLModel_setAMPLsParameter, METH_VARARGS, "" }, { "getAMPLsIntParameter", _wrap_AMPLModel_getAMPLsIntParameter, METH_O, "" }, { "getAMPLsDoubleParameter", _wrap_AMPLModel_getAMPLsDoubleParameter, METH_O, "" }, - { "_getSolutionDict", _wrap_AMPLModel__getSolutionDict, METH_NOARGS, "" }, + { "getSolutionDict", _wrap_AMPLModel_getSolutionDict, METH_NOARGS, "" }, { NULL, NULL, 0, NULL } /* Sentinel */ };