Skip to content

Commit

Permalink
doc
Browse files Browse the repository at this point in the history
  • Loading branch information
VascoSch92 committed May 29, 2024
1 parent 607c8a2 commit cfdb69a
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 41 deletions.
12 changes: 6 additions & 6 deletions symmetria/elements/_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ class _Element(ABC):

@abstractmethod
def __bool__(self) -> bool:
"""Implement method `bool( )`."""
"""Implement method `bool()`."""
raise NotImplementedError

@abstractmethod
def __call__(self, item: Any) -> Any:
"""Implement method `self( )`."""
"""Implement call on an item."""
raise NotImplementedError

@abstractmethod
Expand All @@ -32,17 +32,17 @@ def __mul__(self, other):

@abstractmethod
def __pow__(self, power: int) -> "_Element":
"""Implement method `__pow__()`."""
"""Implement power of an element."""
raise NotImplementedError

@abstractmethod
def __repr__(self) -> str:
"""Implement method `__repr__( )`."""
"""Implement representaiton method."""
raise NotImplementedError

@abstractmethod
def __str__(self) -> str:
"""Implement method `__str__( )`."""
"""Implement method `str()`."""
raise NotImplementedError

# TODO: decide if we want to implement this method also for the classes Cycle and CycleDecomposition
Expand Down Expand Up @@ -114,7 +114,7 @@ def is_regular(self) -> bool:
@property
@abstractmethod
def map(self) -> Dict[int, int]:
"""Return a dictionary representing the map defining the element."""
"""Return a dictionary representing the map defined the element."""
raise NotImplementedError

def name(self) -> str:
Expand Down
63 changes: 51 additions & 12 deletions symmetria/elements/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,16 @@ def __eq__(self, other: Any) -> bool:
:return: True if the cycle is equal to `other`, i.e., they define the same map. Otherwise, False.
:rtype: bool
:example:
>>> from symmetria import Cycle
...
>>> Cycle(1, 2, 3) == Cycle(3, 1, 2)
True
>>> Cycle(1, 3, 2) == Cycle(1, 2, 3)
False
>>> Cycle(1, 2, 3) == 13
False
"""
if isinstance(other, Cycle):
lhs_length, rhs_length = len(self), len(other)
Expand All @@ -209,7 +219,7 @@ def __eq__(self, other: Any) -> bool:
def __getitem__(self, item: int) -> int:
"""Return the value of the cycle at the given index `item`.
The index corresponds to the position in the cycle, starting from 0.
The index corresponds to the position in the cycle in its standardize form, starting from 0.
:param item: The index of the cycle.
:type item: int
Expand All @@ -218,6 +228,16 @@ def __getitem__(self, item: int) -> int:
:rtype: int
:raises IndexError: If the index is out of range.
:example:
>>> from symmetria import Cycle
...
>>> cycle = Cycle(1, 3, 2)
>>> for idx in range(len(cycle)):
... cycle[idx]
1
3
2
"""
return self._cycle[item]

Expand Down Expand Up @@ -260,6 +280,10 @@ def __len__(self) -> int:
return len(self._cycle)

def __mul__(self, other: "Cycle") -> "Cycle":
"""
:raise NotImplementedError: Multiplication between cycles is not supported. However, composition is supported.
Try to call your cycle on the cycle you would like to compose.
"""
raise NotImplementedError(
"Multiplication between cycles is not supported. However, composition is supported. \n"
"Try to call your cycle on the cycle you would like to compose."
Expand All @@ -274,14 +298,18 @@ def __pow__(self, power: int) -> "Cycle":
:return: the power of the cycle.
:rtype: Cycle
:raises TypeError: If `power` is not an integer.
:example:
>>> from symmetria import Cycle
...
>>> Cycle(1, 3, 2) ** 0
>>> Cycle(1, 3, 2)**0
Cycle(1, 2, 3)
>>> Cycle(1, 3, 2) ** 1
>>> Cycle(1, 3, 2)**1
Cycle(1, 3, 2)
>>> Cycle(1, 3, 2) ** -1
>>> Cycle(1, 3, 2)**-1
Cycle(1, 2, 3)
>>> Cycle(1, 3, 2)**2
Cycle(1, 2, 3)
"""
if isinstance(power, int) is False:
Expand All @@ -293,10 +321,10 @@ def __pow__(self, power: int) -> "Cycle":
elif power <= -1:
return self.inverse() ** abs(power)
else:
return self(self ** (power - 1))
return Cycle(*[self.map[(self ** (power - 1)).map[idx]] for idx in self.domain])

def __repr__(self) -> str:
r"""Return a string representation of the cycle in the format "Cycle(x, y, z, ...)",
r"""Return a string representation of the cycle in the format `Cycle(x, y, z, ...)`,
where :math:`x, y, z, ... \in \mathbb{N}` are the elements of the cycle.
:return: A string representation of the cycle.
Expand All @@ -316,7 +344,10 @@ def __str__(self) -> str:
r"""Return a string representation of the cycle in the form of cycle notation.
Recall that for a cycle :math:`\sigma` of order n, its cycle notation is given by
:math:`(\sigma(x) \sigma^2(x), ..., \sigma^n(x))`, where x is an element in the support of the cycle.
.. math:: (\sigma(x)\quad\sigma^2(x)\quad...\quad\sigma^n(x)),
where x is an element in the support of the cycle, and :math:`n \in \mathbb{N}` is the cycle order.
:return: A string representation of the cycle.
:rtype: str
Expand All @@ -334,7 +365,7 @@ def __str__(self) -> str:
def cycle_decomposition(self) -> "CycleDecomposition":
"""Convert the cycle into its cycle decomposition, representing it as a product of disjoint cycles.
In the specific case of a cycle, it converts it from the class `Cycle` to the class `CycleDecomposition`.
In the specific case of a cycle, it converts it from the class ``Cycle`` to the class ``CycleDecomposition``.
:return: The cycle decomposition of the permutation.
:rtype: CycleDecomposition
Expand All @@ -357,7 +388,10 @@ def cycle_notation(self) -> str:
r"""Return a string representing the cycle notation of the cycle.
Recall that for a cycle :math:`\sigma` of order n, its cycle notation is given by
:math:`(\sigma(x) \sigma^2(x), ..., \sigma^n(x))`, where x is an element in the support of the cycle.
.. math:: (\sigma(x)\quad\sigma^2(x)\quad...\quad\sigma^n(x)),
where x is an element in the support of the cycle, and :math:`n \in \mathbb{N}` is the cycle order.
:return: The cycle notation of the cycle.
:rtype: str
Expand Down Expand Up @@ -409,16 +443,20 @@ def domain(self) -> Iterable[int]:

@property
def elements(self) -> Tuple[int]:
"""Return a tuple containing the elements of the cycle.
"""Return a tuple containing the elements of the cycle in its standard form.
:return: The elements of the cycle.
:rtype: Tuple[int]
:example:
>>> from symmetria import Cycle
...
>>> Cycle(1).elements
(1,)
>>> Cycle(3, 1, 2).elements
(1, 2, 3)
>>> Cycle(3, 4, 7, 1, 2).elements
(1, 2, 3, 4, 7)
"""
return self._cycle

Expand Down Expand Up @@ -470,7 +508,7 @@ def inverse(self) -> "Cycle":
the only permutation :math:`\tau \in S_n` such that :math:`\sigma * \tau = \tau * \sigma = id`,
where :math:`id` is the identity permutation.
In the case of cycles, it suffices to consider the backward cycle.
Note that for a cycle, its inverse is just the backward cycle.
:return: The inverse of the cycle.
:rtype: Cycle
Expand Down Expand Up @@ -634,7 +672,8 @@ def orbit(self, item: Any) -> List[Any]:
r"""Compute the orbit of `item` object under the action of the cycle.
Recall that the orbit of the action of a cycle :math:`\sigma` on an element x is given by the set
:math:`\{ \sigma^n(x): n \in \mathbb{N}\}`.
.. math:: \{ \sigma^n(x): n \in \mathbb{N}\}.
:param item: The initial element or iterable to compute the orbit for.
:type item: Any
Expand Down
38 changes: 30 additions & 8 deletions symmetria/elements/cycle_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,23 @@ def _call_on_permutation(self, original: "Permutation") -> "Permutation":
return symmetria.elements.permutation.Permutation.from_cycle_decomposition(self) * original

def __eq__(self, other: Any) -> bool:
"""Check if the cycle decomposition is equal to the `another` object.
"""Check if the cycle decomposition is equal to the `other` object.
:param other: The object to compare with.
:type other: Any
:return: True if the cycle decomposition is equal to `other`, i.e., they define the same map. Otherwise, False.
:rtype: bool
:example:
>>> from symmetria import Cycle, CycleDecomposition
...
>>> CycleDecomposition(Cycle(1, 2)) == CycleDecomposition(Cycle(1, 2))
True
>>> CycleDecomposition(Cycle(1), Cycle(2)) == CycleDecomposition(Cycle(1), Cycle(2))
True
>>> CycleDecomposition(Cycle(1), Cycle(2, 3)) == CycleDecomposition(Cycle(1))
False
"""
if isinstance(other, CycleDecomposition):
if len(self) != len(other):
Expand Down Expand Up @@ -291,6 +301,8 @@ def __pow__(self, power: int) -> "CycleDecomposition":
:return: the power of the cycle decomposition.
:rtype: Permutation
:raises TypeError: If `power` is not an integer.
:example:
>>> from symmetria import Cycle, CycleDecomposition
...
Expand All @@ -300,6 +312,8 @@ def __pow__(self, power: int) -> "CycleDecomposition":
CycleDecomposition(Cycle(1, 2), Cycle(3))
>>> CycleDecomposition(Cycle(1, 2), Cycle(3)) ** -1
CycleDecomposition(Cycle(1, 2), Cycle(3))
>>> CycleDecomposition(Cycle(1, 3), Cycle(2, 4))**2
CycleDecomposition(Cycle(1), Cycle(2), Cycle(3), Cycle(4))
"""
if isinstance(power, int) is False:
raise TypeError(f"Power operation for type {type(power)} not supported.")
Expand All @@ -313,9 +327,13 @@ def __pow__(self, power: int) -> "CycleDecomposition":
return self * (self ** (power - 1))

def __repr__(self) -> str:
r"""Return a string representation of the cycle decomposition in the format
'CycleDecomposition(Cycle(x, ...), Cycle(y, ...), ...)', where :math:`x, y, ... \in \mathbb{N}` are
the elements of the cycles.
r"""Return a string representation of the cycle decomposition.
The string representation is in the following format:
.. math:: 'CycleDecomposition(Cycle(x, ...), Cycle(y, ...), ...)',
where :math:`x, y, ... \in \mathbb{N}` are the elements of the cycles.
:return: A string representation of the cycle decomposition.
:rtype: str
Expand All @@ -333,7 +351,7 @@ def __repr__(self) -> str:
return f"CycleDecomposition({', '.join([cycle.__repr__() for cycle in self])})"

def __str__(self) -> str:
"""Return a string representation of the cycle decmposition in the cycle notation.
"""Return a string representation of the cycle decomposition in the cycle notation.
:return: A string representation of the cycle decomposition.
:rtype: str
Expand Down Expand Up @@ -646,7 +664,8 @@ def orbit(self, item: Any) -> List[Any]:
r"""Compute the orbit of `item` object under the action of the cycle decomposition.
Recall that the orbit of the action of a cycle decomposition :math:`\sigma` on an element x is given by the set
:math:`\{ \sigma^n(x): n \in \mathbb{N}\}`.
..math:: \{ \sigma^n(x): n \in \mathbb{N}\}.
:param item: The initial element or iterable to compute the orbit for.
:type item: Any
Expand Down Expand Up @@ -708,8 +727,9 @@ def sgn(self) -> int:
return prod([cycle.sgn() for cycle in self])

def support(self) -> Set[int]:
"""Return a set containing the indices in the domain of the permutation whose images are different from
their respective indices, i.e., the set of :math:`n` in the permutation domain which are not mapped to itself.
r"""Return a set containing the indices in the domain of the permutation whose images are different from
their respective indices, i.e., the set of :math:`n \in \mathbb{N}` in the permutation domain which are
not mapped to itself.
:return: The support set of the cycle decomposition.
:rtype: Set[int]
Expand All @@ -721,5 +741,7 @@ def support(self) -> Set[int]:
set()
>>> CycleDecomposition(Cycle(1), Cycle(2, 3)).support()
{2, 3}
>>> CycleDecomposition(Cycle(3, 4, 5, 6), Cycle(2, 1)).support()
{1, 2, 3, 4, 5, 6}
"""
return {element for cycle in self if len(cycle) != 1 for element in cycle.elements}
Loading

0 comments on commit cfdb69a

Please sign in to comment.