The Sage Notebook is a web application that provides a convenient interface to Sage commands, components and features.
A symbolic derivative (from Maxima).
f(x) = x^3*e^-x
df = f.derivative()
df
Derivative of a function is again a function, and can be evaluated.
slope = df(4)
slope
Arbitrary precision numerical values on request (from MPmath).
N(slope, digits=20)
Can display plots in the notebook (matplotlib).
plot(df, 0, 10, color='red', thickness=5)
Study the multivariate integral $\displaystyle\int_{-4}^4\int_0^{x^2} y^2-10x^2\,dy\,dx$.
var('x y z')
integral(integral(y^2-10*x^2, (y, 0, x^2)), (x, -4, 4))
surface = plot3d(y^2-10*x^2, (x, -4, 4), (y, 0, 16))
show(surface)
region = implicit_plot3d(y-x^2, (x, -4, 4), (y, 0, 16), (z, 0, 98), color='red', opacity=0.20)
show(surface+region)
Interactive demonstrations are easy to create with the interact
decorator and modified function arguments.
@interact
def plotter(maxdegree=range(2,40)):
import sage.plot.colors
colors = sage.plot.colors.rainbow(maxdegree+1)
var('x')
wholeplot = plot(x^1, (x, 0, 1), color=colors[1])
for i in range(2, maxdegree+1):
newplot = plot(x^i, (x, 0, 1), color=colors[i])
wholeplot = wholeplot + newplot
show(wholeplot)
@interact
def taylor(order=slider(1, 12, 1, default=Integer(2), label="Degree of polynomial $\hat{f}$")):
var('x')
x0 = 0
f = sin(x)*e^(-x)
p = plot(f, -1, 5, thickness=2)
dot = point((x0,f(x=x0)), pointsize=80, rgbcolor=(1,0,0))
ft = f.taylor(x, x0 ,order)
pt = plot(ft, -1, 5, color='green', thickness=2)
html("Taylor series approximation to ${0}$ of degree {1} at $x={2}$".format(latex(f), Integer(order), x0) )
show(dot + p + pt, ymin = -0.5, ymax = 1)
Exclusive of combinatorics (see Part 2).
Prototypical use of Sage: permutation groups. Built from the mature open source package GAP (Groups, Algorithms, Programming).
G = DihedralGroup(8)
G
G.list()
G.is_abelian()
sg = G.subgroups()
[H.order() for H in sg]
H = sg[14]
H.list()
H.is_normal(G)
Create graphs in a natural way:
harary = Graph([(0,1), (1,2), (2,3), (3,0), (1,3)])
harary
harary.plot()
harary.num_verts(), harary.num_edges()
harary.is_planar()
H = harary.hamiltonian_cycle()
H.plot()
harary.degree_sequence()
sorted(harary.degree_sequence())
There are many pre-defined graphs (digraphs, too):
graphs.
Constant time generation of free trees
, by B. Richmond, A. Odlyzko, B.D. McKay
trees_iterator = graphs.trees(8)
T8 = list(trees_iterator)
T8
From a path to a star:
[tree.diameter() for tree in T8]
Visually:
graphs_list.show_graphs(T8)
graphs.HanoiTowerGraph(n, d)
- Generalize to $n$ pegs and $d$ disks
- State graph: intermediate configurations, edges are
one move
- Labels: $d$-tuple, large disk to small disk; entries are peg numbers
- Example: $n=3$, $d=4$: $(2,0,2,1)$
T = graphs.HanoiTowerGraph(3, 4, positions=True)
T.show(figsize=12)
A solution is path between states ``all the disks on one peg'' and ``all the disks on another peg.''
solution=T.shortest_path((0,0,0,0), (1,1,1,1))
solution
Minimum number of moves:
len(solution) - 1
T.diameter()
More general:
T = graphs.HanoiTowerGraph(4, 3, positions=True)
T.show(figsize=12)
T = graphs.HanoiTowerGraph(4, 4, labels=False, positions=True)
T.show(figsize=12)
Forget about graphics, work with graph itself.
T = graphs.HanoiTowerGraph(4, 8, labels=False, positions=False)
T.num_verts()
Code vertices to integers: $d$-tuples, base $n$. All disks on peg 0, move to all disks on peg 3.
solution = T.shortest_path(0, 4^8-1)
solution
len(solution)-1
Theorem: automorphisms of the state graph are just the obvious ones (renumber pegs)
T = graphs.HanoiTowerGraph(4, 6, labels=False, positions=False)
A = T.automorphism_group()
A.order()
S4 = SymmetricGroup(4)
S4.is_isomorphic(A)
Automorphisms are computed via Brendan McKay's nauty
algorithm, re-implemented as NICE
.
Many possible fields and rings: finite fields, field extensions, algebraic numbers.
Over the integers and rationals powered by Integer Matrix Library (IML).
A = matrix(QQ,
[[1, -2, 3, 2, -1, -4, -3, 4],
[3, -2, 2, 5, 0, 6, -5, -5],
[0, -1, 2, 1, -2, -4, -1, 4],
[-3, 2, -1, -1, -6, -3, 5, 3],
[3, -4, 4, 0, 7, -7, -7, 6]])
A
A.rref()
b = vector(QQ, [2, -1, 3, 4, -3])
A.solve_right(b)
And it is fast.
A = random_matrix(ZZ, 1000, 1000)
time A.determinant()
We can combine linear algebra with graph theory (aka algebraic graph theory
).
K = graphs.KneserGraph(8,3)
K.plot()
adj = K.adjacency_matrix()
adj
K.spectrum()
A small singular graph.
(I. Sciriha, 2007)
S = graphs.CycleGraph(4)
S.add_vertices([4, 5, 6])
S.add_edges([(2,4), (2,5), (2,6)])
S.add_edges([(3,4), (3,5), (3,6)])
S.plot()
adj = S.adjacency_matrix()
ker = adj.kernel()
ker
Notice this is the kernel over the integers, and is computed as a module. It is easy to upgrade to the rationals.
adjQ = adj.change_ring(QQ)
kerQ = adjQ.kernel()
kerQ
A matrix kernel (null space) is a vector space, and has all the attendant properties.
kerQ.dimension()
kerQ.basis()
Numerical linear algebra is supplied by SciPy, through to LAPACK, ATLAS, BLAS.
A matrix of double-floating point real numbers (RDF).
B = matrix(RDF,
[[0.4706, 0.3436, 0.7156, 0.1706, 0.3863, 0.222, -0.9673],
[0.9433, -0.7333, -0.2906, -0.5203, 0.3548, 0.7577, 0.3936],
[-0.8998, 0.9269, -0.9646, -0.2294, -0.8171, 0.4568, 0.5949],
[0.8814, 0.89, -0.2059, 0.7434, -0.1642, 0.6918, 0.7113],
[-0.0034, -0.9842, 0.7213, -0.7196, -0.7422, 0.3335, 0.5829],
[-0.5676, 0.6433, -0.2296, 0.2681, 0.2992, 0.6988, 0.3332],
[0.0366, -0.5788, 0.5882, 0.1559, -0.6434, 0.871, -0.6518]])
B
And the QR decomposition of B
.
Q, R = B.QR()
Q
(Q.conjugate_transpose()*Q).round(4)
R.round(4)
(Q*R-B).round(4)
import pylab
A_image = pylab.mean(pylab.imread(DATA + 'mystery.png'), 2)
@interact
def svd_image(i=(1,(1..50)), display_axes=True):
u,s,v = pylab.linalg.svd(A_image)
A = sum(s[j]*pylab.outer(u[0:,j], v[j,0:]) for j in range(i))
# g = graphics_array([matrix_plot(A),matrix_plot(A_image)])
show(matrix_plot(A), axes=display_axes, figsize=(6,8))
html('Compressed using %s singular values
'%i)
$\dots$is superb.
latex(integrate(sec(x), x))
A = random_matrix(QQ, 6, num_bound=9, den_bound=9)
latex(A)
With "typeset" button checked.
A = random_matrix(QQ, 6, num_bound=9, den_bound=9)
A
Note to self: un-check "typeset" button.
P = graphs.PetersenGraph()
P.set_latex_options(vertex_shape='diamond', vertex_color='red', vertex_label_color='gold', edge_color='blue')
latex(P)
Shift-Click
on blue bar to activate. TeX-aware.
We can add text to our notebooks using TeX syntax and dollar signs. Previous multivariate integral:
\int_0^4\int_0^{x^2} y^2-10x^2\,dy\,dx
Can embed images this way also.
SageTeX allows you to call Sage to compute values, expressions or plots for automatic inclusion in your LaTeX document. (And will write your papers for you!)
LaTeX source: Today's date, 2012-05-22 = 20120522, factors as \sage{factor(20110212)}.
Final Document: Today's date, 2012-05-22 = 20120522, factors as $2 \cdot 338 \cdot 26267$.
Can author in the worksheet or in LaTeX, ReStructured Text, XML to produce worksheets (this is an example).
A huge number of examples are provided for (a) learning to use Sage commands, and (b) to test Sage commands. We call these ``doctests.''
M = matrix(QQ, [[1, -2, 2], [-4, 5, 6], [1, 2, 4]])
M
Illustrate tab-completion (rational form), help (doctests, zig-zag form
), source code.
M.
A Sage-inspired project to convert Python to C, then compile.
Factorial, Python-style.
def py_fact(n):
fact = 1
for i in range(n):
fact = fact*(i+1)
return fact
py_fact(12)
timeit('py_fact(12)')
Cython-style. (cdef, long in header)
%cython
def cy_fact(n):
cdef:
long fact, i
fact = 1
for i in range(n):
fact = fact*(i+1)
return fact
cy_fact(12)
timeit('cy_fact(12)')
See Beezer's Home Page.