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

Steinhaus-Johnson-Trotter algorithm for permutations #38064

Merged
merged 11 commits into from
Jun 22, 2024

Conversation

JosePisco
Copy link
Contributor

I suggest this diff against develop to implement the Steinhaus-Johnson-Trotter algorithm that generates the permutations of a list using only transpositions of two elements of the list. The algorithm can be selected upon initialization with the parameter of the same name, defaults to "lex" which is the current algorithm.

Since the Permutation class is a bit weird and creates a new list and a new object on every iteration, I had to tweak a bit the parameters in input to the class __init__ method adding

  • algorithm: this one is fine, it allows to choose which algorithm to use to generate the permutations
  • directions: this one is meant to keep track of the internal state specific to the SJT algorithm. To find the two elements to transpose for the next permutation, we need to find elements according to some conditions regarding each of their direction. Since the Permutation class creates a new object at each iteration, I tried to find the best way to pass on the internal state to the new object. Maybe the internal state can be directly computed from the list, I haven't checked. Because of this dependency on the internal state, only the identity permutation can be used when initializing a Permutation object with algorithm='sjt' (see examples from doc). I am aware that adding an extra optional parameter to the object construction might not be the best option thus I will gladly take your feedback and opinions.

I haven't implemented the prev() method. I think it should be done if this is accepted.

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

⌛ Dependencies

Copy link

github-actions bot commented May 24, 2024

Documentation preview for this PR (built with commit f9d76cf; changes) is ready! 🎉
This preview will update shortly after each push to this PR.

@grhkm21
Copy link
Contributor

grhkm21 commented May 27, 2024

Linter is failing. I think a few of the other CI fails are fixed in some PRs, so maybe a rebase to trigger CI will resolve them.

Copy link
Contributor

@grhkm21 grhkm21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are also missing examples/doctests in docstrings everywhere - see developer guide, in particular the EXAMPLES block.

src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Show resolved Hide resolved
@JosePisco JosePisco force-pushed the sjt-algorithm-for-permutations branch from fe085c6 to 80ca849 Compare May 29, 2024 09:48
@JosePisco
Copy link
Contributor Author

Thanks to @grhkm21 for the review and for the tips.
After a rebase on develop, I hope commit c2fbaff meets the requested changes.

Copy link
Contributor

@grhkm21 grhkm21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I think I messed up the styling for input docstring before

src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Show resolved Hide resolved
src/sage/combinat/permutation.py Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
@grhkm21
Copy link
Contributor

grhkm21 commented May 30, 2024

Also can you resolve the comments that are fixed, so i can see what to look

@JosePisco
Copy link
Contributor Author

JosePisco commented May 31, 2024

Many thanks again @grhkm21 for reviewing the code.
Commit a44383f suggests changes that were discussed.

I've made SJT.next() method to return an SJT object, but then the Permutation class constructor takes an sjt=None parameter upon construction (we still need to pass on directions). I've closed some discussions but let some open so I don't unilaterally decide on changes.

Copy link
Contributor

@grhkm21 grhkm21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final style changes, hopefully non controversial ones. should be ok afterwards. thanks in advance

src/sage/combinat/SJT.py Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/SJT.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
src/sage/combinat/permutation.py Outdated Show resolved Hide resolved
@JosePisco
Copy link
Contributor Author

Ah thank you for catching these small style issues. Commit 1052244 meets the changes.

@JosePisco JosePisco force-pushed the sjt-algorithm-for-permutations branch from 1052244 to 6ed2a79 Compare June 4, 2024 07:54
@JosePisco
Copy link
Contributor Author

Last linting error has been fixed. If everybody agrees with the changes and the overall code suggestion, this PR is ready for merging on my side.

@grhkm21
Copy link
Contributor

grhkm21 commented Jun 8, 2024

Sorry for the delay

Copy link
Contributor

@grhkm21 grhkm21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! Feel free to open an issue for the TODOs e.g. implement .previous() or something

else:
self._directions = directions

def __idx_largest_element_non_zero_direction(self, perm, directions):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually internal methods are single underscores, but this is okay too

if self._algorithm != "lex" and self._algorithm != "sjt":
raise ValueError("unsupported algorithm %s; expected 'lex' or 'sjt'"
% self._algorithm)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Sorry, please fix this (CI lint is failing)

Copy link
Contributor

@grhkm21 grhkm21 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good

vbraun pushed a commit to vbraun/sage that referenced this pull request Jun 10, 2024
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->
I suggest this diff against develop to implement the Steinhaus-Johnson-
Trotter algorithm that generates the permutations of a list using only
transpositions of two elements of the list. The algorithm can be
selected upon initialization with the parameter of the same name,
defaults to "lex" which is the current algorithm.

Since the `Permutation` class is a bit weird and creates a new list and
a new object on every iteration, I had to tweak a bit the parameters in
input to the class `__init__` method adding
- `algorithm`: this one is fine, it allows to choose which algorithm to
use to generate the permutations
- `directions`: this one is meant to keep track of the internal state
specific to the SJT algorithm. To find the two elements to transpose for
the next permutation, we need to find elements according to some
conditions regarding each of their direction. Since the `Permutation`
class creates a new object at each iteration, I tried to find the best
way to pass on the internal state to the new object. Maybe the internal
state can be directly computed from the list, I haven't checked. Because
of this dependency on the internal state, only the identity permutation
can be used when initializing a `Permutation` object with
`algorithm='sjt'` (see examples from doc). I am aware that adding an
extra optional parameter to the object construction might not be the
best option thus I will gladly take your feedback and opinions.

I haven't implemented the `prev()` method. I think it should be done if
this is accepted.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#38064
Reported by: grnx
Reviewer(s): grhkm21, grnx
vbraun pushed a commit to vbraun/sage that referenced this pull request Jun 16, 2024
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->
I suggest this diff against develop to implement the Steinhaus-Johnson-
Trotter algorithm that generates the permutations of a list using only
transpositions of two elements of the list. The algorithm can be
selected upon initialization with the parameter of the same name,
defaults to "lex" which is the current algorithm.

Since the `Permutation` class is a bit weird and creates a new list and
a new object on every iteration, I had to tweak a bit the parameters in
input to the class `__init__` method adding
- `algorithm`: this one is fine, it allows to choose which algorithm to
use to generate the permutations
- `directions`: this one is meant to keep track of the internal state
specific to the SJT algorithm. To find the two elements to transpose for
the next permutation, we need to find elements according to some
conditions regarding each of their direction. Since the `Permutation`
class creates a new object at each iteration, I tried to find the best
way to pass on the internal state to the new object. Maybe the internal
state can be directly computed from the list, I haven't checked. Because
of this dependency on the internal state, only the identity permutation
can be used when initializing a `Permutation` object with
`algorithm='sjt'` (see examples from doc). I am aware that adding an
extra optional parameter to the object construction might not be the
best option thus I will gladly take your feedback and opinions.

I haven't implemented the `prev()` method. I think it should be done if
this is accepted.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#38064
Reported by: grnx
Reviewer(s): grhkm21, grnx
vbraun pushed a commit to vbraun/sage that referenced this pull request Jun 16, 2024
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->
I suggest this diff against develop to implement the Steinhaus-Johnson-
Trotter algorithm that generates the permutations of a list using only
transpositions of two elements of the list. The algorithm can be
selected upon initialization with the parameter of the same name,
defaults to "lex" which is the current algorithm.

Since the `Permutation` class is a bit weird and creates a new list and
a new object on every iteration, I had to tweak a bit the parameters in
input to the class `__init__` method adding
- `algorithm`: this one is fine, it allows to choose which algorithm to
use to generate the permutations
- `directions`: this one is meant to keep track of the internal state
specific to the SJT algorithm. To find the two elements to transpose for
the next permutation, we need to find elements according to some
conditions regarding each of their direction. Since the `Permutation`
class creates a new object at each iteration, I tried to find the best
way to pass on the internal state to the new object. Maybe the internal
state can be directly computed from the list, I haven't checked. Because
of this dependency on the internal state, only the identity permutation
can be used when initializing a `Permutation` object with
`algorithm='sjt'` (see examples from doc). I am aware that adding an
extra optional parameter to the object construction might not be the
best option thus I will gladly take your feedback and opinions.

I haven't implemented the `prev()` method. I think it should be done if
this is accepted.

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->

- [x] The title is concise and informative.
- [x] The description explains in detail what this PR is about.
- [ ] I have linked a relevant issue or discussion.
- [x] I have created tests covering the changes.
- [x] I have updated the documentation and checked the documentation
preview.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on. For example,
-->
<!-- - sagemath#12345: short description why this is a dependency -->
<!-- - sagemath#34567: ... -->
    
URL: sagemath#38064
Reported by: grnx
Reviewer(s): grhkm21, grnx
@vbraun vbraun merged commit 7f3080f into sagemath:develop Jun 22, 2024
4 checks passed
@mkoeppe mkoeppe added this to the sage-10.4 milestone Jul 8, 2024
@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

@bpavo

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants