PREP Tutorial, Introductory Programming
system:sage


<div style="color: #000000; background-image: initial; background-repeat: initial; background-attachment: initial; -webkit-background-clip: initial; -webkit-background-origin: initial; background-color: #ffffff; background-position: initial initial; margin: 8px;">
<h1 style="font-size: 2em;">Sage Introductory Programming Tutorial</h1>
<p>This&nbsp;<a href="http://www.sagemath.org" target="_blank">Sage</a>&nbsp;worksheet is one of the tutorials developed for the MAA PREP Workshop "Sage: Using Open-Source Mathematics Software with Undergraduates" (funding provided by NSF DUE 0817071).&nbsp;</p>
<p>This tutorial will cover the following topics (and various others throughout):
<ul>
<li><a href="#Methods">Methods and Dot Notation</a></li>
<li><a href="#Lists">Loops, Lists, and List Comprehensions</a></li>
<li><a href="#Defs">Defining New Functions</a></li>
<li><a href="#Gotchas">Gotchas</a></li>
<li><a href="#Advanced">Advanced Introductory Topics</a></li>
</ul>

<p>We will motivate our examples using basic matrices and situations one might want to handle in everyday use of matrices in the classroom.</p>
</div>
<h2 id="Methods"><span style="color: #ff0000;">Methods and Dot Notation</span></h2>
<p><span style="color: #000000;">Making a new matrix is not too hard in Sage.<br /></span></p>

{{{id=1|
A = matrix([[1,2],[3,4]])
///
}}}

<p>Some commands are available right off the bat, like derivatives are.&nbsp; This is the determinant.</p>

{{{id=4|
det(A)
///
-2
}}}

<p>But some things are not available this way - for instance a row-reduced echelon form.&nbsp; We can 'tab' after this to make sure.</p>

{{{id=104|
r
///
}}}

<p>So, <span style="color: #000000;">as we've already seen, many </span>of  the commands in Sage are  "methods" of objects.&nbsp; This is a huge  advantage, once you get familiar  with it.&nbsp; First, we do the determinant again.</p>

{{{id=5|
A.det()
///
-2
}}}

<p>Then we do the row-reduced echelon form.</p>

{{{id=106|
A.rref()
///
[1 0]
[0 1]
}}}

<p>It is very important to keep in the parentheses.&nbsp; Things that would be legal without them would be called 'attributes', but Sage prefers stylistically to hide them, since math is made of functions and not elements of sets.&nbsp; (Or so a category-theorist would say.)</p>

{{{id=8|
# Won't work
A.det
///
<built-in method det of sage.matrix.matrix_integer_dense.Matrix_integer_dense object at 0x424ad40>
}}}

<p>To find out what you can do, don't forget that you can use the 'tab' key.</p>

{{{id=12|
A.
///
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "_sage_input_34.py", line 10, in <module>
    exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("QS4="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single')
  File "", line 1, in <module>
    
  File "/tmp/tmpjy2UuS/___code___.py", line 2
    A.
     ^
SyntaxError: invalid syntax
}}}

<p>And it is always helpful to read the documentation to tell if you need an argument (here, one of the columns).</p>

{{{id=6|
A.column(1)
///
(2, 4)
}}}

<p>Notice that this gives the SECOND column!&nbsp; You might have thought that this would give the first column, but Sage (along with the Python programming language) begins numbering at zero.&nbsp; This is another very important point.</p>
<p>Incidentally, sometimes you will have surprises.&nbsp; Subtle changes in an object can affect what commands are available, or what their outcomes are.</p>

{{{id=107|
A.echelon_form()
///
[1 0]
[0 2]
}}}

<p>This is because our original matrix had only integer coefficients, and you can't make the last entry one via elementary operations unless you multiply by a rational number!</p>

{{{id=13|
B = A.change_ring(QQ); B.echelon_form()
///
[1 0]
[0 1]
}}}

<h2 id="Lists"><span style="color: #ff0000;">Loops, Lists, and Set Builders ("List Comprehension")<br /></span></h2>
<p>We've already seen one or two examples of a fundamental object called a <em>list</em>.&nbsp; You should think of a list as an ordered set, where the elements of the set can be pretty much anything - including other lists.</p>

{{{id=53|
my_list=[2,'Grover',[3,2,1]]; my_list
///
[2, 'Grover', [3, 2, 1]]
}}}

<p>Although we won't dwell on it here, it is possible to access any elements of such a list quite easily using square brackets - as long as you remember that the counting starts at zero!</p>

{{{id=119|
my_list[0]; my_list[2]; my_list[0:1]
///
2
[3, 2, 1]
[2]
}}}

<p>However, our main reason for introducing this is more practical, as we'll now see.</p>
<p>One of the best uses of the computer in the classroom is to quickly show tedious things.&nbsp; One of the most tedious things to do by hand in linear algebra is taking powers of matrices.&nbsp; Here we make the first four powers of our matrix by hand.</p>

{{{id=110|
A = matrix([[1,2],[3,4]])
A^0; A^1; A^2; A^3; A^4; A^5
///
[1 0]
[0 1]
[1 2]
[3 4]
[ 7 10]
[15 22]
[ 37  54]
[ 81 118]
[199 290]
[435 634]
[1069 1558]
[2337 3406]
}}}

<p>This is not terrible, but it's not exactly nice either, particularly if you might want to do something <em>with</em> these new matrices.</p>
<p>Instead, we can do what is known as a <em>loop</em> construction.&nbsp; It is <strong>extremely</strong> important that we include both the colon in the first line and the indentation in the second line, for that is the basic syntactical structure of Python.</p>

{{{id=112|
for i in [0,1,2,3,4]:
    A^i
///
[1 0]
[0 1]
[1 2]
[3 4]
[ 7 10]
[15 22]
[ 37  54]
[ 81 118]
[199 290]
[435 634]
}}}

<p>The syntax is vaguely mathematical - for $i$ in the set [0,1,2,3,4], return $A^i$.&nbsp; Recall that the square brackets create a list, and note that the powers of the original matrix come in the same order as the list.</p>
<p>This is better, but still not perfect.&nbsp; It would be best to make it quicker to write.&nbsp; There are two ways to do this in Sage:</p>

{{{id=66|
for i in [0..4]:
    det(A^i)
///
1
-2
4
-8
16
}}}

{{{id=114|
for i in range(5):
    det(A^i)
///
1
-2
4
-8
16
}}}

<p>These ways of constructing lists are very useful (and demonstrate that, like many Sage/Python things, that counting begins at zero in things like 'range').&nbsp; The examples below show that one can get step sizes other than one as well.</p>

{{{id=115|
range(3, 23, 2); [3,5..21]
///
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
[3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
}}}

<p>It is also important to emphasize that the 'range' command does <em>not</em> include its last value!&nbsp; Confirm this in the examples above.</p>
<p>This all works well.&nbsp; However, after a short time this will seem tedious as well (you may have to trust us on this).&nbsp; It turns out that there is a very powerful way to create such lists in a way that very strongly resembles the so-called set builder notation, called a <em>list comprehension</em>.&nbsp;</p>
<p>We start with a relatively easy example: $$\{n^2\mid n\in\ZZ, 3 \leq n \leq 12\}$$</p>
<p>This is a natural for the list comprehension, and can be very  powerful when used in Sage.</p>

{{{id=116|
[n^2 for n in range(3, 13)]
///
}}}

<p>This sort of turns the loop around.&nbsp; The notation is easiest if you think of it mathematically; "The set of $n^2$, for (any) $n$ in the range between 3 and 13."</p>

<p>This is phenomenally useful.&nbsp; Here is another example, from groups: $G = S_4$, $T=\{|g|\mid g\in G\}$</p>

{{{id=69|
G = SymmetricGroup(4)
orders = [g.order() for g in G]
orders.sort()
orders
///
[1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4]
}}}

<p>And plotting!</a>

{{{id=55|
plot([x^n for n in [2..6]],(x,0,1))
///
<html><font color='black'><img src='cell://sage0.png'></font></html>
}}}

<p>Now we apply it to the example we were doing in the first place.&nbsp; Notice we now have a nice concise description of all determinants of these matrices, without the syntax of colon and indentation.</p>

{{{id=121|
[det(A^i) for i in [0..4]]
///
[1, -2, 4, -8, 16]
}}}

<h2 id="Defs"><span style="color: #ff0000;">Defining Functions (Extending Sage)</span></h2>

<p>It is often the case that Sage can do something, but doesn't have a simple command for it.&nbsp; For instance, you might want to take a matrix and output the square of that matrix minus the original matrix.</p>

{{{id=77|
A = matrix([[1,2],[3,4]])
A^2-A
///
[ 6  8]
[12 18]
}}}

<p>How might one do this for other matrices?&nbsp; Of course, you could just always do $A^2-A$ again and again.&nbsp; But this would be tedious and hard to follow, as with so many things that motivate a little programming.&nbsp; Here is how we solve this problem.</p>

{{{id=129|
def square_and_subtract(mymatrix):
    """
    Return `A^2-A`
    """
    return mymatrix^2-mymatrix
///
}}}

<p>The 'def' command has created a new function called 'square_and_subtract'.&nbsp; It should even be available using tab-completion! &nbsp;If you type 'square_and_subtract?', then the documentation string should appear.</p>
<p>Here are things to note about its construction:</p>
<ul>
<li>The input is inside the parentheses.</li>
<li>The indentation is important, as above.</li>
<li>The documentation string typically is started and ended with three quotation marks, and is optional (though usually is a good idea to include!). &nbsp;Mathematics can be typeset by putting the math into backticks `A` (preferred) or normal dollar signs \$A\$.</li>
<li>There will usually be a return value, given by 'return'.&nbsp; This is what Sage will give below the input cell.</li>
</ul>

{{{id=144|
square_and_subtract?
///
<html><!--notruncate-->
<div class="docstring">
    
  <p><strong>File:</strong> /tmp/tmpP9p_cQ/___code___.py</p>
<p><strong>Type:</strong> &lt;type &#8216;function&#8217;&gt;</p>
<p><strong>Definition:</strong> square_and_subtract(mymatrix)</p>
<p><strong>Docstring:</strong></p>
<blockquote>
Return <span class="math">A^2-A</span></blockquote>


</div>
</html>
}}}

{{{id=75|
square_and_subtract(A)
///
[ 6  8]
[12 18]
}}}

{{{id=131|
square_and_subtract(matrix([[1.5,0],[0,2]]))
///
[0.750000000000000 0.000000000000000]
[0.000000000000000  2.00000000000000]
}}}

<p>You may have noticed that there is nothing that requires the input 'mymatrix' to be a matrix.&nbsp; Sage will just try to square whatever you give it and subtract the original thing.</p>

{{{id=135|
square_and_subtract(sqrt(5))
///
-sqrt(5) + 5
}}}

<p>Try to define a function which inputs a matrix and returns the determinant of the cube of the matrix.&nbsp; (There are a few ways to do this, of course!)</p>

{{{id=132|

///
}}}

{{{id=133|

///
}}}

<h2 id="Gotchas"><span style="color: #ff0000;">Gotchas</span></h2>
<p>Before we finish the tutorial, there are a few things that often trip people up, mostly related to symbols, which should be pointed out.</p>
<p>One thing is that it's possible to clobber constants!</p>

{{{id=80|
i
///
4
}}}

<p>Can you figure out why $i=4$?&nbsp; Look carefully above to see when this happened.</p>
<p>By the way, this isn't necessarily bad (for instance, if you are only dealing with real matrices!), but definitely is something a Sage user needs to know.&nbsp; Also, it's possible to restore symbolic constants.</p>

{{{id=84|
reset('i')
i; i^2
///
I
-1
}}}

{{{id=83|
type(e)
///
<type 'sage.symbolic.constants_c.E'>
}}}

{{{id=85|
type(pi)
///
<type 'sage.symbolic.expression.Expression'>
}}}

<p>Variables are another thing to keep in mind.&nbsp; In order to maintain maximum flexibility while not allowing things to happen which shouldn't, only $x$ is predefined, nothing else.</p>

{{{id=86|
type(x)
///
}}}

{{{id=87|
type(y)
///
}}}

<p>Finally, there are a few names which are "reserved" by Python/Sage, and which aren't allowed as variable names.&nbsp; It's not surprising that 'for' is not allowed, but neither is 'lambda' ($\lambda$)!&nbsp;</p>

{{{id=138|
var('lambda')
///
lambda
}}}

{{{id=140|
lambda^2-1
///
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "_sage_input_19.py", line 10, in <module>
    exec compile(u'open("___code___.py","w").write("# -*- coding: utf-8 -*-\\n" + _support_.preparse_worksheet_cell(base64.b64decode("bGFtYmRhXjItMQ=="),globals())+"\\n"); execfile(os.path.abspath("___code___.py"))' + '\n', '', 'single')
  File "", line 1, in <module>
    
  File "/tmp/tmpqbO3zX/___code___.py", line 3
    lambda**_sage_const_2 -_sage_const_1 
                          ^
SyntaxError: invalid syntax
}}}

<p>There are lots of ways to get around this.&nbsp; One popular, though annoying, way is this.</p>

{{{id=141|
var('lambda_')
///
lambda_
}}}

{{{id=143|
lambda_^2-1
///
lambda_^2 - 1
}}}

<p>Note that showing the expression still shows the Greek letter.</p>

{{{id=145|
show(lambda_^2-1)
///
<html><div class="math">\newcommand{\Bold}[1]{\mathbf{#1}}\lambda^{2} - 1</div></html>
}}}

<h2 id="Advanced"><span style="color: #ff0000;">Advanced Introductory Topics</span></h2>
<p>There are several things which are useful to know about, but which are not always introduced immediately in programming.&nbsp; We give a few examples here, but they are mainly here to make sure you have seen them so that they are not completely surprising when they come up again.</p>
<p>We saw the "block" structure of Python earlier, with the indentation.&nbsp; This gives the opportunity to introduce conditional statements and comparisons.</p>

{{{id=123|
B = matrix([[0,1,0,0],[0,0,1,0],[0,0,0,1],[0,0,0,0]])
for i in range(5): # all integers from 0 to 4, remember
    if B^i==0: # We ask if the power is the zero matrix
        print i
///
4
}}}

<p style="text-align: justify;">Another useful concept is that of a <em>dictionary</em>.&nbsp; This can be thought of as a mathematical mapping from "keys" to "values".&nbsp; The order is <em>not</em> important and <em>not</em> guaranteed.&nbsp; A dictionary is delimited by curly brackets and correspondence is indicated by colons.</p>
<p style="text-align: justify;">Again, we will not give a big example.&nbsp; What if one wants to specify a matrix using just the nonzero entries?&nbsp; A dictionary is a great way to do this.&nbsp; This one puts 3 as an entry in the $(2,3)$ spot, for example (remember, this is the <em>third</em> row and <em>fourth</em> column, since we start with zero!).</p>

{{{id=48|
D = {(2,3):3, (4,5):6, (6,0):-3}
C = matrix(D)
C
///
[ 0  0  0  0  0  0]
[ 0  0  0  0  0  0]
[ 0  0  0  3  0  0]
[ 0  0  0  0  0  0]
[ 0  0  0  0  0  6]
[ 0  0  0  0  0  0]
[-3  0  0  0  0  0]
}}}

<p>That was a lot easier than inputting the whole matrix!</p>
<p>Sometimes it does matter how you define the same elements in Sage; we saw that above with matrices over the rationals versus integers, for instance.&nbsp; We will not go in great depth about this, either, but it is worth knowing about.&nbsp;&nbsp;</p>
<p>"It depends on what the meaning of the word 'is' is." &ndash;Bill Clinton,   1998</p>

{{{id=73|
a = 2
b = 2/1
c = 2.0
d = 2 + 0*I
e = 2.0 + 0.0*I
///
}}}

<p>Notice that each of these has or does not have $I=\sqrt{-1}$, decimal points, or division.</p>

{{{id=124|
print parent(a)
print parent(b)
print parent(c)
print parent(d)
print parent(e)
///
Integer Ring
Rational Field
Real Field with 53 bits of precision
Symbolic Ring
Symbolic Ring
}}}

<p>At times this will become important.&nbsp; Finally, sometimes one has to be careful about making changes to objects, as the '=' sign doesn't just say things are equal, but passes along a "reference" to the object it is made equal to.</p>

{{{id=91|
A = matrix(QQ,[[1,2],[3,4]])
B = A
C = copy(A)
///
}}}

{{{id=93|
A[0,0]=987
///
}}}

{{{id=94|
show([A,B,C])
///
<html><div class="math">\newcommand{\Bold}[1]{\mathbf{#1}}\left[\left(\begin{array}{rr}
987 & 2 \\
3 & 4
\end{array}\right), \left(\begin{array}{rr}
987 & 2 \\
3 & 4
\end{array}\right), \left(\begin{array}{rr}
1 & 2 \\
3 & 4
\end{array}\right)\right]</div></html>
}}}

{{{id=148|

///
}}}