diff --git a/mip/entities.py b/mip/entities.py index fbf3bfa6..4f4a4f53 100644 --- a/mip/entities.py +++ b/mip/entities.py @@ -60,6 +60,16 @@ class LinExpr: .. code:: python m += x1 + x2 + x3 == 1 + + If used in intermediate calculations, the solved value of the linear + expression can be obtained with the ``x`` parameter, just as with + a ``Var``. + + .. code:: python + + a = 10*x1 + 7*x4 + print(a.x) + """ def __init__( @@ -348,6 +358,18 @@ def violation(self: "LinExpr"): return viol + @property + def x(self) -> Optional[numbers.Real]: + """Value of this linear expression in the solution. None + is returned if no solution is available.""" + x = self.__const + for var, coef in self.__expr.items(): + var_x = var.x + if var_x is None: + return None + x += var_x * coef + return x + class Constr: """ A row (constraint) in the constraint matrix. diff --git a/test/mip_test.py b/test/mip_test.py index bd01af7a..1af5cb14 100644 --- a/test/mip_test.py +++ b/test/mip_test.py @@ -591,3 +591,31 @@ def test_variable_bounds(solver: str, val: int): assert round(m.objective_value) == val assert round(x.x) == 2 * val assert round(y.x) == val + + +@pytest.mark.parametrize("val", range(1, 4)) +@pytest.mark.parametrize("solver", SOLVERS) +def test_linexpr_x(solver: str, val: int): + m = Model("bounds", solver_name=solver) + + x = m.add_var(lb=0, ub=2 * val) + y = m.add_var(lb=val, ub=2 * val) + obj = x - y + + assert obj.x is None # No solution yet. + + m.objective = maximize(obj) + m.optimize() + + assert m.status == OptimizationStatus.OPTIMAL + assert round(m.objective_value) == val + assert round(x.x) == 2 * val + assert round(y.x) == val + + # Check that the linear expression value is equal to the same expression + # calculated from the values of the variables. + assert abs((x + y).x - (x.x + y.x)) < TOL + assert abs((x + 2*y).x - (x.x + 2*y.x)) < TOL + assert abs((x + 2*y + x).x - (x.x + 2*y.x + x.x)) < TOL + assert abs((x + 2*y + x + 1).x - (x.x + 2*y.x + x.x + 1)) < TOL + assert abs((x + 2*y + x + 1 + x/2).x - (x.x + 2*y.x + x.x + 1 + x.x/2)) < TOL