查找一组过滤组合的算法
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'))]
我正在使用 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'))]