# SageMath Installation

Windows : https://www.sagemath.org/download-windows.html

Mac : https://www.sagemath.org/download-mac.html

Linux : https://www.sagemath.org/download-linux.html

As the whole package is around 10GB, it takes quite some time to install the whole package.

### Running Sage IDE

After the installation, run sagemath in terminal by typing `sage`

```
$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 9.4, Release Date: 2021-08-22 │
│ Using Python 3.9.5. Type "help()" for help. │
└────────────────────────────────────────────────────────────────────┘
sage:
```

### Color Scheme

You can change the color scheme by typing the command

```
sage: %colors Linux
```

Valid schemes: `['NoColor', 'Linux', 'LightBG', 'Neutral', '']`

I find the `Linux`

color scheme most suitable dark background terminal.

### Running Sage from file

You can run a sage file from the terminal with

`$ sage test.sage`

Or a python file with

In the python file, import sage by

```
from sage.all import *
...
```

Then run it with this command

`$ sage -python test.py`

# SageMath syntax

Althought SageMath uses syntax very identical to python, there are still some subtle difference between them.

The official documentation often uses syntax that is supported only in `.sage`

file.

Common syntax difference

Behavior | Sage | Python |
---|---|---|

Exponent | ^ | ** |

XOR | ^^ | ^ |

Polynomial | `R.<x> = QQ[]` |
`QQ['x']` |

Multivariable Polynomial | `R.<x,y,z> = QQ[]` |
`QQ['x','y','z']` |

Most of the syntax are supported in both files

The best part of SageMath is that it provides simple syntax for many complex mathematical operations.

## Ring and Field

First, one must identify these symbols

Symbol | Meaning | Type |
---|---|---|

ZZ | Integers | Ring |

Rational Numbers | Field | |

RR | Real Numbers | Field |

CC | Complex Numbers | Field |

Zmod(N) | Integer Modulo N | Ring |

GF(N) | Finite Field of size N | Field |

Note that for `GF(N)`

the N must be $p^a$ where p is a prime.

The main differences between a ring and a field is

- Not all non-zero element in a Ring has an inverse.
- Ring might has zero divisor.

Take integer modulo 6 ring as an example

- The number 3 does not have inverse. There is no such number $a$ such that $3 \cdot a \equiv 1 \mod 6$
- The number 3 and 2 is a zero divisor. $3 \cdot 2 \equiv 0 \mod 6$

You need to be very careful for the choice of your Ring/Field as some functions are only valid for field but not for ring.

In general, field are easier to work with as it has more properties. Most of the function that works for ring will work for field.

Therefore, if you are dealing with integer modulo a prime number, you should use `GF(p)`

instead of `Zmod(p)`

Once you convert a number to `GF(p)`

or `Zmod(p)`

, you don’t have to keep applying `%`

operator as the modulo operation will already be done automatically.

```
sage: a = 63283
sage: b = 45342
sage: a = GF(17)(a)
sage: b = GF(17)(b)
sage: a + b
12
sage: a / b
3
sage: a^-1
2
sage: a^30
4
```

Operation `+, -, *, ^`

are well defined for Rings and Field.

Opeartion `/`

can be use if the element has an inverse

Factor a number with the `factor()`

function

```
sage: a = 63283
sage: a.factor()
11^2 * 523
```

## Polynomial

### Univariate Polynomial

Recall the syntax to declare a polynomial is `R.<x> = QQ[]`

`R`

represents the Polynomial Ring

`x`

represents the variable

`QQ`

represents the ring for the coefficient of the polynomial.

Let’s say you want to declare a polynomial such that the coefficient can only be an integer.

Then it will be `R.<x> = ZZ[]`

```
sage: R.<x> = ZZ[]
sage: f = 1*x + 2*x^2 + 3*x^3
sage: g = 3*x + 10*x^2
```

You can use `+, -, *, /, ^`

for polynomials as usual

```
sage: f-g
3*x^3 - 8*x^2 - 2*x
sage: f*g
30*x^5 + 29*x^4 + 16*x^3 + 3*x^2
sage: f/g
(3*x^2 + 2*x + 1)/(10*x + 3)
sage: g^3
1000*x^6 + 900*x^5 + 270*x^4 + 27*x^3
```

Factor the polynomiak with `factor()`

```
sage: f.factor()
x * (3*x^2 + 2*x + 1)
```

To apply some value to the polynomial, use the syntax `f(x = 2)`

or `f(2)`

```
sage: f(2)
34
sage: f(x=2)
34
```

To extract the coefficient of the polynomial, use `list()`

function

```
sage: g.list()
[0, 3, 10]
```

To get the roots of a polynomial, use `roots()`

function

```
f.roots()
```

Note : This function is only defined for univariate polynomial in integer Ring or Field.

### Multivariate Polynomial

Declaring the polynomial by `R.<x,y> = QQ[]`

Operation `+, -, *, /, ^`

are well defined as usual

```
sage: R.<x,y> = QQ[]
sage: f = x + y + x*y
sage: g = x^2 + y^2
sage: f + g
x^2 + x*y + y^2 + x + y
sage: f ^ -1 * g
(x^2 + y^2)/(x*y + x + y)
```

You can use `f(x = 2, y = 3)`

to apply some value to the polynomial

```
sage: f(x=3,y=5)
23
```

There are 2 ways that I use to solve system of equations

#### Resultant

If the underlying ring for the polynomial is either integer ring or field, then you can use resultant to solve system of linear equations.

```
sage: R.<x,y> = QQ[]
sage: f = x + y + x*y
sage: g = x^2 + y^2
sage: k = f.resultant(g, x)
sage: k
y^4 + 2*y^3 + 2*y^2
```

As `roots()`

are only definied for univariate polynomial, we must change `k`

to a univariate polynomial first.

```
sage: k = k(x = 0)
sage: k = k.univariate_polynomial()
sage: k.roots()
[(0, 2)]
```

#### Groebner basis

Groebner basis is much slower and less consistent. It might not find a solution for certain equations.

But as it works on any ring, sometimes we have no choice to use it especially when we are dealing with the ring of Integer modulo n.

```
sage: R.<x,y> = Zmod(30)[]
sage: f = x + y + 3
sage: g = 3 * x + y + 10
sage: I = Ideal([f,g])
sage: I.groebner_basis()
[x + 26, y + 7, 15]
```

## Matrix

You can declare a matrix by :

```
sage: Matrix(ZZ, [[2,2,3],[4,2,5],[3,3,3]])
[2 2 3]
[4 2 5]
[3 3 3]
sage: Matrix(GF(2), [[2,2,3],[4,2,5],[3,3,3]])
[0 0 1]
[0 0 1]
[1 1 1]
```

The first parameter represents the underlying field for the entries of the matrix.

Access the entries of the matrix with the natural way

```
sage: A = Matrix(ZZ, [[2,2,3],[4,2,5],[3,3,3]])
sage: A[2][1]
3
```

Operation `+, -, *, ^`

are well defined for a matrix

Operation `/`

is valid if the matrix is invertible

Other functions for matrix includes :

```
sage: A.rref()
[1 0 0]
[0 1 0]
[0 0 1]
sage: A.kernel()
Free module of degree 3 and rank 0 over Integer Ring
Echelon basis matrix:
[]
sage: A.charpoly()
x^3 - 7*x^2 - 16*x - 6
```

## Discrete Logarithm

As long as you are dealing with a finite group, you can always use `discrete_log()`

to find discrete logarithm.

```
sage: a = GF(23)(10)
sage: b = a^13
sage: discrete_log(b,a)
13
```

```
sage: K = GF(3^6,'x')
sage: x = K.gen()
sage: a = x^3 + 3*x^2 + 2
sage: discrete_log(a, x)
299
```

```
sage: a = Matrix(GF(7), [[2,2,3],[4,2,5],[3,3,3]])
sage: b = a^3
sage: discrete_log(b,a)
3
```

## Others

There are other useful functions in SageMath such as

- Chinese Remainder Theorem
- Find multiplicative order
- Dealing with elliptic curve

You can learn how to use them by referring to the official documentation