数学概念的sage实现
第一次学习,参考la佬博客Orz
la佬写的精简干练,一度以为不是在记笔记而是转载XD
第二次完善,拜读V神的文章
第三次总结,研读sage中文文档 & Sage Quick Reference: Linear Algebra
gmpy2
gmpy2 是python里一个优秀的数论相关库
1 | import gmpy2 |
陌生
gmpy2.mpz(n) #初始化一个大整数
gmpy2.mpfr(x) # 初始化一个高精度浮点数x
Sage
R.<X> = PolynomialRing(Zmod(n))
Zmod(n):
- n: 指定模为n的环
- Z: 表示整数
有效的数字只有从0到n,其他的都通过与n取模来保证在0~n这个范围内
参数介绍
- ZZ:整数环
- QQ: 有理数环
- RR:实数环
- CC:复数环
PolynomialRing
建立多项式环
R
指针,指向用PolynomialRing指定的那个环.
实际上用什么字母都可以
.<X>
指定一个变量
数论相关
1 | prime_pi(n) #小于等于n的素数个数 |
陌生
prime_pi(n)
divisors(n)
andnumber_of_divisors(n)
three_squares(n)
andfour_squares(n)
1
2
3
4
5print(three_squares(78))
# (2, 5, 7)
print(four_squares(78))
# (1, 2, 3, 8)
factor
1 | ms = [284461942441737992421992210219060544764, 218436209063777179204189567410606431578, |
输出
(a, b)
- a为底数
- b为幂
1 | 2^2 * 7 * 11 * 37 * 4931 * 68447 * 19044797 * 3883344883673875271 |
它不是查询,sage会正儿八经地给你跑算法拆n
多项式
杂
f.subs({x:x1})
把x1值代入x
f.univariate_polynomial()
univariate单变量的,映射为单变量多项式
f.univariate_polynomial().roots()
单变量多项式求根
f.coefficients()
coefficient系数,多项式系数列表
f.monic()
monicpolynomial首个系数为1的多项式
单元·因式分解
1
2
3
4
5
6x = PolynomialRing(RationalField(), 'x').gen()
# RationalField有理域
f = (x^3 - 1)^2-(x^2-1)^2
f.factor()
# (x - 1)^2 * x^2 * (x^2 + 2*x + 2)二元·因式分解
1
2
3
4
5x, y = PolynomialRing(RationalField(), 2, ['x','y']).gens()
f = (9*y^6 - 9*x^2*y^5 - 18*x^3*y^4 - 9*x^5*y^4 + 9*x^6*y^2 + 9*x^7*y^3 + 18*x^8*y^2 - 9*x^11)
f.factor()
# (9) * (-x^5 + y^2) * (x^6 - 2*x^3*y^2 - x^2*y^3 + y^4)单元·GCD
1
2
3
4
5
6x = PolynomialRing(RationalField(), 'x').gen()
f = 3*x^3 + x
g = 9*x*(x+1)
f.gcd(g)
# x多元·GCD
1
2
3
4
5
6R.<x,y,z> = PolynomialRing(RationalField(), order='lex')
f = 3*x^2*(x+y)
g = 9*x*(y^2 - x^2)
f.gcd(g)
# x^2 + x*y
矩阵
矩阵的定义
A = matrix(定义域, 值)
1
2
3
4
5
6A = matrix(ZZ, [[1,1],[0,4]])
# 创建了定义域在整数环的矩阵
"""
[[1, 1]
[0, 4]]
"""也可以交代清楚指定的行数与列数
1
2
3F1=matrix(QQ,2,2,[0,1,1,0])
列向量置入定义
每个向量以列向量的形式置入矩阵
1
2
3
4sage: column_matrix(QQ,[[1,2,3],[4,5,6],[7,8,9]])
矩阵组合定义
1
2
3
4
5
6
7
8sage: F1=matrix(QQ,2,2,[0,1,1,0])
sage: F2=matrix(QQ,2,2,[1,2,3,4])
sage: F3=matrix(QQ,1,2,[3,1])
sage: block_matrix(2,2,[F1,F2,0,F3])
向右生长
1
2
3sage: F1.augment(F2)
向下生长
1
2
3
4
5sage: F1.stack(F2)
以块为单位的对角阵
1
2
3
4
5
6sage: block_diagonal_matrix([F1,F2])
矩阵属性
A.nrows()
矩阵行数
A.ncols()
矩阵列数
V.dimension()
查看v矩阵的维度
A.transpose()
转置
A.inverse()
矩阵的逆
A.rank()
矩阵的秩
A.det()
将矩阵转换为行列式
A.stack(vector([1,2]))
矩阵末添加一行(向量)
A.insert_row(n, vector([1,2]))
在矩阵第n行插入(向量)
A.change_ring(QQ)
更换环为QQ(有理数环)
A.solve_left(B)
或A/B
求解XA=B
A.solve_right(B)
或A\B
求解AX=B
A.left_kernel()
求解XA=0,线性相关的行向量
A.right_kernel()
解AX=0,线性相关的行向量A.LLL()
LLL算法求最短正交基
A.multiplicative_order()
乘法阶
特别的
zero_matrix(2,3)
创建(2*3)零矩阵
identity_matrix(2,3)
创建(2*3)单位阵
block_matrix(QQ,[[Matrix_A,Matrix_B],[matrix(C),matrix(D)]])
矩阵拼接
1
2
3
4
5
6
7
8
9
10
11
12A = matrix(ZZ, [[1,1],[0,4]])
b = [[2,2],[3,3]]
n = 2
block_matrix(QQ,[[A,zero_matrix(n,2)],[matrix(b),matrix([[4,4],[5,5]])]])
"""
[1 1|0 0]
[0 4|0 0]
[---+---]
[2 2|4 4]
[3 3|5 5]
"""
困惑
关于$matrix()vector()$, *sage是会自动变向量为列向量或行向量来使得乘法可算吗?**
查阅中文文档后,证实Sage为了让乘法合理化,会尽可能调整向量是行或列向量。
而在使用之前,向量的状态是混沌的。
求解方程
普通方程
$\left\{\begin{aligned}x+y&=10\\xy&=21\end{aligned}\right.$
1 | var('x y') # 申明变量 |
线性方程组
1 | A = Matrix([[1,2,3],[3,2,1],[1,1,1]]) |
- 给一个记忆点,斜杠的下端在哪边,未知量x就在哪边
RSA相关方程
$\left\{\begin{aligned}N&=pq\\ \phi &= (p-1)(q-1)\end{aligned}\right.$
1 | P.<p, q> = PolynomialRing(ZZ) |
CRT(中国剩余定理)
$\left\{\begin{aligned}x&≡2 (mod3)\\x&≡3(mod5)\\x&≡2(mod7)\end{aligned}\right.$
Sage内置CRT函数crt([2,3,2], [3,5,7])
但没有模不互素的扩展中国定理excrt(具体原理、代码可见我的博客中Crypto常见算法一文)
离散对数
$a^x ≡ b (\mod n )$
n为合数
利用Pohlig-Hellman算法(后续再补充原理学习)
x = discrete_log(mod(b,n),mod(a,n))
??? n是质数幂也解出来了
n为质数或质数幂
线性筛Index Calculus方法(不了解)
1
2
3
4
5
6
7
8
9R = Integers(99)
a = R(4)
b = a^9
b.log(a)
# 9
# 或
x = int(pari(f"znlog({int(b)},Mod({int(a)},{int(n)}))"))
x = gp.znlog(b, gp.Mod(a, n))
椭圆曲线
$y^2 =x^3 + ax + b$
F = GF(7)
F.order()
素数域的阶
E = EllipticCurve(F,[0,0,0,2,3])
定义椭圆曲线$F_7(2,3)$
G = E.gens()[0]
基点坐标
q = E.order()
阶allPoints = E.points()
所有的点P = E(2,1)
创建点P.xy()
点的xy坐标
结式¶
1 | from sage.matrix.matrix2 import Matrix |
结式求解
1 | f = f1.resultant(f2, xp) # 消xp |