Skip to content

Make permutation space

Generates a list of tuples containing n_permutations of the given elements. This will be used later in make_combination_space so you can have the same permutation and combination spaces for different games played by the same set. Probably makes things more reproducible! The elements themselves can be anything I guess, I tried str (names/labels) and integers (indexes), and tuples (edges, from-to style). Briefly, the permutation space of (A,B,C) is something like this:

(A,B,C) (B,C,A) (C,B,A) (A,C,B) (C,A,B) (B,A,C) (C,A,B) . . . As you might have seen, there might be repetitions for small set of players and that's fine.

Parameters:

Name Type Description Default
elements list

A list of players to be shuffled n times.

required
n_permutations int

Number of permutations, Didn't check it systematically yet but just based on random explorations I'd say something around 1_000 is enough.

required
pair Optional[Tuple]

pair of elements that will always be together in every permutation

None
rng Optional[Generator]

Numpy random generator object used for reproducable results. Default is None.

None
random_seed Optional[int]

sets the random seed of the sampling process. Only used when rng is None. Default is None.

None

Returns:

Type Description
list[tuple]

Permutation space as a list of lists with shape (n_permutations, len(elements))

Source code in msapy/msa.py
@typechecked
def make_permutation_space(*,
                           elements: list,
                           n_permutations: int,
                           pair: Optional[Tuple] = None,
                           rng: Optional[np.random.Generator] = None,
                           random_seed: Optional[int] = None) -> list:
    """
    Generates a list of tuples containing n_permutations of the given elements.
    This will be used later in make_combination_space so you can have the same permutation and combination spaces for
    different games played by the same set. Probably makes things more reproducible!
    The elements themselves can be anything I guess, I tried str (names/labels) and integers (indexes),
    and tuples (edges, from-to style).
    Briefly, the permutation space of (A,B,C) is something like this:

    (A,B,C)
    (B,C,A)
    (C,B,A)
    (A,C,B)
    (C,A,B)
    (B,A,C)
    (C,A,B)
    .
    .
    .
    As you might have seen, there might be repetitions for small set of players and that's fine.

    Args:
        elements (list):
            A list of players to be shuffled n times.

        n_permutations (int):
            Number of permutations, Didn't check it systematically yet but just based on random explorations I'd say
            something around 1_000 is enough.

        pair (Optional[Tuple]):
            pair of elements that will always be together in every permutation

        rng (Optional[np.random.Generator]): Numpy random generator object used for reproducable results. Default is None.

        random_seed (Optional[int]):
            sets the random seed of the sampling process. Only used when `rng` is None. Default is None.

    Returns:
        (list[tuple]): Permutation space as a list of lists with shape (n_permutations, len(elements))
    """

    # ------------------------------#
    _check_valid_elements(elements)
    _check_valid_n_permutations(n_permutations)
    # ------------------------------#

    type_of_elements = type(elements[0])

    # create a numpy random number generator if one is not passed
    if not rng:
        rng = np.random.default_rng(random_seed) if random_seed \
            else np.random.default_rng()

    # return n_permutations random permutations if pair argument is not passed
    if not pair:
        permutation_space = [tuple(type_of_elements(element)
                                   for element in rng.permutation(elements))
                             for _ in range(n_permutations)]

        return permutation_space

    # if the pair argument is passed, then all permutations will have those two elements together using the following logic
    elements = [e for e in elements if e != pair[0]]
    permutation_space = []

    for _ in range(n_permutations):
        permutation = list(rng.permutation(elements))
        permutation.insert(permutation.index(pair[1]), pair[0])
        permutation_space.append(tuple(permutation))

    return permutation_space