将数字分类到相同总和的容器中

问题描述 投票:0回答:1

我正在尝试找到将整数集合排序到总和相同的容器中的最佳方法。为简单起见,我们可以减去平均值,因此我们只对加为零的 bin 感兴趣。

举个例子,

X = np.array([-2368, -2143, -1903, -1903, -1888, -1648, -1528, -1318, -1213,
              -1153, -1033,  -928,  -793,  -703,  -508,  -493,  -463,  -448,
               -418,  -358,  -223,  -118,   -88,   137,   227,   257,   347,
                347,   377,   557,   632,   632,   692,   812,   827,  1007,
               1022,  1262,  1352,  1727,  1892,  2267,  2297,  2327,  2642])

我知道,有一种方法可以将其形成 3 组,每组 15 个数字,其中每组相加为零。但对于我的一生来说,如何系统地找到该解决方案并不明显(可能有很多这样的解决方案,我只需要一个)。

在这个较小的示例中,我们可能可以尝试每种组合,但如果数组有一百万个数字被分成 1000 个容器,这样的穷举就行不通了。

python sorting optimization combinatorics
1个回答
0
投票

可能不完全是你想要的,但你可以通过将其建模为具有二进制变量 x_ib=1 的 MILP 来解决这个问题,前提是项 i 位于 bin b 中。

我得到这个结果:

Bin 1 contains items: 2, 5, 6, 10, 16, 17, 20, 21, 22, 33, 34, 38, 39, 40, 45, 
Bin 2 contains items: 1, 7, 9, 12, 19, 24, 26, 27, 28, 29, 31, 32, 35, 36, 41, 
Bin 3 contains items: 3, 4, 8, 11, 13, 14, 15, 18, 23, 25, 30, 37, 42, 43, 44, 
Total sum: 0

使用这个朱莉娅代码:

using JuMP
using GLPK

function main()
    m = Model(GLPK.Optimizer)

    X = [-2368, -2143, -1903, -1903, -1888, -1648, -1528, -1318, -1213,
         -1153, -1033,  -928,  -793,  -703,  -508,  -493,  -463,  -448,
         -418,  -358,  -223,  -118,   -88,   137,   227,   257,   347,
         347,   377,   557,   632,   632,   692,   812,   827,  1007,
         1022,  1262,  1352,  1727,  1892,  2267,  2297,  2327,  2642]

    n = length(X)

    @variable(m, x[1:n, 1:3], Bin) # x_i,b = 1 iff item i is in bin b

    @objective(m, Max, 0) # No need for an objective function
    @constraint(m, [i in 1:n], sum(x[i,b] for b in 1:3) == 1) # Each item is in a bin
    @constraint(m, [b in 2:3], sum(x[i,b] * X[i] for i in 1:n) == sum(x[i,1] * X[i] for i in 1:n)) # The weight of the item in bin 2 and 3 is equal to that of bin 1

    optimize!(m)

    # Display the solution
    for b in 1:3
        print("Bin ", b, " contains items: ")
        for i in 1:n
            if JuMP.value(x[i,b]) > 0.9
                print(i, ", ")
            end
        end
        println()
    end

    totalSum = 0
    for i in 1:n
        if JuMP.value(x[i,1]) > 0.9
            totalSum += X[i]
        end
    end

    println("Total sum: ", totalSum)
end 
© www.soinside.com 2019 - 2024. All rights reserved.