Python笛卡尔积和条件?

问题描述 投票:4回答:5

在Python中,我使用itertools.product()函数来生成用于仿真的输入参数。

我有一个测试函数,需要4个输入参数a1,a2,b1和b2。我使用以下代码生成参数。示例:

params = itertools.product(range(10,41,2), range(10,41,2), range(0, 2), range(5, 31, 5))

…这给了我3072个组合。不幸的是,某些组合在逻辑上是没有意义的。例如如果a2大于a1,则测试结果是无用的,而且当b1等于0时,b2的值也就完全无关紧要了,因此测试这样的组合没有任何意义。

除了手动执行和嵌套for循环外,是否有可能限制或过滤笛卡尔积?因为我的实际用例有4个以上的参数,所以这就是为什么我喜欢itertools提供的笛卡尔积函数的便利。

有什么想法或选择吗?任何帮助表示感谢,谢谢。

python itertools
5个回答
2
投票

[如果您有很多参数,则使用python-constraint之类的模块的基于约束的方法可能更易于使用-让它辛苦地找出哪些组合有效。

这看起来像

from constraint import Problem

prob = Problem()
prob.addVariables(["a1", "a2"], range(10,41,2))
prob.addVariable("b1", [0, 2])
prob.addVariable("b2", range(5, 31, 5))
prob.addConstraint(lambda a1, a2: a2 <= a1, ["a1", "a2"])
prob.addConstraint(lambda b1, b2: b1 != 0 or b2 == 5, ["b1", "b2"])

for params in prob.getSolutionIter():
    run_sim(**params)

6
投票

Python 3

在Python 3中,您可以使用itertools.filterfalse过滤掉不良组合:

# predicate is true when need to skip the combination
predicate = (lambda (a1, a2, b1, b2): a1 <= a2 and (b1 != 0 or b2 == 5), params)
filtered_params = itertools.filterfalse(predicate, params)

Python 2

您可以使用列表理解或itertools.ifilter

itertools.ifilter

请注意,这两个版本都会循环播放并在引擎盖下过滤掉。如果要避免这种情况,则需要构造一种改进的算法来创建元组而不会出现不良情况。


2
投票

一个选项是使filtered_params = itertools.ifilter (lambda (a1, a2, b1, b2): a1 <= a2 and (b1 != 0 or b2 == 5), params) 成为另一个由params本身提供的生成器。

例如:

itertools.product

您可以根据条件在params = (prod for prod in itertools.product(...) if prod[2] <= prod[1]) 之后添加任何内容。例如,if将检查您在问题中陈述的条件,仅让您通过所需的结果,并丢弃所有未通过测试的产品。


0
投票

在这种情况下,使用numpy的向量运算来表达您的规则可能是最方便/直观/可读的。例如:

prod[2] <= prod[1] and prod[3] != 0

0
投票

您可以结合使用列表理解和对所选参数的任何限制。我建议在执行此操作之前将参数放在一组中,以确保没有不必要的代码。在上面提到的情况下,我不会发生这种情况,但是并不总是使用import numpy as np arr = np.array(list(params), dtype = [('a1',int),('a2',int),('b1',int),('b2',int)]) arr = arr[ arr['a2'] <= arr['a1'] ] arr = arr[ arr['b1'] != 0 ] 来生成参数选项。

例如,在此创建一个元组参数列表,如果参数1大于参数2 + 10,则该列表仅是有效的组合:

range
© www.soinside.com 2019 - 2024. All rights reserved.