一个全面的高性能排列库。
项目描述
Permuta 是一个 Python 库,用于处理 perms(permutations 的缩写)、模式和网格模式。
如果此代码在您的工作中对您有用,请考虑引用它。要生成 BibTeX 条目(或其他格式),请单击上方的“DOI”标记并找到“引用为”部分。
如果您需要支持,可以加入我们的Discord 支持服务器。
安装
要在您的系统上安装 Permuta,请运行:
pip install permuta
也可以在开发模式下安装 Permuta 以处理源代码,在这种情况下,您可以在克隆存储库后运行以下命令:
./setup.py develop
要运行单元测试:
pip install -r test_requirements.txt
./setup.py test
使用 Permuta
安装 Permuta 后,它可以通过 Python 脚本或交互式 Python 会话导入,就像任何其他 Python 库一样:
>>> from permuta import *
从中导入*会为您提供“Perm”和“PermSet”类以及“AvoidanceClass”类(别名为“Av”),用于生成避免一组模式的烫发。它还为您提供了 'MeshPatt' 类和其他一些子模块,我们不会在本自述文件中讨论。
创建单个烫发
排列在 Permuta 中是从零开始的,并且可以使用任何可迭代对象创建。
>>> Perm() # Empty perm
Perm(())
>>> Perm([]) # Another empty perm
Perm(())
>>> Perm((0, 1, 2, 3)) # The zero-based version of 1234
Perm((0, 1, 2, 3))
>>> Perm((2, 1, 3)) # Warning: it will initialise with any iterable
Perm((2, 1, 3))
也可以使用一些特定的类方法来创建排列。
>>> Perm.from_string("201") # strings
Perm((2, 0, 1))
>>> Perm.one_based((1, 3, 2, 4)) # one-based iterable of integers
Perm((0, 2, 1, 3))
>>> Perm.to_standard("a2gsv3") # standardising any iterable using '<'
Perm((2, 0, 3, 4, 5, 1))
>>> Perm.from_integer(210) # an integer between 0 and 9876543210
Perm((2, 1, 0))
>>> Perm.from_integer(321) # any integer given is standardised
Perm((2, 1, 0))
>>> Perm.from_integer(201)
Perm((2, 0, 1))
打印 perms 给出从零开始的字符串。
>>> print(Perm(()))
ε
>>> print(Perm((2, 1, 0)))
210
>>> print(Perm((6, 2, 10, 9, 3, 8, 0, 1, 5, 11, 4, 7)))
(6)(2)(10)(9)(3)(8)(0)(1)(5)(11)(4)(7)
避免、包含和发生方法允许使用模式:
>>> p = Perm((0,2,1,3))
>>> p.contains(Perm((2, 1, 0)))
False
>>> p.avoids(Perm((0, 1)))
False
>>> list(p.occurrences_of(Perm((1, 0))))
[(1, 2)]
>>> list(Perm((0, 1)).occurrences_in(p))
[(0, 1), (0, 2), (0, 3), (1, 3), (2, 3)]
实现了基本对称性:
>>> [p.reverse(), p.complement(), p.inverse()]
[Perm((3, 1, 2, 0)), Perm((3, 1, 2, 0)), Perm((0, 2, 1, 3))]
要获取直接和和偏和,我们使用+和-:
>>> q = Perm((0, 1, 2, 3, 4))
>>> p + q
Perm((0, 2, 1, 3, 4, 5, 6, 7, 8))
>>> p - q
Perm((5, 7, 6, 8, 0, 1, 2, 3, 4))
有许多实用的方法可用:
>>> list(p.fixed_points())
[0, 3]
>>> list(p.ascents())
[0, 2]
>>> list(p.descents())
[1]
>>> list(p.inversions())
[(1, 2)]
>>> p.major_index()
2
创建烫发类
Perm 类是根据以下条件指定的:
>>> basis = Basis(Perm((1, 0, 2)), Perm((1, 2, 0)))
>>> basis
Basis((Perm((1, 0, 2)), Perm((1, 2, 0))))
>>> perm_class = Av(basis)
>>> perm_class
Av(Basis((Perm((1, 0, 2)), Perm((1, 2, 0)))))
你可以询问一个烫发是否属于烫发类:
>>> Perm((3, 2, 1, 0)) in perm_class
True
>>> Perm((0, 2, 1, 3)) in perm_class
False
您可以使其枚举达到固定长度。
>>> perm_class.enumeration(10)
[1, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
>>> perm_class.count(11)
1024
您还可以查看一些众所周知的枚举策略是否适用于给定的类。
>>> from permuta.enumeration_strategies import find_strategies
>>> basis = [Perm((3, 2, 0, 1)), Perm((1, 0, 2, 3))]
>>> for strat in find_strategies(basis):
... print(strat.reference())
The insertion encoding of permutations: Corollary 10
>>> basis = [Perm((1, 2, 0, 3)), Perm((2, 0, 1, 3)), Perm((0, 1, 2, 3))]
>>> for strat in find_strategies(basis):
... print(strat.reference())
Enumeration of Permutation Classes and Weighted Labelled Independent Sets: Corollary 4.3
排列统计
使用PermutationStatistic类,我们可以查找类的统计分布,并查找两个类或给定双射的统计保留(或转换)。首先我们需要导入它。
>>> from permuta.permutils.statistics import PermutationStatistic
要查看给定统计数据的分布,我们获取它的实例并提供长度和类(没有类将使用所有排列的集合)。
>>> PermutationStatistic.show_predefined_statistics() # Show all statistics with id
[0] Number of inversions
[1] Number of non-inversions
[2] Major index
[3] Number of descents
[4] Number of ascents
[5] Number of peaks
[6] Number of valleys
[7] Number of cycles
[8] Number of left-to-right minimas
[9] Number of left-to-right maximas
[10] Number of right-to-left minimas
[11] Number of right-to-left maximas
[12] Number of fixed points
[13] Order
[14] Longest increasing subsequence
[15] Longest decreasing subsequence
[16] Depth
[17] Number of bounces
[18] Maximum drop size
[19] Number of primes in the column sums
[20] Holeyness of a permutation
[21] Number of stack-sorts needed
[22] Number of pop-stack-sorts needed
[23] Number of pinnacles
[24] Number of cyclic peaks
[25] Number of cyclic valleys
[26] Number of double excedance
[27] Number of double drops
[28] Number of foremaxima
[29] Number of afterminima
[30] Number of aftermaxima
[31] Number of foreminima
>>> depth = PermutationStatistic.get_by_index(16)
>>> depth.distribution_for_length(5)
[1, 4, 12, 24, 35, 24, 20]
>>> depth.distribution_up_to(4, Av.from_string("123"))
[[1], [1], [1, 1], [0, 2, 3], [0, 0, 3, 7, 4]]
给定一个双射作为字典,我们可以检查哪些统计信息使用 check_all_preservations保留,哪些统计信息使用check_all_transformed进行转换
>>> bijection = {p: p.reverse() for p in Perm.up_to_length(5)}
>>> for stat in PermutationStatistic.check_all_preservations(bijection):
... print(stat)
Number of peaks
Number of valleys
Holeyness of a permutation
Number of pinnacles
我们可以使用equal_distributed找到所有(预定义的)统计均等分布在两个排列类上。我们还支持使用 joint_equally_distributed 检查多个统计数据的联合分布,以及使用joint_transformed_equally_distributed对联合分布的统计数据进行转换。
>>> cls1 = Av.from_string("2143,415263")
>>> cls2 = Av.from_string("3142")
>>> for stat in PermutationStatistic.equally_distributed(cls1, cls2, 6):
... print(stat)
Major index
Number of descents
Number of ascents
Number of peaks
Number of valleys
Number of left-to-right minimas
Number of right-to-left maximas
Longest increasing subsequence
Longest decreasing subsequence
Number of pinnacles
BiSC算法
BiSC 算法可以告诉您通过一组排列可以避免哪些网格图案。虽然算法的输出只保证描述有限输入的排列集,但用户通常希望算法找到的模式描述无限的排列集。要使用该算法,我们首先需要导入它。
>>> from permuta.bisc import *
模式避免描述的一组排列的一个典型例子是一次通过堆栈时可排序的排列。我们使用函数 stack_sortable ,它为满足此属性的排列返回True 。用户现在有两个选择:运行 auto_bisc(Perm.stack_sortable)并让算法在没有任何用户输入的情况下运行。它将尝试使用合理的值,首先从小排列中学习小模式,然后在失败时只考虑更长的模式。如果用户想要对发生的事情有更多的控制,这也是可能的,我们现在逐步完成:我们将属性输入到bisc并要求它搜索长度为 3 的模式。
>>> bisc(Perm.stack_sortable, 3)
I will use permutations up to length 7
{3: {Perm((1, 2, 0)): [set()]}}
当此命令在未指定要考虑的排列长度的情况下运行时,bisc将创建长度为 7 的排列,以满足堆栈可排序的属性。输出意味着:找到了一个长度为 3 的模式,其基础经典模式是排列 Perm((1, 2, 0))。现在忽略输出中的[set()]。我们可以使用 show_me来更好地可视化找到的模式。在对算法的调用中,我们还指定只应考虑长度为 5 的排列。
>>> SG = bisc(Perm.stack_sortable, 3, 5)
>>> show_me(SG)
There are 1 underlying classical patterns of length 3
There are 1 different shadings on 120
The number of sets to monitor at the start of the clean-up phase is 1
<BLANKLINE>
Now displaying the patterns
<BLANKLINE>
| | |
-+-●-+-
| | |
-●-+-+-
| | |
-+-+-●-
| | |
<BLANKLINE>
我们现在应该忽略在清理阶段开始时要监视的集合数为 1消息。
对于避免经典模式所描述的排列集,我们实际上并不需要这种算法。它的主要目的是描述具有网格模式的集合,例如 West-2-stack-sortable permutations
>>> SG = bisc(Perm.west_2_stack_sortable, 5, 7)
>>> show_me(SG)
There are 2 underlying classical patterns of length 4
There are 1 different shadings on 1230
There are 1 different shadings on 2130
The number of sets to monitor at the start of the clean-up phase is 1
There are 1 underlying classical patterns of length 5
There are 1 different shadings on 42130
<BLANKLINE>
Now displaying the patterns
<BLANKLINE>
| | | |
-+-+-●-+-
| | | |
-+-●-+-+-
| | | |
-●-+-+-+-
| | | |
-+-+-+-●-
| | | |
<BLANKLINE>
|▒| | |
-+-+-●-+-
| | | |
-●-+-+-+-
| | | |
-+-●-+-+-
| | | |
-+-+-+-●-
| | | |
<BLANKLINE>
|▒| | | |
-●-+-+-+-+-
| |▒| | |
-+-+-+-●-+-
| | | | |
-+-●-+-+-+-
| | | | |
-+-+-●-+-+-
| | | | |
-+-+-+-+-●-
| | | | |
<BLANKLINE>
这是好消息,也是坏消息。很好,因为我们很快就得到了我们正在查看的系列的描述,这需要很长时间才能手动找到。坏消息是输出中实际上存在一些冗余。为了更好地理解正在发生的事情,我们首先将研究中的排列放入字典中,字典中将它们按长度分开。
>>> A, B = create_bisc_input(7, Perm.west_2_stack_sortable)
这将创建两个具有键 1、2、...、7 的字典,使得A[i]指向长度为i且可 West-2-stack-sortable 的排列列表,而 B[i]指向补码。我们可以将 A 字典直接传递给 BiSC,因为只有满足该属性的排列才能用于查找模式。我们可以使用第二个字典来检查补码中的每个排列是否至少包含一个我们找到的模式。
>>> SG = bisc(A, 5, 7)
>>> patterns_suffice_for_bad(SG, 7, B)
Starting sanity check with bad perms
Now checking permutations of length 0
Now checking permutations of length 1
Now checking permutations of length 2
Now checking permutations of length 3
Now checking permutations of length 4
Now checking permutations of length 5
Now checking permutations of length 6
Now checking permutations of length 7
Sanity check passes for the bad perms
(True, [])
在这种情况下,B 中直到长度为 7 的每个排列确实包含至少一个找到的模式。如果不是这种情况,则将输出排列列表(而不仅仅是空列表)。
现在,我们声称我们发现的模式实际上存在冗余,长度为 4 的网格模式应该足以描述该集合。这可能会发生,并且从理论上证明一个网格图案隐含在另一个图案(或一组其他图案中,就像这里的情况一样)可能会很棘手。我们再次使用字典 B并运行
>>> bases, dict_numbs_to_patts = run_clean_up(SG, B)
<BLANKLINE>
The bases found have lengths
[2]
找到了1个网格图案基础,有2个图案
>>> show_me_basis(bases[0], dict_numbs_to_patts)
<BLANKLINE>
Displaying the patterns in the basis
<BLANKLINE>
| | | |
-+-+-●-+-
| | | |
-+-●-+-+-
| | | |
-●-+-+-+-
| | | |
-+-+-+-●-
| | | |
<BLANKLINE>
|▒| | |
-+-+-●-+-
| | | |
-●-+-+-+-
| | | |
-+-●-+-+-
| | | |
-+-+-+-●-
| | | |
<BLANKLINE>
这是我们期望的输出。排列的其他几个属性可以从permuta.bisc.perm_properties导入,例如smooth、forest-like、baxter、simsun、quick_sortable等。
bisc和auto_bisc都可以接受属性形式的输入,或排列列表(满足某些属性)。
执照
BSD-3:查看许可证文件。