Python 最小化两个非均匀连续阵列的乘积之和
我有一个优化问题,我需要最小化两个不均匀但连续的数组的和积,比如:Python 最小化两个非均匀连续阵列的乘积之和,python,arrays,dynamic-programming,minimization,sumproduct,Python,Arrays,Dynamic Programming,Minimization,Sumproduct,我有一个优化问题,我需要最小化两个不均匀但连续的数组的和积,比如: A = [1, 2, 3] B = [4, 9, 5, 3, 2, 10] 不允许对值进行混洗,即数组的索引必须保持不变。 换句话说,它是阵列a在阵列B上按连续顺序的分布最小化 或者:假定len(B)>=len(A)使长度为n的数组A的值与数组B的n个值的和积最小化,而不改变数组A或B的顺序 在这种情况下,最低要求为: min_sum = 1*4 + 2*3 + 3*2 = 16 from itertools import
A = [1, 2, 3]
B = [4, 9, 5, 3, 2, 10]
不允许对值进行混洗,即数组的索引必须保持不变。
换句话说,它是阵列a在阵列B上按连续顺序的分布最小化
或者:假定len(B)>=len(A)
使长度为n的数组A的值与数组B的n个值的和积最小化,而不改变数组A或B的顺序
在这种情况下,最低要求为:
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)
解决这个问题的强力方法是:
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)
但是,我需要对多组数组执行此操作。我看到背包问题有很多重叠,我觉得应该用动态规划来解决。然而,我被困在如何编写一个有效的算法来执行这项任务
任何帮助都将不胜感激 使用Python,您可以轻松地对集合进行排序和翻转。您要查找的代码是
A, B = sorted(A), sorted(B)[:len(A)]
min_sum = sum([a*b for a,b in zip(A, B[::-1])])
有两张名单
A = [1, 2, 3]
B = [4, 9, 5, 3, 2, 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)将执行此任务,而不修改原始的A
(与A
)相反)。如果已给出排序的A.sort()
,则可以省略此步骤A
- 您需要
中的B
最低值,其中N
是N
的长度。这可以通过排序(B)[:len(A)]A
- 为了计算乘积的最小和,您需要将最高的
与最低的A
相乘,将第二高的B
与第二低的A
相乘。这就是为什么在获得B
最低值N
后,顺序会与B
[:-1]
打印(最小和)
# 16
印刷品(A)
#[1,2,3]您可能需要从B中逐个获取值,并通过将每个值分配给一个键来保持列表的顺序
A = [1, 3, 2]
B = [4, 9, 5, 3, 2, 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, 3, 2]
B = [4, 9, 5, 3, 2, 10]
1*4 + 3*3 + 2*2 +
Result = 17
然后更改A,输出变为:
A = [1, 2, 3]
B = [4, 9, 5, 3, 2, 10]
1*4 + 2*3 + 3*2 +
Result = 16
不确定这是否有用,但无论如何
这可以表述为一个混合整数规划(MIP)问题。基本上,一个带有一些边约束的指派问题
min sum((i,j),x(i,j)*a(i)*b(j))
sum(j, x(i,j)) = 1 ∀i "each a(i) is assigned to exactly one b(j)"
sum(i, x(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)=50
和len(b)=500生成了一个随机问题。这将产生一个包含650行和25k列的MIP。在我缓慢的笔记本电脑上用50秒(证明了全局最优)就解决了问题。结果表明,在直连图上使用最短路径算法非常快。欧文做了一个演示,展示了一个MIP模型。正如您在评论部分所看到的,我们中的一些人独立地尝试了最短路径方法,在示例中,长度a为100,长度B为1000,我们在大约4秒的时间内得到了最佳解决方案。图表可以如下所示:
节点标记为n(i,j)
,表示访问节点意味着将a(i)
分配给b(j)
。成本a(i)*b(j)
可与任何传入(或传出)弧相关联。然后计算从src到snk的最短路径
顺便说一句,你能谈谈这个问题的背景吗?在python中,你应该注意你所说的数组/列表。示例中的变量A
和B
是set
s。确保你知道其中的区别!正如@AnsFourtyTwo提到的,您需要用[]声明数组。请看这里,以获取长度为n[(然后您可以用数组中的最大值乘以其中的每一个值,直到数字用完为止)的B数组中的最小值。感谢您的回答!不幸的是,在排序A时,违反了A的有序数组的要求。例如A=[1,3,2]
。然后解决方案将是:1*4+3*3+2*2=17
。然而,在这个解决方案中,您将A排序为A=[1,2,3]
,结果仍然是16,这是不允许的。也许我在这里遗漏了一些内容,但它似乎几乎就在那里,但还没有完全实现。如果我没有足够清楚地阐述这个问题,我感到抱歉。如果A=[1, 3, 2]
给出,预期结果是什么?16
或17
?即使没有排序A
,你也可以通过1*4+3*2+2*3
计算最小值。哦,哇,我想我完全理解了你的问题。第一次阅读时很难理解。这非常有用!我希望这是一个MIP问题。我正在探索贪婪算法,如Dijkstra的算法,以提高时间复杂度。您的模型非常有用,但我在编码MIP问题方面没有太多经验。我曾使用过一些API,如GUROBI,但我不太确定如何在这里实现您的代码。我需要一些第三方优化模块吗?我是curi我们来看看你是如何实现这个模型的。谢谢!!!我使用了GAMS+Cplex。但是,这个模型非常简单,你可以使用任何解算器或建模工具。我没有看到任何东西会让Gurobi Python API变得特别困难。我目前正在通过Gurobi实现MIP。但是,我在定义c时遇到了一些问题这里是我目前正在使用的:#二进制变量x=m.addVars(total_cost,name='assign')#约束c1=m.addConstrs((x.sum('*',a)=1表示a中的a),'a')#每个a(a)精确地分配给1b(B)c2=m.addConstrs((x.sum(B,'*'))只需为lhat使用一个循环。