Calcul formel : Mode d'emploi - Exemples en Maple
Claude Gomez, Bruno Salvy, Paul Zimmermann
Masson, 1995
Chapitre V, section 3.4, exercice 2, page 142.
Philippe.Dumas@inria.fr
http://algo.inria.fr/dumas/Maple/
|
|
La procédure demandée prend en entrée l'expression du polynôme et l'ensemble ou la liste des variables (l'expression du polynôme pourrait comporter d'aures variables). On vérifie d'abord que l'on a bien affaire à un polynôme par rapport à ces variables (#1). Ensuite on collecte le polynôme par rapport à ses variables pour garantir le calcul du degré et des coefficients (#2). On vérifie que le degré est bien au plus 2 (#3). Le nombre de variables donne la taille des matrices (#4). Pour pouvoir écrire les matrices comme des tableaux il faut que les ensembles d'indices soient ordonnés. On ordonne donc les variables si nécessaire (#5) et en prime on élimine les redondances éventuelles dans la liste. Ensuite on repère les composantes homogènes de degré 0, 1 et 2 (#6). Après quoi, il ne reste plus qu'à construire les matrices (#7). On peut hésiter sur la forme à employer pour le vecteur ; nous avons préféré la structure d'une matrice de type nx1 plutôt que la structure batârde vector. Enfin on renvoie les trois composantes demandées et la liste des variables, ce qui permet d'interpréter les matrices (#8). Il faut noter que l'on pouvait employer moins de variables locales, mais le code est plus lisible ainsi.
> dismantle:=proc(Phi,vars::{set,list})
local Psi,n,V,d,A,i,j,b;
if not (type(Phi,polynom(anything,vars)) then #1
ERROR("Phi is expected to be a polynom with respect to ",
vars," but dismantle received ",Phi, vars)
fi;
Psi:=collect(Phi,vars); #2
if not degree(Psi,vars)<=2 then #3
ERROR("Phi is expected to have degree at most 2,
but dismantle received ",Phi, vars)
fi;
n:=nops(vars); #4
if type(vars,set) then #5
V:=[op(vars)]
else
V:=[op({op(vars)})]
fi;
Psi:=collect(subs(seq(v=t*v,v=V),Psi),t); #6
for d from 0 to 2 do
Psi.d:=coeff(Psi,t,d)
od;
A:=array(1..n,1..n,symmetric); #7
for i to n do
A[i,i]:=coeff(Psi2,V[i],2);
for j from i+1 to n do
A[i,j]:=coeff(coeff(Psi2,V[i],1),V[j],1)/2
od
od;
b:=array(1..n,1..1);
for i to n do
b[i,1]:=coeff(Psi1,V[i],1)
od;
eval(A),eval(b),Psi0,V #8
end:
Nous testons les exemples rencontrés dans le texte.
> dismantle(7/8*x^2-sqrt(3)/4*x*y+5/8*y^2+2*x+2*sqrt(3)*y+7,
{x,y});
> dismantle(z-(7/8*x^2-sqrt(3)/4*x*y+5/8*y^2+2*x+2*sqrt(3)*y+7),
{x,y,z});
Nous testons aussi un exemple où figure une variable non polynomiale.
> dismantle(x^2-2*x*y*cos(theta)+y^2+x*cos(theta)+y*sin(theta),
[x,y]);