## Comment lines begin with a #. They are useful for human eyes # but ignored by gap. # since computers are profoundly stupid, they cannot # make the sort of casual identifications and # relabellings that humans do. # Hence computer algebra syntax is necessarily quite fussy # Gap also has to worry about allocating its computer # storage in light of all this # # ctrl - D should quit Gap normally # ctrl - C twice should stop it in the middle of an unfortunate computation # whitespace = blanks, tabs, returns are generally meaningless # to Gap, so are useful for clear writing # here are two Gap commands. Copy and enter on one line; # you should get the indicated responses. 2^3; 2 ^ 3; 8 8 # in the next line I hit return BEFORE the ; 2 > ^ > 3 > ; 8 # Gap must distinguish names of things in your # Gap session, e.g. variables, from things # elsewhere on your computer. E.g. file names # which, after all, are outside your session, must # be enclosed in quotes; # # For example, sometimes we want to read Gap input from a pre-prepared # file on our system. Maybe the data is very long or needs easy editing. # to do this, type and enter Read("thefilename"); # Or to record your calculations for posterity, # LogTo("anotherfilename"); # # # you can do some editing within your session # E.g. ctrl-P recovers the last line of input # ctrl-E moves cursor to the end of line, ctrl - A to beginning # ctrl-K erases to end of line, etc. # Try these! See help section on `line editing' # Gap knows various kinds of constants # Integers: 134; -18; 2*6; 2^6; (-3)^5; 134 -18 12 64 -243 Factorial(7); 5040 # it knows truth values = Boolean constants 2^3 = 3^2; 3^3 = (32 - 5); false true # so you are not allowed to let `false' or `true' # refer to other things; # # let's assign to the variable prue the value 19! # this is so big I don't want Gap to print the # full response, so I suppress output using ;; prue := Factorial(19);; # O.K. let's see how big that really was; prue; 121645100408832000 # # `false' , `true' , `quit', and `last' and other keywords cannot # be used as variable names # now try something illegal: true := Factorial(18); Syntax error: ; expected true := Factorial(18); ^ 6402373705728000 # Gap did what it could - ignore the assignment, # but computed the factorial # true=true; true true = false; false # let's abbreviate. We use := to assign # some object to an identifier. For example, we assign the # reserved constant `true' to the identifier `T'; ditto for `false' T := true; F:= false; true false (T or F) and (not T); false # Gap knows permutations in cycle form; # E.g. the permutation taking 3->4->1 and back, # as well as 2->5 and back is perm:=(3,4,1)(2,5); (1,3,4)(2,5) # of course we can multiply permutations # and find inverses perm^3;perm^2;perm^6; (2,5) (1,4,3) () # so the period is 6 - note the identity () quip:=(5,1,4,2); (1,4,2,5) quip*perm; perm*quip*perm^-1; # a product and a conjugate (3,4,5) (2,4,3,5) # you can compute the action on an element 1^quip; 4 # Gap understands elements of finite fields, complex roots of unity w:=E(3); # this is a primitive third root of unity E(3) # namely exp(2*Pi/3); w^3; 1 w^2+w+1; 0 # However, Gap is not really designed for floating point arrithmetic, i.e. # real numbers as a computer grasps them; nor does # Gap do graphics. There are floating point routines and # standard functions: Sin(3.14); 0.00159265 # # Gap will do all sorts of lists, set theory, matrices,etc. # Gap also needs a way to understand characters, namely # individual keyboard symbols whose mathematical content is # suppressed or non-existent 'a'; 'b'='a'; 'a' false # if we want several we need lists # # a variable name, or identifier, is any string of letters # or numbers, with at least one letter; keywords like `true' or # `quit' are not allowed to be variable names. # Case is important: x1 and X1 are different # # to assign some Gap meaning or object to a variable we enter # varname := meaning , for example a:=(1,2,3); # a permutation (1,2,3) b:=(1,3,2)^2; # the `same' permutation? (1,2,3) a=b; true IsIdenticalObj(a,b); false # Hmmm: Gap recognizes that a and b are the `same' permutation; # However, a and b are not identical objects, in the sense that # the two assignments for a and b pointed to different parts of memory. # You see, Gap couldn't know ahead of time that a would equal b, so the # only reasonable response is to put the two objects in # different parts of memory c:=b; (1,2,3) IsIdenticalObj(c,b); IsIdenticalObj(c,a); true false # Now, however, Gap has been programmed to understand that c and b # merely point to the same place in memory - so c and be really are # identical from the machine's strong point of view. # # this sort of fussiness is necessary, particularly when `=' # refers to some sort of equivalence relation. # What happens then in varname := meaning # is that the identifier `varname' is attached to, i.e. # points to the object `meaning'. This object may move about in # memory, but `varname' will go with it, and will always # point to it --- unless we reassign a new meaning; a;b;a=b; (1,2,3) (1,2,3) true a:=193; 193 a; a=b; 193 false # Lists are key structures: e.g. matrices are special lists Pr:=[2,3,5,7]; # a list of the first four primes [ 2, 3, 5, 7 ] # To extend our list we `append' another list Append(Pr,[11,13]); Pr; Length(Pr); [ 2, 3, 5, 7, 11, 13 ] 6 # note how Pr was automatically extended # say we know that the 8th prime is 19 Pr[8]:=19; 19 Pr; [ 2, 3, 5, 7, 11, 13,, 19 ] # notice that Gap left space for the missing 7th element # such a list with holes is NOT DENSE Pr[7]:=17; 17 Pr;# this is now a dense list [ 2, 3, 5, 7, 11, 13, 17, 19 ] # there are many useful manipulations; Reversed(Pr); [ 19, 17, 13, 11, 7, 5, 3, 2 ] Sum(Pr);Product(Pr); 77 9699690 # a set is a dense list without repetitions; # this corresponds to how we normally think of sets; t:=[-3,5,4,5,3,-3,2,5]; [ -3, 5, 4, 5, 3, -3, 2, 5 ] T:=Set(t); [ -3, 2, 3, 4, 5 ] # the elements are ordered in some fashion in a set. # sets and lists can be empty e:=[]; # the empty list [ ] Em:=Set(e); # the empty set - essentially the same thing [ ] # The letter `E' is reserved for use in finite fields # S:=Set([2,7,9]); [ 2, 7, 9 ] Union(T,S);Intersection(T,S);Union(S,Em); [ -3, 2, 3, 4, 5, 7, 9 ] [ 2 ] [ 2, 7, 9 ] W:=Set([(1,2,3),-17/4,[],S]); [ -17/4, (1,2,3), [ ], [ 2, 7, 9 ] ] # sets and lists can contain all sorts of objects W; [ -17/4, (1,2,3), [ ], [ 2, 7, 9 ] ] W[3]; [ ] W[4][3]; 9 # a range is an arithmetic progession R1:=[25,22..-5]; [ 25, 22 .. -5 ] Elements(R1); [ -5, -2, 1, 4, 7, 10, 13, 16, 19, 22, 25 ] J:=[1..20];Elements(J); [ 1 .. 20 ] [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ] # we can create lists in many ways List(J,IsPrime); [ false, true, true, false, true, false, true, false, false, false, true, false, true, false, false, false, true, false, true, false ] # suppose we want to extract only the primes from [1..20] Filtered(J,IsPrime); [ 2, 3, 5, 7, 11, 13, 17, 19 ] # a matrix is a list of lists of entires from some field or ring # here is a 2 by 2 matrix of rational numbers A:=[[3/5,-4/5],[4/5,3/5]]; [ [ 3/5, -4/5 ], [ 4/5, 3/5 ] ] Display(A); [ [ 3/5, -4/5 ], [ 4/5, 3/5 ] ] DefaultFieldOfMatrix(A); Rationals Determinant(A); 1 A^4; # its 4th power [ [ -527/625, 336/625 ], [ -336/625, -527/625 ] ] Display(last); [ [ -527/625, 336/625 ], [ -336/625, -527/625 ] ] Display(A-A); [ [ 0, 0 ], [ 0, 0 ] ] A^0;A^-1; [ [ 1, 0 ], [ 0, 1 ] ] [ [ 3/5, 4/5 ], [ -4/5, 3/5 ] ] Display(last); [ [ 3/5, 4/5 ], [ -4/5, 3/5 ] ] Trace(A); 6/5 w:=E(5); # a primitive 5th root of unity: think exp(2*Pi/5) E(5) # lets put the 5th roots on the diagonal B:=DiagonalMat([1,w,w^2,w^3,w^4]); [ [ 1, 0, 0, 0, 0 ], [ 0, E(5), 0, 0, 0 ], [ 0, 0, E(5)^2, 0, 0 ], [ 0, 0, 0, E(5)^3, 0 ], [ 0, 0, 0, 0, E(5)^4 ] ] Display(B);DefaultFieldOfMatrix(B); [ [ 1, 0, 0, 0, 0 ], [ 0, E(5), 0, 0, 0 ], [ 0, 0, E(5)^2, 0, 0 ], [ 0, 0, 0, E(5)^3, 0 ], [ 0, 0, 0, 0, E(5)^4 ] ] CF(5) B^2; [ [ 1, 0, 0, 0, 0 ], [ 0, E(5)^2, 0, 0, 0 ], [ 0, 0, E(5)^4, 0, 0 ], [ 0, 0, 0, E(5), 0 ], [ 0, 0, 0, 0, E(5)^3 ] ] Display(B^5); [ [ 1, 0, 0, 0, 0 ], [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ] ] Trace(B); 0 # the 5th roots do sum to 0 C:=PermutationMat((1,2,3,4,5),5); [ [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0 ] ] Display(C); [ [ 0, 1, 0, 0, 0 ], [ 0, 0, 1, 0, 0 ], [ 0, 0, 0, 1, 0 ], [ 0, 0, 0, 0, 1 ], [ 1, 0, 0, 0, 0 ] ] # these two 5 by 5 matrices will generate a group Grp:=Group(B,C);; Order(Grp); 125 IsAbelian(Grp); false IsSimple(Grp); false # finally, let's look at some # storage issues; Pr; [ 2, 3, 5, 7, 11, 13, 17, 19 ] Q:=Pr; # a copy of Pr; [ 2, 3, 5, 7, 11, 13, 17, 19 ] # let's change the 3rd entry of Q Q[3]:=5000; 5000 Q;Pr; [ 2, 3, 5000, 7, 11, 13, 17, 19 ] [ 2, 3, 5000, 7, 11, 13, 17, 19 ] # what happened is that Q:=Pr means that # Q merely points to the same Gap object as Pr, so # changing Q also changes Pr; let's restore Pr Pr[3]:=5; 5 Pr; [ 2, 3, 5, 7, 11, 13, 17, 19 ] Q:=ShallowCopy(Pr);; Q;Pr; [ 2, 3, 5, 7, 11, 13, 17, 19 ] [ 2, 3, 5, 7, 11, 13, 17, 19 ] Q[3]:=5000; 5000 Q;Pr; [ 2, 3, 5000, 7, 11, 13, 17, 19 ] [ 2, 3, 5, 7, 11, 13, 17, 19 ] # so now Q points to a new portion of memory. # this is an issue whenever variable point to objects which # can be changed x:=5; 5 y:=x; 5 x;y; 5 5 x:=4; 4 x;y; 4 5 # now for some programming J:=[1..8]; # a typical index set [ 1 .. 8 ] for j in J do Print(j^2); od; # note the ; after the Print command 1491625364964 # well Gap is flexible, so we need formatting commands # the invisible character "\n" issues a new line command for j in J do Print(j, j^2, "\n"); od; 11 24 39 416 525 636 749 864 # try again for j in J do Print(j," ",j^2,"\n"); od; # note how the blank space " " appears 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 perms:=[(1,3,2,6,8)(4,5,9), (1,6)(2,7,8), (1,5,7)(2,3,8,6), > (1,8,9)(2,3,5,6,4), (1,9,8,6,3,4,7,2)];; Length(perms); # let's multiply these permutations 5 prod:=(); # an empty product equals the identity () for p in perms do > prod:=prod*p; > od; prod; # the product of the permutations (1,8,4,2,3,6,5,9) # here is the Sieve of Erathosthenes. # we'll find all primes less than 1500 # notice that n mod p is the Gap command for the remainder # upon dividing n by p 15 mod 5; 15 mod 11; 15 mod 4; 15 mod 21; 0 4 3 15 primes:=[]; # we must have an empty box in which we can put things! [ ] numbers:=[2..1500];# this is the range of all integers from 2 to 1500 [ 2 .. 1500 ] # for p in numbers do > Add(primes,p); > for n in numbers do > if n mod p = 0 then > Unbind(numbers[n-1]); > fi; > od; > od; # Length(primes); 239 # we found 239 primes; to see the last 10 for j in [1..10] do Print(primes[229+j],"\n"); od; 1451 1453 1459 1471 1481 1483 1487 1489 1493 1499 # Note: the function Unbind(numbers[n-1]) deletes # the element at position n-1 of the list `numbers' # and leaves a hole there J; [ 1 .. 8 ] Elements(J); [ 1, 2, 3, 4, 5, 6, 7, 8 ] Unbind(J[5]); J; [ 1, 2, 3, 4,, 6, 7, 8 ] # # # we can write our own functions # for example, we may simply want to abbreviate a wordy Gap command # say we want to abbreviate the # SmithNormalFormIntegerMat function # which produces elemntary divisors on the diagonal of a new matrix sm:=function(A) > return SmithNormalFormIntegerMat(A); > end; function( A ) ... end B:=[[12,24,14],[-62,106,-8]]; [ [ 12, 24, 14 ], [ -62, 106, -8 ] ] Display(B); [ [ 12, 24, 14 ], [ -62, 106, -8 ] ] sm(B); [ [ 2, 0, 0 ], [ 0, 2, 0 ] ] Display(sm(B)); [ [ 2, 0, 0 ], [ 0, 2, 0 ] ] # or suppose we want a (useless!)function that replaces each rational # number by 1 if non-negative, 10 if negative; jump:=function(x) > if x < 0 then > return 10; > else > return 1; > fi; > end; function( x ) ... end jump(19); jump(0); jump(-12/7); 1 1 10 C:=ShallowCopy(B);; Display(C); [ [ 12, 24, 14 ], [ -62, 106, -8 ] ] for j in [1..3] do > for i in [1..2] do > C[i][j]:=jump(C[i][j]); > od; > od; Display(C); [ [ 1, 1, 1 ], [ 10, 1, 10 ] ]