Skip to main content

A comprehensive high performance permutation library.

Project description

Travis Coveralls PyPI https://img.shields.io/pypi/l/Permuta.svg https://img.shields.io/pypi/pyversions/Permuta.svg

Permuta is a Python library for working with perms (short for permutations), patts (patterns), and mesh patts.

Installing

To install Permuta on your system, simply run the following command as a superuser: .. code-block:: bash

# pip install permuta

It is also possible to install Permuta in development mode to work on the source code, in which case you run the following after cloning the repository:

# ./setup.py develop

To run the unit tests using pytest run: .. code-block:: bash

# ./setup.py test

This requires pytest, pytest-cov, pytest-pep8 and pytest-isort.

Demo

Once you’ve installed Permuta, it can be imported by a Python script or an interactive Python session, just like any other Python library:

>>> from permuta.demo import *

For this section we focus on a subset of modified features exposed in the demo submodule. Importing * from it supplies you with the Perm and PermClass classes (and their respective aliases Permutation and Av).

Creating a single perm

There are several ways of creating a perm:

>>> Perm()  # Empty perm
()
>>> Perm([])  # Another empty perm
()
>>> Perm(132)  # From number
(1, 3, 2)
>>> Perm(248)  # Attempted interpretation
(1, 2, 3)
>>> Perm("1234")  # From string
(1, 2, 3, 4)
>>> Perm("dcab")  # This is equivalent to ...
(4, 3, 1, 2)
>>> Perm(["d", "c", "a", "b"])  # ... this
(4, 3, 1, 2)
>>> Perm(0, 0, 2, 1)  # Index is tie-breaker
(1, 2, 4, 3)
>>> Perm("Ragnar", "Christian", "Henning")
(3, 1, 2)
>>> Perm.monotone_increasing(4)
(1, 2, 3, 4)
>>> Perm.monotone_decreasing(3)
(3, 2, 1)

You can visualize a perm using matplotlib/seaborn:

>>> import matplotlib.pyplot as plt
>>> p = Perm((1, 3, 2, 4))
>>> ax = p.plot()
>>> plt.show()
README.d/1324.png

Plot of the perm 1324

The avoids, contains, and occurrence* methods enable working with patts:

>>> p.contains(321)
False
>>> p.avoids(12)
False
>>> p.occurrences_of(21)
[[3, 2]]
>>> Perm(12).occurrences_in(p)
[[1, 3], [1, 2], [1, 4], [3, 4], [2, 4]]

The basic symmetries are implemented:

>>> [p.reverse(), p.complement(), p.inverse()]
[(4, 2, 3, 1), (4, 2, 3, 1), (1, 3, 2, 4)]

To take direct sums and skew sums we use + and -:

>>> q = Perm((1, 2, 3, 4, 5))
>>> p + q
(1, 3, 2, 4, 5, 6, 7, 8, 9)
>>> p - q
(6, 8, 7, 9, 1, 2, 3, 4, 5)

There are numerous practical methods available:

>>> p.fixed_points()
[1, 4]
>>> p.ascents()
[1, 3]
>>> p.descents()
[2]
>>> p.inversions()
[[3, 2]]
>>> p.cycles()
[[1], [3, 2], [4]]
>>> p.major_index()
2

Creating a perm class

You might want the set of all perms:

>>> all_perms = PermClass()
>>> all_perms
<All perms>

Perm classes can be specified with a basis:

>>> basis = [213, Perm((2, 3, 1))]
>>> basis
[213, (2, 3, 1)]
>>> perm_class = Av(basis)
>>> perm_class
<Perms avoiding: (2, 1, 3) and (2, 3, 1)>

Recall that Av is just an alias of PermClass.

You can ask whether a perm belongs to the perm class:

>>> 4321 in perm_class
True
>>> 1324 in perm_class
False

You can get the n-th perm of the class or iterate:

>> [perm_class[n] for n in range(10)]
[(), (1), (1, 2), (2, 1), (1, 2, 3), (1, 3, 2), (3, 2, 1), (3, 1, 2), (4, 3, 2, 1), (4, 1, 3, 2)]
>>> perm_class_iter = iter(perm_class)
>>> [next(perm_class_iter) for _ in range(10)]
[(), (1), (1, 2), (2, 1), (1, 2, 3), (1, 3, 2), (3, 2, 1), (3, 1, 2), (4, 3, 2, 1), (4, 1, 3, 2)]

(BEWARE: Lexicographic order is not guaranteed at the moment!)

The subset of a perm class where the perms are a specific length

You can define a subset of perms of a specific length in the perm class:

>>> perm_class_14 = perm_class.of_length(14)
>>> perm_class_14
<Perms of length 14 avoiding: (2, 1, 3) and (2, 3, 1)>

You can ask for the size of the subset because it is guaranteed to be finite:

>>> len(perm_class_14)
8192

The iterating and containment functionality is the same as with perm_class, but indexing has yet to be implemented:

>>> 321 in perm_class_14
False
>>> (1, 14, 2, 13, 3, 4, 5, 12, 6, 11, 7, 8, 9, 10) in perm_class_14
True
>>> Perm(range(10)) - Perm(range(4)) in perm_class_14
False
>>> next(iter(perm_class_14))
(14, 1, 2, 3, 4, 5, 13, 12, 11, 10, 6, 9, 7, 8)
To get a feeling for the perm class, you can plot a heatmap of this subset

using matplotlib/seaborn:

>>> ax = perm_class_14.plot()
>>> plt.show()
README.d/av_213_231_of_length_14_heatmap.png

A heatmap plot for the perms of length 14 avoiding 213 and 231

Life in Permuta beyond the demo

If your work has reached a place where your require functionality beyond that offered by the demo, it may be time to proceed to the non-demo version of Permuta. The first hurdle will be coming to terms with the zero based indexing. Here’s how to get started:

>>> from permuta import Perm, PermSet, MeshPatt

License

BSD-3: see the LICENSE file.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

permuta-0.1.1.tar.gz (63.9 kB view hashes)

Uploaded Source

Built Distribution

permuta-0.1.1-py3-none-any.whl (159.3 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page