Search code examples
algorithmconstraint-programmingminimization

Allocating numbers (x1, x2, x3, ...) to each element in a list (a1, a2, a3, ...) so that a1/x1 is similar to a2/x2 and so on


Suppose I have a list of numbers = [3, 10, 20, 1, ...] How can I assign a number (x1, x2, x3, x4, ...) to each of the elements in the list, so that 3/x1 ~= 10/x2 ~= 20/x3 ~= 1/x4 = ... ?

Edit: there are some restrictions on the numbers (x1, x2, x3...). they have to be picked from a list of available numbers (which can be floating points as well). The problem is that the number of elements is not the same. There are more X elements. Xs can be assigned multiple times.

The goal is to minimize the difference between 3/x1, 10/x2, 20/x3, 1/x4


Solution

  • It often helps to develop a mathematical model. E.g.

    Let

       a(i)>=0  i=1,..,m
       b(j)>0   j=1,..,n with n > m
    

    be the data.

    Introduce variables (to be determined by the model)

       c      =  common number for all expressions to be close to
       x(i,j) =  1 if a(i) is assigned to b(j)
                 0 otherwise  
    

    Then we can write:

    min sum((i,j), (x(i,j)*(a(i)/b(j) - c))^2 )
    subject to
        sum(j, x(i,j)) = 1   for all i  (each a(i) is assigned to exactly one b(j))
        x(i,j) in {0,1}
        c free
    

    This is a non-linear model. MINLP (Mixed Integer Non-linear Programming) solvers are readily available. You can also choose an objective that can be linearized:

    min sum((i,j), abs(x(i,j)*(a(i)/b(j) - y(i,j))) )
    subject to
        y(i,j) = x(i,j)*c
        sum(j, x(i,j)) = 1   for all i
        x(i,j) in {0,1}
        c free
    

    This can be reformulated as a MIP (Mixed Integer Programming) model. There are many MIP solvers available.

    The solution can look like:

    enter image description here

    The values inside the matrix are a(i)/b(j). Each row corresponds to an a(i), and has exactly one matching b(j).

    More details are here.