GAP简单介绍
本文最后更新于:2026年6月30日 晚上
最近在整理一些群论计算相关的东西,所以顺便把 GAP 的一些基本用法记录下来。GAP 不是用来替代证明的软件,但是它很适合用来做实验,比如构造例子、筛选候选群、计算共轭类和正规子群、调用小阶群库,或者把一个数学定义写成可以反复运行的程序。
这篇文章不准备系统介绍 GAP 的所有功能,只是记录我自己比较常用的一些入口。如果已经学过一点群论,但还没有怎么用过 GAP,那么下面这些例子基本可以直接复制到本地运行。
GAP 的官方网站是:https://www.gap-system.org/。安装页面是:https://www.gap-system.org/install/。官方 Reference Manual 可以在线查看:https://docs.gap-system.org/doc/ref/chap0_mj.html,也可以下载 PDF 版本:https://docs.gap-system.org/doc/ref/manual.pdf。
1. GAP 是什么
GAP 是 Groups, Algorithms, Programming 的缩写。顾名思义,它最初就是围绕群、算法和编程设计的。现在 GAP 的功能已经扩展到更广的离散代数对象,例如半群、代数、有限域、矩阵群、特征标表等;不过从我自己的使用经验看,计算群论仍然是它最核心、最成熟的应用场景。
我对 GAP 的理解大致是:
\[ \text{数学定义} \longrightarrow \text{GAP 对象} \longrightarrow \text{可复现实验}. \]
它不是图形化软件,而是一个交互式解释型语言和算法库。我们可以在终端里直接输入命令,也可以把较长的计算写成
.g 脚本,然后用 Read
运行。对于研究中的辅助计算来说,我更倾向于后者,因为脚本可以保存、修改、复核,也方便在不同机器之间同步。
写这篇文章时,GAP 官网显示的最新版本是 4.16.0,发布日期为 2026-06-02。本机 GAP 输出的版本为:
1 | |
输出:
1 | |
2. GAP 的安装
GAP 的安装方式和操作系统有关。最直接的方式是从官方安装页面下载对应系统的版本,然后按照页面提示安装。官方安装页面会分别给出 Linux、macOS 和 Windows 的说明。
如果使用 Linux,一般可以先尝试系统自带的软件包管理器。例如在 Ubuntu 或 Debian 中,可以先查看仓库里是否有 GAP:
1 | |
如果仓库里的版本满足需求,可以直接安装:
1 | |
这种方式比较省事,但版本可能不是最新。如果需要最新版,或者需要完整编译某些 package,可以从官网下载安装包,然后按照官方说明安装。Ubuntu 或 Debian 下从源代码编译时,通常需要先安装一些编译工具和依赖:
1 | |
解压官方压缩包之后,在 GAP 目录下运行:
1 | |
如果还要编译 package,可以进入 pkg 目录并运行:
1 | |
macOS 用户可以参考官方安装页面,也可以使用 Homebrew
相关方式安装。Windows 用户如果熟悉 Linux 环境,官方更推荐通过 WSL 使用
GAP;如果只是普通使用,也可以下载 Windows 的 .exe
安装包。
安装完成之后,在终端输入:
1 | |
如果能进入 gap> 提示符,就说明 GAP
已经可以正常启动。也可以在 GAP 中输入:
1 | |
查看当前安装的版本。
3. 一次 GAP 会话
启动 GAP 通常只需要在终端输入:
1 | |
进入之后会看到 gap> 提示符。GAP 命令通常以分号
; 结束:
1 | |
输出:
1 | |
如果使用两个分号 ;;,GAP
会执行命令,但不打印返回值。这在给中间变量赋值时很常用:
1 | |
输出:
1 | |
退出 GAP 使用:
1 | |
如果代码稍微长一点,我一般会写到文件里。例如把代码保存为
example.g,然后在 GAP 里运行:
1 | |
这样做的好处很明显:交互式命令适合临时试探,脚本适合正式记录。
4. 查帮助和处理错误
GAP 的 manual 很厚,不太适合从头读到尾。更实际的方式是先掌握基本语法,遇到具体函数时再去查帮助。
1 | |
其中 ?name 用来查比较精确的条目,??keyword
更像关键词搜索。加载 package 之后,相关 package
的文档也可以进入帮助系统。
刚开始使用 GAP 时,还经常会遇到 brk>。例如输入:
1 | |
可能得到:
1 | |
这里的 brk> 不是 GAP 崩溃了,而是 GAP 进入了 break
loop,也就是停在错误现场供用户调试。对普通使用来说,最常见的处理方式是输入:
1 | |
这会从 brk> 回到正常的
gap>。注意,小写 quit; 是退出当前 break
loop;大写 QUIT; 是退出整个 GAP 会话。
5. 几个基本语法习惯
GAP 的语法不复杂,但有几个习惯需要先适应。
第一,赋值用 :=,相等判断用 =:
1 | |
输出:
1 | |
第二,GAP 的列表从 1 开始编号:
1 | |
输出:
1 | |
第三,List、Filtered 和 Set
是非常常用的列表操作:
1 | |
输出:
1 | |
含义分别是:
List(list, f):把函数f作用到列表的每个元素;Filtered(list, condition):保留满足条件的元素;Set(list):排序并去重。
函数的写法也比较直接。比如找出大于 n 的第一个素数:
1 | |
输出:
1 | |
在稍长一点的计算里,我通常会把数学条件先写成函数,然后再对一批群做筛选。这样比把所有判断都写在一个循环里清楚得多。
6. 置换和群
GAP 对置换的支持非常自然,可以直接使用循环记号:
1 | |
输出:
1 | |
这里 a*b 和 b*a
的输出不同,直接反映了置换群的非交换性。实际写脚本的时候,最好始终保持同一种乘法顺序习惯,不要凭直觉来回切换。
常见群可以直接构造:
1 | |
输出:
1 | |
这里比较常用的几个函数是:
Order(G):计算群阶;StructureDescription(G):给出一个便于阅读的结构描述;GeneratorsOfGroup(G):返回生成元。
需要注意的是,StructureDescription
很适合阅读,但不应该总被当成严格的规范形式。真正需要复现实验时,最好同时记录
IdGroup(G) 或其他更明确的不变量。
7. 共轭类、中心化子和正规子群
以 S5 为例,可以这样计算共轭类:
1 | |
输出:
1 | |
这里列出的是每个共轭类的大小和代表元阶数。很多定义检查都可以先降到共轭类代表元上,而不必从全部元素开始。
再看中心化子和正规子群:
1 | |
输出:
1 | |
这类输出通常可以作为进一步计算前的结构信息。比如在做较大搜索之前,先看正规子群、商群或者中心化子,往往能很快判断某条路线是否值得继续。
8. Small Groups 数据库
Small Groups 数据库是 GAP 中非常常用的工具。它可以用统一编号调用小阶群,也可以反过来识别某个群在数据库中的编号。对有限群计算来说,这个功能非常方便。
1 | |
输出:
1 | |
这里 SmallGroup(n,i) 表示小阶群库中第 i 个
n 阶群;IdGroup(G) 返回可复现的
[order,id];NrSmallGroups(n) 返回
n 阶群的个数。
例如,12 阶群一共有 5 个:
1 | |
输出:
1 | |
小阶群库很方便,但也要注意计算规模。演示的时候可以选 12、24、60、120 这类小阶数;如果要遍历大量群,尤其是接近数据库上界的阶数,最好写成脚本离线运行,并把中间结果保存下来。
9. 商群、直积和特征标表
直积可以直接使用 DirectProduct:
1 | |
输出:
1 | |
商群通常写成 G / N,其中 N 是
G 的正规子群:
1 | |
输出:
1 | |
GAP 也可以处理特征标表。例如 S5 的不可约普通特征标:
1 | |
输出:
1 | |
如果安装了 character table library,还可以访问大量已知有限群的特征标表。实际使用中,特征标表经常会和共轭类、正规子群、商群、群扩张等计算配合起来。
10. 一个例子:rational group
下面用 rational group 做一个稍微接近研究的例子。
有限群 (G) 称为 rational group,如果对任意 (xG),以及任意满足
\[ (k, |x|)=1 \]
的整数 (k),元素 (x) 与 (x^k) 在 (G) 中共轭。
按照定义直接检查所有元素当然可以,但会有很多重复。因为共轭性本身就是定义的一部分,所以我们可以先取共轭类代表元,然后只对代表元做检查:
1 | |
然后对几个例子运行:
1 | |
输出:
1 | |
这个例子的重点不是函数本身,而是一个常见思路:
- 先把数学定义拆成明确的可计算条件;
- 再利用群论结构减少重复检查,例如共轭类代表元;
- 对一批候选群批量运行;
- 同时输出阶、结构描述或者数据库编号,方便后续复核。
很多群论计算都可以按这个模式组织。先用小例子验证思路,之后再扩展到较大的搜索。
11. Package 和记录习惯
GAP 的很多功能由 package 提供。加载 package 可以使用:
1 | |
成功加载通常返回 true,未安装或者不可用时可能返回
fail。如果要分享代码,最好在脚本开头写清楚依赖哪些
package。否则同一段代码在不同机器上可能表现不同。
我自己写 GAP 脚本时,一般会注意下面几件事:
- 尽量同时记录
Order(G)、IdGroup(G)、StructureDescription(G); - 对共轭类、子群列表等结果做排序,减少无关顺序差异;
- 大搜索前先用便宜条件筛选,例如阶、可解性、正规子群、商群结构;
- 对较大的群,谨慎使用
Elements(G)这类可能很重的操作; - 耗时搜索分段保存结果,不要把所有结果都压在一次交互式会话里;
- 代码开头写清楚 package 依赖,输出里保留足够多的不变量。
还有几个细节也很容易踩坑:
- 赋值用
:=,比较用=; ;会打印结果,;;会抑制输出;- 看到
brk>时,用quit;回到gap>; StructureDescription方便阅读,但复现时最好再记录IdGroup;- 大规模搜索最好脚本化,不要全靠终端临时输入。
12. 总结
我觉得 GAP 的长处,是把群论里的许多对象和操作直接变成了可运行、可复核的计算实验。对学习者来说,它可以用来验证例子和检查直觉;对研究中的辅助计算来说,它可以帮助我们构造群、筛选候选对象,检查共轭类、正规子群、商群和特征标表。
如果刚开始学习 GAP,可以按下面的顺序练习:
- 熟悉基本语法:赋值、列表、函数、循环;
- 熟悉置换和置换群:
Group、SymmetricGroup、Order; - 熟悉常用群论函数:
ConjugacyClasses、Centralizer、NormalSubgroups; - 学会使用小阶群库:
SmallGroup、IdGroup、NrSmallGroups; - 把一个数学定义写成函数,再对一批例子运行;
- 遇到问题马上查帮助:
?函数名和??关键词。
掌握这些之后,GAP 就不只是一个计算器,而会变成一个很实用的群论实验环境。