Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENHANCEMENT][FEATURE] Improve method sng() and add degree() method #104

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ The version is represented by three digits: a.b.c.

## Unreleased

FEATURE:
- `symmetria.Permutation`: add `degree` method
- `symmetria.CyclePermutation`: add `degree` method
- `symmetria.Cycle`: add `degree` method

ENHANCEMENT:
- `symmetria.Permutation`: change how the sign is computed


## \[0.2.0\] - 2024-06-12

Expand Down
5 changes: 5 additions & 0 deletions docs/source/pages/API_reference/elements/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ Here, **P** denotes the class ``Permutation``, **C** the class ``Cycle``, and **
- ✅
- ✅
- ✅
* - ``degree``
- Return the degree of the permutation
- ✅
- ✅
- ✅
* - ``descents``
- Return the positions of the permutation descents
- ✅
Expand Down
20 changes: 20 additions & 0 deletions symmetria/elements/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,26 @@ def cycle_notation(self) -> str:
"""
return str(self)

def degree(self) -> int:
"""Return the degree of the cycle.

Recall that the degree of a cycle is the number of elements on which it acts.

:return: The degree of the cycle.
:rtype: int

:example:
>>> from symmetria import Cycle
...
>>> Cycle(1).degree()
1
>>> Cycle(1, 3, 2).degree()
3
>>> Cycle(1, 4, 3, 2).degree()
4
"""
return len(self)

def describe(self) -> str:
"""Return a table describing the cycle.

Expand Down
20 changes: 20 additions & 0 deletions symmetria/elements/cycle_decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,26 @@ def cycle_type(self) -> Tuple[int]:
"""
return tuple(sorted(len(cycle) for cycle in self))

def degree(self) -> int:
"""Return the degree of the cycle decomposition.

Recall that the degree of a cycle decomposition is the number of elements on which it acts.

:return: The degree of the cycle decomposition.
:rtype: int

:example:
>>> from symmetria import Cycle, CycleDecomposition
...
>>> CycleDecomposition(Cycle(1)).degree()
1
>>> CycleDecomposition(Cycle(1), Cycle(3, 2)).degree()
3
>>> CycleDecomposition(Cycle(1, 4), Cycle(3, 2)).degree()
4
"""
return max(max(cycle.elements) for cycle in self._cycles)

def descents(self) -> List[int]:
r"""Return the descents of the cycle decomposition.

Expand Down
25 changes: 23 additions & 2 deletions symmetria/elements/permutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,26 @@ def cycle_type(self) -> Tuple[int]:
"""
return tuple(sorted(len(cycle) for cycle in self.cycle_decomposition()))

def degree(self) -> int:
"""Return the degree of the permutation.

Recall that the degree of a permutation is the number of elements on which it acts.

:return: The degree of the permutation.
:rtype: int

:example:
>>> from symmetria import Permutation
...
>>> Permutation(1).degree()
1
>>> Permutation(1, 3, 2).degree()
3
>>> Permutation(1, 4, 3, 2).degree()
4
"""
return len(self)

def descents(self) -> List[int]:
r"""Return the descents of the permutation.

Expand Down Expand Up @@ -1006,7 +1026,8 @@ def sgn(self) -> int:
r"""Return the sign of the permutation.

Recall that the sign, signature, or signum of a permutation :math:`\sigma` is defined as +1 if :math:`\sigma`
is even, and -1 if :math:`\sigma` is odd.
is even, i.e., :math:`\sigma` has an even number of inversions, and -1 if :math:`\sigma` is odd, i.e.,
:math:`\sigma` has an odd number of inversions.

:return: 1 if the permutation is even, -1 if the permutation is odd.
:rtype: int
Expand All @@ -1021,7 +1042,7 @@ def sgn(self) -> int:
>>> Permutation(2, 3, 4, 5, 6, 1).sgn()
-1
"""
return self.cycle_decomposition().sgn()
return -1 if len(self.inversions()) % 2 else 1

def support(self) -> Set[int]:
r"""Return a set containing the indices in the domain of the permutation whose images are different from their
Expand Down
5 changes: 5 additions & 0 deletions tests/tests_elements/tests_cycle/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
(Cycle(1, 2), "(1 2)"),
(Cycle(1, 2, 3), "(1 2 3)"),
]
TEST_DEGREE = [
(Cycle(1), 1),
(Cycle(1, 3, 2), 3),
(Cycle(1, 4, 3, 2), 4),
]
TEST_DESCRIBE = [
(
Cycle(1),
Expand Down
11 changes: 11 additions & 0 deletions tests/tests_elements/tests_cycle/test_generic_method.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
TEST_SGN,
TEST_ORBIT,
TEST_ORDER,
TEST_DEGREE,
TEST_DOMAIN,
TEST_IS_ODD,
TEST_INVERSE,
Expand Down Expand Up @@ -60,6 +61,16 @@ def test_equivalent(lhs, rhs, expected_value) -> None:
)


@pytest.mark.parametrize(
argnames="cycle, expected_value",
argvalues=TEST_DEGREE,
ids=[f"{c.rep()}.degree()={d}" for c, d in TEST_DEGREE],
)
def test_degree(cycle, expected_value) -> None:
"""Tests for the method `degree()`."""
_check_values(expression=f"{cycle.rep()}.degree()", evaluation=cycle.degree(), expected=expected_value)


@pytest.mark.parametrize(
argnames="cycle, expected_value",
argvalues=TEST_DESCRIBE,
Expand Down
5 changes: 5 additions & 0 deletions tests/tests_elements/tests_cycle_decomposition/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
(CycleDecomposition(Cycle(1, 3, 2), Cycle(4)), (1, 3)),
(CycleDecomposition(Cycle(1, 2), Cycle(3, 4)), (2, 2)),
]
TEST_DEGREE = [
(CycleDecomposition(Cycle(1)), 1),
(CycleDecomposition(Cycle(1), Cycle(2, 3)), 3),
(CycleDecomposition(Cycle(1), Cycle(2), Cycle(3)), 3),
]
TEST_DESCENTS = [
(CycleDecomposition(Cycle(1, 2, 3)), [2]),
(CycleDecomposition(Cycle(1), Cycle(2), Cycle(3)), []),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
TEST_SGN,
TEST_ORBIT,
TEST_ORDER,
TEST_DEGREE,
TEST_IS_ODD,
TEST_ASCENTS,
TEST_INVERSE,
Expand Down Expand Up @@ -97,6 +98,20 @@ def test_descents(cycle_decomposition, expected_value) -> None:
)


@pytest.mark.parametrize(
argnames="cycle_decomposition, expected_value",
argvalues=TEST_DEGREE,
ids=[f"{p.rep()}.degree()={d}" for p, d in TEST_DEGREE],
)
def test_degree(cycle_decomposition, expected_value) -> None:
"""Tests for the method `degree()`."""
_check_values(
expression=f"{cycle_decomposition.rep()}.degree()",
evaluation=cycle_decomposition.degree(),
expected=expected_value,
)


@pytest.mark.parametrize(
argnames="cycle_decomposition, expected_value",
argvalues=TEST_DESCRIBE,
Expand Down
5 changes: 5 additions & 0 deletions tests/tests_elements/tests_permutation/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
(Permutation(3, 1, 2), "(1 3 2)"),
(Permutation(3, 1, 2, 4, 5, 6), "(1 3 2)(4)(5)(6)"),
]
TEST_DEGREE = [
(Permutation(1), 1),
(Permutation(1, 3, 2), 3),
(Permutation(1, 2, 3, 4, 5, 6, 7, 8, 9), 9),
]
TEST_DESCENTS = [
(Permutation(1, 2, 3), []),
(Permutation(3, 4, 5, 2, 1, 6, 7), [3, 4]),
Expand Down
11 changes: 11 additions & 0 deletions tests/tests_elements/tests_permutation/test_generic_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
TEST_IMAGE,
TEST_ORBIT,
TEST_ORDER,
TEST_DEGREE,
TEST_DOMAIN,
TEST_IS_ODD,
TEST_ASCENTS,
Expand Down Expand Up @@ -80,6 +81,16 @@ def test_cycle_notation(permutation, expected_value) -> None:
)


@pytest.mark.parametrize(
argnames="permutation, expected_value",
argvalues=TEST_DEGREE,
ids=[f"{p.rep()}.degree()={d}" for p, d in TEST_DEGREE],
)
def test_degree(permutation, expected_value) -> None:
"""Tests for the method `degree()`."""
_check_values(expression=f"{permutation.rep()}.degree()", evaluation=permutation.degree(), expected=expected_value)


@pytest.mark.parametrize(
argnames="permutation, expected_value",
argvalues=TEST_DESCENTS,
Expand Down
Loading