coin-or / python-mip

Python-MIP: collection of Python tools for the modeling and solution of Mixed-Integer Linear programs
Eclipse Public License 2.0
514 stars 89 forks source link

Taking the power in objective function returns TypeError #322

Closed vpozdnyakov closed 1 year ago

vpozdnyakov commented 1 year ago

Describe the bug I cannot take the power in objective function. For example, I cannot minimize the variance of the set of variables.

To Reproduce

from mip import Model, MINIMIZE, BINARY, INTEGER
model = Model(sense=MINIMIZE)
a_list = [3, 4, 5]
x_list = [model.add_var(var_type=INTEGER) for _ in range(3)]
y_list = [a*x for a, x in zip(a_list, x_list)]
y_mean = sum(y_list) / len(y_list)
model.objective = sum([(y_mean - y)**2 for y in y_list]) / len(y)
TypeError: unsupported operand type(s) for ** or pow(): 'LinExpr' and 'int'

Expected behavior Here is no the error

Desktop (please complete the following information):

christian2022 commented 1 year ago

This is by design. MIP in fact is Mixed Integer linear Program. So all constraints and objective functions need to be linear. It looks like you're trying to solve a Minimum Least Squares Problem. Maybe it's an option to replace (y_mean - y)**2 by abs(y_mean - y), so "Least Absolute Deviation", which can be linearized by: y_dev = [model.addvar() for in y_list] mode.add_constr(y_dev[i] <= y_mean - y_list[i] for i in range(len(y_list))] mode.add_constr(y_dev[i] >= y_mean - y_list[i] for i in range(len(y_list))] model.objective = sum(y_dev)

vpozdnyakov commented 1 year ago

@christian2022 thank you!