From 2eae9d0e4b4df6dc0e9a405ce85248def60855f9 Mon Sep 17 00:00:00 2001 From: Olexandr Konovalov <5751387+olexandr-konovalov@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:22:16 +0100 Subject: [PATCH] Add GAP syntax highlight Closes #2 --- episodes/01-command-line.md | 76 ++++++++++++++++++------------------- episodes/02-some-objects.md | 30 +++++++-------- episodes/03-func.md | 54 +++++++++++++------------- episodes/04-testing.md | 16 ++++---- episodes/05-small-groups.md | 42 ++++++++++---------- episodes/06-attributes.md | 28 +++++++------- learners/discuss.md | 22 +++++------ 7 files changed, 134 insertions(+), 134 deletions(-) diff --git a/episodes/01-command-line.md b/episodes/01-command-line.md index e035166..60b4d38 100644 --- a/episodes/01-command-line.md +++ b/episodes/01-command-line.md @@ -47,13 +47,13 @@ including this one, must be finished with a semicolon! Practice entering may wish to enter the following command to display GAP prompts and user inputs in different colours: -```source +```gap ColorPrompt(true); ``` The easiest way to start trying GAP out is as a calculator: -```source +```gap ( 1 + 2^32 ) / (1 - 2*3*107 ); ``` @@ -64,7 +64,7 @@ The easiest way to start trying GAP out is as a calculator: If you want to record what you did in a GAP session, so you can look over it later, you can enable logging with the `LogTo` function, like this. -```source +```gap LogTo("gap-intro.log"); ``` @@ -79,7 +79,7 @@ return to it in the future. A comment in GAP starts with the symbol `#` and continues to the end of the line. You can enter the following after the GAP prompt: -```source +```gap # GAP Software Carpentry Lesson ``` @@ -93,7 +93,7 @@ arrow keys to scroll the *command line history*. Repeat this until you see the formula again, then press Return (the location of the cursor in the command line does not matter): -```source +```gap ( 1 + 2^32 ) / (1 - 2*3*107 ); ``` @@ -108,7 +108,7 @@ Ctrl-A and Ctrl-E to move the cursor to the beginning and end of the line, respectively). Now press the Return key (at any position of the cursor in the command line): -```source +```gap ( 1 + 2^64 ) / (1 - 2*3*107 ); ``` @@ -124,7 +124,7 @@ the same string. If you want to store a value for later use, you can assign it to a name using `:=` -```source +```gap universe := 6*7; ``` @@ -140,7 +140,7 @@ universe := 6*7; - Finally, GAP uses `<>` to check if two things are not equal (rather than the `!=` you might have seen before). - + :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -148,7 +148,7 @@ Whitespace characters (i.e. Spaces, Tabs and Returns) are insignificant in GAP, except if they occur inside a string. For example, the previous input could be typed without spaces: -```source +```gap (1+2^64)/(1-2*3*107); ``` @@ -159,7 +159,7 @@ could be typed without spaces: Whitespace symbols are often used to format more complicated commands for better readability. For example, the following input which creates a 3×3 matrix: -```source +```gap m:=[[1,2,3],[4,5,6],[7,8,9]]; ``` @@ -171,7 +171,7 @@ We can instead write our matrix over 3 lines. In this case, instead of the full `gap>`, a partial prompt `>` will be displayed until the user finishes the input with a semicolon: -```source +```gap gap> m:=[[ 1, 2, 3 ], > [ 4, 5, 6 ], > [ 7, 8, 9 ]]; @@ -183,7 +183,7 @@ gap> m:=[[ 1, 2, 3 ], You can use `Display` to pretty-print variables, including this matrix: -```source +```gap Display(m); ``` @@ -209,7 +209,7 @@ We will explain the differences in these outputs later. Here are some examples of calling other GAP functions: -```source +```gap Factorial(100); ``` @@ -221,7 +221,7 @@ Factorial(100); (the exact width of output will depend on your terminal settings), -```source +```gap Determinant(m); ``` @@ -231,7 +231,7 @@ Determinant(m); and -```source +```gap Factors(2^64-1); ``` @@ -245,7 +245,7 @@ used as arguments of other functions, for example, the all elements of the list which satisfy the function. `IsEvenInt`, unsurprisingly, checks if an integer is even! -```source +```gap Filtered( [2,9,6,3,4,5], IsEvenInt); ``` @@ -257,7 +257,7 @@ A useful time-saving feature of the GAP command-line interfaces is completion of identifiers when the Tab key is pressed. For example, type `Fib` and then press the Tab key to complete the input to `Fibonacci`: -```source +```gap Fibonacci(100); ``` @@ -281,7 +281,7 @@ for general use. Use them with extreme care! It is important to remember that GAP is case-sensitive. For example, the following input causes an error: -```source +```gap factorial(100); ``` @@ -340,7 +340,7 @@ own computer, you can set the help viewer to the default browser. If you are running GAP on a remote machine, this (probably) will not work. (see `?WriteGapIniFile` on how to make this setting permanent): -```source +```gap SetHelpViewer("browser"); ``` @@ -358,13 +358,13 @@ This guide shows how permutations in GAP are written in cycle notation, and also shows common functions which are used with groups. Also, in some places two semi-colons are used at the end of a line. This stops GAP from showing the result of a computation. -```source +```gap a:=(1,2,3);;b:=(2,3,4);; ``` Next, let `G` be a group generated by `a` and `b`: -```source +```gap G:=Group(a,b); ``` @@ -374,7 +374,7 @@ Group([ (1,2,3), (2,3,4) ]) We may explore some properties of `G` and its generators: -```source +```gap Size(G); IsAbelian(G); StructureDescription(G); Order(a); ``` @@ -391,7 +391,7 @@ the entry from the Tutorial does not seem relevant, but the entry from the Reference manual is. It also explains the difference between using `AsSSortedList` and `AsList`. So, this is the list of elements of `G`: -```source +```gap AsList(G); ``` @@ -406,7 +406,7 @@ course, we may use the command line history to restore the last command, edit it and call again. But instead, we will use `last` which is a special variable holding the last result returned by GAP: -```source +```gap elts:=last; ``` @@ -418,7 +418,7 @@ elts:=last; This is a list. Lists in GAP are indexed from 1. The following commands are (hopefully!) self-explanatory: -```source +```gap gap> elts[1]; elts[3]; Length(elts); ``` @@ -439,14 +439,14 @@ gap> elts[1]; elts[3]; Length(elts); - Not required to contain objects of the same type - See more in [GAP Tutorial: Lists and Records](https://www.gap-system.org/Manuals/doc/tut/chap3.html) - + :::::::::::::::::::::::::::::::::::::::::::::::::: Many functions in GAP refer to `Set`s. A set in GAP is just a list that happens to have no repetitions, no holes, and elements in increasing order. Here are some examples: -```source +```gap gap> IsSet([1,3,5]); IsSet([1,5,3]); IsSet([1,3,3]); ``` @@ -463,7 +463,7 @@ here. A `for` loop in GAP allows you to do something for every member of a collection. The general form of a `for` loop is: -```source +```gap for val in collection do od; @@ -471,7 +471,7 @@ od; For example, to find the average order of our group `G` we can do. -```source +```gap s:=0;; for g in elts do s := s + Order(g); @@ -487,7 +487,7 @@ Actually, we can just directly loop over the elements of `G` (in general GAP will let you loop over most types of object). We have to switch to using `Size` instead of `Length`, as groups don't have a length! -```source +```gap s:=0;; for g in G do s := s + Order(g); @@ -502,7 +502,7 @@ s/Size(G); There are other ways of looping. For example, we can instead loop over a range of integers, and accept `elts` like an array: -```source +```gap s:=0;; for i in [ 1 .. Length(elts) ] do s := s + Order( elts[i] ); @@ -517,7 +517,7 @@ s/Length(elts); However, often there are more compact ways of doing things. Here is a very short way: -```source +```gap Sum( List( elts, Order ) ) / Length( elts ); ``` @@ -551,7 +551,7 @@ and returns the value of the expression `e`. Here are some examples: - finding all elements of `G` with no fixed points: -```source +```gap Filtered( elts, g -> NrMovedPoints(g) = 4 ); ``` @@ -561,7 +561,7 @@ Filtered( elts, g -> NrMovedPoints(g) = 4 ); - finding a permutation in `G` that conjugates (1,2) to (2,3) -```source +```gap First( elts, g -> (1,2)^g = (2,3) ); ``` @@ -571,7 +571,7 @@ First( elts, g -> (1,2)^g = (2,3) ); Let's check this (remember that in GAP permutations are multiplied from left to right!): -```source +```gap (1,2,3)^-1*(1,2)*(1,2,3)=(2,3); ``` @@ -581,7 +581,7 @@ true - checking whether all elements of `G` move the point 1 to 2: -```source +```gap ForAll( elts, g -> 1^g <> 2 ); ``` @@ -591,7 +591,7 @@ false - checking whether there is an element in `G` which moves exactly two points: -```source +```gap ForAny( elts, g -> NrMovedPoints(g) = 2 ); ``` @@ -606,7 +606,7 @@ false - `Filtered( elts, g -> 2^g = 2 );` - `Filtered( elts, g -> (1,2)^g = (1,2) );` - + :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/02-some-objects.md b/episodes/02-some-objects.md index 8c00a5d..9e7c054 100644 --- a/episodes/02-some-objects.md +++ b/episodes/02-some-objects.md @@ -31,7 +31,7 @@ of objects, but this is beyond the scope of this lesson!). Some other simple objects are floats, cyclotomics and finite field elements: -```source +```gap 1.15; Float(1232/3456567); ``` @@ -40,7 +40,7 @@ Some other simple objects are floats, cyclotomics and finite field elements: 0.000356423 ``` -```source +```gap E(4); E(4)^2; E(6); ``` @@ -50,7 +50,7 @@ E(4) -E(3)^2 ``` -```source +```gap AsList(GF(2)); Z(5); Z(5)^4; ``` @@ -65,7 +65,7 @@ Another type of composite objects is **records**. While a list contains subobjec by their positions in the list, a record contains subobjects, called *record components*, which are indexed by their names. Elements of a record are accessed with `.` -```source +```gap date:= rec(year:= 2015, month:= "Nov", day:= 17); ``` @@ -73,7 +73,7 @@ date:= rec(year:= 2015, month:= "Nov", day:= 17); rec( day := 17, month := "Nov", year := 2015 ) ``` -```source +```gap date.year; ``` @@ -81,7 +81,7 @@ date.year; 2015 ``` -```source +```gap date.time:= rec(hour:= 14, minute:= 55, second:= 12); ``` @@ -89,7 +89,7 @@ date.time:= rec(hour:= 14, minute:= 55, second:= 12); rec( hour := 14, minute := 55, second := 12 ) ``` -```source +```gap date; ``` @@ -98,7 +98,7 @@ rec( day := 17, month := "Nov", time := rec( hour := 14, minute := 55, second := 12 ), year := 2015 ) ``` -```source +```gap RecNames(date); ``` @@ -111,7 +111,7 @@ specially by GAP, a string is really just a list of characters, and any function which takes a list will also take a string. In contrast, characters are simple objects like integers. -```source +```gap gap> w:="supercalifragilisticexpialidocious"; Length(w); ``` @@ -122,7 +122,7 @@ gap> w:="supercalifragilisticexpialidocious"; Length(w); Strings are denoted by double quotes, and characters by single ones. -```source +```gap gap> "s" in w; 's' in w; IsSubset(w,"s"); IsSubset(w,['s','f']); ['c','a','t'] = "cat"; ``` @@ -136,7 +136,7 @@ true Note that -```source +```gap gap> PositionSublist(w,"sf"); PositionSublist(w,"fr"); ``` @@ -148,7 +148,7 @@ fail Be careful! Some operations may create a new list, while others are destructive. For example: -```source +```gap gap> SortedList(w); w; ``` @@ -159,7 +159,7 @@ gap> SortedList(w); w; but -```source +```gap gap> Sort(w); w; ``` @@ -169,7 +169,7 @@ gap> Sort(w); w; Which letter occurs in "supercalifragilisticexpialidocious" most often? -```source +```gap gap> c := Collected(w); ``` @@ -179,7 +179,7 @@ gap> c := Collected(w); [ 't', 1 ], [ 'u', 2 ], [ 'x', 1 ] ] ``` -```source +```gap gap> k := Maximum( List( c, v -> v[2] ) ); Filtered( c, v -> v[2] = 7 ); ``` diff --git a/episodes/03-func.md b/episodes/03-func.md index 96fc790..8ad6163 100644 --- a/episodes/03-func.md +++ b/episodes/03-func.md @@ -25,7 +25,7 @@ divided by the order of the group). We begin with a very straightforward approach, iterating over all elements of the group in question: -```source +```gap S:=SymmetricGroup(10); ``` @@ -33,7 +33,7 @@ S:=SymmetricGroup(10); Sym( [ 1 .. 10 ] ) ``` -```source +```gap sum:=0; ``` @@ -41,7 +41,7 @@ sum:=0; 0 ``` -```source +```gap for g in S do sum := sum + Order(g); od; @@ -56,7 +56,7 @@ Now assume that we would like to save this fragment of GAP code and later repeat this calculation for some other groups. We may even reformat it to fit it into one line and use a double semicolon to suppress the output of `sum`: -```source +```gap sum:=0;; for g in S do sum := sum + Order(g); od; sum/Size(S); ``` @@ -69,7 +69,7 @@ But here we see the first inconvenience: the code expects that the group in ques must be stored in a variable named `S`, so either we have to reset `S` each time, or we need to edit the code: -```source +```gap S:=AlternatingGroup(10); ``` @@ -77,7 +77,7 @@ S:=AlternatingGroup(10); Alt( [ 1 .. 10 ] ) ``` -```source +```gap sum:=0;; for g in S do sum := sum + Order(g); od; sum/Size(S); ``` @@ -99,7 +99,7 @@ sum:=0;; for g in S do sum := sum + Order(g); od; sum/Size(S); by line. If you have a long file with many commands, and a syntax error is in line *N*, this error will be reported only when GAP completes the evaluation of all preceding lines, and that might be quite time-consuming. - + :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -116,7 +116,7 @@ into functions: The following function takes an argument `G` and computes the average order of its elements: -```source +```gap AvgOrdOfGroup := function(G) local sum, g; sum := 0; @@ -133,7 +133,7 @@ function( G ) ... end Now we can apply it to another group, passing the group as an argument: -```source +```gap A:=AlternatingGroup(10); AvgOrdOfGroup(A); time; ``` @@ -154,7 +154,7 @@ Using a text editor (for example, the one that you may have used for previous Software Carpentry lessons), create a text file called `avgord.g` containing the following function code and comments (a good chance to practise using them!): -```source +```gap ##################################################################### # # AvgOrdOfGroup(G) @@ -175,7 +175,7 @@ end; Now start a new GAP session and create another group, for example `MathieuGroup(11)`: -```source +```gap M11:=MathieuGroup(11); ``` @@ -186,7 +186,7 @@ Group([ (1,2,3,4,5,6,7,8,9,10,11), (3,7,11,8)(4,10,5,6) ]) Clearly, `AvgOrdOfGroup` is not defined in this session, so an attempt to call this function results in an error: -```source +```gap AvgOrdOfGroup(M11); ``` @@ -198,14 +198,14 @@ not in any function at line 2 of *stdin* To be available, it should first be loaded using the function `Read`. Below we assume that the file is in the current directory, so no path is needed. -```source +```gap Read("avgord.g"); ``` This loads the file into GAP, and the function `AvgOrdOfGroup` is now available: -```source +```gap AvgOrdOfGroup(M11); ``` @@ -224,19 +224,19 @@ overwritten. **Never ignore the warnings!** For example, let us edit the file and replace the line -```source +```gap return sum/Size(G); ``` by the line with a deliberate syntax error: -```source +```gap return Float(sum/Size(G); ``` Now read this file with -```source +```gap Read("avgord.g"); ``` @@ -251,7 +251,7 @@ return Float(sum/Size(G); Since there was an error, the `AvgOrdOfGroup` function in our session was not redefined, and remains the same as last time it was successfully read: -```source +```gap Print(AvgOrdOfGroup); ``` @@ -267,7 +267,7 @@ end Now correct the error by adding the missing closing bracket, read the file again and recalculate the average order of an element for `M11`: -```source +```gap Read("avgord.g"); AvgOrdOfGroup(M11); ``` @@ -282,7 +282,7 @@ could happen, first edit the file to roll back the change in the type of the result (so it will return a rational instead of a float), and then comment out two lines as follows: -```source +```gap AvgOrdOfGroup := function(G) # local sum, g; # sum := 0; @@ -295,7 +295,7 @@ end; Now, when you read the file, you will see warnings: -```source +```gap Read("avgord.g"); ``` @@ -326,7 +326,7 @@ more detail: The function is now redefined, as we can see from its output (or can inspect with `PageSource(AvgOrdOfGroup)` which will also display any comments): -```source +```gap Print(AvgOrdOfGroup); ``` @@ -341,7 +341,7 @@ end but an attempt to run it results in a break loop: -```source +```gap AvgOrdOfGroup(M11); ``` @@ -358,7 +358,7 @@ which you can exit using `quit;`. What happens next demonstrates how things may go wrong: -```source +```gap sum:=2^64; g:=[1]; ``` @@ -367,7 +367,7 @@ sum:=2^64; g:=[1]; [ 1 ] ``` -```source +```gap AvgOrdOfGroup(M11); ``` @@ -375,7 +375,7 @@ AvgOrdOfGroup(M11); 18446744073709604747/7920 ``` -```source +```gap sum; g; ``` @@ -388,7 +388,7 @@ Now, before reading the next part of the lesson, please revert the last change by uncommenting the two commented lines, so that you have initial version of `AvgOrdOfGroup` in the file `avgord.g` again: -```source +```gap AvgOrdOfGroup := function(G) local sum, g; sum := 0; diff --git a/episodes/04-testing.md b/episodes/04-testing.md index 829aa4f..edd5364 100644 --- a/episodes/04-testing.md +++ b/episodes/04-testing.md @@ -49,7 +49,7 @@ GAP test files are just text files, but the common practice is to name them with the extension `.tst`. Now create the file `avgord.tst` in the current directory (to avoid typing the full path) with the following content: -```source +```gap # tests for average order of a group element # permutation group @@ -70,7 +70,7 @@ To run the test, one should use the function `Test`, as documented [here](https://www.gap-system.org/Manuals/doc/ref/chap7.html#X87712F9D8732193C). For example (assuming that the function `AvgOrdOfGroup` is already loaded): -```source +```gap Test("avgord.tst"); ``` @@ -90,7 +90,7 @@ Instead, we will now add more groups to `avgord.tst`, to demonstrate that the code also works with other kinds of groups, and to show various ways of combining commands in the test file: -```source +```gap # tests for average order of a group element # permutation group @@ -129,7 +129,7 @@ gap> AvgOrdOfGroup(SL(2,5)); Let us test the extended version of the test again and check that it works: -```source +```gap Test("avgord.tst"); ``` @@ -143,7 +143,7 @@ know the orders of conjugacy classes of elements and their representatives. The following code, which we add into `avgord.g`, reads into GAP and redefines `AvgOrdOfGroup` without any syntax errors: -```source +```gap AvgOrdOfGroup := function(G) local cc, sum, c; cc:=ConjugacyClasses(G); @@ -157,7 +157,7 @@ end; but when we run the test, here comes a surprise! -```source +```gap Read("avgord.g"); Test("avgord.tst"); ``` @@ -201,7 +201,7 @@ false Indeed, we made a typo (deliberately) and replaced `Size(c)` by `Size(cc)`. The correct version of course should look as follows: -```source +```gap AvgOrdOfGroup := function(G) local cc, sum, c; cc:=ConjugacyClasses(G); @@ -216,7 +216,7 @@ end; Now we will fix this in `avgord.g`, and read and test it again to check that the tests run correctly. -```source +```gap Read("avgord.g"); Test("avgord.tst"); ``` diff --git a/episodes/05-small-groups.md b/episodes/05-small-groups.md index 51df5b0..0aab5c4 100644 --- a/episodes/05-small-groups.md +++ b/episodes/05-small-groups.md @@ -65,13 +65,13 @@ gap> List(last,IdGroup); We would like to use our own testing function, which we will create here, using inline notation (available for one-argument functions): -```source +```gap TestOneGroup := G -> IsInt( AvgOrdOfGroup(G) ); ``` Now try, for example -```source +```gap List([TrivialGroup(),Group((1,2))],TestOneGroup); ``` @@ -79,7 +79,7 @@ List([TrivialGroup(),Group((1,2))],TestOneGroup); [ true, false ] ``` -```source +```gap gap> AllSmallGroups(Size,24,TestOneGroup,true); ``` @@ -102,7 +102,7 @@ It creates one group at a time, checks the desired property, and returns as soon as an example is discovered. Otherwise it returns `fail` which is a special kind of boolean variable in GAP. -```source +```gap TestOneOrderEasy := function(n) local i; for i in [1..NrSmallGroups(n)] do @@ -116,7 +116,7 @@ end; For example, -```source +```gap TestOneOrderEasy(1); ``` @@ -124,7 +124,7 @@ TestOneOrderEasy(1); [ 1, 1 ] ``` -```source +```gap TestOneOrderEasy(24); ``` @@ -139,7 +139,7 @@ fail - Use iteration over `[1..NrSmallGroups(n)]` as shown in the function above - Use `IdsOfAllSmallGroups` which accepts same arguments as `AllSmallGroups` but returns ids instead of groups. - + :::::::::::::::::::::::::::::::::::::::::::::::::: @@ -149,7 +149,7 @@ of our testing function prints additional information about the number of the group being tested. It also supplies the testing function as an argument (why do you think this is better?). -```source +```gap TestOneOrder := function(f,n) local i, G; for i in [1..NrSmallGroups(n)] do @@ -167,7 +167,7 @@ end; For example, -```source +```gap TestOneOrder(TestOneGroup,64); ``` @@ -182,7 +182,7 @@ The next step is to integrate `TestOneOrder` into a function which will test all orders from 2 to `n` and stop as soon as it finds an example of a group with the average order of an element being an integer: -```source +```gap TestAllOrders:=function(f,n) local i, res; for i in [2..n] do @@ -197,7 +197,7 @@ end; It reports that there is such a group of order 105: -```source +```gap TestAllOrders(TestOneGroup,128); ``` @@ -225,7 +225,7 @@ To explore it further, we can get its `StructureDescription` (see [here](https://www.gap-system.org/Manuals/doc/ref/chap39.html#X87BF1B887C91CA2E) for the explanation of the notation it uses): -```source +```gap G:=SmallGroup(105,1); AvgOrdOfGroup(G); StructureDescription(G); ``` @@ -237,7 +237,7 @@ G:=SmallGroup(105,1); AvgOrdOfGroup(G); StructureDescription(G); and then convert it to a finitely presented group to see its generators and relators: -```source +```gap H:=SimplifiedFpGroup(Image(IsomorphismFpGroup(G))); RelatorsOfFpGroup(H); ``` @@ -251,7 +251,7 @@ RelatorsOfFpGroup(H); Now we want to try larger groups, starting from order 106 (we check that the other group of order 105 possesses no such property) -```source +```gap List(AllSmallGroups(105),AvgOrdOfGroup); ``` @@ -262,7 +262,7 @@ List(AllSmallGroups(105),AvgOrdOfGroup); With a little modification, we add an extra argument specifying the order from which to start: -```source +```gap TestRangeOfOrders:=function(f,n1,n2) local n, res; for n in [n1..n2] do @@ -277,7 +277,7 @@ end; But now we call it with -```source +```gap TestRangeOfOrders(TestOneGroup,106,256); ``` @@ -302,7 +302,7 @@ conjugacy class of a non-identity element of the group is divisible by *p*; therefore, the average order of a group element may not be an integer. Therefore, *p*\-groups can be excluded from calculation. So, the new version of the code is -```source +```gap TestRangeOfOrders:=function(f,n1,n2) local n, res; for n in [n1..n2] do @@ -319,7 +319,7 @@ end; and using it we are able to discover a group of order 357 with the same property: -```source +```gap gap> TestRangeOfOrders(TestOneGroup,106,512); ``` @@ -353,7 +353,7 @@ we address here is to be able to switch the levels of verbosity of the output without error-prone approach of walking through the code and commenting `Print` statements in and out. It is achieved by creating an info class: -```source +```gap gap> InfoSmallGroupsSearch := NewInfoClass("InfoSmallGroupsSearch"); ``` @@ -368,7 +368,7 @@ This level could be changed to `n` using the command `SetInfoLevel( InfoSmallGroupsSearch, n);`. See actual calls of `Info` in the code below: -```source +```gap TestOneOrderVariadic := function(f,n,r...) local n1, n2, i; @@ -480,7 +480,7 @@ gap> SetInfoLevel( InfoSmallGroupsSearch, INFO_SSS); - Can you find another group with this property in the Small Groups Library (of order not equal to 1536)? - + :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/episodes/06-attributes.md b/episodes/06-attributes.md index 323d518..48bbbfa 100644 --- a/episodes/06-attributes.md +++ b/episodes/06-attributes.md @@ -35,7 +35,7 @@ be calculated only once, as the next time it will return the same value. However, as we see from the runtimes below, each new call of `AvgOrdOfGroup` will repeat the same computation again, with slightly varying runtime: -```source +```gap A:=AlternatingGroup(10); ``` @@ -43,7 +43,7 @@ A:=AlternatingGroup(10); Alt( [ 1 .. 10 ] ) ``` -```source +```gap AvgOrdOfCollection(A); time; AvgOrdOfCollection(A); time; ``` @@ -65,7 +65,7 @@ and unreadable. On the other hand, GAP has the notion of an *attribute* -- a data structure that is used to accumulate information that an object learns about itself during its lifetime. Consider the following example: -```source +```gap G:=Group([ (1,2,3,4,5,6,7,8,9,10,11), (3,7,11,8)(4,10,5,6) ]); gap> NrConjugacyClasses(G);time;NrConjugacyClasses(G);time; ``` @@ -82,7 +82,7 @@ In this case, the group `G` has 10 conjugacy classes, and it took 39 ms to establish that in the first call. The second call has zero cost since the result was stored in `G`, since `NrConjugacyClasses` is an attribute: -```source +```gap NrConjugacyClasses; ``` @@ -96,7 +96,7 @@ Since we already have a function `AvgOrdOfCollection` which does the calculation, the simplest way to turn it into an attribute is as follows: -```source +```gap AverageOrder := NewAttribute("AverageOrder", IsCollection); InstallMethod( AverageOrder, "for a collection", [IsCollection], AvgOrdOfCollection); ``` @@ -110,7 +110,7 @@ Now we may check that subsequent calls of `AverageOrder` with the same argument are performed at zero cost. In this example the time is reduced from more than 16 seconds to zero: -```source +```gap S:=SymmetricGroup(10);; AverageOrder(S); time; AverageOrder(S); time; ``` @@ -137,7 +137,7 @@ based on the type of all arguments. To illustrate this, we will now install a method for `AverageOrder` for a group: -```source +```gap InstallMethod( AverageOrder, [IsGroup], AvgOrdOfGroup); ``` @@ -145,7 +145,7 @@ If you apply it to a group whose `AverageOrder` has already been computed, nothi will happen, since GAP will use the stored value. However, for a newly created group, this new method will be called: -```source +```gap S:=SymmetricGroup(10);; AverageOrder(S); time; AverageOrder(S); time; ``` @@ -168,13 +168,13 @@ S:=SymmetricGroup(10);; AverageOrder(S); time; AverageOrder(S); time; - `ApplicableMethod` in combination with `PageSource` may point you to the source code with all the comments. - + :::::::::::::::::::::::::::::::::::::::::::::::::: A *property* is a boolean-valued attribute. It can be created using `NewProperty` -```source +```gap IsIntegerAverageOrder := NewProperty("IsIntegerAverageOrder", IsCollection); ``` @@ -183,7 +183,7 @@ Observe that it is never necessary to create a function first and then install it as a method. The following method installation instead creates a new function as one of its arguments: -```source +```gap InstallMethod( IsIntegerAverageOrder, "for a collection", [IsCollection], @@ -210,7 +210,7 @@ the average order for large permutation groups via conjugacy classes of elements, for pc groups from the Small Groups Library it could be faster to iterate over their elements than to calculate conjugacy classes: -```source +```gap l:=List([1..1000],i->SmallGroup(1536,i));; List(l,AvgOrdOfGroup);;time; ``` @@ -218,7 +218,7 @@ l:=List([1..1000],i->SmallGroup(1536,i));; List(l,AvgOrdOfGroup);;time; 56231 ``` -```source +```gap l:=List([1..1000],i->SmallGroup(1536,i));; List(l,AvgOrdOfCollection);;time; ``` @@ -235,7 +235,7 @@ l:=List([1..1000],i->SmallGroup(1536,i));; List(l,AvgOrdOfCollection);;time; - Estimate practical boundaries of its feasibility. Can you find an example of a pc group where iterating is slower than calculating conjugacy classes? - + :::::::::::::::::::::::::::::::::::::::::::::::::: diff --git a/learners/discuss.md b/learners/discuss.md index 4cd6291..5877e27 100644 --- a/learners/discuss.md +++ b/learners/discuss.md @@ -85,22 +85,22 @@ permalink: /discuss/ - Don't ask for more than you need as this may have performance implications. For example: - + - If the property is an invariant of a conjugacy class (of elements or of subgroups), you may be interested only at looking at the representatives of conjugacy classes. - + - If you are interested in a list of elements of a collection, without a particular order, use `AsList` instead of `AsSSortedList`. - + - Do not calculate conjugacy classes of all subgroups, if e.g. you are interested only in normal or maximal subgroups - there are special methods to compute them. - + - If you are looking for *p*\-subgroups, first you may calculate a Sylow *p*\-subgroup of a group, and then look at its subgroups and their conjugates. - + - Representation matters: it may be worth to convert a group from fp group to an isomorphic pc group or a permutation group to use faster methods. @@ -111,11 +111,11 @@ permalink: /discuss/ - Subscribe to the **[GAP Forum](https://www.gap-system.org/Contacts/Forum/forum.html)**. - If you need help, choose among these three options, dependently on the question: - + - ask questions in the [GAP Forum](https://www.gap-system.org/Contacts/Forum/forum.html) - + - send them to the [GAP Support](https://www.gap-system.org/Contacts/People/supportgroup.html) - + - post them at the [Mathematics Q\&A site](https://math.stackexchange.com/questions/tagged/gap?sort=frequent&pageSize=50) ## Contributing to GAP @@ -142,7 +142,7 @@ permalink: /discuss/ - This is a simples approach to call GAP from a shell script. Create the shell script called `check-one-order.sh` with the following content: -```source +```gap #!/bin/sh gap -r -b -q avgord.g << EOI @@ -154,7 +154,7 @@ EOI and make it executable using `chmod u+x check-one-order.sh`. Now you may call it as follows: -```source +```gap $ ./check-one-order.sh 24 ``` @@ -162,7 +162,7 @@ $ ./check-one-order.sh 24 fail ``` -```source +```gap $ ./check-one-order.sh 105 ```