How to make integer optimization with absolute values or sum of absolute values in python?

3.2k views Asked by At

I have a program where I want to minimize an absolute difference of two variables (an absolute error function). Say:

e_abs(x, y) = |Ax - By|; where e_abs(x, y) is my objective function that I want to minimize.

The function is subjected to the following constrains:

x and y are integers;
x >= 0; y >= 0
x + y = C, where C is an arbitrary constant (also C >= 0)

I am using the mip library (https://www.python-mip.com/), where I have defined both my objective function and my constrains.

The problem is that mip does not have an "abs" method. So I had to overcome that by spliting the main problem into two optimization sub-problems:

e(x, y) = Ax - By

Porblem 1: minimize e(x, y); subject to e(x, y) >= 0
Porblem 2: maximize e(x, y); subject to e(x, y) <= 0

After solving the two separate problems, compare the two results, yield the min(abs(e)).

That should have worked, but mip does not seem to understand that the error can be negative. As I show below:

constr(0): -1.0941176470588232 X(0, 0) +6.199999999999998 X(1, 0) - error = -0.0
constr(1): error <= -0.0
constr(2): X(0, 0) + X(1, 0) = 1.0

Obs.: consider X(0, 0) as x and X(1, 0) as y in our example

Again, the program results OptimizationStatus.INFEASIBLE, where clearly the combination X(0, 0) = 1 and X(1, 0) = 0 solves the problem.

Is it a formulation issue of my model? Or is it a bad behavior of the mip library?

1

There are 1 answers

5
AirSquid On BEST ANSWER

You can (and should) reformulate. Because you are minimizing the absolute value of a function, you can introduce a dummy variable and 2 constraints on that variable and then minimize the dummy variable to keep it linear. (ABS is a non-linear function).

So, introduce z such that:

z >= Ax - By

and

z >= -(Ax - By)

then your objective is to minimize z

Edit: For sum of absolute differences

In the case where you wish to minimize the sum of absolute differences, only slightly more work is required as you will need to repeat the above process for the indexing variable. Assuming that x and y are indexed by the set I you simply need to (in pseudocode ... implementation differs slightly based on framework):

Introduce z[i], which is indexed by the same set 'I' and

for i in I:
  z[i] >= Ax[i] - By[i]
  z[i] >= -(Ax[i] - By[i])

and minimize:

∑z[i]  (over the set I)