From f94090ed2993402aa81d873301df7b8f587dd9e8 Mon Sep 17 00:00:00 2001 From: KristianJensen Date: Mon, 6 Feb 2017 15:29:43 +0100 Subject: [PATCH] Small fixes (#68) * fix: bug when changing variable names Only update the _variables_to_constriants_mapping dict when new_name != old_name * feat: allow infeasible primals to be retrieved Only _round_primals_to_bounds if solution is optimal * feat: add a tolerance option to scipy_interface Default is set to 1e-9 --- optlang/interface.py | 3 ++- optlang/scipy_interface.py | 17 +++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/optlang/interface.py b/optlang/interface.py index 0b2fb7e7..43fadf15 100644 --- a/optlang/interface.py +++ b/optlang/interface.py @@ -295,7 +295,8 @@ def primal(self): if primal is not None: if self.type in ("integer", "binary"): primal = round(primal) - primal = self._round_primal_to_bounds(primal) + if self.problem.status == OPTIMAL: + primal = self._round_primal_to_bounds(primal) return primal else: return None diff --git a/optlang/scipy_interface.py b/optlang/scipy_interface.py index 4ee41bda..f9111a5b 100644 --- a/optlang/scipy_interface.py +++ b/optlang/scipy_interface.py @@ -234,7 +234,7 @@ def get_constraint_slack(self, name): index = self._get_constraint_index(name) return self._slacks[index] - def optimize(self, method="simplex", verbosity=False, **kwargs): + def optimize(self, method="simplex", verbosity=False, tolerance=1e-9, **kwargs): """Run the linprog function on the problem. Returns None.""" c = np.array([self.objective.get(name, 0) for name in self._variables]) if self.direction == "max": @@ -242,7 +242,7 @@ def optimize(self, method="simplex", verbosity=False, **kwargs): bounds = list(six.itervalues(self.bounds)) solution = linprog(c, self.A, self.upper_bounds, bounds=bounds, method=method, - options={"maxiter": 10000, "disp": verbosity}, **kwargs) + options={"maxiter": 10000, "disp": verbosity, "tol": tolerance}, **kwargs) self._solution = solution self._status = solution.status if SCIPY_STATUS[self._status] == interface.OPTIMAL: @@ -484,9 +484,10 @@ def set_linear_coefficients(self, coefficients): @six.add_metaclass(inheritdocstring) class Configuration(interface.MathematicalProgrammingConfiguration): - def __init__(self, verbosity=0, *args, **kwargs): + def __init__(self, verbosity=0, tolerance=1e-9, *args, **kwargs): super(Configuration, self).__init__(*args, **kwargs) self._verbosity = verbosity + self.tolerance = tolerance @property def verbosity(self): @@ -514,6 +515,14 @@ def timeout(self, value): if value is not None: raise ValueError("Scipy interface does not support timeout") + @property + def tolerance(self): + return self._tolerance + + @tolerance.setter + def tolerance(self, value): + self._tolerance = value + @six.add_metaclass(inheritdocstring) class Model(interface.Model): @@ -578,7 +587,7 @@ def _remove_constraints(self, constraints): super(Model, self)._remove_constraints(constraints) def _optimize(self): - self.problem.optimize(verbosity=bool(self.configuration.verbosity)) + self.problem.optimize(verbosity=bool(self.configuration.verbosity), tolerance=self.configuration.tolerance) status = self.problem.status return status