Python 查找过滤组合集的算法
我正在使用Python查找通过笛卡尔乘积计算的成对组合的过滤集。我可以用启发式算法计算出我需要的东西,但它感觉很笨拙,我担心我正在重新创造一些可能是已知的、已解决的数学概念,而更好的算法是存在的 下面是一个例子: 假设我有一个2产品A和B的订单,并且我有3仓库(1,2,3)中的库存。我想计算所有可能的方式,我可以装运此订单,全部或部分,从我的3个仓库之一。假设无限库存,因此没有限制。最终,可能的方法列表将被输入到优化例程中,以最小化运输成本等。然而,首先,我想找到一种更优雅(并且可能更具可扩展性)的方法来计算可能的实现选项列表 这是我到目前为止所拥有的。任何关于如何以更有效的数学方法解决这一问题的想法都将不胜感激。我不是在寻找避免Python 查找过滤组合集的算法,python,combinatorics,Python,Combinatorics,我正在使用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')]
[(('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'))]
[(('A', '1'), ('B', '2')),
(('A', '1'), ('B', '3')),
(('A', '2'), ('B', '1')),
(('A', '2'), ('B', '3')),
(('A', '3'), ('B', '1')),
(('A', '3'), ('B', '2'))]
然后,计算这些产品/仓库对的可能组合
pwc = list(combinations(PW, 2))
结果:
[('A', '1'),
('A', '2'),
('A', '3'),
('B', '1'),
('B', '2'),
('B', '3')]
[(('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'))]
[(('A', '1'), ('B', '2')),
(('A', '1'), ('B', '3')),
(('A', '2'), ('B', '1')),
(('A', '2'), ('B', '3')),
(('A', '3'), ('B', '1')),
(('A', '3'), ('B', '2'))]
最后,筛选出我们将从不同仓库装运相同产品的任何组合:
[u for u in pwc if ((u[0][0] != u[1][0]) and (u[0][1] != u[1][1]))]
结果:
[('A', '1'),
('A', '2'),
('A', '3'),
('B', '1'),
('B', '2'),
('B', '3')]
[(('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'))]
[(('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 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'))]
[(('A', '1'), ('B', '2')),
(('A', '1'), ('B', '3')),
(('A', '2'), ('B', '1')),
(('A', '2'), ('B', '3')),
(('A', '3'), ('B', '1')),
(('A', '3'), ('B', '2'))]
这与您的方法之间的区别在于,您生成all,然后过滤,而我在您的预期输出中发现了一种模式,并提出了此方法
如果有人能找到更好的简化方法,欢迎提出建议。试试这个:
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'))]
[(('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中的
&
是位运算符。你可能在寻找普通的和关键字。@TigerhawkT3找到了,谢谢!谢天谢地,这似乎并没有改变结果……我已经在挖这个了,谢谢你这么快就掌握了我要做的事情!你知道这是怎么回事吗?我觉得这是一个常见的问题,应该有一个共同的名字,但我的谷歌让我失望了。@ClausHerther我不太确定,但似乎你只是在做所有可能的排列,第一个用'a'
,第二个用'B'
@ClausHerther是的。另外,我刚刚意识到,您可以将P
和W
声明为'AB'
和'123'
。是的,您是对的,从输出中回顾是一种聪明的方法。再次感谢@明天真好!我采取了不同的态度。将PW过滤到两组产品这两组产品并过滤W不同的产品。然而,这种方法要好得多。