Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python cartesian product and conditions?

In Python I am using the itertools.product() function to generate input parameters for a simulation.

I have a test function that requires 4 input parameters a1, a2, b1 and b2. I use the following code generate the parameters. Example:

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

… which gives me 3072 combinations. Unfortunately some combinations logically make no sense. E. g. if a2 is larger than a1 the test results are useless, also when b1 equals 0 the value of b2 is completely irrelevant – so it wouldn’t make sense to test such combinations.

Is there a possibility to restrict or filter the cartesian product beside doing it manually and nesting for-loops? Because my real use case has way more than 4 parameters, that’s why I like the convenience of the cartesian product function from itertools.

Any ideas or alternatives? Any help appreciated, thanks.

like image 639
Alen Avatar asked Jan 11 '15 19:01

Alen


People also ask

How do you code a Cartesian product in Python?

Practical Data Science using Python As we know if two lists are like (a, b) and (c, d) then the Cartesian product will be {(a, c), (a, d), (b, c), (b, d)}. To do this we shall use itertools library and use the product() function present in this library. The returned value of this function is an iterator.

What is Cartesian product explain with an example Python?

The cartesian product (or cross product) of A and B, denoted by A x B, is the set A x B = {(a,b) | a ∈ A and b ∈ B}. The elements (a,b) are ordered pairs. For example if A = {1,2} and B = {4,5,6} then the cartesian products of A and B is AxB = {(1,4),(1,5),(1,6),(2,4),(2,5),(2,6)}.

How do you define a product in Python?

product() can used in two different ways: itertools. product(*iterables, repeat=1): It returns the cartesian product of the provided iterable with itself for the number of times specified by the optional keyword “repeat”.

What are Itertools in Python?

Itertools is a module in Python, it is used to iterate over data structures that can be stepped over using a for-loop. Such data structures are also known as iterables. This module works as a fast, memory-efficient tool that is used either by themselves or in combination to form iterator algebra.


2 Answers

Python 3

In Python 3 you can filter out undesirable combinations using 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

You can use list comprehension or itertools.ifilter:

filtered_params = itertools.ifilter
    (lambda (a1, a2, b1, b2): a1 <= a2 and (b1 != 0 or b2 == 5), params)

Note that both of these versions loop and filter out under the hood. If you want to avoid that, you'll need to construct an improved algorithm that creates the tuples without the undesirables.

like image 160
Ani Avatar answered Oct 23 '22 11:10

Ani


If you have many parameters, a constraint-based approach using a module like python-constraint may be easier to work with - let it do the hard work of figuring out which combinations are valid.

This would look something like

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)
like image 4
Hugh Bothwell Avatar answered Oct 23 '22 11:10

Hugh Bothwell