Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
VascoSch92 committed Jul 14, 2024
1 parent 7b30599 commit 5cc9097
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 78 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ FEATURE:
- `symmetria.Permutation`: add `degree` method
- `symmetria.CyclePermutation`: add `degree` method
- `symmetria.Cycle`: add `degree` method
- `symmetria.random`: add random module to create random permutations

ENHANCEMENT:
- `symmetria.Permutation`: change how the sign is computed
Expand Down
32 changes: 32 additions & 0 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,38 @@ with the symmetric group and its elements.

API reference

.. grid-item-card:: :octicon:`iterations` Generators
:text-align: center
:class-title: sd-fs-5
:class-card: sd-p-3

Generating permutations

.. button-ref:: pages/API_reference/generators/index
:ref-type: doc
:color: primary
:outline:
:click-parent:
:expand:

API Reference

.. grid-item-card:: :octicon:`file-code` CLI
:text-align: center
:class-title: sd-fs-5
:class-card: sd-p-3

Command Line Interface

.. button-ref:: pages/cli/command_line_interface
:ref-type: doc
:color: primary
:outline:
:click-parent:
:expand:

API reference



.. warning:: The documentations is still a working in progress.
Expand Down
44 changes: 44 additions & 0 deletions docs/source/pages/API_reference/generators/deterministic.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
Deterministic Generation
========================

`Symmetria` provides a way to generate all the permutations of a given degree. The generation follows different
algorithms which can be specified.

You can use the generator of permutations in the following way

.. code-block:: python
import symmetria
permutations = symmetria.generate(algorithm="lexicographic", degree=3)
A list of implemented algorithms to generate permutations:

.. list-table:: overview
:widths: 35 50 15
:header-rows: 1

* - Algorithm
- Description
- Reference
* - ``lexicographic``
- The permutations are generate following the **lexicographic order**.
- `[1]`_
* - ``heap``
- The permutations are generate following the **Heap's algorithm**.
- `[2]`_
* - ``steinhaus-johnson-trotter``
- The permutations are generate following the **Steinhaus-Johnson-Trotter algorithm**.
- `[3]`_

.. _[1]: https://en.wikipedia.org/wiki/Lexicographic_order
.. _[2]: https://academic.oup.com/comjnl/article/6/3/293/360213
.. _[3]: https://en.wikipedia.org/wiki/Steinhaus–Johnson–Trotter_algorithm

====

The API of the method is given as following:

.. automodule:: symmetria.generators.algorithm.api
:members: generate
:exclude-members: random, random_generator
18 changes: 0 additions & 18 deletions docs/source/pages/API_reference/generators/generate.rst

This file was deleted.

31 changes: 5 additions & 26 deletions docs/source/pages/API_reference/generators/index.rst
Original file line number Diff line number Diff line change
@@ -1,36 +1,15 @@
Generators
==========

`Symmetria` provides a way to generate all the permutations of a given degree. The generation follows different
algorithms which can be specified.
`Symmetria` provides a way to generate permutations of a given degree in two way:

.. note:: The permutation are generated following a well-defined pattern, i.e., they are not random.
- algorithmically, i.e., the permutations are generated following a given algorithm;
- randomly, i.e., the permutations are generate randomly.

A list of implemented algorithms to generate permutations:

.. list-table:: overview
:widths: 35 50 15
:header-rows: 1

* - Algorithm
- Description
- Reference
* - ``lexicographic``
- The permutations are generate following the **lexicographic order**.
- `[1]`_
* - ``heap``
- The permutations are generate following the **Heap's algorithm**.
- `[2]`_
* - ``steinhaus-johnson-trotter``
- The permutations are generate following the **Steinhaus-Johnson-Trotter algorithm**.
- `[3]`_

.. _[1]: https://en.wikipedia.org/wiki/Lexicographic_order
.. _[2]: https://academic.oup.com/comjnl/article/6/3/293/360213
.. _[3]: https://en.wikipedia.org/wiki/Steinhaus–Johnson–Trotter_algorithm

.. toctree::
:maxdepth: 1
:hidden:

generate
deterministic
random
48 changes: 48 additions & 0 deletions docs/source/pages/API_reference/generators/random.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Random Generation
=================

`Symmetria` provides a way to generate random permutation.

You can use the random generation of permutations in the following way

.. code-block:: python
import symmetria
permutations = symmetria.random_generator(algorithm="lexicographic", degree=3)
If you don't want to have a generator and you want to just have a singular random permutation
you can use write

.. code-block:: python
import symmetria
permutation = symmetria.random(algorithm="lexicographic", degree=3)
A list of implemented algorithms to generate permutations:

.. list-table:: overview
:widths: 35 50 15
:header-rows: 1

* - Algorithm
- Description
- Reference
* - ``random``
- A permutation is generated by choosing the integer uniformly.
-
* - ``fisher-yates``
- The permutations are generate following the **Steinhaus-Johnson-Trotter algorithm**.
- `[1]`_

.. _[1]: https://en.wikipedia.org/wiki/Lexicographic_order

====

The API of the method is given as following:

.. automodule:: symmetria.generators.random.api
:members: random_generator
:exclude-members: random
13 changes: 11 additions & 2 deletions symmetria/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
from symmetria.elements.cycle import Cycle
from symmetria.generators.api import generate
from symmetria.elements.permutation import Permutation
from symmetria.generators.random.api import random, random_generator
from symmetria.generators.algorithm.api import generate
from symmetria.elements.cycle_decomposition import CycleDecomposition

__version__ = "0.2.0"
__all__ = ["__version__", "generate", "Permutation", "Cycle", "CycleDecomposition"]
__all__ = [
"__version__",
"generate",
"random",
"random_generator",
"Permutation",
"Cycle",
"CycleDecomposition",
]
26 changes: 26 additions & 0 deletions symmetria/generators/_validators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from typing import List


def _check_algorithm_parameter(value: str, supported: List[str]) -> None:
"""Private method to check the value provided for the parameter `algorithm`.
Recall that the parameter `algorithm` must be a string present in the list `supported`.
"""
if isinstance(value, str) is False:
raise TypeError(f"The parameter `algorithm` must be of type string, but {type(value)} was provided.")
if value not in supported:
raise ValueError(
f"The given algorithm ({value}) is not supported. \n "
f"Here, a list of supported algorithm for generations of permutations {supported}."
)


def _check_degree_parameter(value: int) -> None:
"""Private method to check the value provided for the parameter `degree`.
Recall that the parameter `degree` must be a non-negative integer different from zero.
"""
if isinstance(value, int) is False:
raise TypeError(f"The parameter `degree` must be of type int, but {type(value)} was provided.")
if value < 1:
raise ValueError(f"The parameter `degree` must be a non-zero positive integer, but {value} was provided.")
Empty file.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from typing import List, Generator

import symmetria.elements.permutation
from symmetria import Permutation


def _lexicographic(degree: int, start: List[int]) -> Generator["Permutation", None, None]:
def _lexicographic(degree: int, start: List[int]) -> Generator[Permutation, None, None]:
"""Private method to generate all the permutations of degree `degree` in lexicographic order.
The algorithm is described as follows:
Expand Down Expand Up @@ -38,7 +39,7 @@ def _lexicographic(degree: int, start: List[int]) -> Generator["Permutation", No
permutation[k + 1 :] = reversed(permutation[k + 1 :])


def _heap(degree: int, start: List[int]) -> Generator["Permutation", None, None]:
def _heap(degree: int, start: List[int]) -> Generator[Permutation, None, None]:
"""Private method to generate all the permutations of degree `degree` using the Heap's algorithm.
A description of the algorithm can be founded in the article:
Expand All @@ -63,7 +64,7 @@ def _heap(degree: int, start: List[int]) -> Generator["Permutation", None, None]
yield from _heap(k - 1, permutation)


def _steinhaus_johnson_trotter(degree: int, start: List[int]) -> Generator["Permutation", None, None]:
def _steinhaus_johnson_trotter(degree: int, start: List[int]) -> Generator[Permutation, None, None]:
"""Private method to generate all the permutations of degree `degree` using the Steinhaus-Johnson-Trotter algorithm.
A description of the algorithm is given at:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import List, Generator

from symmetria.generators._algorithms import (
from symmetria import Permutation
from symmetria.generators._validators import _check_degree_parameter, _check_algorithm_parameter
from symmetria.generators.algorithm._algorithms import (
_heap,
_lexicographic,
_steinhaus_johnson_trotter,
Expand All @@ -15,7 +17,7 @@
]


def generate(degree: int, algorithm: str = "lexicographic") -> Generator["Permutation", None, None]:
def generate(degree: int, algorithm: str = "lexicographic") -> Generator[Permutation, None, None]:
"""Generate all the permutations of the given degree based on the chosen algorithm.
The method generates all the permutations of the given degree using the specified algorithm.
Expand Down Expand Up @@ -45,37 +47,12 @@ def generate(degree: int, algorithm: str = "lexicographic") -> Generator["Permut
Permutation(3, 1, 2)
Permutation(3, 2, 1)
"""
_check_algorithm_parameter(value=algorithm)
_check_algorithm_parameter(value=algorithm, supported=_SUPPORTED_ALGORITHM)
_check_degree_parameter(value=degree)
return _relevant_generator(algorithm=algorithm, degree=degree)


def _check_algorithm_parameter(value: str) -> None:
"""Private method to check the value provided for the parameter `algorithm`.
Recall that the parameter `algorithm` must be a string present in the list _SUPPORTED_ALGORITHM
"""
if isinstance(value, str) is False:
raise TypeError(f"The parameter `algorithm` must be of type string, but {type(value)} was provided.")
if value not in _SUPPORTED_ALGORITHM:
raise ValueError(
f"The given algorithm ({value}) is not supported. \n "
f"Here, a list of supported algorithm for generations of permutations {_SUPPORTED_ALGORITHM}."
)


def _check_degree_parameter(value: int) -> None:
"""Private method to check the value provided for the parameter `degree`.
Recall that the parameter `degree` must be a non-negative integer different from zero.
"""
if isinstance(value, int) is False:
raise TypeError(f"The parameter `degree` must be of type int, but {type(value)} was provided.")
if value < 1:
raise ValueError(f"The parameter `degree` must be a non-zero positive integer, but {value} was provided.")


def _relevant_generator(algorithm: str, degree: int) -> Generator["Permutation", None, None]:
def _relevant_generator(algorithm: str, degree: int) -> Generator[Permutation, None, None]:
"""Private method to pick the correct algorithm for generating permutations."""
if algorithm == "lexicographic":
return _lexicographic(degree=degree, start=list(range(1, degree + 1)))
Expand Down
Empty file.
33 changes: 33 additions & 0 deletions symmetria/generators/random/_algorithms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from random import randint, shuffle
from typing import List, Generator

from symmetria import Permutation


def _random_shuffle(permutation: List[int]) -> Permutation:
"""Private method to generate a random permutation using the random module of Python."""
shuffle(permutation)
return Permutation(*permutation)


def _random_shuffle_generator(degree: int) -> Generator[Permutation, None, None]:
"""Private method to generate random permutations using the random module of Python."""
permutation = list(range(1, degree + 1))
while True:
yield _random_shuffle(permutation=permutation)


def _fisher_yates_shuffle(permutation: List[int]) -> Permutation:
"""Private method to generate a random permutation using the Fisher-Yates shuffle."""
n = len(permutation)
for i in range(n - 1, 0, -1):
j = randint(0, i)
permutation[i], permutation[j] = permutation[j], permutation[i]
return Permutation(*permutation)


def _fisher_yates_shuffle_generator(degree: int) -> Generator[Permutation, None, None]:
"""Private method to generate random permutations using the Fisher-Yates shuffle."""
permutation = list(range(1, degree + 1))
while True:
yield _fisher_yates_shuffle(permutation=permutation)
Loading

0 comments on commit 5cc9097

Please sign in to comment.