Skip to content

Commit

Permalink
Merge pull request #186 from PermutaTriangle/develop
Browse files Browse the repository at this point in the history
Version 2.2.0
  • Loading branch information
christianbean authored Oct 21, 2021
2 parents 6411ca8 + a120b25 commit 1fb948a
Show file tree
Hide file tree
Showing 24 changed files with 8,016 additions and 55 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ jobs:
- python: 3.9
toxenv: py39
os: ubuntu-latest
- python: "3.10"
toxenv: py310
os: ubuntu-latest
- python: pypy-3.7
toxenv: pypy37
os: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dfa_db/*
.mypy_cache
# Mac stuff
*.DS_Store
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
repos:
- repo: https://github.com/psf/black
rev: 21.6b0
rev: 21.9b0
hooks:
- id: black
7 changes: 4 additions & 3 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
[MASTER]
ignore-patterns=test_.*?py,
# TODO: REMOVE
bisc.py,
bisc.py,
bisc_subfunctions.py
ignore= tests
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc())+'/permuta')"
disable=bad-continuation,
disable=bad-continuation,
missing-module-docstring,
fixme,
unsubscriptable-object
unsubscriptable-object,
unspecified-encoding
good-names=i,j,n,k,x,y,_

[SIMILARITIES]
Expand Down
31 changes: 16 additions & 15 deletions .zenodo.json
Original file line number Diff line number Diff line change
@@ -1,50 +1,51 @@
{
"upload_type": "software",
"title": "Permuta: A Python Library for Permutations and Patterns",
"creators": [
{
"name": "Ragnar Pall Ardal"
},
{
"name": "Tomas Ken Magnusson"
"name": "Arnar Bjarni Arnarson"
},
{
"affiliation": "Reykjavik University",
"name": "Émile Nadeau"
},
{
"name": "Bjarni Jens Kristinsson"
"name": "Christian Bean"
},
{
"name": "Bjarki Agust Gudmundsson"
"name": "Alfur Birkir Bjarnason"
},
{
"affiliation": "Reykjavik University",
"name": "Christian Bean"
"name": "Jon Steinn Eliasson"
},
{
"affiliation": "Reykjavik University",
"name": "Henning Ulfarsson"
"name": "Bjarki Agust Gudmundsson"
},
{
"affiliation": "Reykjavik University",
"name": "Jon Steinn Eliasson"
"name": "Sigurjón Ingi Jónsson"
}
{
"name": "Bjarni Jens Kristinsson"
},
{
"name": "Murray Tannock"
"name": "Tomas Ken Magnusson"
},
{
"name": "Alfur Birkir Bjarnason"
"affiliation": "Reykjavik University",
"name": "Émile Nadeau"
},
{
"affiliation": "Marquette University",
"name": "Jay Pantone"
},
{
"name": "Arnar Bjarni Arnarson"
"name": "Murray Tannock"
},
{
"affiliation": "Reykjavik University",
"name": "Sigurjón Ingi Jónsson"
}
"name": "Henning Ulfarsson"
},
]
}
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## Unreleased

## 2.2.0 - 2021-10-21
### Added
- Bijection class for known bijection.
- An implementation of the Simion and Schmidt bijection.
- Enumeration strategy to check whether a class has finitely many simple permutations

### Changed
- Perm.to_standard now uses an lru cache

## 2.1.0 - 2021-06-14
### Added
- Statistic: bounce of a permutation.
Expand Down
12 changes: 8 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ permuta
Permuta is a Python library for working with perms (short for permutations),
patterns, and mesh patterns.

If this code is useful to you in your work, please consider citing it. To generate a
BibTeX entry (or another format), click the "DOI" badge above and locate the "Cite As"
section.

If you need support, you can join us in our `Discord support server`_.

.. _Discord support server: https://discord.gg/ngPZVT5
Expand Down Expand Up @@ -259,7 +263,7 @@ and a class (no class will use the set of all permutations).
>>> depth.distribution_up_to(4, Av.from_string("123"))
[[1], [1], [1, 1], [0, 2, 3], [0, 0, 3, 7, 4]]
Given a bijection as a dictionary, we can check which statistics are preserved with
Given a bijection as a dictionary, we can check which statistics are preserved with
``check_all_preservations`` and which are transformed with ``check_all_transformed``

.. code-block:: python
Expand Down Expand Up @@ -499,9 +503,9 @@ BSD-3: see the `LICENSE <https://github.com/PermutaTriangle/Permuta/blob/master/
Citing
######

If you found this library helpful with your research and would like to cite us,
you can use the following `BibTeX`_ or go to `Zenodo`_ for alternative formats.
If you found this library helpful with your research and would like to cite us,
you can use the following `BibTeX`_ or go to `Zenodo`_ for alternative formats.

.. _BibTex: https://zenodo.org/record/4725759/export/hx#.YImTibX7SUk

.. _Zenodo: https://doi.org/10.5281/zenodo.4725759
.. _Zenodo: https://doi.org/10.5281/zenodo.4725759
5 changes: 4 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@
warn_return_any = True
warn_unused_configs = True
warn_no_return = False
files = permuta/**/*.py
files = permuta/**/*.py

[mypy-automata.*]
ignore_missing_imports = True
2 changes: 1 addition & 1 deletion permuta/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .patterns import BivincularPatt, CovincularPatt, MeshPatt, Perm, VincularPatt
from .perm_sets.permset import Av, Basis, MeshBasis

__version__ = "2.1.0"
__version__ = "2.2.0"

__all__ = [
"Perm",
Expand Down
5 changes: 4 additions & 1 deletion permuta/enumeration_strategies/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@

from .abstract_strategy import EnumerationStrategy
from .core_strategies import core_strategies
from .finitely_many_simples import FinitelyManySimplesStrategy
from .insertion_encodable import InsertionEncodingStrategy

fast_enumeration_strategies: List[Type[EnumerationStrategy]] = [
InsertionEncodingStrategy
]
fast_enumeration_strategies.extend(core_strategies)

long_enumeration_strategies: List[Type[EnumerationStrategy]] = []
long_enumeration_strategies: List[Type[EnumerationStrategy]] = [
FinitelyManySimplesStrategy
]

all_enumeration_strategies: List[Type[EnumerationStrategy]] = (
fast_enumeration_strategies + long_enumeration_strategies
Expand Down
5 changes: 3 additions & 2 deletions permuta/enumeration_strategies/core_strategies.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from abc import abstractmethod, abstractproperty
from abc import abstractmethod
from typing import ClassVar, FrozenSet, List, Type

from permuta import Av, MeshPatt, Perm
Expand All @@ -13,7 +13,8 @@ class CoreStrategy(EnumerationStrategyWithSymmetry):
# https://arxiv.org/pdf/1912.07503.pdf
# See this paper for corr_number

@abstractproperty
@property
@abstractmethod
def patterns_needed(self) -> FrozenSet[Perm]:
"""Return the set of patterns that are needed for the strategy to be useful."""

Expand Down
14 changes: 14 additions & 0 deletions permuta/enumeration_strategies/finitely_many_simples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from permuta.enumeration_strategies.abstract_strategy import EnumerationStrategy
from permuta.permutils.pin_words import PinWords


class FinitelyManySimplesStrategy(EnumerationStrategy):
"""Enumeration strategies related to the class having finitely many simple
permutations."""

def applies(self) -> bool:
return PinWords.has_finite_simples(self.basis)

@classmethod
def reference(cls) -> str:
return "The class contains only finitely many simple permutations"
27 changes: 11 additions & 16 deletions permuta/patterns/perm.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import bisect
import collections
import functools
import itertools
import math
import numbers
Expand All @@ -12,7 +13,6 @@
from typing import (
TYPE_CHECKING,
Callable,
ClassVar,
Deque,
Dict,
Iterable,
Expand Down Expand Up @@ -43,8 +43,6 @@
class Perm(TupleType, Patt):
"""A perm class."""

_TO_STANDARD_CACHE: ClassVar[Dict[Tuple, "Perm"]] = {}

def __new__(cls, iterable: Iterable[int] = ()) -> "Perm":
"""Return a Perm instance.
Expand All @@ -60,11 +58,6 @@ def __init__(self, _iterable: Iterable[int] = ()) -> None:
# Cache for data used when finding occurrences of self in a perm
self._cached_pattern_details: Optional[List[Tuple[int, int, int, int]]] = None

@classmethod
def clear_cache(cls):
"""Clears to_standardize cache."""
cls._TO_STANDARD_CACHE = {}

@classmethod
def to_standard(cls, iterable: Iterable) -> "Perm":
"""Return the perm corresponding to iterable. Duplicate elements
Expand All @@ -76,13 +69,15 @@ def to_standard(cls, iterable: Iterable) -> "Perm":
>>> Perm.to_standard("caaba")
Perm((4, 0, 1, 3, 2))
"""
iterable = tuple(iterable)
if iterable not in cls._TO_STANDARD_CACHE:
cls._TO_STANDARD_CACHE[iterable] = cls(
idx
for (idx, _) in sorted(enumerate(iterable), key=operator.itemgetter(1))
).inverse()
return cls._TO_STANDARD_CACHE[iterable]
return cls._to_standard(tuple(iterable))

@classmethod
@functools.lru_cache(maxsize=10000)
def _to_standard(cls, iterable: Tuple) -> "Perm":
"""A cached function that standardise a tuple."""
return cls(
idx for (idx, _) in sorted(enumerate(iterable), key=operator.itemgetter(1))
).inverse()

standardize = to_standard
from_iterable = to_standard
Expand Down Expand Up @@ -2134,7 +2129,7 @@ def rank(self) -> int:
fact = [1]
for i in range(n):
fact.append(fact[i] * (i + 1))
vals: List[int] = list()
vals: List[int] = []
for idx, val in enumerate(self):
ordered_pos = bisect.bisect_left(vals, val)
res += (val - ordered_pos) * fact[n - idx - 1] + fact[n - idx - 1]
Expand Down
2 changes: 1 addition & 1 deletion permuta/perm_sets/permset.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def _ensure_level_classical_pattern_basis(self, level_number: int) -> None:
max_size = max(lengths)
for nplusone in range(len(self.cache), level_number + 1):
n = nplusone - 1
new_level: Dict[Perm, Optional[List[int]]] = dict()
new_level: Dict[Perm, Optional[List[int]]] = {}
last_level = self.cache[-1]
check_length = nplusone in lengths
smaller_elems = {b for b in self.basis if len(b) == nplusone}
Expand Down
47 changes: 47 additions & 0 deletions permuta/permutils/bijections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import itertools

from permuta import Perm


class Bijections:
"""A collection of known bijections."""

# pylint: disable=too-few-public-methods

@staticmethod
def simion_and_schmidt(perm: Perm, inverse: bool = False) -> Perm:
"""The bijection from `Restricted permutations` by R. Simion and F. Schmidt
between Av(123) and Av(132).
"""
n = len(perm)
if n == 0:
return Perm()
if inverse:
if perm.contains(Perm((0, 2, 1))):
raise ValueError("Map only works for 132 avoiding permutations")
return Bijections._simion_and_schmidt_inv(perm, n)
if perm.contains(Perm((0, 1, 2))):
raise ValueError("Map only works for 123 avoiding permutations")
return Bijections._simion_and_schmidt(perm, n)

@staticmethod
def _simion_and_schmidt(perm: Perm, n: int) -> Perm:
used, img, min_val = {perm[0]}, [perm[0]] * n, perm[0]
for idx, val in itertools.islice(enumerate(perm), 1, None):
if min_val > val: # val is L2R minima
img[idx], min_val = val, val
else:
img[idx] = next(k for k in range(min_val + 1, n) if k not in used)
used.add(img[idx])
return Perm(img)

@staticmethod
def _simion_and_schmidt_inv(perm: Perm, n: int) -> Perm:
used, img, min_val = {perm[0]}, [perm[0]] * n, perm[0]
for idx, val in itertools.islice(enumerate(perm), 1, None):
if min_val > val: # val is L2R minima
img[idx], min_val = val, val
else:
img[idx] = next(k for k in range(n - 1, -1, -1) if k not in used)
used.add(img[idx])
return Perm(img)
2 changes: 1 addition & 1 deletion permuta/permutils/insertion_encodable.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class InsertionEncodablePerms:
"""

_ALL_PROPERTIES: ClassVar[int] = 15
_CACHE: ClassVar[Dict[Tuple, int]] = dict()
_CACHE: ClassVar[Dict[Tuple, int]] = {}

@staticmethod
def _is_incr_next_incr(perm: Perm) -> bool:
Expand Down
Loading

0 comments on commit 1fb948a

Please sign in to comment.