查找一组过滤组合的算法

Algorithm to find a filtered set of combinations

我正在使用 Python 查找通过笛卡尔积计算的一组已过滤的对组合。我可以使用启发式算法计算出我需要的东西,但它感觉很笨重,而且我担心我正在重新发明一些可能是已知且已解决的数学概念,并且存在更好的算法。

这是一个例子:

假设我有一个 2 产品 A 和 B 的订单,并且我在 3 个仓库中有库存(1,2, 3).我想计算从我的 3 个仓库之一全部或部分运送此订单的所有可能方式。假设无限库存,所以没有约束。最终可能的方法列表将被送入优化例程,以最大限度地减少运输成本等。但是,首先我想找到一种更优雅(并且可能更具可扩展性)的方法来计算可能的实现选项列表。

这是我目前所拥有的。任何关于如何以更数学有效的方式解决这个问题的想法将不胜感激。我不是在寻找避免 for 循环的方法,我知道我可能可以使用广播。谢谢!

from itertools import *

# Products in order
P = ['A', 'B'] 

# Possible warehouses
W = ['1', '2', '3'] 

# Get the Cartesian product of all products in the order
# and all warehouses
PW = list(product(P, W))

结果:

[('A', '1'), 
 ('A', '2'), 
 ('A', '3'), 
 ('B', '1'), 
 ('B', '2'), 
 ('B', '3')]

然后,计算这些 product/warehouse 对的可能组合

pwc = list(combinations(PW, 2))

结果:

[(('A', '1'), ('A', '2')),
 (('A', '1'), ('A', '3')),
 (('A', '1'), ('B', '1')),
 (('A', '1'), ('B', '2')),
 (('A', '1'), ('B', '3')),
 (('A', '2'), ('A', '3')),
 (('A', '2'), ('B', '1')),
 (('A', '2'), ('B', '2')),
 (('A', '2'), ('B', '3')),
 (('A', '3'), ('B', '1')),
 (('A', '3'), ('B', '2')),
 (('A', '3'), ('B', '3')),
 (('B', '1'), ('B', '2')),
 (('B', '1'), ('B', '3')),
 (('B', '2'), ('B', '3'))]

最后,过滤掉我们将从不同仓库运送相同产品的任何组合:

[u for u in pwc if ((u[0][0] != u[1][0]) and (u[0][1] != u[1][1]))]

结果:

[(('A', '1'), ('B', '2')),
 (('A', '1'), ('B', '3')),
 (('A', '2'), ('B', '1')),
 (('A', '2'), ('B', '3')),
 (('A', '3'), ('B', '1')),
 (('A', '3'), ('B', '2'))]

那么,有"filtered cartesian join combination"这样的东西吗?

(希望这一切都有意义!)

据我所知,这一行可以解决您的问题:

from itertools import permutations, repeat
[tuple(zip(x, y)) for x, y in zip(repeat('AB'), permutations('123', 2))]

输出:

[(('A', '1'), ('B', '2')),
 (('A', '1'), ('B', '3')),
 (('A', '2'), ('B', '1')),
 (('A', '2'), ('B', '3')),
 (('A', '3'), ('B', '1')),
 (('A', '3'), ('B', '2'))]

这个方法和你的方法的区别是你生成所有然后过滤,而我在你预期的输出中找到了一个模式并想出了这个方法。

如果有人能看到更好的简化方法,欢迎提出建议。

试试这个:

from itertools import *

# Products in order
P = ['A', 'B'] 

# Possible warehouses
W = ['1', '2', '3'] 

# Get the Cartesian product of all products in the order
# and all warehouses
PW = list(product(P, W))

# Split PW in two groups based on P then product those groups
u = list(product(*[list(filter(lambda x: x[0] == i, PW)) for i in P]))

# Filter result for where different W's
list(filter(lambda x: x[0][1] != x[1][1], u))

输出:

[(('A', '1'), ('B', '2')),
 (('A', '1'), ('B', '3')),
 (('A', '2'), ('B', '1')),
 (('A', '2'), ('B', '3')),
 (('A', '3'), ('B', '1')),
 (('A', '3'), ('B', '2'))]