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 ; CHANGEMENTS DE REPRESENTATIONS SUR k[y1,..., yn][x1,..., xn]
21 ;=========================================================================
23 ; contract (avec ou sans test)
24 ; partpol ..................
25 ; part2cont et cont2part
27 ;=============================================================================
31 (macsyma-module partpol
)
34 ((lambda ()) ((mlist) $mpol $lvar
)
35 ((mprog) (($operation
)) (($tpartpol_init
) $mpol $lvar
)))
37 (add2lnc '(($tpartpol
) $mpol $lvar
) $functions
)
40 ((lambda ()) ((mlist) $mpol $lvar
)
41 ((mprog) (($operation
)) (($p_tpartpol_init
) $mpol $lvar
)))
43 (add2lnc '(($p_tpartpol
) $mpol $lvar
) $functions
)
45 ; Passage d'un polynome symetrique sous la forme rat a ses partitions
47 ((lambda ()) ((mlist) $pol $lvar
)
48 ((mprog) (($operation
)) (($partpol_init
) $pol $lvar
)))
50 (add2lnc '(($partpol
) $pol $lvar
) $functions
)
52 ; CONTRACTION D'UN POLYNOME SYMETRIQUE
55 ((lambda ()) ((mlist) $psym $lvar
)
56 ((mprog) (($operation
)) (($tcontract_init
) $psym $lvar
)))
58 (add2lnc '(($tcontract
) $psym $lvar
) $functions
)
61 ((lambda ()) ((mlist) $psym $lvar
)
62 ((mprog) (($operation
)) (($contract_init
) $psym $lvar
)))
64 (add2lnc '(($contract
) $psym $lvar
) $functions
)
66 ; PASSAGE D'UN POLYNOME SYMETRIQUE CONTRACTE A LA LISTE
70 ((lambda ()) ((mlist) $pcont $lvar
)
71 ((mprog) (($operation
)) (($cont2part_init
) $pcont $lvar
)))
73 (add2lnc '(($cont2part
) $pcont $lvar
) $functions
)
76 ((lambda ()) ((mlist) $ppart $lvar
)
77 ((mprog) (($operation
)) (($part2cont_init
) $ppart $lvar
)))
79 (add2lnc '(($part2cont
) $ppart $lvar
) $functions
)
82 ((lambda ()) ((mlist) $pc $lvar
)
83 ((mprog) (($operation
)) (($explose_init
) $pc $lvar
)))
85 (add2lnc '(($explose
) $pc $lvar
) $functions
)
86 ;*****************************************************************************
91 ; DECLARATIONS AU COMPILATEUR
92 ; $tcontract_init $contract_init
93 ; $p_tpartpol_init p_tpartpol
94 ; $tpartpol_init tpartpol
95 ; $partpol_init partpol appellees par apply
96 ; $cont2part_init cont2part
99 ; Franz Lisp declaration 'localf' is currently untranslated
102 (progn (defvar drapeaux
) (defvar modele
))
103 (progn (defvar lvar
) (defvar permut
))
104 ;*****************************************************************************
105 ; FORME CONTRACTE D'UN POLYNOME SYMETRIQUE
106 ; appels : contract(pol,lvar) ou tcontract(pol,lvar) t pour test
107 ; $lvar = [x1, ..., xp] = ((mlist) x1, ..., xp) au depart
108 ; lvar = (x1, ..., xp)
110 ;-----------------------------------------------------------------------------
111 ; AVEC TEST DE SYMETRIE
112 ; tpartpol ramene des partition sout la forme [part](2). Pour
114 ; de polyn\^ome on peut directement utiliser la fonction 2ecrit.
115 ; Sinon, pour utiliser $distri_ecrit (i.e. ecrit_pol), il faut faire
117 ;-----------------------------------------------------------------------------
118 (defun $tcontract_init
($pol $lvar
)
119 (if (meval (list '($is
) (list '(mequal) $pol
0))) 0
121 (2ecrit (tpartpol $pol $lvar
) (cdr $lvar
)))))
122 ;-----------------------------------------------------------------------------
123 ; SANS TEST DE SYMETRIE
124 ;-----------------------------------------------------------------------------
125 (defun $contract_init
($pol $lvar
)
126 (if (meval (list '($is
) (list '(mequal) $pol
0))) 0
129 (meval (list '($partpol
) $pol $lvar
))
131 ;======================================================================
132 ; PASSAGE D'UN POLYNOME SYMETRIQUE MACSYMA
133 ; A SA REPRESENTATION PARTITIONNEE.
135 ; $partpol_init ramene REP(pol)(1) ............ lexicographique decroissant
136 ; $partpol ...... REP(pol)(2) ............ lexicographique decroissant
137 ; tpartpol si on desire en plus tester la symetrie
138 ; ----------------------------------------------------------------------------
139 ; AVEC TEST DE SYMETRIE
140 ; $pol est un polynome macsyma sous la forme expand
141 ; Si on part d'un polynome non symetrique une erreur est declanchee
142 ; $p_tpartpol_init ramene REP(pol)(1) dans l'ordre des longueurs decroissant
143 ; p_tpartpol ...... REP(pol)(2) ......................................
144 ;============================================================================
145 ; lpol est sous la forme((coe . [partition](2))...) mais n'est pas
146 ; un polynome partitionne car on n'a encore retire aucun monome.
147 (defun $p_tpartpol_init
($pol $lvar
)
148 (if (meval (list '($is
) (list '(mequal) $pol
0))) (cons '(mlist) nil
)
150 (macsy_list (ch1repol (p_tpartpol $pol $lvar
))))))
152 ; appele par pui en drapeau 5 &&&&&&mais si erreur pas de cath !
154 (defun p_tpartpol ($pol $lvar
)
155 (if (meval (list '($is
) (list '(mequal) $pol
0))) (cons '(mlist) nil
)
156 (let ((lpol (sort (prep (lect $pol
(cons '(mlist) $lvar
)))
158 (tpartpol2 lpol
(list-length (cdr $lvar
))))))
160 (defun $tpartpol_init
($pol $lvar
)
161 (if (meval (list '($is
) (list '(mequal) $pol
0))) (cons '(mlist) nil
)
163 (macsy_list (ch1repol (tpartpol $pol $lvar
))))))
165 ;appele par e_sym (22 ..) &&&&&&&& pas de catch si erreur
166 ; pol est sous la forme((coe .I)...) les +petit part devant
168 (defun tpartpol ($pol $lvar
)
169 (let ((pol (sort (prep (lect $pol $lvar
)) '$lexic
)))
170 (tpartpol2 pol
(list-length (cdr $lvar
)))))
173 (and (not (equal (cdr p
) (cdr q
))) ($lex
(cdr p
) (cdr q
))))
174 ;--------------------------------------------------------------------------
176 ;-----------------------------------------------------------------------------
177 ; Reunir les partitions identiques, rendre le coefficient de la
178 ; forme monomiale associee.
179 (defun tpartpol2 (lpol card
)
180 (tpartpol3 card lpol
(card_orbit (cdar lpol
) card
))
182 ;-----------------------------------------------------------------------
183 ; partitionnement avec test de symetrie : tpartpol3
184 ; modification physique sur la forme distribuee
185 ; Tout les monome ont leur exposants represente par [partition](2)
186 ; on a perdu l'information : "exposant attache a une variable"
187 ; dont on n'a pas besoin.
189 ; Le monome de tete de pol = (coe1 . exposants1)
190 ; le deuxieme monome de tete de pol = (coe2 . exposants2)
191 ; 1- exposants1 est le (p+1)ieme que
192 ; l'on trouve identique a exposants2
193 ; (on a reordonne les exposants)
194 ; 1-1 coe1 distinct de coe2 ==> non symetrique
195 ; 1-2 coe1 = coe2 ==> (compteur ==> compteur-1) : on a un element
196 ; supplementaire de l'orbite de exposants2
197 ; on l'elimine de pol puisqu'un seul representant
199 ; 2- exposant1 different de exposants2
200 ; 1-1 compteur > 1 ==> Il manque des elements de l'orbit de exposants2
201 ; 1-2 compteur = 1 ==> - (coe1 . exposants1) represente toute l'orbite
203 ; - On passe a l'orbite suivante qui
204 ; est (coe2 . exposants2) en mettant
205 ; compteur = card_orbite(exposants2)
206 ;--------------------------------------------------------------------------
207 ; pas le cas de la cste
209 ; ex : 3xy + 3yz + 2xz est non symetrique
210 (defun tpartpol3 (card pol compteur
)
213 (throw 'rate
'|manque des elements de l
'orbite|
))
214 (let ((coe1 (caar pol
)) (coe2 (caadr pol
)) (exp1 (cdar pol
))
216 (if (equal exp1 exp2
)
217 (if (equal coe1 coe2
)
218 (tpartpol3 card
(rplacd pol
(cddr pol
))
221 '|polynome non symetrique par ses coefficients|
))
223 (tpartpol3 card
(cdr pol
) (card_orbit exp2 card
))
224 (throw 'rate
'|manque des monomes|
))))))
225 ;-----------------------------------------------------------------
226 ; PARTITIONNEMENT D'UN POLYNOME
227 ; ENTREES : UN POLYNOME $psym SOUS FORME DISTRIBUEE OU SINON DONNES PAR UNE
228 ; REPRESENTATION MACSYMA ET LA LISTE $lvar DE SES VARIABLES
229 ; SORTIE : LE POLYNOME PARTITIONNE AVEC COMME REPRESENTATION :
230 ; REP([pol]) = [ppart](1)
231 ;-----------------------------------------------------------------
232 (defun $partpol_init
($psym $lvar
)
233 (if (meval (list '($is
) (list '(mequal) $psym
0))) (cons '(mlist) nil
)
235 (mapcan #'(lambda ($exposant
)
236 (and (apply '>= (cddr $exposant
))
238 (if (equal 'mlist
(caar $psym
))
239 (cdr $psym
) ; $psym est sous forme distribuee
240 (cdr (meval (list '($distri_lect
)
244 ;-----------------------------------------------------------------------
245 ; FORME CONTRACTEE D'UN POLYNOME ==> REP([pol])(i)
246 ; $cont2part_init --> [$ppart](1) ($ car liste macsyma)
247 ; cont2part et partipol --> [ppart](2)
248 ; appele par $elem_init et $pui_init
249 ;-----------------------------------------------------------------------
250 ; dans lect on met $polcontrac sous forme expand
251 (defun $cont2part_init
($polcontrac $lvar
)
252 (if (meval (list '($is
) (list '(mequal) $polcontrac
0)))
254 (macsy_list (cont2part_rep1 $polcontrac $lvar
))))
256 (defun cont2part_rep1 (polcontrac $lvar
)
257 (ordonne_expo (lect polcontrac $lvar
)))
258 ; Rend des partitions de type 2
260 (defun cont2part (polcontrac lvar
)
261 (ch2repol (cont2part_rep1 polcontrac
(cons '(mlist) lvar
))))
262 ; on le met sous forme rat
263 ; rat = (((rat simp)...) . listebase . 1)
265 (defun $partipol
(polycontracte)
266 (let ((rat ($rat polycontracte
)))
267 (cons '(mlist) (mapcar 'list2croch
(partipol rat
)))))
269 (defun partipol (rat) (partipol1 (cadr rat
) (cons nil nil
)))
271 ; on aura lpart = ( (coe a1 m1 a2 m2 ....) ....) par
274 (defun partipol1 (rat lpart
)
275 (partipol2 lpart
(cdr rat
) nil nil
)
278 ; representation des partitions avec un coe et eventuellement des
279 ; exposants nuls en tete.
280 ; rat est la liste elementaire
281 ;on depile ie on remonte
282 ; on a enfin une partition solution
283 ; deplacement en profondeur dans
284 ; le coefficient qui est une liste de base et auquel on enleve la variable.
285 ; on met en instance le deplacement en largeur dans rrat
286 ; on note dans la pile l'etat actuel : la pile la partition
287 ; en construction et le reste des exposant coe a parcourir
290 (defun partipol2 (lpart rat part pile
)
291 (if (null rat
) (and pile
(apply 'partipol2
(cons lpart pile
)))
292 (if (numberp (cadr rat
))
296 (cons (car rat
) part
) '<)
298 (cddr rat
) part pile
)
299 (partipol2 lpart
(cdadr rat
) (cons (car rat
) part
)
300 (if (cddr rat
) (list (cddr rat
) part pile
) pile
)))))
301 ;=======================================================================
302 (defun $part2cont_init
($ppart $lvar
)
303 (if (null (cdr $ppart
)) 0
304 (meval (list '($distri_ecrit
) $ppart $lvar
))))
305 ;========================================================================
306 ; RAMENER TOUT LE POLYNOME SYMETRIQUE
307 ; ASSOCIE A UNE FORME CONTRACTEE
308 ; dans k[y1, ... ,yn][x1, ... ,xn]
309 ; EN SE SERVANT DE permut ECRIT PAR PHILIPPE ESPERET
310 ; appel : explose(polynome,[x1, ... ,xp])
311 ;-------------------------------------------------------------------------
313 ; lvar = [x1, ... ,xp] on ne demande pas de preciser y1, ..., yn
314 ; On utilise le lecteur rendant les formes distribuees et
315 ; l'ecrivain qui se trouvent dans le fichier util.l
316 ;-------------------------------------------------------------------------
318 (defun $explose_init
($pc $lvar
)
319 (if (meval (list '($is
) (list '(mequal) $pc
0))) 0
320 (let ((lcoenuplet (lect $pc $lvar
)))
321 (meval (list '($distri_ecrit
)
323 (mapcan #'(lambda (coenuplet)
324 (let ((coe (car coenuplet
)))
325 (mapcar #'(lambda (permu)
328 (permut (cdr coenuplet
)))))
331 ;=======================================================================
332 ; ORBITE D'UN POLYNOME
333 ;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
334 ;========================================================================
336 ;------------------------------------------------------------------------
337 ; prep : Fonction ordonnant tout d'abord tout les exposants
338 ; dans le sens decroissant puis representent ces exposants
339 ; sous forme [partition](2) (sans les 0)
340 ; Creons tout d'abords une fonction, ordonne_expo, qui a partir d'un polynome
341 ; sous forme distribuee range tout les exposants dans l'ordre
344 (defun ordonne_expo (pol)
345 (mapcar #'(lambda (mon)
347 (sort (cdr mon
) '>)))
350 ; Avec changement de repre'sentation
351 (defun prep (pol) (ch2repol (ordonne_expo pol
)))