1 Premiers contacts
Implantation
Entrée [3]:
Entrée [4]:
Entrée [5]:
Entrée [6]:
Out[4]:
[ 0 0 1/2 2 0 -2 -1 0 0 0]
[ 0 0 -2 -1 2 -2 0 0 0 0]
[ 0 0 0 0 -2 1 0 0 1/2 0]
[ 0 0 0 0 0 0 1 -1 0 1/2]
[ 0 0 0 0 1 2 -1 2 0 0]
[ 1 0 0 0 -1 0 -2 0 0 0]
[ -1 0 -2 0 0 0 0 0 0 2]
[ 0 1 0 0 -1 0 1 -1 0 0]
[ -1 0 1 0 -2 0 0 0 0 0]
[ 2 -2 0 0 0 0 0 0 0 1]
Out[6]:
Une matrice carrée de taille 6 sur l'anneau Integer Ring kk = QQ
n = 10
matrix.random(kk,n,n,density=.4) #sparse=true
class MatriceCarree(object):
def __init__(self,anneau,taille):
self._anneau = anneau self._taille = taille def nrows(self):
return self._taille def ncols(self):
return self._taille def base_ring(self):
return self._anneau def __repr__(self):
return "Une matrice carrée de taille %s sur l'anneau %s"%(self.nrows(), self.base_r
matcar = MatriceCarree(ZZ,6); matcar
class MatriceDense(MatriceCarree):
def __init__(self,anneau,mat):
self._taille = mat.nrows() self._anneau = anneau
self._mat = matrix(anneau,mat) def __repr__(self):
return "Une matrice dense de taille %s sur l'anneau %s"%(self.nrows(),self.base_rin def mat(self):
return self._mat def is_sparse(self):
return false def columns(self):
return self.mat().columns() def __getitem__(self,l):
return self.mat()[l]
def __add__(M, N):
S = Matrix(M.ncols(), M.ncols(), M.base_ring().zero()) if N in M.base_ring():
for i in range(0, M.ncols()):
for j in range(0, M.ncols()):
S[i, j] = M[i, j] + N return S
for i in range(0, M.ncols()):
for j in range(0, M.ncols()):
S[i, j] = M[i, j] + N[i, j]
return MatriceDense(M.base_ring(), S) def __mul__(M, N):
P = Matrix(M.ncols(),M.ncols(),M.base_ring().zero()) if N in M.base_ring():
for i in range(0,M.ncols()):
for j in range(0, M.ncols()):
P[i, j] = N * M[i, j]
return P
for i in range(0,M.ncols()):
for j in range(0,M.ncols()):
P[i,j] = sum(M[i, k] * N[k, j] for k in range(0,M.ncols())) return MatriceDense(M.base_ring(), P)
Entrée [9]:
Entrée [10]:
Out[9]:
Une matrice creuse de taille 10 sur l'anneau Rational Field
Out[10]:
(Rational Field, (1/2, -2), True) class MatriceCreuse(MatriceCarree):
def __init__(self,anneau,size,row,col,val):
assert size >= max(row)+1 assert size >= max(col)+1 assert len(row) == len(col) assert len(row) == len(val) assert len(col) == len(val) #assert is_sorted(row) #assert is_sorted(col) self._taille = int(size) self._row = vector(ZZ, row) self._col = vector(ZZ, col) self._val = vector(anneau, val) self._anneau = anneau
def __repr__(self):
return "Une matrice creuse de taille %s sur l'anneau %s"%(self.nrows(),self.base_ri def ligne(self):
return self._row def colonne(self):
return self._col def coef(self):
return self._val def is_sparse(self):
return true
def mul_vec(M,v): #M creuse, pas v ;v vecteur ligne, renovie M * v^T w = [M.base_ring().zero() for i in range(0,len(v))]
for i in range(0,len(M.ligne())):
w[M.ligne()[i]] = w[M.ligne()[i]] + M.coef()[i] * v[M.colonne()[i]]
return w
def __mul__(M,N): #M creuse, pas N
return MatriceDense(M.base_ring(),matrix(M.base_ring(), [M.mul_vec(v) for v in N.c
macreuse = MatriceCreuse(kk,10,[1,2],[6,8],[1/2,-2]); macreuse
macreuse.base_ring(),macreuse.coef(),macreuse.is_sparse()
Entrée [12]:
Entrée [13]:
Entrée [14]:
Out[11]:
(
Une matrice dense de taille 2 sur l'anneau Rational Field, False, 4, [2 4] [2 3]
[6 8], [4 5]
)
Out[14]:
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 1/2 0 0 0]
[ 0 0 0 0 0 0 0 0 -2 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
madense = MatriceDense(kk,matrix([[1,2],[3,4]])); madense,madense.is_sparse(),madense[1,1],
def random_creuse(anneau,taille,phicoef): # phicoef < 2/3 row = []
col = []
val = []
P = [1-phicoef,phicoef] # 1 avec proba phicoef
X = GeneralDiscreteDistribution(P) # X est une v.a. sur {0, 1} de loi P(X=0) = 1 - phic for i in range(0,taille):
for j in range(0,taille):
if X.get_random_element() == 1:
row.append(i) col.append(j)
val.append(anneau.random_element())
return MatriceCreuse(anneau,taille,row,col,val) # à modifier en [row, col, val, taille]
def creuse_a_pleine(M):
res = matrix(M.base_ring(),M.nrows(),M.nrows(),M.base_ring().zero()) for i in range(0, len(M.ligne())):
res[M.ligne()[i],M.colonne()[i]] = M.coef()[i]
return MatriceDense(M.base_ring(),res)
creuse_a_pleine(macreuse).mat()
Entrée [16]:
Entrée [17]:
Out[15]:
[ 0 0 0 11/2 -9/2 -1 1 0 -8 -1 0 -1/2 2 0 0]
[ 3 0 -2 -1 2 1 5 -111/4 0 -1/2 -3/
2 1/6 -3/4 1/3 0]
[ 0 -1/14 1/12 1/3 0 0 0 -1 0 0 0 0 -3 1/2 2]
[ 0 -6 -1 -1/13 0 -1 0 -1/3 -1/4 1/2 -1/
3 2 0 -1/2 1]
[ 0 0 1/5 0 1 -1/29 -4 -3 1/3 0 0 1/3 0 -26 3]
[ -2/7 1 0 0 -1 0 -1/2 1 0 1 0 1/3 -1 0 11]
[ 0 -1 -1 0 0 0 0 -35 1/21 -1 0 1/36 2 1/7 1]
[ 1 -5 -1/11 0 -1 1 -1/6 -1 12/5 -1 - 1 0 2 0 1/3]
[ 0 0 0 1 0 0 1/2 0 -1 0 0 0 -1 0 0]
[ 1 -2 0 15 0 1 -1/158 -1/2 1/3 0 - 2 24 0 0 -2]
[ 0 1/9 10/3 0 0 -1/2 0 0 -5/2 0 3 0 7 -169/2 -6]
[ -1/3 0 -3/5 1 1 0 2 7 1/2 -1/2 -1/
5 0 -2/9 -3 5]
[ 73 2 0 -1/9 0 0 1 3/2 -2 0 0 0 1 0 5/2]
[ 0 0 0 0 0 1 0 1 1 0 1 0 0 0 -1/19]
[ 0 1 0 -7/13 0 0 -1 0 0 3/4 0 0 -2 -1 0]
Out[17]:
Une matrice creuse de taille 2 sur l'anneau Integer Ring creuse_a_pleine(random_creuse(QQ,15,.7)).mat()
def pleine_a_creuse(M):
row = []
col = []
val = []
for i in range(0,M.nrows()):
for j in range(0,M.ncols()):
if M[i,j] <> M.base_ring().zero():
row.append(i) col.append(j) val.append(M[i,j])
return MatriceCreuse(M.base_ring(),M.nrows(),row,col,val)
pleine_a_creuse(matrix([[0,1],[3,5]]))
Opérations
Entrée [19]:
Entrée [20]:
Entrée [21]:
Comparaisons
Entrée [22]:
Entrée [23]:
Out[18]:
Une matrice dense de taille 2 sur l'anneau Integer Ring
Out[19]:
[0, 7/2, -18, 0, 0, 0, 0, 0, 0, 0]
Out[20]:
Une matrice dense de taille 10 sur l'anneau Rational Field
Out[21]:
Une matrice dense de taille 10 sur l'anneau Rational Field creuse_a_pleine(_)
macreuse.mul_vec(list(1..macreuse.nrows()))
macreuse*creuse_a_pleine(macreuse)
macreuse*matrix.identity(macreuse.nrows())
k = GF(17); n = 50; density=.01;
M = random_creuse(k,n,density) N = matrix.random(k,n,n)
Mdense = creuse_a_pleine(M) Mdense_sage = Mdense.mat()
Mcreuse_sage = Mdense_sage.sparse_matrix()
Entrée [25]:
Entrée [26]:
Entrée [27]:
Exponentiation
Entrée [28]:
CPU times: user 31 ms, sys: 0 ns, total: 31 ms Wall time: 44.4 ms
Out[24]:
Une matrice dense de taille 50 sur l'anneau Finite Field of size 17
CPU times: user 687 ms, sys: 172 ms, total: 859 ms Wall time: 1.02 s
Out[25]:
Une matrice dense de taille 50 sur l'anneau Finite Field of size 17
CPU times: user 0 ns, sys: 16 ms, total: 16 ms Wall time: 4.18 ms
Out[26]:
50 x 50 dense matrix over Finite Field of size 17 (use the '.str()' method t o see the entries)
CPU times: user 32 ms, sys: 0 ns, total: 32 ms Wall time: 122 ms
Out[27]:
50 x 50 dense matrix over Finite Field of size 17 (use the '.str()' method t o see the entries)
time M*N
time Mdense*N
time Mdense_sage*N
time Mcreuse_sage*N
def expo_naif(M,n):
if n == 0:
return identity_matrix(M.base_ring(), M.nrows()) else:
return M * expo_naif(M,n-1)
Entrée [30]:
Entrée [31]:
Entrée [32]:
Entrée [33]:
CPU times: user 453 ms, sys: 94 ms, total: 547 ms Wall time: 629 ms
Out[32]:
Une matrice dense de taille 50 sur l'anneau Finite Field of size 7
CPU times: user 3.52 s, sys: 437 ms, total: 3.95 s Wall time: 7.39 s
Out[33]:
Une matrice dense de taille 50 sur l'anneau Finite Field of size 7 def expo_rap(M,n):
if n == 0:
return identity_matrix(M.base_ring(), M.nrows()) else:
N = expo_rap(M, n // 2) N = N * N
if n % 2 == 0:
return N return M * N
def expo(M,n):
if M.is_sparse():
return expo_naif(M,n) return expo_rap(M,n)
M = random_creuse(GF(7), 50, 1/100) Mdense = creuse_a_pleine(M)
Mdense_sage = Mdense.mat()
Mcreuse_sage = Mdense_sage.sparse_matrix() # .sparse_matrix() convertie en une matrice creu n = 30
Mcreusesage = matrix.random(GF(7), 100, density=.07, sparse=true)
time expo_naif(M,n)
time expo_rap(M,n)
Entrée [35]:
Entrée [36]:
Entrée [37]:
CPU times: user 5.92 s, sys: 797 ms, total: 6.72 s Wall time: 10 s
Out[34]:
Une matrice dense de taille 50 sur l'anneau Finite Field of size 7
CPU times: user 15 ms, sys: 0 ns, total: 15 ms Wall time: 13.1 ms
Out[35]:
50 x 50 dense matrix over Finite Field of size 7 (use the '.str()' method to see the entries)
CPU times: user 16 ms, sys: 0 ns, total: 16 ms Wall time: 5.91 ms
Out[36]:
50 x 50 dense matrix over Finite Field of size 7 (use the '.str()' method to see the entries)
CPU times: user 0 ns, sys: 0 ns, total: 0 ns Wall time: 9.35 ms
Out[37]:
50 x 50 dense matrix over Finite Field of size 7 (use the '.str()' method to see the entries)
time expo_rap(Mdense,n)
time expo_naif(Mdense_sage,n)
time expo_rap(Mdense_sage,n)
time Mdense_sage^n
Entrée [39]:
Entrée [40]:
2 Méthode de la puissance
Entrée [45]:
3 Suites récurrentes linéaires
Entrée [46]:
CPU times: user 203 ms, sys: 16 ms, total: 219 ms Wall time: 252 ms
Out[38]:
50 x 50 dense matrix over Finite Field of size 7 (use the '.str()' method to see the entries)
CPU times: user 15 ms, sys: 0 ns, total: 15 ms Wall time: 33.7 ms
Out[39]:
50 x 50 dense matrix over Finite Field of size 7 (use the '.str()' method to see the entries)
CPU times: user 0 ns, sys: 31 ms, total: 31 ms Wall time: 5.04 ms
Out[40]:
50 x 50 sparse matrix over Finite Field of size 7 (use the '.str()' method t o see the entries)
time expo_naif(Mcreuse_sage,n)
time expo_rap(Mcreuse_sage,n)
time Mcreuse_sage^n
#MnR = MatrixAlgebras()
K = QQ
Entrée [49]:
Entrée [50]:
Entrée [51]:
Entrée [52]:
Entrée [53]:
Out[49]:
[X - 1, 0]
Out[50]:
[X^2 + X + 1, 0]
Out[51]:
[X, 2]
Out[52]:
[X^2 - X - 1, 3*X + 3]
Out[53]:
(X^2 - X - 1, 3*X + 3)
def division(A, B): # A, B sont dans KX ; renvoie [quotient, reste]
if B == KX.zero():
raise ValueError, "le quotient est nul"
if B.degree() > A.degree(): # le degré du polynôme nul est -1 return [KX.zero(), A]
Qloc = A.leading_coefficient() / B.leading_coefficient() * X^(A.degree() - B.degree()) respart = division(A - Qloc * B, B)
return [Qloc + respart[0], respart[1]]
division(X^2 - 1, X+1)
division(X^3-1,X-1)
division(X^2 + X + 2,X+1)
division(X^4+1,X^2+X+2)
(X^4+1).quo_rem(X^2+X+2)
Entrée [55]:
Entrée [56]:
Entrée [57]:
Entrée [58]:
Out[55]:
X^2 + 1
Out[56]:
X^2 + 1
def euclide(A, B): # A, B dans KX non tous nuls ; renvoie le pgcd unitaire de A et B via l' R0 = A
R1 = B
while R1 <> KX.zero():
R = R0 R0 = R1
R1 = division(R, R1)[1]
return R0 / R0.leading_coefficient()
euclide(X^4-1,X^3+X)
gcd(X^4-1,X^3+X)
def euclide_etendu_restr(A, m): # on fait l'algo d'Euclide à A et X^2m, mais on s'arrête dè R0 = A
R1 = X^(2*m) U0 = KX.one() U1 = KX.zero() V0 = KX.zero() V1 = KX.one() # U0 A + V0 B = R0 while R1.degree() >= m:
d = division(R0, R1) R0 = R1
R1 = d[1]
U = U0 V = V0 U0 = U1 V0 = V1
U1 = U - U0 * d[0]
V1 = V - V0 * d[0]
return U1
euclide_etendu_restr(X^2-X-1,2)
4 Inverse d'une matrice creuse
Entrée [60]:
Entrée [61]:
Entrée [62]:
Entrée [63]:
Out[59]:
(1, 3*X^3 - 2*X^2 + X - 1, -3*X + 5)
Out[62]:
[1 2]
[0 1]
Out[63]:
[ 1 -2]
[ 0 1]
xgcd(X^2 - X -1,X^4)
K = QQ
def pol_ann_en_inv(P, M): #P annulateur de M, renvoie M^-1 puiss = P.exponents()
if puiss[0] <> 0:
raise ValueError, "le polynôme ne possède pas de terme constant"
coeff = P.coefficients() #mode creux, comme puiss
# on doit renvoyer -sum(expo(M, puiss[i] - 1) * coeff[i] for i in range(1,len(coeff))) puissM = matrix.identity(M.base_ring(), M.nrows())
res = matrix.zero(M.base_ring(), M.nrows()) puiss[0] = 1
for i in range(1, len(puiss)):
for j in range(puiss[i-1], puiss[i]):
puissM = M * puissM
# puissM est maintenant M^(puiss[i] - 1) res = puissM * coeff[i] + res
return res * (-1 / coeff[0])
mamat = matrix([[1,2],[0,1]]); mamat
pol_ann_en_inv(X^2-2*X+1,mamat)
Entrée [65]:
Entrée [69]:
Entrée [70]:
Entrée [71]:
Entrée [72]:
Out[64]:
[ 1 -2]
[ 0 1]
Out[65]:
[ 1 -2]
[ 0 1]
Out[69]:
[ 1 0 1 -2]
[-1 0 0 -1]
[ 0 -1 -1 -1]
[ 0 2 0 0]
Out[70]:
[ 1/4 -3/4 1/4 1/8]
[ 0 0 0 1/2]
[ 1/4 1/4 -3/4 -3/8]
[-1/4 -1/4 -1/4 -1/8]
Out[71]:
[1 0 0 0]
[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
pol_ann_en_inv(X^2 - 2*X + 1,MatriceDense(QQ,mamat))
pol_ann_en_inv(X^2 - 2*X + 1, pleine_a_creuse(MatriceDense(QQ,mamat)))
mamat = matrix.random(K,4); mamat
pol_ann_en_inv(mamat.characteristic_polynomial(),mamat)
_*mamat
Entrée [74]:
Entrée [75]:
Entrée [76]:
Out[73]:
-X^2 + X + 1
Out[75]:
6069298007649371338953278671329/13988103834131136374639461553351*X^4 + 60692 98007649371338953278671329/13988103834131136374639461553351*X^2 - 3034649003 8246856694766393356645/13988103834131136374639461553351*X - 4855438406119497 0711626229370632/13988103834131136374639461553351
Out[76]:
[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
[0 0 0 0]
trouve_pol_ann_suite([0,1,1,2,3,5,8])
def trouve_pol_ann(M):
# M est creuse
# on veut trouver un polynôme annulateur de degré n (la taille de M) # ... donc e = n
e = M.ncols()
x = vector(K.random_element() for i in range(0, M.ncols())) y = vector(K.random_element() for i in range(0, M.ncols())) My = y
U = [0 for i in range(0, 2*e)]
for i in range(0, 2*e):
U[i] = x * My
My = vector(M.mul_vec(My)) return trouve_pol_ann_suite(U)
# on a bien deg R < e (sinon U serait tout le temps nul)
trouve_pol_ann(pleine_a_creuse(mamat))
_(mamat)
Entrée [78]:
Entrée [79]:
Entrée [80]:
Entrée [81]:
Out[77]:
[ 0 0 0 0 1/2 0 -9 6/19 0 1]
[ 0 0 1/2 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 0 0 0 4/11 0 0 0 0]
[ 0 0 0 0 0 0 0 0 0 0]
[ 0 0 -2 0 0 0 0 0 0 0]
[ 0 0 0 0 0 13/2 0 0 0 0]
[ 0 0 -1 0 0 3 0 0 -5 0]
[ 0 0 0 0 0 0 0 -8 0 0]
Out[78]:
272868624574203272592341138144129249862203078312056345653001916851585408561/
1221764729207972438622472012367319362578429953779113583024604394069602750000 00*X^5 + 2728686245742032725923411381441292498622030783120563456530019168515 85408561/2443529458415944877244944024734638725156859907558227166049208788139 2055000000*X^4
Out[79]:
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0 0 0]
M = random_creuse(K,10,.2); creuse_a_pleine(M).mat()
trouve_pol_ann(M)
_(creuse_a_pleine(M).mat())
def inverse(M):
return pol_ann_en_inv(trouve_pol_ann(M), M)
Entrée [83]:
Entrée [84]:
Entrée [ ]:
Out[82]:
[ -2643795/12437527 1656900/12437527 1715175/12437527 -32106 060/12437527 -1922760/12437527 5351010/12437527 32106060/124375 27 -26182485/12437527 381150/12437527 -20560701/12437527]
[ 2854005/24875054 -77055/24875054 -412299/12437527 7059 900/12437527 1037820/12437527 -1176650/12437527 -7059900/124375 27 -11444529/24875054 -91622/12437527 17261387/37312581]
[ 377685/12437527 -236700/12437527 -245025/12437527 4586 580/12437527 274680/12437527 -764430/12437527 -4586580/124375 27 3740355/12437527 -54450/12437527 15374770/12437527]
[ 3695230/12437527 7953670/12437527 3764412/12437527 -78359 600/12437527 2687440/12437527 39179800/37312581 78359600/124375 27 -151907466/12437527 50586644/12437527 -51973128/12437527]
[-1018292275/298500648 27140435/298500648 11687475/49750108 -69515 525/37312581 -92572025/37312581 69515525/223875486 69515525/373125 81 -145248215/99500216 3895825/74625162 -295612945/49750108]
[ 5212053/24875054 -1633230/12437527 -3381345/24875054 31647 402/12437527 1895292/12437527 7162960/12437527 -31647402/124375 27 51616899/24875054 -375705/12437527 19023224/12437527]
[ -1678985/24875054 -659345/24875054 31149/12437527 74 780/12437527 -610540/12437527 -37390/37312581 -74780/124375 27 -1793865/24875054 6922/12437527 -1184751/12437527]
[ -1678985/24875054 -659345/24875054 31149/12437527 12512 307/12437527 -610540/12437527 -37390/37312581 -74780/124375 27 -1793865/24875054 6922/12437527 -1184751/12437527]
[ -11558701/24875054 198820/12437527 3390957/24875054 -4230 900/12437527 -4203164/12437527 705150/12437527 4230900/124375 27 -5385015/24875054 376773/12437527 -10717884/12437527]
[ -74865017/74625162 -659345/522376134 10383/87062689 747 80/261188067 -87220/37312581 -37390/783564201 -74780/2611880 67 -597955/174125378 6922/261188067 -394917/87062689]
Out[83]:
Une matrice dense de taille 10 sur l'anneau Rational Field
Out[84]:
'[1 0 0 0 0 0 0 0 0 0]\n[0 1 0 0 0 0 0 0 0 0]\n[0 0 1 0 0 0 0 0 0 0]\n[0 0 0 1 0 0 0 0 0 0]\n[0 0 0 0 1 0 0 0 0 0]\n[0 0 0 0 0 1 0 0 0 0]\n[0 0 0 0 0 0 1 0 0 0]\n[0 0 0 0 0 0 0 1 0 0]\n[0 0 0 0 0 0 0 0 1 0]\n[0 0 0 0 0 0 0 0 0 1]' inverse(M)
M*_
_.mat().str()