微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

最小化两个不均匀连续数组的乘积之和 输出

如何解决最小化两个不均匀连续数组的乘积之和 输出

我有一个优化问题,我需要最小化两个不均匀但连续的数组的和积,例如:

A = [1,2,3]
B = [4,9,5,3,10]

不允许对值进行混洗,即数组的索引必须保持不变。 换句话说,它是数组 A 对数组 B 以连续顺序的分布最小化。

或:鉴于 len(B)>=len(A) 在不改变数组 A 或 B 的顺序的情况下,最小化长度为 n 的数组 A 的值与数组 B 的 n 个值的和积。

在这种情况下,最小值为:

min_sum = 1*4 + 2*3 + 3*2 = 16

解决这个问题的蛮力方法是:

from itertools import combinations

sums = [sum(a*b for a,b in zip(A,b)) for b in combinations(B,len(A))]
min_sum = min(sums)

但是,我需要为多组数组执行此操作。我看到背包问题有很多重叠,我觉得应该用动态规划来解决。然而,我被困在如何编写一个有效的算法来执行此操作。

任何帮助将不胜感激!

解决方法

有两个列表

A = [1,2,3]
B = [4,9,5,3,10]

可以使用以下方法找到最佳和积:

min_sum = sum(a*b for a,b in zip(sorted(A),sorted(B)[:len(A)][::-1]))

如果总是给 A 排序,可以使用这个简化版本:

min_sum = sum(a*b for a,b in zip(A,sorted(B)[:len(A)][::-1]))

需要注意的重要部分:

  • 您需要对 A 的因子进行排序。 sorted(A) 将完成这项工作,而无需修改原始 A(与 A.sort() 相反)。如果 A 已经被排序,这一步可以省略。
  • 您需要 N 中的 B 最小值,其中 NA 的长度。这可以通过 sorted(B)[:len(A)]
  • 完成
  • 为了计算乘积的最小和,您需要将 A 的最高数乘以 B 的最低数,A 的第二高数乘以第二低数B。这就是为什么在获得 NB 最低值后,顺序会被 [::-1]
  • 反转

输出

print(min_sum)
# 16
print(A)
# [1,3]              <- The original list A is not modified
print(B)
# [4,10]    <- The original list B is not modified
,

使用 Python,您可以轻松地对集合进行排序和翻转。您正在寻找的代码是

A,B = sorted(A),sorted(B)[:len(A)]
min_sum = sum([a*b for a,B[::-1])])
,

您可能需要从 B 中一个一个地获取值,并通过将每个值分配给一个键来保持列表的顺序。

A = [1,2]
B = [4,10]

#create a new dictionary with key value pairs of B array values
new_dict = {}
j=0
for k in B:
    new_dict[j] = k
    j+= 1


#create a new list of the smallest values in B up to length of array A
min_Bmany =[]
for lp in range(0,len(A)):
    #get the smallest remaining value from dictionary new_dict
    rmvky=  min(zip(new_dict.values(),new_dict.keys()))

    #append this item to minimums list
    min_Bmany.append((rmvky[1],rmvky[0]))
    #delete this key from the dictionary new_dict
    del new_dict[rmvky[1]]

#sort the list by the keys(instead of the values)
min_Bmany.sort(key=lambda r: r[0])

#create list of only the values,but still in the same order as they are in original array
min_B =[]
for z in min_Bmany:
    min_B.append(z[1])


print(A)
print(min_B)

ResultStr = ""
Result = 0

#Calculate the result
for s in range(0,len(A)):
    ResultStr = ResultStr + str(A[s]) +"*" +str(min_B[s])+ " + "
    Result = Result + A[s]*min_B[s]

print(ResultStr)
print("Result = ",Result)

输出如下:

A = [1,10]
1*4 + 3*3 + 2*2 + 
Result =  17

然后改变A,输出变成:

A = [1,10]
1*4 + 2*3 + 3*2 + 
Result =  16
,

不确定这是否有帮助,但无论如何。

这可以表述为混合整数规划 (MIP) 问题。基本上,一个带有一些边约束的分配问题。

  min sum((i,j),x(i,j)*a(i)*b(j))
      sum(j,j)) = 1    ∀i        "each a(i) is assigned to exactly one b(j)"
      sum(i,j)) ≤ 1    ∀j        "each b(j) can be assigned to at most one a(i)"
      v(i) = sum(j,j*x(i,j))         "position of each a(i) in b"
      v(i) ≥ v(i-1)+1       ∀i>1      "maintain ordering"
      x(i,j) ∈ {0,1}                  "binary variable"       
      v(i) ≥ 1                        "continuous (or integer) variable"

示例输出:

----     40 VARIABLE z.L                   =       16.000  

----     40 VARIABLE x.L  assign

            j1          j4          j5

i1       1.000
i2                   1.000
i3                               1.000


----     40 VARIABLE v.L  position of a(i) in b

i1 1.000,i2 4.000,i3 5.000

可爱的小 MIP 模型。

作为一个实验,我用 len(a)=50len(b)=500 生成了一个随机问题。这导致具有 650 行和 25k 列的 MIP。在我的慢速笔记本电脑上在 50 秒内解决(证明全局最优)。

,

事实证明,在有向图上使用最短路径算法非常快。 Erwin 做了一个 post 展示了一个 MIP 模型。正如您在那里的评论部分所看到的,我们中的一些人独立尝试了最短路径方法,在 A 长度为 100,B 长度为 1000 的示例中,我们在 4 秒附近获得了最佳解决方案。>

,

图形看起来像:

enter image description here

节点被标记为n(i,j),表示访问节点意味着将a(i)分配给b(j)。成本a(i)*b(j) 可以与任何传入(或任何传出)弧相关联。然后计算从src到snk的最短路径。

顺便说一句,你能谈谈这个问题的背景吗?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。