(*elems)
return out
Given an input array with lists of options, e.g.,

    ((+r, -r), 2), ((+s, -s), 2), ((0,), 1)

    this methods returns all combinations, i.e.,

    (+r, 0, -s, +r, +s),
    (0, -s, -r, +r, +s),
    ...
Given an input array with lists of options, e.g.,
Given an input array with lists of options e . g .
def combine(*elems):
    """Given an input array with lists of options, e.g.,

    ((+r, -r), 2), ((+s, -s), 2), ((0,), 1)

    this methods returns all combinations, i.e.,

    (+r, 0, -s, +r, +s),
    (0, -s, -r, +r, +s),
    ...
    """
    # https://stackoverflow.com/a/45321972/353337

    # Could be replaced by Knuth's "Algorithm L"; see, e.g.,
    # <https://stackoverflow.com/a/4250183/353337>.
    def partitions(*sizes):
        if not sizes or all(s <= 0 for s in sizes):
            yield ()
        for i_size, size in enumerate(sizes):
            if size <= 0:
                continue
            next_sizes = sizes[:i_size] + (sizes[i_size] - 1,) + sizes[i_size + 1 :]
            for p in partitions(*next_sizes):
                yield (i_size,) + p

    values, sizes = zip(*elems)
    templates = partitions(*sizes)
    prod = [itertools.product(*(values[ti] for ti in t)) for t in templates]
    out = np.array(list(itertools.chain.from_iterable(prod)))
    return out
def combine ( * elems ) : # https://stackoverflow.com/a/45321972/353337 # Could be replaced by Knuth's "Algorithm L"; see, e.g., # <https://stackoverflow.com/a/4250183/353337>. def partitions ( * sizes ) : if not sizes or all ( s <= 0 for s in sizes ) : yield ( ) for i_size , size in enumerate ( sizes ) : if size <= 0 : continue next_sizes = sizes [ : i_size ] + ( sizes [ i_size ] - 1 , ) + sizes [ i_size + 1 : ] for p in partitions ( * next_sizes ) : yield ( i_size , ) + p values , sizes = zip ( * elems ) templates = partitions ( * sizes ) prod = [ itertools . product ( * ( values [ ti ] for ti in t ) ) for t in templates ] out = np . array ( list ( itertools . chain . from_iterable ( prod ) ) ) return out