edsuser.red 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. module edsuser;
  2. % Miscellaneous user functions
  3. % Author: David Hartley
  4. fluid '(alglist!* subfg!* !*arbvars xvars!*);
  5. global '(indxl!*);
  6. put('index_expand,'rtypefn,'quotelist);
  7. put('index_expand,'listfn,'indexexpandeval0);
  8. symbolic procedure indexexpandeval0(u,v);
  9. % u:list of prefix, v:bool -> indexexpandeval0:prefix list
  10. % kludge to add v argument to index_expand listfn
  11. makelist foreach p in getrlist indexexpandeval u collect reval1(p,v);
  12. symbolic procedure indexexpandeval u;
  13. % u:list of prefix -> indexexpandeval:prefix list
  14. if length u neq 1 then
  15. rerror(eds,000,"Wrong number of arguments to index_expand")
  16. else if rlistp(u := reval car u) then
  17. makelist purge foreach x in cdr u join cdr indexexpandeval {x}
  18. else makelist indexexpand u;
  19. symbolic procedure indexexpand u;
  20. % u:prefix -> indexexpand:list of prefix
  21. % u has always been reval'd, so there is no need to expand
  22. % summations.
  23. if eqexpr u then indexexpandeqn u else
  24. if boolexpr u then indexexpandbool u else
  25. begin scalar i,v,alglist!*;
  26. u := simp!* u;
  27. % Expand free indices (put them into some order for safety)
  28. i := idsort purge if numr u and not domainp numr u then
  29. flatindxl allind !*t2f lt numr u;
  30. v := foreach j in mkaindxc(i,nil) join
  31. if numr(j := subfreeindices(numr u,pair(i,j))) then
  32. {absf numr j ./ denr j}; % nprimitive too?
  33. return for each q in purge v collect mk!*sq multsq(q,1 ./ denr u);
  34. end;
  35. symbolic procedure indexexpandeqn u;
  36. % u:rule|equation -> indexexpandeqn:list of rule|equation
  37. begin scalar i,v,lh,rh;
  38. scalar alglist!*;
  39. % Expand free indices on lhs (put them into some order for safety)
  40. lh := reval cadr u where subfg!* = nil; % avoid let rules
  41. i := idsort purge flatindxl allindk lh;
  42. rh := aeval caddr u;
  43. v := foreach j in mkaindxc(i,nil) join
  44. if j := subfreeindeqn({car u,lh,rh},pair(i,j)) then {j};
  45. % Remove duplicates
  46. i := {};
  47. v := foreach r in v join
  48. if not(cadr r member i) then
  49. << i := cadr r . i; {r} >>;
  50. return v;
  51. end;
  52. symbolic procedure subfreeindeqn(u,l);
  53. % u:rule|equation, l:alist -> subfreeindeqn:rule|equation|nil
  54. % Make index substitution l in u. Only index symmetry simplifications
  55. % are allowed, so the lhs can either vanish (nil returned) or acquire
  56. % an overall sign (sign transferred to rhs).
  57. begin scalar lh,rh;
  58. lh := subfreeindk(cadr u,l);
  59. if null atomf lh then lh := revop1 lh; % gets done in rule!-list
  60. % anyway
  61. lh := reval lh where subfg!* = nil; % avoid let rules;
  62. if lh = 0 then return nil;
  63. rh := simp!* caddr u;
  64. rh := quotsq(subfreeindices(numr rh,l),subfreeindices(denr rh,l));
  65. if eqcar(lh,'minus) then
  66. << lh := cadr lh;
  67. rh := negsq rh >>;
  68. return {car u,lh,mk!*sq rh};
  69. end;
  70. symbolic procedure boolexpr u;
  71. % u:any -> boolexpr:bool
  72. not atom u and flagp(car u,'boolean);
  73. symbolic procedure indexexpandbool u;
  74. % u:prefix -> indexexpandbool:list of prefix
  75. begin scalar i,v,alglist!*;
  76. % Expand free indices on lhs (put them into some order for safety)
  77. i := idsort purge flatindxl allindk u;
  78. v := foreach j in mkaindxc(i,nil) collect
  79. car u .
  80. foreach a in cdr u collect reval subfreeindk(a,pair(i,j));
  81. return purge v;
  82. end;
  83. symbolic procedure subfreeindices(u,l);
  84. % u:sf, l:a-list -> subfreeindices:sq
  85. % Discriminates indices from variables, modified from EXCALC's
  86. % subfindices to go inside operators other than EXCALC's.
  87. begin scalar alglist!*;
  88. return
  89. if domainp u then u ./ 1
  90. else
  91. addsq(
  92. multsq(if atom mvar u then
  93. !*p2q lpow u
  94. else if sfp mvar u then
  95. exptsq(subfreeindices(mvar u,l),ldeg u)
  96. else
  97. exptsq(simp subfreeindk(mvar u,l),ldeg u),
  98. subfreeindices(lc u,l)),
  99. subfreeindices(red u,l))
  100. end;
  101. symbolic procedure subfreeindk(u,l);
  102. % u:kernel, l:a-list -> subfreeindk:kernel
  103. % Extends subindk to indexed variables
  104. if atom u then u
  105. else if flagp(car u,'indexvar) then
  106. car u . subla(l,cdr u)
  107. else subindk(l,u);
  108. put('linear_divisors,'rtypefn,'quotelist);
  109. put('linear_divisors,'listfn,'lineardivisors);
  110. symbolic procedure lineardivisors(u,v);
  111. % u:{prefix}, v:bool -> lineardivisors:prefix list
  112. makelist foreach f in lineardivisorspf xpartitop reval car u collect
  113. !*pf2a1(f,v);
  114. symbolic procedure lineardivisorspf f;
  115. % f:pf -> lineardivisorspf:list of pf
  116. begin scalar x,g,v;
  117. foreach p in xpows f do x := union(wedgefax p,x);
  118. foreach k in x do
  119. << v := intern gensym() . v;
  120. g := addpf(k .* !*k2q car v .+ nil,g)>>;
  121. x := edssolve(xcoeffs wedgepf(g,f),v);
  122. if length x neq 1 or caar x neq t then
  123. errdhh "Bad solve result in lineardivisorspf";
  124. x := cadar x;
  125. v := updkordl v;
  126. g := numr subf(numr !*pf2sq g,x);
  127. x := {};
  128. while g do
  129. << x := xpartitsq(lc g ./ 1) . x;
  130. g := red g >>;
  131. setkorder v;
  132. return reverse xautoreduce x;
  133. end;
  134. symbolic procedure xdecomposepf f;
  135. % f:pf -> xdecomposepf:list of pf
  136. begin scalar x;
  137. x := lineardivisorspf f;
  138. if length x = degreepf f then return reverse x;
  139. end;
  140. put('exfactors,'rtypefn,'quotelist);
  141. put('exfactors,'listfn,'exfactors);
  142. symbolic procedure exfactors(u,v);
  143. % u:{prefix}, v:bool -> exfactors:prefix list
  144. makelist foreach f in xfactorspf xpartitop reval car u collect
  145. !*pf2a1(f,v);
  146. symbolic procedure xfactorspf f;
  147. % f:pf -> xfactorspf:list of pf
  148. begin scalar x;
  149. x := lineardivisorspf f;
  150. f := xreduce(f,foreach g in x collect
  151. addpf(1 .* (-1 ./ 1) .+ nil,g));
  152. return
  153. if f = !*k2pf 1 then reverse x
  154. else f . reverse x;
  155. end;
  156. symbolic operator exact;
  157. symbolic procedure exact u;
  158. % u:prefix -> exact:bool
  159. % True if u is an exact pform kernel
  160. eqcar(u,'d);
  161. flag('(exact),'boolean);
  162. put('derived_system,'rtypefn,'getrtypecar);
  163. put('derived_system,'edsfn,'deriveeds);
  164. put('derived_system,'listfn,'derivelist);
  165. symbolic procedure derivelist(u,v);
  166. % u:{xeds|rlist}, v:bool -> derivelist:rlist
  167. !*sys2a1(derive !*a2sys reval car u,v) where xvars!* = nil;
  168. symbolic procedure deriveeds s;
  169. % s:eds -> deriveeds:eds
  170. begin
  171. s := copyeds s;
  172. if pfaffian s then
  173. eds_sys s := derive pfaffpart eds_sys s
  174. else rerror(eds,000,"non-Pfaffian system in derived_system");
  175. return s;
  176. end;
  177. symbolic procedure derive s;
  178. % s:sys -> derive:sys
  179. begin scalar c,f;
  180. if null s then s;
  181. s := xautoreduce s;
  182. c := for each f in s collect
  183. if degreepf f = 1 then intern gensym()
  184. else rerror(eds,000,"non-Pfaffian system in derived_system");
  185. f := zippf(s,foreach k in c collect !*k2q k);
  186. s := edssolve(xcoeffs xreduce(exdfpf f,s),c);
  187. if length s neq 1 or null caar s then
  188. errdhh{"Bad solve result in derive:",s};
  189. s := cadr car s;
  190. f := pullbackpf(f,s);
  191. c := setdiff(c,foreach m in s collect car m);
  192. f := xrepartit f where xvars!* = c;
  193. return for each x in reverse c collect xcoeff(f,{x});
  194. end;
  195. symbolic procedure allcoords f;
  196. % f:prefix -> allcoords:list of kernel
  197. % Pick up 0-form kernels in f
  198. makelist purge
  199. foreach k in (xvarspf xpartitop f where xvars!* = t) join
  200. if xdegree k = 0 and
  201. not assoc(k,depl!*) and
  202. not eqcar(k,'partdf) then {k}
  203. else if (xdegree k = 1) and exact k then {cadr k};
  204. endmodule;
  205. end;