Programming in SageMath
This part of the tutorial covers the essential programming tools that you need to use in order to do more advanced mathematics. The first chapter, on SageMath objects, is essential before moving on to study mathematical structures. The second chapter is more specifically about programming: conditionals and iterative loops, creating your own commands and saving your work. It is not necessary for basic computations with mathematical structures, but becomes invaluable for doing in-depth work. The third chapter explains how to interact with some of the main mathematical software packages included in SageMath. Finally there is a brief chapter on interactive use of SageMath.
Objects
SageMath Objects |
---|
Universes and coercion |
Universes and Coercion |
Universes |
A key concept in SageMath is the universe of an object. The most effective way to gain a familiarity with universes and the related concept, coercion, is to see a few examples. We begin with the most common universes: the integers, and the rational, real and complex numbers. |
ZZ, QQ, RR, CC |
In SageMath, |
|
|
|
|
|
|
|
|
in |
We can check if a given objects live in a universe using the |
|
|
|
|
|
|
|
|
|
|
The letter |
|
|
|
|
|
|
|
|
parent |
To directly check which universe a number is in, we use the .parent function. |
SageMath will choose the simplest universe for each number. : |
|
|
|
|
|
|
|
|
Another important universe is the Symbolic Ring. You might think that |
or π would have parent RR, the real numbers, while I would be in CC. |
But RR and CC have finite precision, and these numbers satisfy formulas that make them special, for example |
|
|
|
|
|
|
Coercion, Coercion; implicit |
We often perform operations with elements from different universes as long as there is some sort of natural conversion that can be done to both elements so that they live in the same universe. For instance, when we compute 1 + 1/2 = 3/2, we implicitly convert 1 from the Integer universe to the universe of rational numbers, before performing the operation. This conversion is often so natural that we don't even think about it and, luckily for you, SageMath does many of these conversions without you having to worry about them either. : |
|
|
|
|
|
|
SageMath's treatment of symbolic constants like |
|
|
|
|
SageMath will always choose the universe which offers the most precision, and the same will be true for other symbolic constants like |
|
|
|
|
|
|
|
|
Coercion; explicit |
What if we want to convert a number from a universe to another? Luckily, we can easily accomplish that through a process called coercion. We coerce a number into another universe, if it makes sense, by applying the parent structure to the object like it was a function. For example: : |
|
|
|
|
|
|
|
|
And in case we try to make some nonsensical conversions, SageMath will raise a |
|
|
|
|
|
|
|
Exercises: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Booleans |
Booleans |
bool, True, False |
Another important universe is the Booleans. The Boolean universe is just known as bool in SageMath, and it contains just two elements |
|
|
not |
There are several logical operations on Booleans (i.e. operations lke and, or on |
|
|
|
|
and, or |
Suppose we want to combine two Booleans X and Y. To accomplish that, we will use |
|
|
|
The following example will show exactly that. : |
|
|
|
|
|
|
|
|
Above we have a list of truth statements. To control their order of evaluation, we can use parentheses. : |
|
|
|
|
In the first example (True |
Another important operator on Booleans is the exclusive or operator, represented by |
|
|
|
|
|
|
== |
To check if two objects are equal we use the == operator. |
The result is a Boolean: |
|
|
|
|
|
|
!=, <> |
Please notice that we used two equal signs, not one! |
To check if two things are not equal, we have two options: The |
|
|
|
|
|
|
<, <=, >= |
If two objects belong to a universe that has an ordering, then we may compare two elements of the universe using < and > and get a Boolean output. |
Additionally, we use |
|
|
|
|
|
|
|
|
|
|
|
|
Exercises: |
|
|
|
|
|
|
|
|
|
Variables |
Variables |
You should be familiar with " |
The term 'variable', can hold different meanings. For instance, in computer programming, a 'variable' is a space in memory used to store and retrieve a certain piece of information. In mathematics, a variable such as x is a quantity with indeterminate value: a symbol that we can manipulate with the same rules of arithmetic that are applied to numbers. |
In SageMath, both usages are present. We will use the term variable for the computer programming variable and symbolic variable for the mathematical variable. |
Variables; symbolic |
SageMath initializes the Symbolic Ring to have one symbolic variable, |
|
|
|
|
var |
If we need another symbolic variable, we have to declare it, using the |
|
|
|
|
|
|
|
|
|
Variables; assignment |
Now, let's look at variables, which are used to store a particular number. : |
|
|
|
|
|
We use an |
SageMath allows us to re-assign a different value to a variable. : |
|
|
|
|
|
|
The order of operations in SageMath allows us to reference a variable while assigning it a new value. For instance, we can increment the variable |
|
|
|
|
SageMath also offers us a convenient way to assign values to multiple variables at once. : |
|
|
|
|
|
Additionally, we can display a sequence of variables using commas. : |
|
|
|
If we are assigning several variables at a time, and for some reason we wish to skip a value on the right-hand side, we may use an underscore on the left hand side. For example, : |
|
|
|
|
|
|
|
|
There is also a quick way to initialize two variables with the same value. We do this by just chaining together the assignment. : |
|
|
|
|
|
restore, variables; restore |
When you define either a variable or a symbolic variable, it will stay in memory until you quit your session. Sometimes we would like to restore a variable back to its default value. We do this with the |
|
|
|
|
|
|
|
|
|
|
reset, variables;reset |
You can reset the entire environment to its defaults by running the |
|
|
|
|
|
|
|
|
|
|
|
variables; deleting, del |
And finally if you really want the variable obliterated, you can use the sledgehammer of memory management, the |
|
|
|
|
|
|
Exercises: |
|
|
|
|
|
|
|
|
|
|
|
|
|
Lists |
list, list; definition |
A list is an ordered collection of objects. The elements of a list are indexed by the integers, starting with 0. Here is a quick example of how to construct a list and access its elements. : |
|
|
|
|
|
|
|
|
|
|
|
Notice how we access the elements: though 2 is the first element of the list |
list; length, len |
The |
|
|
|
|
Note that a list of length 5 is indexed from 0 to 4. |
Lists can contain numbers from any universe, or even " |
|
|
|
|
|
We can even have lists of lists! : |
|
|
|
|
|
To access a particular element within our list of lists we chain their indices. For example, to access the |
|
|
Where we read M[2][1] as "Access the element at index 1 within the list with index 2 " in M . |
Note that |
list; slice, slices |
Slicing and Indexing |
Probably the nicest feature of lists in Python, and thus SageMath, is the slice notation. Let's suppose you have the following list: : |
|
|
|
and you would like to access the sub-list |
|
|
We use |
By leaving the last index blank, the slice will extend to the end of the list. Similarly, when the first index is left blank the slice will start at the beginning of the list. : |
|
|
|
|
By leaving both indices blank, we get a copy of the entire list. : |
|
|
Slices also can use negative indices. When a negative number is used the position is measured relative to the end (or beginning) of the list. For example: : |
|
|
|
|
The first ends the slice two elements before the end of the list, while the second begins the slice at this same position. And like expected, we can use two negative indices to take slices relative to the last element of a list. : |
|
|
|
|
You should note that the last slice is empty since the beginning of the list is the same position as the end. |
list; index, index |
If we wish to know the index of an element, we use the |
|
|
|
|
|
|
|
|
count, list; count |
We can also count the number of times that an element occurs in a list. : |
|
|
Creating |
Since they are used rather frequently, SageMath offers a convenient way to create lists of consecutive integers. : |
|
|
|
|
|
|
In the first two examples it is quite clear what is happening. In the last example above, however, it is a bit trickier. If we input |
|
|
|
|
|
|
Additionally, we can use this construction method with some of SageMath's symbolic constants such as |
|
|
Modifying lists |
sort, list;sort |
Sorting the list |
|
|
|
|
|
The |
|
|
|
|
|
|
|
|
|
We may alter the elements of a list as follows: : |
|
|
|
|
In "programming vernacular", data-types that can be changed in place are |
called mutable. |
Lists are mutable, but some data types in SageMath are not. |
list; append, append |
To add an element to the end of a list, we use the |
|
|
|
|
list; extend, extend |
Similarly, we may use the |
|
|
|
|
list; concatenation |
It is, perhaps, simpler to use the |
|
|
|
|
remove, list;remove |
If we wish to remove an element from a list, we use the meth:.remove method. : |
|
|
|
|
Note that a list may contain the same element more than once; |
|
|
|
|
|
|
|
Operations on a List |
sum, prod |
If your lists contain elements where it makes sense, the |
|
|
|
|
|
where |
|
|
The sum and product commands are defined on lists where the arithmetic make sense and will complain rather loudly when it doesn't. : |
|
|
|
|
zip, list; zip |
Concatenation isn't the only way which we can join together the elements of two lists. One useful tool is the |
|
|
When the lists aren't of the same length, |
|
|
|
|
map, lists; map |
Another useful command when dealing with lists is |
|
|
|
|
|
|
.map is often used in functional programming. For more on |
this style of programming with python see the Python Documentation. |
Exercises: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Sets |
Set |
A Set in SageMath is a data type which behaves a lot like a mathematical set and it differs from a list in a few key ways: |
|
|
To see an example of that last point, we will construct a Set by converting a list into a set. : |
|
|
|
|
Set; cardinality,cardinality |
To find the size of a Set we will use the |
|
|
in |
Testing for membership can be done easily by using the |
|
|
|
|
Set; union, Set; intersection, Set; difference, Set; symmetric difference, union, intersection, set difference, symmetric difference |
All of the usual set operations: |
|
|
|
|
|
|
|
|
|
|
|
|
|
Set; subsets, subsets |
Use the .subsets method to construct the subsets of a set, |
or to construct the subsets with a specified number of elements. |
Notice that the |
|
|
|
|
|
|
|
|
|
|
Exercises: |
|
|
|
|
|
|
Strings |
string |
To construct a string in SageMath we may use single or double quotes. : |
|
|
|
|
|
Note the difference between asking for the value of |
|
|
|
|
|
strings; len , len |
You can find the length of a string using the |
|
|
|
strings; concatenation, concatenation of strings |
Just like with lists, we can concatenate strings just by adding them together. : |
|
|
strings; split, split |
and we can separate a list by using the |
|
|
which divides the string into a list of words. We can divide a list using different characters as separators. For example we can get a list from the following comma separated values. : |
|
|
|
map, split |
We can use the |
|
|
You should note how the output above differs from what we get when we use only the |
|
|
The list directly above contains strings which represent numbers. We must convert those strings into what we need in order to actually use them. |
strings; join, joining strings |
The opposite of splitting up a string into a list is the joining of elements of a list. We do this with the |
|
|
|
Just like when I split a sting, I can join a list using a different separating value than just a space. I do so by supplying an optional second argument to the |
|
|
Exercises: |
|
|
|
|
|
|
================= |
Programming Tools |
SageMath syntax is based on the widely-used language Python, and thereby inherits Python's compact and very readable style. In this chapter we cover the syntax for the essentials of programming in Python. For more complex issues we provide links to other resources.
You should be familiar with
solving_equations_inequalities
,booleans
, andvariables
conditionals, if statement
A conditional statement is what we use when we want our code to make decisions. For example, suppose we want to divide a number by 2 only if it is even. We can do this in SageMath by using an .if
statement. :
sage: n=44
sage: if n%2 == 0:
....: print n/2
....:
22
sage: n=37
sage: if n%2 == 0:
....: print n/2
....:
sage:
For n=44
, the condition is met and the .print
command is executed. Conversely, for n=37
, nothing will happen since the condition has not been met. Most of what programming is is the skillful application of simple statements like this.
Unlike some other languages, SageMath is picky about indentation, a practice it inherits from Python. Instead of using some kind of punctuation to denote the beginning and ending of a block of code, SageMath uses indentation (notice though that we do need a colon after the condition is written). All of the code to be run under a certain condition must be at the same level of indentation. This might take some time to get used to, but it produces neat, organized code that is often easier to read.
elif, if-else statement
At times, we may wish to check whether our expression satisfies more than one condition. To do so, use the .elif
statement, which is short for else if. :
sage: m=31
sage: if m%3==0:
....: print m/3
....: elif m%3==1:
....: print (m-1)/3
....:
10
Notice that we return to the same level of indentation for .elif
as was used for .if
. We may use as many elifs as we desire. The tests are evaluated in order and once the first one is met, the associated code is executed and SageMath will leave the entire conditional. For a simple example, consider the following: :
sage: r=55
sage: if 11.divides(r):
....: print 11
....: elif r==55:
....: print 55
....:
11
Here both conditions are met, but only the code associated with the first condition is actually executed. Understanding how conditionals are executed is important to controlling the flow of your program.
There is also a subtle shortcut that we used in the previous example. 11.divides(r)
already returns either True
or False
, hence we did not need to use an equality here. We could have used the more verbose 11.divides(r)==True
but it is not necessary.
else
Often we wish to execute some code if none of our conditions above are met. For this we use the .else
operator. :
sage: n=2*3*5+1
sage: if 2.divides(n):
....: print 2
....: elif 3.divides(n):
....: print 3
....: else:
....: print n
....:
31
Since none of the conditions were met, our code defaulted to printing the number 31.
You should be familiar with
variables
andbooleans
loops, loops;while, while statement
While loops are one of the most useful techniques in programming. Essentially, a while loop runs a block of code while a condition is still satisfied. Let's see a simple example: :
sage: i=0
sage: while i < 5:
....: print i^2
....: i=i+1
....:
0
1
4
9
16
Once the condition i<5
is False, SageMath exits the loop structure; the variable i
still exists, though.
You should be familiar with
variables
,booleans
, andlists
for, for statement, loops; for
A for loop repeatedly runs a block of code a fixed number of times. In SageMath, for loops iterate over a fixed list. :
sage: for i in [0..4]:
....: print i^2
....:
0
1
4
9
16
We may iterate over any list, it need not be consecutive integers. Here are a few more (really silly) examples. :
sage: for str in ["apple","banana","coconut","dates"]:
....: print str.capitalize()
....:
Apple
Banana
Coconut
Dates
sage: for char in "Leonhard Euler":
....: print char.swapcase()
....:
l
E
O
N
H
A
R
D
e
U
L
E
R
You should be familiar with
lists
andfor_loops
list; comprehensions
A particularly useful technique in Python (and SageMath by extension) is the construction of lists using list comprehensions. This feature is very similar to the set builder notation we often use in mathematics. For example, the set of even integers can be written as:
{2⋅k | k∈ℤ}
Where we do not explicitly list the elements of the set but rather give a rule which can be used to construct the set. We can do something very similar in python by placing a for
inside of a list, like in the following example. Here is how we would construct the list of even integers from 0 to 20. :
sage: [ 2*k for k in [0..10] ]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
This concept may seem a bit intimidating at first, but it is extremely concise way to write some powerful code.
We can use list comprehension to apply a function to each number of a given list, much like we did before with the .map
command. :
sage: [pi/4,pi/2..2*pi]
[1/4*pi, 1/2*pi, 3/4*pi, pi, 5/4*pi, 3/2*pi, 7/4*pi, 2*pi]
sage: [ cos(x) for x in [pi/4, pi/2..2*pi]]
[1/2*sqrt(2), 0, -1/2*sqrt(2), -1, -1/2*sqrt(2), 0, 1/2*sqrt(2), 1]
We can also use the list comprehension filter (or reduce) the results by adding a conditional to our list comprehension. For example, to construct the list of all natural numbers that are less than 20 which are relatively prime to 20 we do the following: :
sage: [ k for k in [1..19] if gcd(k,20) == 1 ]
[1, 3, 7, 9, 11, 13, 17, 19]
Notice that the syntax for the construction is nearly identical to the mathematical way that we would write the same set of numbers:
{k∈ℕ | k<20 and gcd(k,20)=1}
In mathematics we often construct the Cartesian Product of two sets:
A × B = {(a,b) | a∈A,b∈B}
We can do something similar by using multiple for's in the list comprehension. For example, to construct the list of all pairs of elements in the list constructed earlier we do the following: :
sage: U = [ k for k in [1..19] if gcd(k,20) == 1]
sage: [ (a,b) for a in U for b in U ]
[(1, 1), (1, 3), (1, 7), (1, 9), (1, 11), (1, 13), (1, 17), (1, 19), (3, 1), (3, 3), (3, 7), (3, 9), (3, 11), (3, 13), (3, 17), (3, 19), (7, 1), (7, 3), (7, 7), (7, 9), (7, 11), (7, 13), (7, 17), (7, 19), (9, 1), (9, 3), (9, 7), (9, 9), (9, 11), (9, 13), (9, 17), (9, 19), (11, 1), (11, 3), (11, 7), (11, 9), (11, 11), (11, 13), (11, 17), (11, 19), (13, 1), (13, 3), (13, 7), (13, 9), (13, 11), (13, 13), (13, 17), (13, 19), (17, 1), (17, 3), (17, 7), (17, 9), (17, 11), (17, 13), (17, 17), (17, 19), (19, 1), (19, 3), (19, 7), (19, 9), (19, 11), (19, 13), (19, 17), (19, 19)]
It should be noted that you don't have to form tuples of the pairs of elements. For instance, you can also find the their product or their sum. Any valid expression involving a
and b
will be fine. :
sage: [ a*b for a in U for b in U ]
[1, 3, 7, 9, 11, 13, 17, 19, 3, 9, 21, 27, 33, 39, 51, 57, 7, 21, 49, 63, 77, 91, 119, 133, 9, 27, 63, 81, 99, 117, 153, 171, 11, 33, 77, 99, 121, 143, 187, 209, 13, 39, 91, 117, 143, 169, 221, 247, 17, 51, 119, 153, 187, 221, 289, 323, 19, 57, 133, 171, 209, 247, 323, 361]
sage: [ a + b for a in U for b in U ]
[2, 4, 8, 10, 12, 14, 18, 20, 4, 6, 10, 12, 14, 16, 20, 22, 8, 10, 14, 16, 18, 20, 24, 26, 10, 12, 16, 18, 20, 22, 26, 28, 12, 14, 18, 20, 22, 24, 28, 30, 14, 16, 20, 22, 24, 26, 30, 32, 18, 20, 24, 26, 28, 30, 34, 36, 20, 22, 26, 28, 30, 32, 36, 38]
sage: [ gcd(a,b) for a in U for b in U ]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 7, 1, 1, 1, 1, 1, 1, 3, 1, 9, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1, 1, 1, 1, 1, 1, 1, 1, 13, 1, 1, 1, 1, 1, 1, 1, 1, 17, 1, 1, 1, 1, 1, 1, 1, 1, 19]
Similar constructions work for more than 2 sets; just add more for statements.
Since list comprehensions allow for us to put any valid expression, we can add another conditional which affects the output of our list. For example, let take the list of integers which were relatively prime to 20 and test if they are prime numbers or not. :
sage: U
[1, 3, 7, 9, 11, 13, 17, 19]
sage: [ 'prime' if x.is_prime() else 'not prime' for x in U]
['not prime', 'prime', 'prime', 'not prime', 'prime', 'prime', 'prime', 'prime']
Exercises:
- Use a list comprehension to generate lists which have the same members as the following sets:
- The set of all odd integers greater than − 10 and less than 30.
- The set of all integers which are divisible by 3, less than or equal to 100 and greater than − 20.
- The set of all prime numbers less than 100.
- Use a list comprehension to compute the tan (x) for all x ∈ {0,π/4,π/2,3π/4,π}
functions, functions; definition, functions; arguments, functions; return values, def, return
Once your computations get complicated enough you may want to hide some of this complexity by creating your own command that can be easily re-used like SageMath's built-in commands. These user-defined commands are commonly called functions, though they differ from mathematical functions.
For example, suppose that we wanted to compute the greatest common divisor of 75 and 21. We can use the euclidean algorithm and SageMath to do this. Here is how that would look: :
sage: def euclid(a,b):
....: r = a%b
....: while r != 0:
....: a=b; b=r
....: r = a%b
....: return b
a
and b
are called the arguments of the command and the expression following the .return
keyword is called the return value. The arguments are in the input of the command whereas the return value is the output.
Those of you who have previous programming experience may notice the absence of end or block delimiters, such as ; or end. SageMath, like Python, uses indentation to denote where a block of code begins and ends. This syntax rule forces the programmer to write visually-separated blocks of code, thus making it more readable.
Once the command euclid
has been defined, the code can easily be re-used with different arguments, just like a built-in command. :
sage: euclid(75,21)
3
sage: euclid(455,67)
1
sage: euclid(754,99)
1
sage: euclid(756,9)
9
functions; multiple arguments
User-defined commands may have any number of arguments, including none at all. :
sage: def g(x,y):
....: return x*y
....:
sage: g(2,3)
6
sage: g(sqrt(2),sqrt(2))
2
sage: def h():
....: return 1/2
....:
sage: h()
1/2
Defining a return value is also optional, but all commands in SageMath return something. If we do not specify a return value, then SageMath returns the empty object None
. :
sage: def lazy(x):
....: print x^2
....:
sage: lazy(sqrt(3))
3
sage: a = lazy(sqrt(3))
3
sage: a
None
What the above is showing is that while the command displays the number 3, the return value is actually None. While this is valid code, it is good practice to have your commands actually return the value that you are interested in computing.
By separating the values with commas, your command can have multiple return values. :
sage: def s(x):
....: return x^2,x^3
....:
sage: s(1)
(1, 1)
sage: s(2)
(4, 8)
sage: a,b=s(3)
sage: a
9
sage: b
27
Defining your own commands in SAGE is easy. However, elegantly encapsulating your code is an art which requires a lot of practice and thought. For a more thorough introduction to functions (commands), this chapter on Python functions
is a good place to start.
external files, sessions
In practice, especially when using SageMath for research and projects, it is convenient to being able to load external files. One such instance is when we have a block of code which we wish to run for several different cases. It would be quite tedious to retype all of the code; instead we read it from an external file.
Suppose we have a file in the same directory from which we started SageMath called pythag.sage <pythag.sage>
with the following content.
# Begin pythag.sage
a=3
b=4
c=sqrt(a^2+b^2)
print c
# End
loading a file, load
Note that all characters after a # of a SageMath file are ignored when loaded. We may now load the file in SageMath using the .load
command. :
sage: load pythag.sage
5
After having loaded the file, all of the variables initialized now exist in our SageMath session. :
sage: a,b,c
(3, 4, 5)
save_session, load_session
SageMath allows us to save a session to pick up where we left off. That is, suppose we have done various calculations and have several variables stored. We may call the save_session function to store our session into a file in our working directory (typically sage_session.sobj). Following, we may exit SageMath, power off our computer, or what have you. At any later time, we may load the file by opening SageMath from the directory containing the save file and using the load_session function.
Here is an example: :
sage: a=101
sage: b=103
sage: save_session()
sage: exit
Exiting SAGE (CPU time 0m0.06s, Wall time 0m31.27s).
Now start SageMath from the same folder as the save file. :
sage: load_session()
sage: a
101
sage: b
103
We may specify the name of a save session, if we so desire. :
sage: T=1729
sage: save_session('ramanujan')
sage: exit
Exiting SAGE (CPU time 0m0.06s, Wall time 0m16.57s).
And again we load our session ramanujan
with .load_session
. :
sage: load_session('ramanujan')
sage: T
1729
external programs
There are many open-source software packages available for doing specialized mathematics. One of the objectives of SageMath developers is to create a single clean interface from which these packages may all be accessed. For many computations in advanced mathematics SageMath uses the functionality in one of these packages. A SageMath user can also explicitly call a function from one of the packages. This chapter briefly describes how to do so.
external programs; gap
For this portion of the tutorial we are going to show how to use GAP from within a SageMath session. The commands here follow closely with the Groups and Homomorphisms section of the GAP tutorial. A reader who is interested in learning more about the capabilities of this system shoud consult the Gap Project's main website.
You can pass a command to GAP by using .gap
with the command as a string. The following example constructs the symmetric group on eight points using GAP. :
sage: s8 = gap('Group( (1,2), (1,2,3,4,5,6,7,8) )')
sage: s8
Group( [ (1,2), (1,2,3,4,5,6,7,8) ] )
s8
has GAP as a parent. :
sage: parent(s8)
Gap
The interface to the GAP system translates the commands in GAP to methods in SageMath. For example, to compute the Derived Subgroup of S8 you use the .DerivedSubgroup
method. :
sage: a8 = s8.DerivedSubgroup(); a8
Group( [ (1,2,3), (2,3,4), (2,4)(3,5), (2,6,4), (2,4)(5,7), (2,8,6,4)(3,5) ] )
sage: a8.Size(); a8.IsAbelian(); a8.IsPerfect()
20160
false
true
The output of s8.DerivedSubgroup() is identical to the output of the GAP command DerivedSubgroup(s8) and this is the common convention when the command has one argument. When it requires two, say the group and an additional parameter, the additional parameter is given as an argument to the method. For example, the GAP command SylowSubgroup(a8,2) computes the maximal 2-subgroup of A8. The following SageMath code does the same, then uses GAP to compute its size. :
sage: sy12 = a8.SylowSubgroup(2); sy12.Size()
64
In the same vein, we can use GAP to compute the normalizer's and centralizers of these groups. :
sage: a8.Normalizer(sy12)
Group( [ (1,6)(2,4), (1,6)(5,8), (2,4)(3,7), (2,8)(4,5), (1,7)(2,8)(3,6)(4,5),
(1,8)(2,7)(3,4)(5,6) ] )
sage: a8.Normalizer(sy12) == sy12
True
sage: cent = a8.Centralizer(sy12.Centre());
sage: cent
Group( [ ( 1, 6)( 2, 4)( 3, 7)( 5, 8), (3,5)(7,8), (3,7)(5,8), (2,3)(4,7),
(1,2)(4,6) ] )
sage: cent.Size()
192
Gap itself has commands which can maniputale lists of objects. In this example we first compute the derived series of cent
and then compute the size of each of these subgroups using GAP's .List
command. :
sage: cent.DerivedSeries(); cent.DerivedSeries().List('Size')
[ Group( [ ( 1, 6)( 2, 4)( 3, 7)( 5, 8), (3,5)(7,8), (3,7)(5,8), (2,3)(4,7),
(1,2)(4,6) ] ),
Group( [ (2,4)(3,7), ( 1, 3)( 2, 8)( 4, 5)( 6, 7), ( 1, 7, 4)( 2, 6, 3) ] ),
Group( [ ( 1, 6)( 2, 4)( 3, 7)( 5, 8), ( 1, 6)( 3, 7),
( 1, 4)( 2, 6)( 3, 5)( 7, 8), ( 1, 7)( 2, 5)( 3, 6)( 4, 8),
( 1, 4, 6, 2)( 3, 8, 7, 5) ] ),
Group( [ ( 1, 6)( 2, 4)( 3, 7)( 5, 8) ] ), Group( () ) ]
[ 192, 96, 32, 2, 1 ]
Since the GAP command constructs a full-fledged SageMath object we can so the same in a more SageMath-y manner by using a list comprehension. :
sage: [ g.Size() for g in cent.DerivedSeries() ]
[192, 96, 32, 2, 1]
To convert a GAP group to a native SageMath one we first extract a list of generators. Then feed that list to the usual group constructor. :
sage: gens = s8.GeneratorsOfGroup(); gens
[ (1,2), (1,2,3,4,5,6,7,8) ]
sage: SG = PermutationGroup(gens); SG
Permutation Group with generators [(1,2), (1,2,3,4,5,6,7,8)]
sage: parent(SG)
<class 'sage.groups.perm_gps.permgroup.PermutationGroup_generic_with_category'>
Going from a SageMath group to a GAP one is even easier. :
sage: gap(SG)
Group( [ (1,2), (1,2,3,4,5,6,7,8) ] )
sage: parent(gap(SG))
Gap
From time to time you will want to just use GAP directly without using the interface. When working from the command line, the .gap_console
command does just this. :
sage: gap_console()
GAP4, Version: 4.4.12 of 17-Dec-2008, x86_64-unknown-linux-gnu-gcc
gap>
From which we can exit by typing quit;
at the gap prompt. :
gap> quit;
sage:
If the reader is using the notebook then using GAP directly is even easier. It is done by just selecting GAP from a drop down menu (highlighted in yellow in the picture below).
Now the SageMath notebook acts as a web interface to the GAP system.
external programs; singular
As with the GAP interface, the SageMath interface to Singular substitutes the language commands with methods in SageMath. For example, the following code in Singular: :
> ring R = 0,(x,y,z),lp;
> R;
// characteristic : 0
// number of vars : 3
// block 1 : ordering lp
// : names x y z
// block 2 : ordering C
Constructs a polynomial ring in three variables; x,y and z over the field of characteristic 0 using the lexicographic term ordering. To do the same within SageMath we use the .ring
method of the .singular
object. :
sage: R = singular.ring('0','(x,y,z)','lp')
sage: R
// characteristic : 0
// number of vars : 3
// block 1 : ordering lp
// : names x y z
// block 2 : ordering C
Since much of the language that Singular uses is not valid in SageMath the quotations around the arguments are important.
Polynomials are constructed in this ring by using the .poly
method. :
sage: p = singular.poly('x^2 * y^2 - 1')
sage: q = singular.poly('x^2 * y^2 - z')
sage: singular.ideal([p,q])
x^2*y^2-1,
x^2*y^2-z
To construct the ideal (in R) generated by those polynomials and a Groebner basis it you enter the following. :
sage: I = singular.ideal([p,q])
sage: I.groebner()
z-1,
x^2*y^2-z
Reduction modulo this ideal is accomplished using the .reduce
method. :
sage: r = singular.poly('x^3 - x^2 * y^2 - x^2 * z + x')
sage: singular.reduce(p,I)
z-1
sage: singular.reduce(q,I)
0
sage: singular.reduce(r,I)
x^3-x^2*z+x-z
and if you would like this reduction done using a Groebner basis, we just combine the methods discussed previously. :
sage: singular.reduce(q,I.groebner())
0
sage: singular.reduce(p,I.groebner())
0
sage: singular.reduce(r,I.groebner())
x^3-x^2+x-1
The quotations are not necessary when passing a Singular object as in the last few examples as there is no ambiguity.
Finally a task that Singular excels at is the factorization of multivariate polynomials. This is done using the .factorize
method. :
sage: p.factorize()
[1]:
_[1]=1
_[2]=x*y-1
_[3]=x*y+1
[2]:
1,1,1
sage: q.factorize()
[1]:
_[1]=1
_[2]=x^2*y^2-z
[2]:
1,1
sage: r.factorize()
[1]:
_[1]=-1
_[2]=x
_[3]=-x^2+x*y^2+x*z-1
[2]:
1,1,1
Using Python packages in SageMath -----------------------------
interact, @interact, interactive applets
In this section we will discuss the creation of interactive "applets" in the SageMath notebook. These are done using the @interact
decorator and are often called interacts. A decorator is a just a fancy piece of python which allows for you to create new functions out of old in a quick and concise fashion. You don't have to fully understand decorators to be able to follow this material but If you are interested you can read a very nice blog post about decorators by Bruce Eckel of Thinking in Python Fame.
We will begin with the most simple applet. One that creates a single input box and then displays the results.
Notice how changing the text in the input box changes the output. Every time something within the interact changes the "applet" is refreshed and will display those changes. This is the heart of the interactivity.
Next we will add another control to the applet. This time we will add a slider. This control has a handle which the user can slide horizontally, and by sliding change a number in pre-defined increments. For this example, the slider has 0 as its smallest number and 10 as its largest and moves in increments of 1 unit.
Next we will add a selection control. This control allows the user to select one of a finite number of different options. In this case, the user can select any color, as long as that color is red, blue, green, or black.
While this initial example shows the use of a couple of common interactive controls, it still does not do anything very interesting. The next example will combine both the use of sliding and selection controls toward creating an applet which plots the trigonometric functions and there standard transformations.
The example here only scratches the surface of what is possible with SageMath interacts. For a, growing, list of examples of interacts see this page on the sage wiki.