of {$slidecount} ½ {$title}, {$author}



G A P

Groups, Algorithms, Programming

www.gap-system.org

键盘操作

Full screen
F11 key
Next Slide
Page down key, Return key
Previous Slide
Page up key
Next Item
Single mouse click, Right Arrow key, Space bar
Previous Item
Left Arrow key
First Slide
Home key
Last Slide
End key
Font size
Use +/- key to increase/decrease font size
Miscellaneous
C-key: navigates to Table of Content
M-key: Mouse navigation on/off
P-key: Print mode / Show all Slides
S-key: Statusbar off/on

首页




GAP
Groups, Algorithms, Programming
a System for Computational Discrete Algebra


Haifeng Xu

(hfxu@yzu.edu.cn)

GAP website: www.gap-system.org

Original Document: http://www-circa.mcs.st-and.ac.uk/gapintro0.php
http://www.math.colostate.edu/~hulpke

目录

GAP 简述

GAP 简述

GAP 是用于计算离散代数的一套系统, 特别地专注于计算群论.

GAP 主要用于研究群及其表示、环、向量空间、代数、组合结构等等, 是教师教学与科研的很好的工具, 比如用于抽象代数的教学.

当前版本是 GAP 4.4.12, GAP 3 也可以使用.

GAP 的历史

GAP 的历史

1986年

GAP始于1986年德国亚琛工业大学(RWTH, Rheinisch-Westfälische Technische Hochschule Aachen)数学系四位学生为完成硕士毕业而成立的一个联合“文凭”项目.
这四位学生是Johannes Meier, Alice Niemeyer, Werner Nickel and Martin Schönert.
当这四位学生毕业时, 其他更多的学生包括博士生也加入到这个项目中来, 扩充一些库, 以完成硕士或博士论文.从某种程度上说, 这模仿了一所德国大学建立的过程.(To some extent this mimics on the setup of a German university.)

1997年

GAP 的开发由英国的圣安德鲁斯大学(St Andrews University--苏格兰第一大学)协调.

2005年3月

GAP 的研发中心亚琛(Aachen,德国),不伦瑞克(Braunschweig,德国),柯林斯堡(Fort Collins, 美国, Colorado State University)和圣安德鲁斯(St Andrews, 苏格兰)对于进一步开发和维护取得一致.

2008年7月

GAP 因为在计算代数方面软件工程上的杰出贡献而获得 ACM/SIGSAM Richard Dimick Jenks Memorial Prize.
Jenks 奖的目的是肯定那些优秀软件工程在计算机代数领域所作出的贡献, 并鼓励在未来作出更出色的研究与开发.

目前

国际合作开发, 很多 GAP 用户作出了重要贡献. 开发者目前主要集中在西半球.

GAP 的版权

GAP 的版权

GAP 是自由软件, 其源代码是公开的.

GAP 按 GPL 协议发布, 这意味着允许对该软件进行修改并重新发布.

但若是限制进一步的发布则是不允许的.

若发布新的版本中, 则源代码中应包含README文件, 详细写清楚该版本进行了哪些修改.

第三方贡献的加入机制是开放的.

下载及安装

下载及安装

GAP 几乎可以安装在所有平台上, 包括 UNIX/Linux, Windows 或 Macintosh.

对于 Mac OS X 的用户, 推荐安装 UNIX 版本的 GAP.
也可以试一下科罗拉多州立大学 Alexander Hulpke 的
Mac installer.

这些版本的文件都是相同的, 只是安装过程不太一样.

需要500MB左右的存储空间, 内存至少128MB.

需要下载哪些东西

下载 http://www.gap-system.org/Download/

Linux 下的安装

Linux 下的安装

Ubuntu

sudo apt-get install gap

Install from the source

将下载的 gap4r4p12.tar.gz (或.bz2) 解压缩到将要安装 gap 的目录, 比如 /usr/local/lib,
在该目录下执行命令

./configure
make

Windows 下的安装

Windows 下的安装

将gap4r4p12-win.zip (或.zoo)解压缩至 C:\ (也可以是其他目录)

这将建立一个文件夹 gap4r4, 双击 C:\gap4r4\bin\gap.bat 即可启动 gap

如果安装到其他目录, 则需修改 gap.bat 文件.

有一个 gap4r4p12.exe 文件, 直接安装即可.

Package 的安装

Package 的安装

不是所有 Package 都能在 Windows 或 Mac 下安装的. 比如 ACE(ACE coset enumerator)

各个宏包的安装方式可能不同, 有的解压缩到 pkg 目录就可以了, 有的可能需要如类Unix环境的安装方式

.configure ../..
make

宏包之间存在某些依赖关系, 或为了发挥该宏包的全部功能, 需要安装额外的系统.

因此, 请根据每个 Package 的 README 或相关手册进行安装.

宏包依赖关系举例

宏包依赖关系举例

下一页是 GAP 宏包的依赖关系图

GAP 宏包依赖关系图

数学功能

GAP 的数学功能

相对于 MAPLE 来说更小的C-内核

基本的数据类型

函数库(大多用GAP语言写的)提供的功能很全面.

数据库(Data library)--占用了最大的磁盘空间.

宏包(Packages)--它们中的大多数都是 GAP 开发组以外的用户所提供的.

与 Maple 及 C 的区别

与 Maple 及 C 的区别

没有分析/计算的功能(加入这方面的功能需要大量的工作, 未来或许加入)

浮点运算非常基本

不支持一般的项(terms)或表达式(expressions)

所有的表达式都必须被赋值, 并且通常是"normal form"

不太重视图形用户界面(GUI)

GAP 的优点

GAP 的优点

GAP 系统很好地适应了学术环境.

贡献者的数学知识渊博.

学生可以在具有研究水平的项目中作出贡献, 并且其成果被采纳.

无需了解复杂的 C 语言或内存管理便可写出可用的代码.

GAP 的作者仍在维护该系统.

不需付钱便可开发一个专业的系统.

GAP 的问题

GAP 的问题

有一些功能要实现或很好地实现, 相对来说比较困难、乏味. 这些功能当然是可取的, 需要的. 但是它们的实现在数学上还不能算作 "research".

有限域上的矩阵运算, I/O 进程, 任意精度的浮点数. 更一般地: 发布“标准算法”.

通常很难找到对此感兴趣的开发者来实现这些功能, 并且能坚持三年内进行系统维护的.

资助机构并不急于支持基础性的工作.

系统对普通用户来说可能太复杂了.

其他问题

其他问题

某些问题通过 Email 是很难解决的.

学术界一般没有“程序设计”背景.

GAP 的协作开发

GAP 的协作开发

通讯主要靠 email, 因为圈子比较小, 所以有时也能经常碰到.

版本控制使用 CVS, 当然也可以使用其他.

一开始稍微明确一下各个开发者的负责范畴.

没有特别指定开发环境, 主要是在标准的Unix下工作.

任务的复杂




能成为一个可用的系统, 背后是大量的工作. 不要低估它.

作出您的贡献, 如果您愿意的话

写宏包

宏包(Package)为 GAP 提供了许多新功能.

当然也可以对 GAP 的内核(core) 作改进, 但通常来说, 编写宏包所需的协调性更少.

写文档

所有问题中至少60%可以在已有的文档中找到.

但是如果这些文档写得比较差或者找不到, 不妨自己写一个?

哪些人在用 GAP

哪些人在用 GAP

开发者.

(计算)群论的研究者.

需要用到群论的其他学科的研究者
(数学、物理、化学、计算机科学).

业余爱好者.

学生(有一些教科书涉及 GAP 的练习).

总体来说, GAP 的用户大多不是计算机专家.

GAP 的设计哲学

GAP 的设计哲学

GAP 的设计和新算法的补充是数学研究者研究工作的一部分.

不可能让一个系统做所有事情.
特别的任务/作业, 有特定的/优化的程序来完成.

阅读哪些文档

文档阅读

Tutorial

Programming

Manual

Extending

New features for developers

编辑器选择 vim gap.vim

VIM

对于 Linux 下的 vim, 将下面的代码拷贝到 .vimrc 文件中

if has("syntax")
  syntax on             " Default to no syntax highlightning 
endif

" For GAP files
augroup gap
  " Remove all gap autocommands
  au!
  autocmd BufRead,BufNewFile *.g,*.gi,*.gd source ~/.vim/gap.vim
  autocmd BufRead,BufNewFile *.g,*.gi,*.gd set filetype=gap comments=s:##\ \ ,m:##\ \ ,e:##\ \ b:#

" I'm using the external program `par' for formating comment lines starting
" with `##  '. Include these lines only when you have par installed.
  autocmd BufRead,BufNewFile *.g,*.gi,*.gd set formatprg="par w76p4s0j"
  autocmd BufWritePost,FileWritePost *.g,*.gi,*.gd set formatprg="par w76p0s0j"
augroup END

/usr/share/doc/gap-core/etc

Vim 编辑 gap 文件的例子



运行界面



Gap folder



GAP 安装在哪

GAP core 的安装位置

/usr/bin/gap
/usr/bin/gap.real
/usr/bin/update-gap-workspace
/usr/lib/gap/sysinfo.gap
/usr/share/doc/gap-core/changelog-3.4.Debian.gz
/usr/share/doc/gap-core/changelog-4.2.Debian.gz
/usr/share/doc/gap-core/changelog.Debian.gz
/usr/share/doc/gap-core/copyright
/usr/share/doc/gap-core/description4r4p10.gz
/usr/share/doc/gap-core/description4r4p11.gz
/usr/share/doc/gap-core/description4r4p12
/usr/share/doc/gap-core/description4r4p5.gz
/usr/share/doc/gap-core/description4r4p6.gz
/usr/share/doc/gap-core/description4r4p7.gz
/usr/share/doc/gap-core/description4r4p8.gz
/usr/share/doc/gap-core/description4r4p9
/usr/share/doc/gap-core/etc/README.vim-utils
/usr/share/doc/gap-core/etc/gap.vim.gz
/usr/share/doc/gap-core/etc/gap_indent.vim
/usr/share/gap/sysinfo.gap
/usr/share/man/man1/gap.1.gz
/usr/share/man/man1/gap.real.1.gz
/usr/share/man/man1/update-gap-workspace.1.gz
/usr/share/menu/gap-core
/usr/share/pixmaps/gap.xpm

GAP support

gap-trouble@dcs.st-and.ac.uk

gap-forum.dcs.st-and.ac.uk

GAP 编程>Arithmetic

Arithmetic

(2 + 3)*(7 - 5);

10

2*3/66;

1/11

2^100-1;

1267650600228229401496703205375

5/2 + 3/5;

31/10

66/1512 + 1/252;

1/21

Sqrt(100);

10

Sqrt(100) in Integers;

true

Sqrt(99) in Integers;

false

Let us comment here regarding spaces in the input. We could (and often do) leave spaces round the contents of brackets. For example

Sqrt( 100 );

10

More spaces (although we wouldn't in general suggest that anyone does this) are still OK.

Sqrt(    100    );

10

We can even leave a space before the (.

Sqrt ( 100 );

10

GAP 编程>Arithmetic

Arithmetic

However, we obviously can't leave spaces in the middle of commands or numbers. For example the following will produce an error.

Sqr t(100);

Variable: 'Sqr' must have a value

Syntax error: ; expected
Sqr t(100);
^
100

Sqrt(10 0);

Syntax error: ) expected
Sqrt(10 0);
^

We return to giving commands for the manipulation of numbers.

(66/1512 + 1/252) in Rationals;

true

(66/1512 + 1/252) in Integers;

false

We can find Greatest Common Divisors of integers

Gcd(1512,1215);

27

Gcd(1020,1512,1215);

3

and their Least Common Multiples.

Lcm(1512,1215);

68040

Lcm(1020,1512,1215);

1156680

GAP 编程>Arithmetic

Arithmetic

Given two integers $a$, $b$ with greatest common divisor $d$ we can find $x$, $y$ such that $xa+yb=d$ with Gcdex(a,b):

a:= 1512;; b:= 1215;; 
g:= Gcdex(a,b);

rec( gcd := 27, coeff1 := -4,
  coeff2 := 5, coeff3 := 45,
  coeff4 := -56 )

Note that "rec" indicates a record with various components.

d:= g.gcd;; x:= g.coeff1;; y:= g.coeff2;;
d= a*x+b*y;

true

Notice the use of ;;

to avoid GAP printing back the input line.

To work mod n we can use the obvious method.

(5 + 7) mod 9;

3

3^7 mod 10;

7

However, to compute large powers mod n it is better to use PowerModInt.

PowerModInt(2, 1000, 10);

6

gives the same result as

2^1000 mod 10;

6

GAP 编程>Arithmetic

Arithmetic

What do you think PowerModInt does and why do you think it might be faster?

So if we want to compute 1000251291 mod 251291 we should use

PowerModInt(1000, 251291, 251291);

1000

Is this the answer you expect? Try

PowerModInt(1001, 251291, 251291);

1001

PowerModInt(1002, 251291, 251291);

1002

PowerModInt(1003, 251291, 251291);

1003

What well known theorem does this illustrate?

What about

PowerModInt(1000, 251293, 251293);

64280

If $p$ is a prime number, then \[ a^p\equiv a\quad(\text{mod}\ p) \]

IsPrime(251291);

true

IsPrime(251293);

false

GAP 编程>Arithmetic

Arithmetic

Another useful function for working with integers is RootsMod

which finds modular roots.

RootsMod(4, 15);

[ 2, 7, 8, 13 ]

finds all the square roots of 4 mod 15. It has the same effect as

RootsMod(4, 2, 15);

[ 2, 7, 8, 13 ]

For the cube roots of 4 mod 15 use

RootsMod(4, 3, 15);

[ 4 ]

In fact the RootsMod

function returns a set. We now look further at sets and lists.

GAP 编程>Sets and lists

Lists

GAP writes its lists with [ ].

We can define a list using a range.

r_1:= [ 1..10 ];

[ 1 .. 10 ]

This list $r_1$ consists of all the integers from 1 to 10. For example:

5 in r_1;

true

11 in r_1;

false

The list $r_1$ contains Length(r_1) or Size(r_1) elements

Length(r_1);

10

GAP will also use ranges to produce an arithmetic progression. For example:

r_2:=[1,3..17];

[ 1, 3 .. 17 ]

We can get GAP to display the elements of the list.

Elements(r_2);

[ 1, 3, 5, 7, 9, 11, 13, 15, 17 ]

More examples:

r_3:=[2,4..16];

[ 2, 4 .. 16 ]

Elements(r_3);

[ 2, 4, 6, 8, 10, 12, 14, 16 ]

GAP 编程>Sets and lists

Lists

r_4:=[5,8..35];

[ 5, 8 .. 35 ]

Elements(r_4);

[ 5, 8, 11, 14, 17, 20, 23, 26, 29,
  32, 35 ]

We can also write out all the elements to define a list:

s:= [ 1, 8, 6, 2 ];

[ 1, 8, 6, 2 ]

GAP will do a form of arithmetic with lists.
We can generate the same arithmetic progression as before:

2*[1..9]-1;

[ 1, 3, 5, 7, 9, 11, 13, 15, 17 ]

We can add or subtract lists -- even of different lengths

[1,2,3]+[4,5];

[ 5, 7, 3 ]

We can add new elements to lists. GAP does not return any output to the screen.

t:=[ 1, 2, 2, 3, 4, 5, 6 ];

[ 1, 2, 2, 3, 4, 5, 6 ]

Add(t, 10);

But we can see what has happened:

t;

[ 1, 2, 2, 3, 4, 5, 6, 10 ]

GAP 编程>Sets and lists

Lists

The command Add

will simply add an entry to the end of an existing list. If we want to create a new list which is equal to the original list but has an added element we can first make a copy of the list and then add the element. For example

lis:= [1,2,1,2,5,9];

[ 1, 2, 1, 2, 5, 9 ]

newlis:= ShallowCopy(lis);

[ 1, 2, 1, 2, 5, 9 ]

GAP has various commands for copying and ShallowCopy is the one we need here. We can now modify our copy without changing the original list.

Add(newlis, -5);

lis; newlis;

[ 1, 2, 1, 2, 5, 9 ]
[ 1, 2, 1, 2, 5, 9, -5 ]

We can filter out elements from a list with particular properties. For example to find all the elements in the list t which are prime we input

t1:= Filtered(t, IsPrimeInt);

[ 2, 2, 3, 5 ]

To filter out the elements which have a given property, one must use Filtered(t, f)

where $f$ is a function which takes the value true on the elements to be filtered. We will discuss functions later.

GAP 编程>Sets

Sets

GAP will sometimes consider a list as a set, but often needs to convert it before applying set operations.

s:= [ 1, 8, 6, 2 ];

[ 1, 8, 6, 2 ]

We test if it is a set:

IsSet(s);

false

GAP will only count a list of integers as a set if it is ordered increasingly and contains no repetitions. The next example has a repeated entry.

t:= [ 1, 2, 2, 3, 4, 5, 6 ];

[ 1, 2, 2, 3, 4, 5, 6 ]

IsSet(t);

false

Of course s and t are lists and we can create sets from them:

ss:= Set(s);

[ 1, 2, 6, 8 ]

tt:= Set(t);

[ 1, 2, 3, 4, 5, 6 ]

Notice that this operation removes repetitions and puts the elements into increasing order.

GAP 编程>Sets

Sets

The usual set operations work and GAP treats the lists as if they were sets before applying the operations:

Intersection(s, t);

[ 1, 2, 6 ]

IsEqualSet(Intersection(s,t),Intersection (ss,tt));

true

Union(s, t);

[ 1, 2, 3, 4, 5, 6, 8 ]

Difference(s, t);

[ 8 ]

Difference(t, s);

[ 3, 4, 5 ]

To add an element to the set ss we use AddSet. Again we get no output.

AddSet(ss, 4);

ss;

 [ 1, 2, 4, 6, 8 ]

GAP 编程>Loops

Loops

We begin with elementary loops.

for i in [1..10] do
  Print(i);
od;

12345678910

Notice that the output is 12345678910. Suppose we want to print a space between consecutive numbers.

for i in [1..10] do
  Print(i," ");
od;

1 2 3 4 5 6 7 8 9 10 

Suppose we want to print each number on a separate line. We use "\n" to make a new line.

for i in [1..10] do
  Print(i, "\n");
od;

1
2
3
4
5
6
7
8
9
10

GAP 编程>Loops

Loops

A slightly more useful loop might be:

for i in [1..10] do
  Print(i," squared is ",i^2,"\n");
od;

1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
6 squared is 36
7 squared is 49
8 squared is 64
9 squared is 81
10 squared is 100

Notice that we have put spaces in " squared is " so that it displays properly.

GAP 编程>Conditionals

Conditionals

We now introduce conditionals into our loop. We test to see if an integer i is prime and if so we print it.

for i in [1..20] do
  if IsPrimeInt(i) then Print(i, " is prime ", "\n"); fi;
od;

2 is prime
3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime

Of course most even numbers cannot be prime so we could reduce the number of times the loop is run by only looking at odd numbers. However, 2 will not be listed!

for i in [1, 3 .. 19] do
  if IsPrimeInt(i) then    Print(i," is prime ","\n");   fi;
od;

3 is prime
5 is prime
7 is prime
11 is prime
13 is prime
17 is prime
19 is prime

GAP 编程>Conditionals

Conditionals

The next loop prints the primes in the first 50 terms of the Fibonacci sequence.

for i in [1..50] do
  if IsPrimeInt(Fibonacci(i)) then    Print(Fibonacci(i)," is prime ","\n");   fi;
od;

2 is prime
3 is prime
5 is prime
13 is prime
89 is prime
233 is prime
1597 is prime
28657 is prime
514229 is prime
433494437 is prime
2971215073 is prime

We can test whether numbers less than 1000 are primes in another way, rather than use IsPrimeInt. For example

13 in Primes;

true

Fibonacci(13) in Primes;

true

Note however that Primes only contains the 168 primes less than 1000. For example

IsPrimeInt(1597);

true

1597 in Primes;

false

GAP 编程>Functions

Functions

We move on to functions. The following code defines a function that simply squares the argument it is given.

squared:= function(n);
  return n^2;
end;

function( n ) ... end

If you want to see the function written out fully, you can ask GAP to Print it.

Print(squared);

function ( n )
;
return n ^ 2;
end

Try applying this function and see the result.

squared(12345);

152399025

There are simpler ways to write easy functions like this. For example

cubed:= n -> n^3;

function( n ) ... end

Print(cubed);

function ( n )
return n ^ 3;
end

cubed(123456);

1881640295202816

GAP 编程>Functions

Functions

We can produce lists of cubes as follows:

List( [1..10], cubed );

[ 1, 8, 27, 64, 125, 216, 343, 512,
  729, 1000 ]

This is a very useful construction. Here are a few more examples.

First the squares of the even numbers between 2 and 14.

List( [2,4..14], n->n^2 );

[ 4, 16, 36, 64, 100, 144, 196 ]

A more complicated example

f:=function(n);
  if n mod 2 =0 then
    return n^2;
  else
    return n^3;
  fi;
end;
function( n ) ... end

List( [1..20], f);

[ 1, 4, 27, 16, 125, 36, 343, 64, 729,
  100, 1331, 144, 2197, 196, 3375, 256, 
  4913, 324, 6859, 400 ]

GAP 编程>Functions

Functions

If we define a function which returns true or false, we may use this to filter a list.

is1mod4:=function(n);
  if n mod 4 = 1 then
    return true;
  else
    return false;
  fi;
end;
function( n ) ... end

Filtered([1..20], is1mod4);

[ 1, 5, 9, 13, 17 ]

GAP 编程>Functions

A famous sequence

There is a famous open question which asks whether one always reaches 1 if one starts with any number and successively applies that rule. For example, if we start with 3 we get

3, 10, 5, 16, 8, 4, 2, 1

f:= function(n);
  if n mod 2 = 0 then
    return n/2;
  else
    return 3*n+1;
  fi;
end;
function( n ) ... end

Let us now write a function t to return the number of steps that are required to reach 1. Note that we define local variables to use in the function. We do this so that if variables with the same name are used elsewhere their value will not be affected by the function. Note that there is no semi-colon before the local variables are listed.

t:= function(i) local k, m;
  k:= 0;
  m:= i;
  while m > 1 do
    k:= k+1;
    m:= f(m);
  od;
  return k;
end;
function( i ) ... end

GAP 编程>Functions

3n+1 problem

When we wrote the code for the function we put extra spaces at the beginning of each line so that it was easier to see where conditional clauses and loops began and ended.

Let us produce a sequence with ith entry the number of steps required to reach 1 starting from i.

s:= List( [1..1000], t );

GAP 编程>Functions

3n+1 problem

[ 0, 1, 7, 2, 5, 8, 16, 3, 19, 6, 14, 9, 9, 17, 17, 4, 12, 20, 20, 7, 7, 15, 15, 10,
 23, 10, 111, 18, 18, 18, 106, 5, 26, 13, 13, 21, 21, 21, 34, 8, 109, 8, 29, 16, 16,
 16, 104, 11, 24, 24, 24, 11, 11, 112, 112, 19, 32, 19, 32, 19, 19, 107, 107, 6, 27,
 27, 27, 14, 14, 14, 102, 22, 115, 22, 14, 22, 22, 35, 35, 9, 22, 110, 110, 9, 9, 30,
 30, 17, 30, 17, 92, 17, 17, 105, 105, 12, 118, 25, 25, 25, 25, 25, 87, 12, 38, 12,
 100, 113, 113, 113, 69, 20, 12, 33, 33, 20,  20, 33, 33, 20, 95, 20, 46, 108, 108,
 108, 46, 7, 121, 28, 28, 28, 28, 28, 41, 15, 90, 15, 41, 15, 15, 103, 103, 23, 116,
 116, 116, 23, 23, 15, 15, 23, 36, 23, 85, 36, 36, 36, 54, 10, 98, 23, 23, 111, 111,
 111, 67, 10, 49, 10, 124, 31, 31, 31, 80, 18, 31, 31, 31, 18, 18, 93, 93, 18, 44, 18,
 44, 106, 106, 106, 44, 13, 119, 119, 119, 26, 26, 26, 119, 26, 18, 26, 39, 26, 26,
 88, 88, 13, 39, 39, 39, 13, 13, 101, 101, 114, 26, 114, 52, 114, 114, 70, 70, 21, 52,
 13, 13, 34, 34, 34, 127, 21, 83, 21, 127, 34, 34, 34, 52, 21, 21, 96, 96, 21, 21, 47,
 47, 109, 47, 109, 65, 109, 109, 47, 47, 8, 122, 122, 122, 29, 29, 29, 78, 29, 122,
 29, 21, 29, 29, 42, 42, 16, 29, 91, 91, 16, 16, 42, 42, 16, 42, 16, 60, 104, 104,
 104, 42, 24, 29, 117, 117, 117, 117, 117, 55, 24, 73, 24, 117, 16, 16, 16, 42, 24,
 37, 37, 37, 24, 24, 86, 86, 37, 130, 37, 37, 37, 37, 55, 55, 11, 24, 99, 99, 24, 24,
 24, 143, 112, 50, 112, 24, 112, 112, 68, 68, 11, 112, 50, 50, 11, 11, 125, 125, 32,
 125, 32, 125, 32, 32, 81, 81, 19, 125, 32, 32, 32, 32, 32, 50, 19, 45, 19, 45,  94,
 94, 94, 45, 19, 19, 45, 45, 19, 19, 45, 45, 107, 63, 107, 58, 107, 107, 45, 45, 14,
 32, 120, 120, 120, 120, 120, 120, 27, 58, 27, 76, 27, 27, 120, 120, 27, 19, 19, 19,
 27, 27, 40, 40, 27, 40, 27, 133, 89, 89, 89, 133, 14, 133, 40, 40, 40, 40, 40, 32,
 14, 58, 14, 53, 102, 102, 102, 40, 115, 27, 27, 27, 115, 115, 53, 53, 115, 27, 115,
 53, 71, 71, 71, 97, 22, 115, 53, 53, 14, 14, 14, 40, 35, 128, 35, 128, 35, 35, 128,
 128, 22, 35, 84, 84, 22, 22, 128, 128, 35, 35, 35, 27, 35, 35, 53, 53, 22, 48, 22,
 22, 97, 97, 97, 141, 22, 48, 22, 141, 48, 48, 48, 97, 110, 22, 48, 48, 110, 110, 66,
 66, 110, 61, 110, 35, 48, 48, 48, 61, 9, 35, 123, 123, 123, 123, 123, 61, 30, 123,
 30, 123, 30, 30, 79, 79, 30, 30, 123, 123, 30, 30, 22, 22, 30, 22, 30, 48, 43, 43,
 43, 136, 17, 43, 30, 30, 92, 92, 92, 43, 17, 136, 17, 30, 43, 43, 43, 87, 17, 43, 43,
 43, 17, 17, 61, 61, 105, 56, 105, 30, 105, 105, 43, 43, 25, 30, 30, 30, 118, 118,
 118, 30, 118, 56, 118, 118, 118, 118, 56, 56, 25, 74, 74, 74, 25, 25, 118, 118, 17,
 56, 17, 69, 17, 17, 43, 43, 25, 131, 38, 38, 38, 38, 38, 69, 25, 131, 25, 131, 87,
 87, 87, 131, 38, 25, 131, 131, 38, 38, 38, 38, 38, 30, 38, 30, 56, 56, 56, 131, 12,
 51, 25, 25, 100, 100, 100, 38, 25, 144, 25, 100, 25, 25, 144, 144, 113, 51, 51, 51,
 113, 113, 25, 25, 113, 51, 113, 144, 69, 69, 69, 95, 12, 64, 113, 113, 51, 51, 51,
 64, 12, 64, 12, 38, 126, 126, 126, 38, 33, 126, 126, 126, 33, 33, 126, 126, 33, 126,
 33, 64, 82, 82, 82, 170, 20, 33, 126, 126, 33, 33, 33, 64, 33, 25, 33, 25, 33, 33,
 51, 51, 20, 46, 46, 46, 20, 20, 46, 46, 95, 33, 95, 139, 95, 95, 46, 46, 20, 139, 20,
 20, 46, 46, 46, 95, 20, 90, 20, 46, 46, 46, 46, 139, 108, 20, 64, 64, 108, 108, 59,
 59, 108, 33, 108, 152, 46, 46, 46, 59, 15, 33, 33, 33, 121, 121, 121, 152, 121, 33,
 121, 59, 121, 121, 121, 121, 28, 121, 59, 59, 28, 28, 77, 77, 28, 77, 28, 103, 121,
 121, 121, 72, 28, 59, 20, 20, 20, 20, 20, 72, 28, 46, 28, 134, 41, 41, 41, 134, 28,
 41, 41, 41, 28, 28, 134, 134, 90, 134, 90, 41, 90, 90, 134, 134, 15, 28, 134, 134,
 41, 41, 41, 85, 41, 41, 41, 41, 41, 41, 33, 33, 15, 59, 59, 59, 15, 15, 54, 54, 103,
 28, 103, 147, 103, 103, 41, 41, 116, 147, 28, 28, 28, 28, 28, 178, 116, 147, 116, 28,
 54, 54, 54, 147, 116, 116, 28, 28, 116, 116, 54, 54, 72, 147, 72, 46, 72, 72, 98, 98,
 23, 67, 116, 116, 54, 54, 54, 116, 15, 67, 15, 54, 15, 15, 41, 41, 36, 129, 129, 129,
 36, 36, 129, 129, 36, 129, 36, 67, 129, 129, 129, 116, 23, 129, 36, 36, 85, 85, 85,
 129, 23, 173, 23, 85, 129, 129, 129, 36, 36, 36, 36, 36, 36, 36, 28, 28, 36, 28, 36,
 28, 54, 54, 54, 129, 23, 49, 49, 49, 23, 23, 23, 142, 98, 49, 98, 36, 98, 98, 142,
 142, 23, 98, 49, 49, 23, 23, 142, 142, 49, 23, 49, 36, 49, 49, 98, 98, 111, 93, 23,
 23, 49, 49, 49, 49, 111 ]

GAP 编程>Functions

3n+1 problem

If you don't want to see the list s then end the line with ;;
The following loop will product the same list s as we just constructed above but of course takes longer to write.

s:= [];;
for i in [1..1000] do
  Add(s, t(i));
od;
Print(s, "\n");

GAP 编程>Functions

3n+1 problem

[ 0, 1, 7, 2, 5, 8, 16, 3, 19, 6, 14, 9, 9, 17, 17, 4, 12, 20, 20, 7, 7, 15, 15, 10,
 23, 10, 111, 18, 18, 18, 106, 5, 26, 13, 13, 21, 21, 21, 34, 8, 109, 8, 29, 16, 16,
 16, 104, 11, 24, 24, 24, 11, 11, 112, 112, 19, 32, 19, 32, 19, 19, 107, 107, 6, 27,
 27, 27, 14, 14, 14, 102, 22, 115,  22, 14, 22, 22, 35, 35, 9, 22, 110, 110, 9, 9, 30,
 30, 17, 30, 17, 92, 17, 17, 105, 105, 12, 118, 25, 25, 25, 25, 25, 87, 12, 38, 12,
 100, 113, 113, 113, 69, 20, 12, 33, 33, 20, 20, 33, 33, 20, 95, 20, 46, 108, 108,
 108, 46, 7, 121, 28, 28, 28, 28, 28, 41, 15, 90, 15, 41, 15, 15, 103, 103, 23, 116,
 116, 116, 23, 23, 15, 15, 23, 36, 23, 85, 36, 36, 36, 54, 10, 98, 23, 23, 111, 111,
 111, 67, 10, 49, 10, 124, 31, 31, 31, 80, 18, 31, 31, 31, 18, 18, 93, 93, 18, 44, 18,
 44, 106, 106, 106, 44, 13, 119, 119, 119, 26, 26, 26, 119, 26, 18, 26, 39, 26, 26,
 88, 88, 13, 39, 39, 39, 13, 13, 101, 101, 114, 26, 114, 52, 114, 114, 70, 70, 21, 52,
 13, 13, 34, 34, 34, 127, 21, 83, 21, 127, 34, 34, 34, 52, 21, 21, 96, 96, 21, 21, 47,
 47, 109, 47, 109, 65, 109, 109, 47, 47, 8, 122, 122, 122, 29, 29, 29, 78, 29, 122,
 29, 21, 29, 29, 42, 42, 16, 29, 91, 91,  16, 16, 42, 42, 16, 42, 16, 60, 104, 104,
 104, 42, 24, 29, 117, 117, 117, 117, 117, 55, 24, 73,  24, 117, 16, 16, 16, 42, 24,
 37, 37, 37, 24, 24, 86, 86, 37, 130, 37, 37, 37, 37, 55, 55, 11, 24, 99, 99, 24, 24,
 24, 143, 112, 50, 112, 24, 112, 112, 68, 68, 11, 112, 50, 50, 11, 11, 125, 125, 32,
 125, 32, 125, 32, 32, 81, 81, 19, 125, 32, 32, 32, 32, 32, 50, 19, 45, 19, 45, 94,
 94, 94, 45, 19, 19, 45, 45, 19, 19, 45, 45, 107, 63, 107, 58, 107, 107, 45, 45, 14,
 32, 120, 120, 120, 120, 120, 120, 27, 58, 27, 76, 27, 27, 120, 120, 27, 19, 19, 19,
 27, 27, 40, 40, 27, 40, 27, 133, 89, 89, 89, 133, 14, 133, 40, 40, 40, 40, 40, 32,
 14, 58, 14, 53, 102, 102, 102, 40, 115, 27, 27, 27, 115, 115, 53, 53, 115, 27, 115,
 53, 71, 71, 71, 97, 22, 115, 53, 53, 14, 14, 14, 40, 35, 128, 35, 128, 35, 35, 128,
 128, 22, 35, 84, 84, 22, 22, 128, 128, 35, 35, 35, 27, 35, 35, 53, 53, 22, 48, 22,
 22, 97, 97, 97, 141, 22, 48, 22, 141, 48, 48, 48, 97, 110, 22, 48, 48, 110, 110, 66,
 66, 110, 61, 110, 35, 48, 48, 48, 61, 9, 35, 123, 123, 123, 123, 123, 61, 30, 123,
 30, 123, 30, 30, 79, 79, 30, 30, 123, 123, 30, 30, 22, 22, 30, 22, 30, 48, 43, 43,
 43, 136, 17, 43, 30, 30, 92, 92, 92, 43, 17, 136, 17, 30, 43, 43, 43, 87, 17, 43, 43,
 43, 17, 17, 61, 61, 105, 56, 105, 30, 105, 105, 43, 43, 25, 30, 30, 30, 118, 118,
 118, 30, 118, 56, 118, 118, 118, 118, 56, 56, 25, 74, 74, 74, 25, 25, 118, 118, 17,
 56, 17, 69, 17, 17, 43, 43, 25, 131, 38, 38, 38, 38, 38, 69, 25, 131, 25, 131, 87,
 87, 87, 131, 38, 25, 131, 131, 38, 38, 38, 38, 38, 30, 38, 30, 56, 56, 56, 131, 12,
 51, 25, 25, 100, 100, 100, 38, 25, 144, 25, 100, 25, 25, 144, 144, 113, 51, 51, 51,
 113, 113, 25, 25, 113, 51, 113, 144, 69, 69, 69, 95, 12, 64, 113, 113, 51, 51, 51,
 64, 12, 64, 12, 38, 126, 126, 126, 38, 33, 126, 126, 126, 33, 33, 126, 126, 33, 126,
 33, 64, 82, 82, 82, 170, 20, 33, 126, 126, 33, 33, 33, 64, 33, 25, 33, 25, 33, 33,
 51, 51, 20, 46, 46, 46, 20, 20, 46, 46, 95, 33, 95, 139, 95, 95, 46, 46, 20, 139, 20,
 20, 46, 46, 46, 95, 20, 90, 20, 46, 46, 46, 46, 139, 108, 20, 64, 64, 108, 108, 59,
 59, 108, 33, 108, 152, 46, 46, 46, 59, 15, 33, 33, 33, 121, 121, 121, 152, 121, 33,
 121, 59, 121, 121, 121, 121, 28, 121, 59, 59, 28, 28, 77, 77, 28, 77, 28, 103, 121,
 121, 121, 72, 28, 59, 20, 20, 20, 20, 20, 72, 28, 46, 28, 134, 41, 41, 41, 134, 28,
 41, 41, 41, 28, 28, 134, 134, 90, 134, 90,  41, 90, 90, 134, 134, 15, 28, 134, 134,
 41, 41, 41, 85, 41, 41, 41, 41, 41, 41, 33, 33, 15, 59, 59, 59, 15, 15, 54, 54, 103,
 28, 103, 147, 103, 103, 41, 41, 116, 147, 28, 28, 28, 28, 28, 178, 116, 147, 116, 28,
 54, 54, 54, 147, 116, 116, 28, 28, 116, 116, 54, 54, 72, 147, 72, 46, 72, 72, 98, 98,
 23, 67, 116, 116, 54, 54, 54, 116, 15, 67, 15, 54, 15, 15, 41, 41, 36, 129, 129, 129,
 36, 36, 129, 129, 36, 129, 36, 67, 129, 129, 129, 116, 23, 129, 36, 36, 85, 85, 85,
 129, 23, 173, 23, 85, 129, 129, 129, 36, 36, 36, 36, 36, 36, 36, 28, 28, 36, 28, 36,
 28, 54, 54, 54, 129, 23, 49, 49, 49, 23, 23, 23, 142, 98, 49, 98, 36, 98, 98, 142,
 142, 23, 98, 49, 49, 23, 23, 142, 142, 49, 23, 49, 36, 49, 49, 98, 98, 111, 93, 23,
 23, 49, 49, 49, 49, 111 ]

GAP 编程>Functions

3n+1 problem

Notice the fact that lots of adjacent entries in s are equal. So often beginning with consecutive numbers we find that the same number of steps is required to reach 1. As we reach larger numbers we see three consecutive numbers with this property etc.

We construct a list len whose nth entry will be the number of times n consecutive numbers take the same number of steps. Note that when we reach the end of the list, we do not know whether the next entry would have been the same as the last one and so we do not count this run.

len:= ListWithIdenticalEntries(20, 0);

[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0 ]
count:= 1;;
for i in [ 2 .. Length(s) ] do
  if s[i] = s[i-1] then
    count:= count + 1;
  else
    len[count]:= len[count] + 1;
    count:= 1;
  fi;
od;
len;
[ 394, 150, 72, 5, 10, 2, 1, 0, 0, 0, 0, 
  0, 0, 0, 0, 0, 0, 0, 0, 0 ]

Remove the trailing 0's in len

i:= Length(len);
while len[i] = 0 do
  Unbind(len[i]);
  i:= i-1;
od;
len;
[ 394, 150, 72, 5, 10, 2, 1 ]

GAP 编程>Functions

3n+1 problem

For each i print the number of i consecutive integers taking the same number of steps to reach 1.

for i in [1..Length(len)] do
  Print("There are ",len[i],
    " runs of length ", i, "\n");
od;
There are 394 runs of length 1
There are 150 runs of length 2
There are 72 runs of length 3
There are 5 runs of length 4
There are 10 runs of length 5
There are 2 runs of length 6
There are 1 runs of length 7

We again note that we added spaces in the strings in the Print statement.

Another thing that one can investigate about this problem is the highest number reached by the sequence before it collapses to 1.

GAP 编程>Functions

Stirling numbers of the second kind

We now investigate Stirling numbers of the second kind.

Stirling2(n, r) is the number of ways a set of n elements can be partitioned into r disjoint non-empty subsets.

For example, if $n=2k$, and $r=2$, then \[ \text{Stirling}2(n,2)=\sum_{i=1}^{k-1}C_n^i+\frac{C_n^k}{2}, \]

If $n=2k+1$, then \[ \text{Stirling}2(n,2)=\sum_{i=1}^{k}C_n^i. \]

First we list the these numbers for a fixed n, take n = 12.

l:= List( [1..12], k -> Stirling2(12, k) );

[ 1, 2047, 86526, 611501, 1379400,
  1323652, 627396, 159027, 22275, 1705,
  66, 1 ]

Find the maximum value

m:= Maximum(l);

1379400

and its position in the list

Position(l, m);

5

Let us now construct a list stir from these lists of Stirling numbers so that the nth entry of stir is the list of Stirling numbers for a set of n elements. This would give a seriously large output, so we suppress it.

stir:= List( [1..50], n -> List([1..n], k -> Stirling2(n, k)) );;

GAP 编程>Functions

Stirling numbers of the second kind

Now find where the maximum occurs for each n.

for i in [1..Length(stir)] do
  Print("row ", i, " has maximum in position ",
    Position(stir[i], Maximum(stir[i])), "\n");
od;
row 1 has maximum in position 1
row 2 has maximum in position 1
row 3 has maximum in position 2
row 4 has maximum in position 2
row 5 has maximum in position 3
row 6 has maximum in position 3
row 7 has maximum in position 4
row 8 has maximum in position 4
row 9 has maximum in position 4
row 10 has maximum in position 5
row 11 has maximum in position 5
row 12 has maximum in position 5
row 13 has maximum in position 6
row 14 has maximum in position 6
row 15 has maximum in position 6
row 16 has maximum in position 7
row 17 has maximum in position 7
row 18 has maximum in position 7
row 19 has maximum in position 8
row 20 has maximum in position 8
row 21 has maximum in position 8
row 22 has maximum in position 9
row 23 has maximum in position 9
row 24 has maximum in position 9
row 25 has maximum in position 10
row 26 has maximum in position 10
row 27 has maximum in position 10
row 28 has maximum in position 10
row 29 has maximum in position 11
row 30 has maximum in position 11
row 31 has maximum in position 11
row 32 has maximum in position 12
row 33 has maximum in position 12
row 34 has maximum in position 12
row 35 has maximum in position 12
row 36 has maximum in position 13
row 37 has maximum in position 13
row 38 has maximum in position 13
row 39 has maximum in position 14
row 40 has maximum in position 14
row 41 has maximum in position 14
row 42 has maximum in position 14
row 43 has maximum in position 15
row 44 has maximum in position 15
row 45 has maximum in position 15
row 46 has maximum in position 15
row 47 has maximum in position 16
row 48 has maximum in position 16
row 49 has maximum in position 16
row 50 has maximum in position 16

It is not easy to predict where the maximum will occur for a given $n$. However, there is an asymptotic result known, namely that as $n\rightarrow\infty$, the maximum position tends to $n/\ln n$.

GAP 编程>Functions

Divisors of consecutive integers

We now examine a problem which involves elementary number theory.

Are there infinitely many pairs of consecutive integers with the same number of divisors?

Is there an infinite number of pairs of consecutive integers that each have 4 divisors?

We have no hope of solving the problem but let us investigate it.

First note that DivisorsInt(n) returns a list of divisors of n.

DivisorsInt(1512);

[ 1, 2, 3, 4, 6, 7, 8, 9, 12, 14, 18, 21, 24, 27, 28, 36, 42, 54, 56, 63, 72, 84, 108, 126, 168, 189, 216, 252, 378, 504, 756, 1512 ]

It is easy to find the number of divisors of n.

Length(DivisorsInt(1512));

32

For ease of typing let us define f(n) to be the number of divisors of n.

f:= n -> Length(DivisorsInt(n));

function( n ) ... end

GAP 编程>Functions

Divisors of consecutive integers

Let us look for pairs of consecutive integers with the same number of divisors.

for i in [1..200] do
  if f(i) = f(i+1) then
    Print("pair ", i," ", i+1, " has ",f(i), " divisors ", "\n");
  fi;
od;
pair 2 3 has 2 divisors
pair 14 15 has 4 divisors
pair 21 22 has 4 divisors
pair 26 27 has 4 divisors
pair 33 34 has 4 divisors
pair 34 35 has 4 divisors
pair 38 39 has 4 divisors
pair 44 45 has 6 divisors
pair 57 58 has 4 divisors
pair 75 76 has 6 divisors
pair 85 86 has 4 divisors
pair 86 87 has 4 divisors
pair 93 94 has 4 divisors
pair 94 95 has 4 divisors
pair 98 99 has 6 divisors
pair 104 105 has 8 divisors
pair 116 117 has 6 divisors
pair 118 119 has 4 divisors
pair 122 123 has 4 divisors
pair 133 134 has 4 divisors
pair 135 136 has 8 divisors
pair 141 142 has 4 divisors
pair 142 143 has 4 divisors
pair 145 146 has 4 divisors
pair 147 148 has 6 divisors
pair 158 159 has 4 divisors
pair 171 172 has 6 divisors
pair 177 178 has 4 divisors
pair 189 190 has 8 divisors

GAP 编程>Functions

Divisors of consecutive integers

We can easily move to finding three consecutive integers with the same number of divisors.

for i in [1..200] do
  if f(i) = f(i+1) and f(i+1)=f(i+2)	then
    Print("triple ", i," ", i+1, " ", i+2," has ", f(i)," divisors ", "\n");
  fi;
od;
triple 33 34 35 has 4 divisors
triple 85 86 87 has 4 divisors
triple 93 94 95 has 4 divisors
triple 141 142 143 has 4 divisors

Then we can look for even longer runs. This code uses a different kind of loop.

i:=1;;
over:=false;;
while not over do
  if f(i) = f(i+1) and f(i+1)=f(i+2) and f(i+2)=f(i+3) and f(i+3)=f(i+4) and f(i+4)=f(i+5) and f(i+5)=f(i+6) then
    Print("Sequence of length 7 starting ",i," has ",f(i)," divisors \n");
    over:=true;
  fi;
  i:=i+1;
od;
Sequence of length 7 starting 171893 has 8 divisors

GAP 编程>Functions

Divisors of consecutive integers

As an exercise you may care to turn the above into a function with a parameter n which returns sequences of length n of integers with the same number of divisors.

Can one find such runs of arbitrary length? GAP can help, but won't tell you the answer!


JOC/EFR January 2003

GAP 编程>Functions

Divisors of consecutive integers

GAP 编程>Functions

Divisors of consecutive integers

GAP 编程>Functions

Divisors of consecutive integers

改进 GAP

How to improve GAP(编写自己的宏包, 编写GUI)

Data Libraries

References

http://www-circa.mcs.st-and.ac.uk/gapintro.php

End






Thanks very much!

Welcome to visit my site: www.atzjg.net