置换群群元的开平方:以BRICS+的sqrt为例
很少见的置换群的题目,这次是个开平方,本来以为只有两个解,然后开出了2^20+个解。。。
前置知识·
置换群·
首先什么是置换(Permutation)应该好懂,比如我对这三个元素做置换
1 | import itertools |
就会有以上六种情况(其实就是排列组合中的排列,Permutation又可译作排列)
假设这三个集合组成的元素是,我们会称排列出来的以上六种情况组成一个对称群(Symmetric Group),然后的(其中一个)子群就被称作置换群(Permutation Group)
如果是像上面那样从开始,递增到的集合,则通常会把简写成,又称做阶对称群(虽然这个“阶”有点怪怪的,英文中说的是“We call this group the symmetric group on n letters.”)
置换群中的一个元素是一个置换,比如
表示一个置换,表示把换做,把换作,把换做,或者写作
群操作·
再来看群操作,置换群中的群操作是置换的复合,通常用符号表示
以上表示的意思是先做置换,再做置换,通常为了方便也会省略直接写成
群元也可以自己和自己复合,比如就是置换做两遍,也会写作
在SageMath代码中就是直接用*
表示群操作,用^
表示自己复合多少次了,如
1 | G = Permutations(3) |
以上G
就是的置换群,g
和h
是随机选的群中的两个元素,其中[3, 1, 2]
表示的是,只是为了方便把第一排省略了
在这个例子中可以看到g
的阶是,因为[1, 2, 3]
即是单位元,顺带提一句,置换群的群阶是其对称群的阶的一个因子,而的阶是
回圈表述·
最后来说说群元的另一种表述方法,上面把~所有置换情况列出来的表述方法叫列表法,通常只是为了看起来直观,而在代数中更常用的是使用回圈(Cycles)表示一个置换
假设在一个置换中存在以下情况:
那么在中就存在一个长度为的回圈,这个圈写作(PS:所以圆括号是表示回圈,不能乱用)
PS:有的文章也会从下标为的开始,不过我习惯开始,而且一会也更好说明
举个复杂点的栗子,比如
那么在中就存在三个回圈:、和,不熟悉的建议在纸上画一下,看看是不是会连成一个闭合的圈,比较特殊的是单个元素也认为可以自己成一个圈
所以也可以用回圈的方法表述为:,通常长度为的回圈可以省略不写,所以可以简写为
在SageMath中如果使用PermutationGroupElement
定义一个置换群元的话,打印出来会是回圈的表述,而不是Permutations
的列表表述,如
1 | PermutationGroupElement([2, 4, 1, 3, 6, 5, 7]) # (1,2,4,3)(5,6) |
置换群开方·
所谓开方,即知道一个置换群元和自己的复合,求这个群元
网上翻一下可以在StackExchange上翻到这个帖子,里面有说如何找一个平方根,但并没有把情况说全,可以参考着推一下
平方操作·
首先看一下“平方”操作会发生什么,如前文所说的,平方其实就是自己跟自己复合,也就,即对于每个数,做了两次的置换
举个栗子
简单算个平方
拿做栗子,本来中是、,现在是连着做两次,即,省略中间过程的,即,其他情况类似,可以看上表的最后一行
接下来看回圈的表述,做两次置换其实等同于中的每个回圈都分别做两次置换, 因为这些回圈只是把拆分成几个部分,即令,则
所以只用分析在平方过程中的回圈会发生什么就好了,如上面所说,回圈的平方也就是在这个回圈中转两下,或者说做两个置换,即令,则
到这里根据长度的奇偶性会出现两种情况:
- 如果是偶数,由于,所以会被拆分为两个圈,这两个圈的长度相同且都为
- 如果是奇数,由于,所以还是一个长度为的圈,只是里面元素的顺序会改变,变为
代进上面的栗子,是偶数圈,所以被拆分成两个圈,是奇数圈,所以没有拆分,但是顺序变成了
开方操作·
简单地说,开方就是上面平方操作的逆,但实际情况会复杂一点,首先不妨令
奇数圈·
先看比较简单的奇数圈,由于奇数圈在平方过程中没被拆分且长度不变,所以如果在中发现有奇数圈的话,那它就可能是中的某个同长度的奇数圈平方所得,即。如果还能发现,在的所有圈中仅有这个圈的长度是的话,那就石锤了,肯定是中的某个同长度的奇数圈平方所得
假设真的有,这时只需要更改一下的顺序即可恢复,不妨假设这俩长度都是,令
根据和是奇数,由上面内容可得
把两个表列出来对一下
换个好看点的表达,折叠一下:
把行的顺序排一下即得,这在数学上表达会有点麻烦,但在代码中就是上面取一个下面取一个这样就好了,比如
1 | def sqrtOdd(oddCircles): |
偶数圈·
再来看偶数圈的情况,因为偶数圈平方会产生分裂,所以情况会变得非常复杂
首先如果在的所有回圈中找到两个回圈,比如和,拥有相同的长度,那么其可能由中的一个长度为的回圈平方产生,即
如果这个长度是偶数,那么就石锤了,因为奇数圈平方只会产生奇数圈。如果是奇数,那么可能会产生误会,即和其实是由中两个长度为的奇数圈和平方产生
假设真的有,令
那么根据上面平方的分析就会有
然后接下来似乎是直接
就可以了,但,在回圈的表述上有一个坑,举个栗子,比如现在有一个回圈是,那么其实
以上三个其实是同一个回圈的不同表述,可以用代码check一下,PermutationGroupElement
会默认把最小的元素放在第一个位置
1 | PermutationGroupElement('(2, 3, 1)') # (1,2,3) |
这在单个回圈使用的时候其实是没有问题的,但是在两个回圈组合的时候就会有问题,还是先从栗子入手,比如现在
如果直接套上面结果的话,会有
然后得出
但其实还能这样
然后得出 ,明显这是一个不同的解
类似地还可以得出和两个不同的解
那如何解呢,还是以这个栗子,先画个图,可以把问题转化为下面的问题,现在有和两个轮盘
把他们重叠在一起,然后顺时针读数就可以得到
现在两个轮盘都是可以转动的,在所有转动情况中,总共有多少种读数呢,答案是,只需要固定其中一个轮盘,然后转动另一个轮盘就好了,比如我转动红色的
最后一共有四种情况,就是上面的四个解
再回到
按照上面轮盘分析,一共会有个解,引入一个变量,假设是那个定死的轮盘,是那个转动的轮盘,即有
然后重排的顺序,即可得,用上面的写法会比较难排,不妨换个思路,我不转而是转,即
列表
即可排出
同样也是代码会比数学上好搞,参考代码(变量名会有点不一样,我懒得改了-):
1 | def sqrtEven(evenCircles): |
BRICS+的sqrt·
题目:sqrt.zip
题目不长,就是给定的置换群的群元P
的平方,求P
,根据上面分析列出所有情况遍历flag
即可
首先获得P
的所有回圈,使用PermutationGroupElement(P2)
打印即可,但有个坑是它会省略长度为的回圈,需要自己补回去
然后结果是:有个长度的回圈、个长度的回圈、个长度的回圈和个长度的回圈
- 长度的明显是某个长度的回圈平方所得
- 那两个长度的也明显是某个长度的回圈平方所得
- 那个长度为的就有点麻烦,因为可能三个都是奇数圈平方,也有可能只有一个是奇数圈平方,另外两个是偶数圈平方
- 那个长度的就更麻烦了
在代码上我选择先把那个解决掉,通过暴力枚举出所有阶为(或阶为)的回圈的组合o2Circles
然后再对那个(circles3
)排列组合
然后再处理剩下简单的两种情况
参考代码:
1 | # sage |
PS:这只是针对输入的代码,通解的代码好像有点麻烦,就先留坑了
PPS:set()
会有个坑,就是每次输出的顺序都是不一样的,导致复现的时候时间不准,后面加了sorted
测出顺序爆破24:42
,逆序19:43
,完整爆破40min+,可以考虑多线程了(阴间题
参考·
- Judson T W. Abstract algebra: theory and applications[M]. 2020.
- https://math.stackexchange.com/questions/266569/how-to-find-the-square-root-of-a-permutation