3 ; ***************************************************************
5 ; * MANIPULATIONS DE FONCTIONS SYMETRIQUES *
6 ; * (version01: Commonlisp pour Maxima) *
8 ; * ---------------------- *
11 ; * (Mathe'matiques Effectives, De'veloppements Informatiques, *
12 ; * Calculs et Ingenierie, Syste`mes) *
13 ; * LITP (Equipe Calcul Formel) *
14 ; * Universite' Paris 6, *
15 ; * 4 place Jussieu, 75252 Paris cedex 05. *
16 ; * e-mail : avb@sysal.ibp.fr *
17 ; ***************************************************************
19 ;=============================================================================
20 ; CALCULS D'IMAGES DIRECTES, D'ORBITES ...
21 ; DANS LE CAS LE PLUS GENERAL
22 ; LA FONCTION resolvante PEUX ETRE AMENEE A UTILISER CE PROGRAMME
23 ; LORSQUE LA FONCTION RESOLVANTE N'A AUCUNE PROPRIETE EXPLOITABLE
24 ; Si CE N'EST SON ARITE EN COMPARAISON DES DEGRES DES POLYNOMES A TRANSFORMER
25 ;===========================================================================
29 (macsyma-module directnew
)
33 ((lambda ()) ((mlist) $list_pol $x $fonction $list_list_var
)
34 ((mprog) (($operation
))
35 (($direct_init
) $list_pol $x $fonction $list_list_var
)))
37 (add2lnc '(($direct
) $list_pol $x $fonction $list_list_var
) $functions
)
39 ((lambda ()) ((mlist) $fonction $list_var
)
40 ((mprog) (($operation
)) (($orbit_init
) $fonction $list_var
)))
42 (add2lnc '(($orbit
) $fonction $list_var
) $functions
)
43 (mdefprop $multi_orbit
44 ((lambda ()) ((mlist) $fonction $list_var
)
45 ((mprog) (($operation
)) (($multi_orbit_init
) $fonction $list_var
)))
47 (add2lnc '(($multi_orbit
) $fonction $list_var
) $functions
)
49 ((lambda ()) ((mlist) $multi_orbit $list_list_var $ldegre
)
50 ((mprog) (($operation
))
51 (($pui_direct_init
) $multi_orbit $list_list_var $ldegre
)))
53 (add2lnc '(($pui_direct
) $multi_orbit $list_list_var $ldegre
) $functions
)
55 ;============================================================================
57 ; P1,....,Pp polynomes dans k[X^i] et de degre di respectivement
58 ; X^i = (x^i_1, x^i_2, ..., x^i_di) pour i= 1 ... p
59 ; X = (X^1,X^2,...,X^p)
60 ; P polynome dans k[X]
61 ; ON CALCUL P_*(P1,...,Pp)
62 ;============================================================================
63 ; DECLARATIONS AU COMPILATEUR FRANZLISP
68 (defvar sauvedrapeau
))
74 ; Franz Lisp declaration 'localf' is currently untranslated
76 ;============================================================================
77 ; Orbite d'un polynome dans k[y1,...,yn] sous S_n
78 ; k eventuellemnt anneau de polynomes
79 ;----------------------------------------------------------------------------
80 ; On fait permuter ses variables et on l'applique a chacune
81 ; de ces permutations. Puis on elimine les egaux au fur et
83 ;----------------------------------------------------------------------------
84 (defun $orbit_init
($p $lvar
) (cons '(mlist) (orbit $p $lvar
)))
85 (defun orbit ($p $lvar
)
86 (let ((p_dist (lect $p $lvar
))
88 (orbit2 list$pol p_dist
(cdr $lvar
) nil
)
90 ; les permutations circulaires ne changeraient rien
91 (defun orbit2 (list$pol p_dist f_lvar d_lvar
)
93 (mapc #'(lambda (f_lvar2)
94 (let (($pol
(ecrit_pol p_dist
(append d_lvar f_lvar2
))))
95 (or (contient list$pol $pol
)
96 (flet ((franz.attach
(newelt oldlist
)
97 "equivalent to Franz Lisp 'attach'."
100 (cons (car oldlist
) (cdr oldlist
)))
101 (rplaca oldlist newelt
))))
102 (franz.attach $pol list$pol
))))
103 (orbit2 list$pol p_dist
(cdr f_lvar2
)
104 (append d_lvar
(list (car f_lvar2
)))))
105 (permut_circu (cdr f_lvar
) (list (car f_lvar
))))
106 (orbit2 list$pol p_dist
(cdr f_lvar
)
107 (append d_lvar
(list (car f_lvar
))))))
108 ; on ne ramene pas l'identite
109 (defun permut_circu (debut fin
)
111 ((null (cdr debut
)) (list (cons (car debut
) fin
)))
112 (t (cons (append debut fin
)
113 (permut_circu (cdr debut
) (cons (car debut
) fin
))))))
114 (defun contient (list$pol $pol
)
117 (mapc #'(lambda ($pol2
)
118 (and (meval (list '($is
)
119 (list '(mequal) $pol $pol2
)))
123 ;==========================================================================
124 ; CALCUL DE L'ORBITE DU POLYNOME P SOUS S_d1xS_d2x...xS_dp
125 ;--------------------------------------------------------------------------
126 (defun $multi_orbit_init
($p $llvar
)
127 (cons '(mlist) (multi_orbit_init $p
(cdr $llvar
))))
129 (defun multi_orbit_init ($p llvar
)
131 ((null llvar
) (list $p
))
132 (t (multi_orbit (orbit $p
(car llvar
)) nil
(cdr llvar
)))))
133 ; On se deplace en largeur dans l'arbre ie. on fait agir tout S_i avant
134 ; de passer a S_(i+1).
135 ; En d'autres termes : On calcul l'orbite du polynome P sous
136 ; S_1 x ... x S_i et on en deduit son orbite sous S_1 x ... x S_(i+1).
137 ; Quand on passe a S_(i+1) si un des polynomes generes par l'action de
138 ; S_(i+1) (sur un polynome q de l'etape S_i ) est egal a un
139 ; polynome r (distinct de q bien entendu!) genere par
140 ; l'action de S_i on elimine froidement r. (Pourquoi refaire ce qui vient
142 ; au depart i = 1 et llvar = (X^2 X^3 ... X^p) (cf. probleme general)
143 ; on a toute l'orbite sous S_1 x ... x S_(i+1).
146 ; on ote de lpoli les polynomes communs a orbit
147 (defun multi_orbit (lpoli lpoli
+1 llvar
)
151 ((null (cdr llvar
)) lpoli
+1)
152 (t (multi_orbit lpoli
+1 nil
(cdr llvar
)))))
153 (t (let ((orbit (orbit (car lpoli
) (car llvar
))))
154 (epure lpoli
(cons nil
(copy-tree orbit
)))
155 (multi_orbit (cdr lpoli
) (nconc orbit lpoli
+1) llvar
)))))
156 ; Que fait epure? He bien il enleve physiquement de (cdr l1) tout
157 ; les polynomes se trouvant eventuellement dans (cdr l2) en les diminuant
158 ; toutes deux physiquement.
165 ; car on calcul la difference
166 ; on l'a retire de l2 (ne reviendra pas)
167 (epure (rplacd l1
(cddr l1
)) l2
)) ; allez! oust!
168 ; l2 diminue' physiquement egalement
169 (t (epure (cdr l1
) l2
)))))
171 ; on regarde si l'oppose de $-pol est dans l2
172 ; si oui on le retire de l2 et on repond : t sinon : nil
174 (defun dans (l2 $pol
)
177 ((meval (list '($is
) (list '(mequal) (cadr l2
) $pol
)))
178 (rplacd l2
(cddr l2
))
179 ; on en profite pour le retirer de l2
181 (t (dans (cdr l2
) $pol
)))))
183 ;=========================================================================
184 ; REMARQUE SUR CE QUI PRECEDE
185 ;=========================================================================
186 ; On peut se demander : Pourquoi ne pas lire une seule fois
187 ; le polynome en le mettant sous la forme d'une
188 ; liste (c m1 m2 ... mp) representant cm1m2...mp ? ou c est
189 ; un element de k et chaque mi un monome de k[X^i].
190 ; Ceci n'a pas ete fait pour 3 raisons
191 ; la premiere etant que la donnee d'entree (le polynome P) est
192 ; forcement petite (sinon les calculs satureront par la suite)
193 ; et que le calcul de sa multi_orbite est negligeable devant
194 ; ce qui l'attend. Alors au vu des difficultes mises en evidence
195 ; par les deux autres raisons on se dit que ce n'est vraiment
197 ; la seconde est qu'on est amene a comparer l'egalite des polynomes
198 ; a chaque etape i de multi_orbit. Et que meme si les monomes
199 ; de k[X^1,...,X^(i-1)] sont mis en coefficients comment fait-on
200 ; pour ceux dependant des X^q (q > i)?
201 ; La troisieme est que le coefficient lie a un monome en X^i est
202 ; en fait un polynome en les autres groupe de variables et qu'il
203 ; faudra bien les reunir d'une facon ou d'une autre.
204 ; Apres maintes considerations j'ai opte pour la version decrite
205 ; precedemment qui oblige a repasser le lecteur sur le polynome et ses
206 ; permute's a chaque fois que l'on veut calculer son orbite sous S_di.
207 ;===========================================================================
208 ; CALCUL DES FONCTIONS PUISSANCES
209 ; SOUS FORME CONTRACTE SOUS S_d1 x ... x S_dp = S_D
210 ; SOIT O = {f1,f2, ...,fo} des polynomes en X^1, en X^2, ... et
211 ; en X^p. On cherche les fonctions puissances P_r(O) (r= 1..o)
212 ; sur O mais dans une forme contracte sous
213 ; S_D (O etant bien constitue pour que cela soit possible).
214 ;(ie. ne prendre qu'un monome par orbite)
215 ;-----------------------------------------------------------------------------
218 ; X^1=(x,y) elementaires : e1, e2, puissances : p1, p2
219 ; X^2=(a,b) elementaires : f1, f2, puissances : g1, g2.
220 ; O = (ax + by , ay + bx)
221 ; P_1(O) = ax + by + ay + bx = (a + b)(x +y)
222 ; forme contracte : ax
223 ; P_1(O) = e1*f1 = p1*g1
224 ; P_2(O) = (ax + by)^2 + (ay + bx)^2
225 ; = a^2x^2 + b^2y^2 + a^2y^2 + b^2y^2 + 2(axby + aybx)
226 ; = (a^2 + b^y^2)(x^2 + y^2) + 4axby
227 ; forme contracte : a^2x^2 + 4axby
228 ; P_1(O) = (e1^2 - 2e2)(f1^2 - 2f2) + 4e2f2
229 ; = p2g2 + (p1^2 - p2)(g1^2 -g2)
230 ;-----------------------------------------------------------------------------
232 ; SE DEBARASSER SYSTEMATIQUEMENT DE TOUT MONOMES SI ON EN A DEJA
233 ; UN DANS SA MULTI_ORBITE AFIN D'EVITER AU MIEUX L'EXPLOSION EN ESPACE.
234 ; CE QUI EXPLIQUE EN PARTIE POURQUOI ON PREFERE LES FONCTIONS PUISSANCES
235 ; AUX FONCTIONS SYMETRIQUES ELEMENTAIRES SUR O.
236 ; On ne garde que les monomes representes par des multipartitions.
237 ; Remarque : il serait plus efficace d'utiliser le logiciel de
238 ; Jean-Charles Faugere.
239 ;-----------------------------------------------------------------------------
240 ; 1_ l'appel et la boucle principale
241 ; on retire le degre en tete
242 (defun $pui_direct_init
($or $llvar $ldegre
)
244 (cdr (pui_direct (cdr $or
)
245 (mapcar 'cdr
(cdr $llvar
))
248 (defun pui_direct (or llvar ldegre
)
250 (ldegre_arite (mapcar 'list
252 (mapcar 'list-length llvar
)))
253 (degre_resol (* (list-length or
) ;le degre de P_*(P1,...,Pp)
254 (apply '* (mapcar #'(lambda (nb) (apply
257 (do ((o (and (print degre_resol
) (1- degre_resol
))
258 (and (print o
) (1- o
)))
259 (listpui (list (pui_contract 0 or llvar degre_resol ldegre_arite
))
260 (cons (pui_contract 0 or llvar o ldegre_arite
) listpui
)))
261 ((eql 0 o
) (cons degre_resol listpui
)))))
263 ; 2_ Obtention de la rieme fonction puissance
264 ; dans Or on a des polynomes macsyma
265 ; dans $pui_contract des polynomes sous formes contractees
266 ; on ne conserve que les monomes dont les exposants correspondent a des
268 ; Ramene un polynome macsyma
269 ;-----------------------------------------------------------------------
270 (defun pui_contract ($pui_cont or llvar r ldegre_arite
)
272 ((null or
) $pui_cont
)
274 ($add_sym
(multi_partitions ($exp_sym
(car or
) r
)
278 (cdr or
) llvar r ldegre_arite
))))
280 ; on jette les momones a exposants non multi_partitionne dans $pol.
281 ; map applique a toute les sous-listes et rend son deuxieme arguments
282 ; ie. la premiere liste.
284 (defun multi_partitions ($pol llvar ldegre_arite
)
285 (do ((rllvar (cdr (reverse llvar
)) (cdr rllvar
))
286 (rldegre_arite (cdr (reverse ldegre_arite
)) (cdr rldegre_arite
))
287 (pol_multipartitionne
288 (garde_que_partition_init (cons nil
290 (cons '(mlist) (car (last
292 (car (last ldegre_arite
)))))
294 (if pol_multipartitionne
295 (multi_ecrit pol_multipartitionne llvar
) 0))
296 (setq pol_multipartitionne
298 (mapl #'(lambda (p_m)
302 (cons nil
(lect (caar p_m
)
305 (car rldegre_arite
)))))
306 pol_multipartitionne
)))))
308 ; le coefficient binomial permet de tenir compte de l'arite'
309 ; de la fonction resolvante.
311 (defun garde_que_partition_init ($pol_dist degre_arite
)
312 (do ((pol $pol_dist
) (degre (car degre_arite
)) (arite (cadr degre_arite
)))
313 ((null (cdr pol
)) (cdr $pol_dist
))
314 (let ((exposants (cdadr pol
)))
316 ((apply #'>= exposants
)
318 (let ((lg (longueur exposants
)))
319 (rplaca pol
(list ($mult_sym
(caar pol
)
320 (binomial (- degre lg
)
323 (t (rplacd pol
(cddr pol
)))))))
325 ; remarque en common lisp : (>= 4 3 2 1 0) ==> true permet de tester
326 ; si une liste est une partition
328 (defun garde_que_partition ($pol_dist degre_arite
)
330 (degre (car degre_arite
))
331 (arite (cadr degre_arite
)))
332 ((null (cdr pol
)) (cdr $pol_dist
))
333 (let ((exposants (cdadr pol
)))
335 ((apply '>= exposants
)
337 (let ((lg (longueur exposants
)))
339 ($mult_sym
(caar pol
)
340 (binomial (- degre lg
)
342 (t (rplacd pol
(cddr pol
)))))))
344 (defun distribu (multipartition pol_part
)
345 (mapcar #'(lambda (coe_partition)
346 (cons (car coe_partition
)
347 (cons (cdr coe_partition
) multipartition
)))
349 ;=========================================================================
350 ; BOUCLE PINCIPALE DE L'IMAGE DIRECTE
351 ;=========================================================================
352 (defun $direct_init
($lpol $x $p $llvar
)
353 (direct (cdr $lpol
) $x $p $llvar
))
355 (defun direct (l$pol $x $p $llvar
)
356 (cond ((equal '$parallele $directnew
)
357 (direct-parallele l$pol $x $p $llvar
))
360 ($multi_base
(if (equal '$elementaire $direct
)
361 (macsy_list (multi_polynome2ele l$pol $x
))
362 (multi_ele2pui (multi_polynome2ele l$pol $x
))))
363 (pui_* (pui_direct (multi_orbit_init $p
(cdr $llvar
))
364 (mapcar 'cdr
(cdr $llvar
))
365 (mapcar 'cadr
(cdr $multi_base
) )))
369 (mapcar #'(lambda ($pi
)
376 ; Ici on calcule les fonctions puissances des racines de la resolvante
377 ; au fur et a mesure. Avant nous calculions les fonctions puissances
378 ; des racines de la resolvante generique sur la base des formes
379 ; monomiales et ensuite on specialisait. En fait nous n'exploitions
380 ; pas l'aspect parallele du calcul.
382 (defun direct-parallele (l$pol $x $p $llvar
)
384 (llvar (mapcar 'cdr
(cdr $llvar
)))
385 ($multi_base
(if (equal '$elementaire $direct
)
386 (macsy_list (multi_polynome2ele l$pol $x
))
387 (multi_ele2pui (multi_polynome2ele l$pol $x
))))
388 (multi_orbite (multi_orbit_init $p
(cdr $llvar
)))
389 (ldegre (mapcar 'cadr
(cdr $multi_base
) )) ; degres des polynomes
390 (ldegre_arite (mapcar 'list
392 (mapcar 'list-length llvar
)))
393 (degre_resol (* (list-length multi_orbite
) ;le degre de P_*(P1,...,Pp)
394 (apply '* (mapcar #'(lambda (nb) (apply
397 (do ((r (and (print degre_resol
) (1- degre_resol
))
398 (and (print r
) (1- r
)))
399 (listpui (list (multi_decomp_init (pui_contract 0
406 (cons (multi_decomp_init (pui_contract 0
415 (pui2polynome '$y
(cons degre_resol listpui
))))))
417 ;====================================================================
418 ; FONCTIONS SYMETRIQUES ELEMENTAIRES DES RACINES DES POLYNOMES DE
419 ; l$pol EN LA VARIABLE $y.
421 (defun multi_polynome2ele (l$pol $y
)
422 (mapcar #'(lambda ($pol
) (polynome2ele $pol $y
)) l$pol
))
424 ;=========================================================================
425 ; DECOMPOSITION D'UN POLYNOME SYMETRIQUE CONTRACTE
426 ; EN PLUSIEURS PAQUETS DE VARIABLES
427 ; DONT LES FONCTIONS SYMETRIQUES ELEMENTAIRES
428 ; RESPECTIVES SONT DONNEES
429 ;=========================================================================
431 (defun multi_decomp_init ( $multi_pc $multi_base $llvar
)
433 ((equal '$elementaires $direct
)
434 (meval (list '($multi_elem
) $multi_base
436 (t (meval (list '($multi_pui
) $multi_base
437 $multi_pc $llvar
)))))
439 ; on a les fonctions symetriques elementaires des racines des differents
440 ; polynomes. On recupere en fonction d'elles leurs fonctions puissances.
442 (defun multi_ele2pui (multi_lelem)
444 (mapcar #'(lambda (lelem)
445 (meval (list '($ele2pui
)
447 (cons '(mlist) lelem
))))