bonjour.
j'ai besoin d'une fonction qui donne une base du noyau d'une matrice de dimension m*n.
j'ai trouvé une page qui détaille le code d'un algorithme en language xcas, un pseudo c, sur cette page:
http://www-fourier.ujf-grenoble.fr/~parisse/giac/doc/fr/casrouge/node263.html
il s'agit de la methode de gauss-jordan. je sais qu'elle est implantée d'office sur ams mais la fonction ne convient pas pour le calcul exact, elle donne des arrondis dans tous les sens... peu pratique
j'essaie de le traduire en basic, voici le code proposé (ces commentaires ne sont pas de moi) :
gaussjordan_noyau(M):={
local pivo,jc,jl,k,j,nl,nc,temp,l,a,noyau;
nl:=nrows(M);
nc:=ncols(M);
//on met des 0 sous la diagonale
jc:=0;
jl:=0;
// on traite toutes les colonnes
while (jc<nc and jl<nl) {
//choix du pivot que l'on veut mettre en M[jl,jc]
k:=jl;
while (M[k,jc]==0 and k<nl-1) {k:=k+1;}
//on ne fait la suite que si on a pivo!=0
if (M[k,jc]!=0) {
pivo:=M[k,jc];
//echange de la ligne jl et de la ligne k
for (l:=jc;l<nc;l++){
temp:=M[jl,l];
M[jl,l] := M[k,l];
M[k,l]:=temp;
}
//fin du choix du pivot qui est M[jl,jc]
//on met 1 sur la diagonale de la colonne jc
for (l:=0;l<nc;l++) {
M[jl,l]:=M[jl,l]/pivo;
}
//on met des 0 au dessus de la diagonale de la colonne jc
for (k:=0;k<jl;k++) {
a:=M[k,jc];
for (l:=0;l<nc;l++){
M[k,l]:=M[k,l]-M[jl,l]*a;
}
}
//on met des 0 sous la diagonale de la colonne jc
for (k:=jl+1;k<nl;k++) {
a:=M[k,jc];
for (l:=jc;l<nc;l++){
M[k,l]:=M[k,l]-M[jl,l]*a;
}
}
}
else{
//on ajoute une ligne de 0 si ce n'est pas le dernier zero
if (jl<nc-1){
for (j:=nl;j>jl;j--){
M[j]:=M[j-1];
}
M[jl]:=makelist(0,1,nc);
nl:=nl+1;
}
}
//ds tous les cas,le numero de colonne et de ligne augmente de 1
jc:=jc+1; jl:=jl+1;
//il faut faire toutes les colonnes
if (jl==nl and jl<nc) { M[nl]:=makelist(0,1,nc);nl:=nl+1;}
}
noyau:=[];
//on enleve les lignes en trop pour avoir une matrice carree de dim nc
//on retranche la matrice identite
M:=M[0..nc-1]-idn(nc);
for(j:=0;j<nc;j++){
if (M[j,j]==-1) {noyau:=append(noyau,M[0..nc-1,j]);}
}
return noyau;
}
et voici ce que j'ai réussi à en tirer pour l'instant :
la fonction disponible ici :
http://membres.lycos.fr/xantares/main.matker.89f
voici le code :
matker(m)
Func
Local pivo,jc,jl,k,j,nl,nc1,temp,l,a,noyau
rowDim(m)nl
// nc est remplacée par nc1 car variable réservée
colDim(m)->nc1
0->jc
0->jl
While jc<nc1 and jl<nl
jl->k
While m[k+1,jc+1]=0 and k<nl-1
k+1->k
EndWhile
If m[k+1,jc+1]?0 Then
m[k+1,jc+1]pivo
For l,jc,nc1-1
m[jl+1,l+1]temp
m[k+1,l+1]m[jl+1,l+1]
tempm[k+1,l+1]
EndFor
For l,0,nc1-1
m[jl+1,l+1]/pivom[jl+1,l+1]
EndFor
For k,0,jl-1
m[k+1,jc+1]a
For l,0,nc1-1
m[k+1,l+1]-m[jl+1,l+1]*am[k+1,l+1]
EndFor
EndFor
For k,jl+1,nl-1
m[k+1,jc+1]->a
For l,jc,nc1-1
m[k+1,l+1]-m[jl+1,l+1]*a->m[k+1,l+1]
EndFor
EndFor
Else
If jl<nc1-1 Then
// là j'ajoute une ligne à la matrice m.
(augment(m™,newMat(nc1,1)))™->m
For j,nl,jl+1,1
For k,0,nc1-1
m[j-1+1,k+1]->m[j+1,k+1]
EndFor
EndFor
For j,0,nc1-1
0m[jl+1,j+1]
EndFor
nl+1nl
EndIf
EndIf
jc+1->jc
jl+1->jl
If jl=nl and jl<nc1 Then
For j,0,nc1-1
0m[nl+1,j+1]
EndFor
nl+1nl
EndIf
EndWhile
// il n'y a pas commme pour les listes l'élément neutre {} donc je rajoute un vecteur de zéros
newMat(nc1,1)noyau
subMat(m,1,1,nc1,nc1)-identity(nc1)m
For j,0,nc1-1
If m[j+1,j+1]=1 Then
// là je on colle un vecteur à noyau
augment(noyau,subMat(m,1,j,nc1,j))noyau
EndIf
EndFor
Return noyau
EndFunc
je suppose que le bout de code :
{noyau:=append(noyau,M[0..nc-1,j]);}
signifie que l'on rajoute à la matrice noyau le vecteur j de la matrice m d'où mon code:
augment(noyau,subMat(m,1,j,nc1,j))noyau
-aver les carrés représentant l'affectation ->
(fait avec tiedit pis je peux pas remplacer)
-comme pour le c il y a un décalage des indexs des listes donc j'ai mis +1 dans les appels des listes. (partout)
-la fonction makelist, apelée makelist(0,1,nc) est équivalente d'apres le site à seq(i,i,1,nc)
mais en basic les matrices ne sont pas des listes de listes (du mois ce qu'on en voit quand on programme) : dans ce language xcas m(i) designe la liste représentant la ligne i de la matrice m.
-La commande append(l,elem) permet de mettre à la fin d'une liste l, un élément (ou une liste) elem.
finalement cette fonction ne fonctionne que partiellement puisque je n'obtiens que 1 vecteur
des 2 vecteurs de la base si le noyau a dim 2 et aucun vecteur si la base a dim 1, en dehors du fait que je rajoute le vecteur nul manuellement à l'initialisation de la variable de sortie noyau.
il ya peut être de l'espoir car le vecteur obtenu est exact et correspond à l'exemple donné.
c'est donc ici qu'il y a une cou**** comme on dit dans le jargon informatique.
s'il y a des allergiques au maths ne fuyez pas tout de suite c juste un probleme conversion. (peut-être que vous avez déjà fui en fait devant mon pavé là).
si quelqu'un a vu la faille ou a déjà programmé une fonction similaire je suis intéressé.
merci d'avoir tout lu.
-Edité le Dimanche 12 mars 2006 à 20:11 par Xantares-