Skip to content

Commit 6411ca8

Browse files
authored
Merge pull request #175 from PermutaTriangle/develop
Version 2.1.0
2 parents e840107 + c43e5e1 commit 6411ca8

File tree

12 files changed

+2366
-516
lines changed

12 files changed

+2366
-516
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
repos:
22
- repo: https://github.com/psf/black
3-
rev: 20.8b0
3+
rev: 21.6b0
44
hooks:
55
- id: black

.zenodo.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@
4141
},
4242
{
4343
"name": "Arnar Bjarni Arnarson"
44+
},
45+
{
46+
"affiliation": "Reykjavik University",
47+
"name": "Sigurjón Ingi Jónsson"
4448
}
4549
]
46-
}
50+
}

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
66

77
## Unreleased
88

9+
## 2.1.0 - 2021-06-14
10+
### Added
11+
- Statistic: bounce of a permutation.
12+
- Statistic: maximum drop size.
13+
- Statistic: number of primes in the column sums.
14+
- Statistic: holeyness of a permutation.
15+
- Algorithm: `pop stack sort`.
16+
- Statistic: count stack sorts.
17+
- Statistic: count pop stack sorts.
18+
- Statistic: Pinnacle set and number of pinnacles.
19+
20+
### Changed
21+
- Functions for ascents and descents now take an optional argument to specify what step size to calculate.
22+
- Moved sorting functions from `permuta/bisc/perm_properties.py` to `permuta/patterns/perm.py`.
23+
924
## 2.0.3 - 2021-04-28
1025
### Added
1126
- using Github Actions for testing and deployment

README.rst

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ permuta
1616
:alt: Travis
1717
:target: https://travis-ci.org/PermutaTriangle/Permuta
1818
.. image:: https://requires.io/github/PermutaTriangle/Permuta/requirements.svg?branch=master
19-
:target: https://requires.io/github/PermutaTriangle/Permuta/requirements/?branch=master
20-
:alt: Requirements Status
19+
:target: https://requires.io/github/PermutaTriangle/Permuta/requirements/?branch=master
20+
:alt: Requirements Status
21+
.. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.4725759.svg
22+
:target: https://doi.org/10.5281/zenodo.4725759
2123

2224
Permuta is a Python library for working with perms (short for permutations),
2325
patterns, and mesh patterns.
@@ -235,6 +237,22 @@ and a class (no class will use the set of all permutations).
235237
[14] Longest increasing subsequence
236238
[15] Longest decreasing subsequence
237239
[16] Depth
240+
[17] Number of bounces
241+
[18] Maximum drop size
242+
[19] Number of primes in the column sums
243+
[20] Holeyness of a permutation
244+
[21] Number of stack-sorts needed
245+
[22] Number of pop-stack-sorts needed
246+
[23] Number of pinnacles
247+
[24] Number of cyclic peaks
248+
[25] Number of cyclic valleys
249+
[26] Number of double excedance
250+
[27] Number of double drops
251+
[28] Number of foremaxima
252+
[29] Number of afterminima
253+
[30] Number of aftermaxima
254+
[31] Number of foreminima
255+
238256
>>> depth = PermutationStatistic.get_by_index(16)
239257
>>> depth.distribution_for_length(5)
240258
[1, 4, 12, 24, 35, 24, 20]
@@ -251,6 +269,8 @@ Given a bijection as a dictionary, we can check which statistics are preserved w
251269
... print(stat)
252270
Number of peaks
253271
Number of valleys
272+
Holeyness of a permutation
273+
Number of pinnacles
254274
255275
We can find all (predefined) statistics equally distributed over two permutation
256276
classes with ``equally_distributed``. We also support checks for joint distribution
@@ -272,6 +292,7 @@ of jointly distributed stats with ``jointly_transformed_equally_distributed``.
272292
Number of right-to-left maximas
273293
Longest increasing subsequence
274294
Longest decreasing subsequence
295+
Number of pinnacles
275296
276297
The BiSC algorithm
277298
==================
@@ -287,20 +308,19 @@ To use the algorithm we first need to import it.
287308
>>> from permuta.bisc import *
288309
289310
A classic example of a set of permutations described by pattern avoidance are
290-
the permutations sortable in one pass through a stack. We start by loading a
291-
function ``stack_sortable`` which returns ``True`` for permutations that
292-
satisfy this property. The user now has two choices: Run
293-
``auto_bisc(stack_sortable)`` and let the algorithm run without any more user
294-
input. It will try to use sensible values, starting by learning small patterns
295-
from small permutations, and only considering longer patterns when that fails.
296-
If the user wants to have more control over what happens that is also possible
297-
and we now walk through that: We input the property into ``bisc`` and ask it to
298-
search for patterns of length 3.
311+
the permutations sortable in one pass through a stack. We use the function
312+
``stack_sortable`` which returns ``True`` for permutations that satisfy this
313+
property. The user now has two choices: Run
314+
``auto_bisc(Perm.stack_sortable)`` and let the algorithm run
315+
without any more user input. It will try to use sensible values, starting by
316+
learning small patterns from small permutations, and only considering longer
317+
patterns when that fails. If the user wants to have more control over what
318+
happens that is also possible and we now walk through that: We input the
319+
property into ``bisc`` and ask it to search for patterns of length 3.
299320

300321
.. code-block:: python
301322
302-
>>> from permuta.bisc.perm_properties import stack_sortable
303-
>>> bisc(stack_sortable, 3)
323+
>>> bisc(Perm.stack_sortable, 3)
304324
I will use permutations up to length 7
305325
{3: {Perm((1, 2, 0)): [set()]}}
306326
@@ -315,7 +335,7 @@ be considered.
315335

316336
.. code-block:: python
317337
318-
>>> SG = bisc(stack_sortable, 3, 5)
338+
>>> SG = bisc(Perm.stack_sortable, 3, 5)
319339
>>> show_me(SG)
320340
There are 1 underlying classical patterns of length 3
321341
There are 1 different shadings on 120
@@ -341,8 +361,7 @@ patterns, such as the West-2-stack-sortable permutations
341361

342362
.. code-block:: python
343363
344-
>>> from permuta.bisc.perm_properties import west_2_stack_sortable
345-
>>> SG = bisc(west_2_stack_sortable, 5, 7)
364+
>>> SG = bisc(Perm.west_2_stack_sortable, 5, 7)
346365
>>> show_me(SG)
347366
There are 2 underlying classical patterns of length 4
348367
There are 1 different shadings on 1230
@@ -394,7 +413,7 @@ which keeps them separated by length.
394413

395414
.. code-block:: python
396415
397-
>>> A, B = create_bisc_input(7, west_2_stack_sortable)
416+
>>> A, B = create_bisc_input(7, Perm.west_2_stack_sortable)
398417
399418
This creates two dictionaries with keys 1, 2, ..., 7 such that ``A[i]`` points
400419
to the list of permutations of length ``i`` that are West-2-stack-sortable, and
@@ -476,3 +495,13 @@ License
476495
#######
477496

478497
BSD-3: see the `LICENSE <https://github.com/PermutaTriangle/Permuta/blob/master/LICENSE>`_ file.
498+
499+
Citing
500+
######
501+
502+
If you found this library helpful with your research and would like to cite us,
503+
you can use the following `BibTeX`_ or go to `Zenodo`_ for alternative formats.
504+
505+
.. _BibTex: https://zenodo.org/record/4725759/export/hx#.YImTibX7SUk
506+
507+
.. _Zenodo: https://doi.org/10.5281/zenodo.4725759

permuta/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from .patterns import BivincularPatt, CovincularPatt, MeshPatt, Perm, VincularPatt
22
from .perm_sets.permset import Av, Basis, MeshBasis
33

4-
__version__ = "2.0.4"
4+
__version__ = "2.1.0"
55

66
__all__ = [
77
"Perm",

permuta/bisc/perm_properties.py

Lines changed: 1 addition & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,10 @@
1-
from collections import deque
21
from itertools import islice
3-
from typing import Deque, List, Tuple
2+
from typing import List
43

54
from permuta.patterns.meshpatt import MeshPatt
6-
from permuta.patterns.patt import Patt
75
from permuta.patterns.perm import Perm
86
from permuta.permutils.groups import dihedral_group
97

10-
11-
def _is_sorted(lis: List[int]) -> bool:
12-
# Return true if w is increasing, i.e., sorted.
13-
return all(elem == i for elem, i in zip(lis, range(len(lis))))
14-
15-
16-
def _stack_sort(perm_slice: List[int]) -> List[int]:
17-
n = len(perm_slice)
18-
if n in (0, 1):
19-
return perm_slice
20-
max_i, max_v = max(enumerate(perm_slice), key=lambda pos_elem: pos_elem[1])
21-
# Recursively solve without largest
22-
if max_i == 0:
23-
n_lis = _stack_sort(perm_slice[1:n])
24-
elif max_i == n - 1:
25-
n_lis = _stack_sort(perm_slice[0 : n - 1])
26-
else:
27-
n_lis = _stack_sort(perm_slice[0:max_i])
28-
n_lis.extend(_stack_sort(perm_slice[max_i + 1 : n]))
29-
n_lis.append(max_v)
30-
return n_lis
31-
32-
33-
def stack_sortable(perm: Perm) -> bool:
34-
"""Returns true if perm is stack sortable."""
35-
return _is_sorted(_stack_sort(list(perm)))
36-
37-
38-
def _bubble_sort(perm_slice: List[int]) -> List[int]:
39-
n = len(perm_slice)
40-
if n in (0, 1):
41-
return perm_slice
42-
max_i, max_v = max(enumerate(perm_slice), key=lambda pos_elem: pos_elem[1])
43-
# Recursively solve without largest
44-
if max_i == 0:
45-
n_lis = perm_slice[1:n]
46-
elif max_i == n - 1:
47-
n_lis = _bubble_sort(perm_slice[0 : n - 1])
48-
else:
49-
n_lis = _bubble_sort(perm_slice[0:max_i])
50-
n_lis.extend(perm_slice[max_i + 1 : n])
51-
n_lis.append(max_v)
52-
return n_lis
53-
54-
55-
def bubble_sortable(perm: Perm) -> bool:
56-
"""Returns true if perm is stack sortable."""
57-
return _is_sorted(_bubble_sort(list(perm)))
58-
59-
60-
def _quick_sort(perm_slice: List[int]) -> List[int]:
61-
assert not perm_slice or set(perm_slice) == set(
62-
range(min(perm_slice), max(perm_slice) + 1)
63-
)
64-
n = len(perm_slice)
65-
if n == 0:
66-
return perm_slice
67-
maxind = -1
68-
# Note that perm does not need standardizing as sfp uses left to right maxima.
69-
for maxind in Perm(perm_slice).strong_fixed_points():
70-
pass
71-
if maxind != -1:
72-
lis: List[int] = (
73-
_quick_sort(perm_slice[:maxind])
74-
+ [perm_slice[maxind]]
75-
+ _quick_sort(perm_slice[maxind + 1 :])
76-
)
77-
else:
78-
firstval = perm_slice[0]
79-
lis = (
80-
list(filter(lambda x: x < firstval, perm_slice))
81-
+ [perm_slice[0]]
82-
+ list(filter(lambda x: x > firstval, perm_slice))
83-
)
84-
return lis
85-
86-
87-
def quick_sortable(perm: Perm) -> bool:
88-
"""Returns true if perm is quicksort sortable."""
89-
return _is_sorted(_quick_sort(list(perm)))
90-
91-
92-
_BKV_PATT = Perm((1, 0))
93-
94-
95-
def bkv_sortable(perm: Perm, patterns: Tuple[Patt, ...] = ()) -> bool:
96-
"""Check if a permutation is BKV sortable.
97-
See:
98-
https://arxiv.org/pdf/1907.08142.pdf
99-
https://arxiv.org/pdf/2004.01812.pdf
100-
"""
101-
# See
102-
n = len(perm)
103-
inp = deque(perm)
104-
# the right stack read from top to bottom
105-
# the left stack read from top to bottom
106-
right_stack: Deque[int] = deque([])
107-
left_stack: Deque[int] = deque([])
108-
expected = 0
109-
while expected < n:
110-
if inp:
111-
right_stack.appendleft(inp[0])
112-
if Perm.to_standard(right_stack).avoids(*patterns):
113-
inp.popleft()
114-
continue
115-
right_stack.popleft()
116-
117-
if right_stack:
118-
left_stack.appendleft(right_stack[0])
119-
if Perm.to_standard(left_stack).avoids(_BKV_PATT):
120-
right_stack.popleft()
121-
continue
122-
left_stack.popleft()
123-
124-
assert left_stack
125-
# Normally, we would gather elements from left stack but since we only care
126-
# about wether it sorts the permutation, we just compare it against expected.
127-
if expected != left_stack.popleft():
128-
return False
129-
expected += 1
130-
return True
131-
132-
133-
def west_2_stack_sortable(perm: Perm) -> bool:
134-
"""Returns true if perm can be sorted by two passes through a stack"""
135-
return _is_sorted(_stack_sort(_stack_sort(list(perm))))
136-
137-
138-
def west_3_stack_sortable(perm: Perm) -> bool:
139-
"""Returns true if perm can be sorted by three passes through a stack"""
140-
return _is_sorted(_stack_sort(_stack_sort(_stack_sort(list(perm)))))
141-
142-
1438
_SMOOTH_PATT = (Perm((0, 2, 1, 3)), Perm((1, 0, 3, 2)))
1449

14510

permuta/misc/math.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def is_prime(n: int) -> bool:
2+
"""Primality test using 6k+-1 optimization."""
3+
if n <= 3:
4+
return n > 1
5+
if n % 2 == 0 or n % 3 == 0:
6+
return False
7+
i = 5
8+
while i ** 2 <= n:
9+
if n % i == 0 or n % (i + 2) == 0:
10+
return False
11+
i += 6
12+
return True

0 commit comments

Comments
 (0)