In [ ]:
# Sage - System for Algebra and Geometry Experimentation (or Sagemath) is a computer algebra system, whose mission is to provide
# free, opensource alternative to Mathematica, Maple, Magma, Matlab...
# It is written mostly in Python (and Cython), and it can be thought of as an interface to many 
# mathematical libraries (PARI/GP, NTL, GAP, Singular, ...)
#
# Started by a researcher who was angry, he could not modify proprietary code
#
# There is an online version which you can use for shorter calculations: https://sagecell.sagemath.org/
# Also a clould version (needs registration, and the free tier is slow): https://cocalc.com/
# And finally you can also install it as a standalone application: https://www.sagemath.org/
In [ ]:
# uses python-like language
# mostly the syntax is the same, but there are differences

print(1^3)
print(2^3)
print(x)
print(pi)
print(sqrt(4))
print(factor(56))
print(type(I))
In [ ]:
"""
online documentation: https://doc.sagemath.org/html/en/index.html
documentation for the jupyter notebook: https://jupyter.org/documentation
(also another way to write comments apart from #)
"""
In [ ]:
# Arithmetics
# as in Python with some modifications:
print(type(2))
print(1/2) # returns the exact result
print(2^3) # 2 to the 3rd power = 8
print(2**3) # same as above
print(2^^3) # bit XOR
print(log(I,e)) # logarithm of I to the base e
In [ ]:
# functions
y = var('y') # defining symbolic variable
# x = var('x') # this is already defined

def f(x,y):
    return x^3+y^2+x*y


def g(x):
    return sin(x)+cos(x)


# we can differentiate and integrate:
print( diff(g(x),x) )
print( diff(f(x,y),y) )
print( integrate(f(x,y),x) )


def f1(x):
    return g(x)

def f2(x):
    return sin(x)-cos(x)

# we can plot
plot3d(f(x,y),(x,-2,2),(y,-2,2))
plot(g(x))
plot(g(x), (x,-10,10))

# we can combine the plots
p1 = plot(f1(x), color='blue')
p2 = plot(f2(x), color='green')
show(p1+p2)

#we can also plot the zeroes of a function:
implicit_plot(f(x,y),(x,-2,2),(y,-2,2))
In [ ]:
# equations
# we can solve polynomial equations
solve(x^3+x^2+x == 0, x)

#does not "work" for other equations
solve(g(x) == 0,x)
# we can still use numerical methods
find_root(g(x), -5,2)
          
#we can also solve systems
equations = [ x^2+y == 0, x+y == 0 ]
solve(equations, x, y)
In [ ]:
# more algebra
# out of the box Sage supports a vast collections of objects
# usually there is no need or you to define your classes - they are already there
# polynomial rings, matrices, finite fields, elliptic groups...

F = GF(7)
F = GF(8)
#F = GF(6) #for large enough moduli, you can fool sage - it will not prove that the modulus is prime
F = GF(2)
R.<z> = F[] # defining the ring of polynomials over the finite field

# we then do not have to do the modular reductions, everything works
factor(z^2+1)
print(z^2+z^2)
In [ ]:
# Matrices

# we can create matrix as an array of arrays

B = Matrix(ZZ, [[1,2,3],[1,2,3]])

# or a list of elements and specify the dimensions
B = Matrix(ZZ,3,2,[1,2,3,1,2,3])
B = Matrix(ZZ,2,3,[1,2,3,1,2,3])
print(B)


# we can also solve equations in this way:
print(B.solve_right(vector(ZZ,[1,1])))


print(B)
print(B.T)
print(B.LU())

print(Matrix.identity(3))
print(Matrix(2))

A = random_matrix(ZZ,3,3,x = -20, y = 20)

print(det(A))
In [ ]:
# also arithmetics works

print (A, '\n')
print (A.T, '\n')
print (A*A,'\n')
In [ ]:
# Sage has a good documentation - if you are ever stuck, it can at least give you an idea what to do:

# documentation regarding a function or an object: {}?, where {} is the thing you want to know about
### random_matrix?
### A?

# a list of attributes and methods dir({})
### dir(A)
### dir?
In [ ]:
# Note, that the algebraic objects in sage know their parents - we need to be careful and not get too crazy

A = random_matrix(GF(97), 5,5)
print (A,'\n')
B = random_matrix(GF(83), 5,5)
print (B,'\n')
C = random_matrix(ZZ,5,5,x = 0, y = 83)
print (C,'\n')

#print(A*B)
print(A*C,'\n')
print(B*C)
In [ ]:
# However, we can be a bit crazy
m, n, q = 5, 3, 101

A = random_matrix(GF(q), n, m)
A.echelonize()
print (A, '\n')
N = A.change_ring(ZZ)
S = matrix(ZZ, m-n, n).augment(q * identity_matrix(m-n))
print (S, '\n')
N.stack(S, subdivide=True)
In [ ]:
# Note, most of the procedures mentioned here are just a wrapped versions of procedures from C/C++ libraries
# it is possible to use these libraries directly
# but you will lose a lot of syntactic sugar
# proceed at your own risk
In [ ]:
# Credits discussion
# Q&A
In [ ]:
# Short practical exercise

# Exercise: Intersecting Circles and Lines

# Objective: Use SageMath to find the intersection points of two circles and a line
# and then visualize them on a plot.