pullback.red 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. module pullback;
  2. % Pullback transformations
  3. % Author: David Hartley
  4. Comment. Data structure:
  5. map ::= list of kernel . prefix
  6. endcomment;
  7. fluid '(xvars!* kord!* subfg!*);
  8. global '(!*sqvar!*);
  9. fluid '(cfrmcob!* cfrmcrd!* cfrmdrv!* cfrmrsx!*);
  10. % Type coersions
  11. symbolic procedure !*a2map u;
  12. % u:list of equation -> !*a2map:map
  13. % should remove x=x entries
  14. unrollmap for each j in getrlist u collect
  15. if eqexpr j then !*a2k lhs j . rhs j
  16. else rerror(eds,000,"Incorrectly formed pullback map");
  17. symbolic procedure !*map2a u;
  18. % u:map -> !*map2a:prefix
  19. makelist foreach p in u collect {'equal,car p,cdr p};
  20. % Pullback
  21. put('pullback,'rtypefn,'getrtypecar);
  22. put('pullback,'cfrmfn,'pullbackcfrm);
  23. put('pullback,'edsfn,'pullbackeds);
  24. put('pullback,'listfn,'pullbacklist);
  25. put('pullback,'simpfn,'simppullback);
  26. symbolic procedure pullbackcfrm(m,x);
  27. % m:cfrm, x:list of equation|inequality -> pullbackcfrm:cfrm
  28. % pullback m using map x
  29. begin
  30. x := !*a2rmap x;
  31. m := car pullbackcfrm1(m,car x);
  32. return if cadr x then cfrmprotect{'restrictcfrm1,m,{{},cadr x}}
  33. else m
  34. end;
  35. symbolic procedure pullbackeds(s,x);
  36. % s:eds, x:list of equation|inequality -> pullback:eds
  37. % pulls back s using rmap x
  38. pullback0(s,!*a2rmap x);
  39. symbolic procedure pullbacklist(u,v);
  40. % u:{prefix list of prefix ,prefix list of equation|inequality}, v:bool
  41. % -> pullbacklist:prefix list of prefix
  42. begin scalar x;
  43. x := car !*a2rmap reval cadr u; % throw away rsx
  44. u := reval car u;
  45. return
  46. makelist foreach f in cdr u join
  47. if (f := !*pf2a1(pullbackpf(xpartitop f,x),v)) neq 0 then {f};
  48. end;
  49. symbolic procedure simppullback u;
  50. % u:{prefix,prefix list of equation} -> simppullback:sq
  51. (if degreepf f < 0 then rerror(eds,000,"Cannot pull back vectors")
  52. else !*pf2sq repartit pullbackpf(f,x))
  53. where f = xpartitop car u,
  54. x = car !*a2rmap reval cadr u;
  55. symbolic procedure pullbackcfrm1(m,x);
  56. % m:cfrm, x:map -> pullbackcfrm1:{cfrm,{cob,map}}
  57. % Pull back coframing m. Also returns extended map showing which
  58. % cobasis elements have been eliminated in case of ambiguity (e.g.
  59. % anholonomic cobases).
  60. begin scalar n,cfrmcrd!*,cfrmrsx!*;
  61. if null x then return m;
  62. m := copycfrm m;
  63. x := unrollmap x;
  64. % Get source coframing (or subcoframing thereof)
  65. n := !*map2srccfrm x;
  66. %%if xnp(foreach p in x collect car p,cfrm_crd n) then
  67. %% rerror(eds,000,"Recursive map in pullback");
  68. % New coordinates (ordering here critical)
  69. cfrm_crd m := rightunion(cfrm_crd m,cfrm_crd n);
  70. cfrm_crd m := setdiff(cfrm_crd m,foreach p in x collect car p);
  71. % Pull back rsx and check (ordering here critical)
  72. cfrm_rsx m := rightunion(cfrm_rsx m,cfrm_rsx n);
  73. cfrm_rsx m := pullbackrsx(cfrm_rsx m,x);
  74. if 0 member cfrm_rsx m then
  75. rerror(eds,000,
  76. "Map image not within target coframing in pullback");
  77. % Get target cobasis, and differentiate appropriate part of map
  78. % Need to use new coframing's coordinates
  79. cfrmcrd!* := cfrm_crd m;
  80. cfrmrsx!* := (foreach p in cfrm_rsx m collect
  81. xpartitop p) where xvars!* = cfrmcrd!*;
  82. x := !*map2cotangent x;
  83. if not subsetp(car x,cfrm_cob m) then
  84. rerror(eds,000,
  85. "Map image not within target coframing in pullback");
  86. % New cobasis (ordering here critical)
  87. cfrm_cob m := rightunion(cfrm_cob m,cfrm_cob n);
  88. cfrm_cob m := setdiff(cfrm_cob m,car x);
  89. % Pullback derivatives (ordering here critical)
  90. cfrm_drv m := rightunion(cfrm_drv m,cfrm_drv n);
  91. cfrm_drv m := pullbackdrv(cfrm_drv m,cadr x);
  92. return {purgecfrm m,x};
  93. end;
  94. symbolic procedure unrollmap x;
  95. % x:map -> unrollmap:map
  96. % Straighten out recursive maps. Designed to work only for weakly
  97. % reduced maps (ie row-echelon form).
  98. begin scalar r,z,cfrmcrd!*; integer c;
  99. cfrmcrd!* := foreach p in x collect car p;
  100. %%%edsdebug("Unroll input",x,'map);
  101. while x and (c := c+1) < 20 do
  102. begin
  103. foreach p in x do
  104. << r := simp!* cdr p;
  105. if cfrmconstant numr r and cfrmconstant denr r then
  106. z := p . z >>;
  107. x := pullbackmap(setdiff(x,z),append(x,z));
  108. %%%edsdebug("Recursive part",x,'map);
  109. end;
  110. if x then rerror(eds,000,"Recursive map");
  111. return z;
  112. end;
  113. symbolic procedure !*map2srccfrm x;
  114. % x:map -> !*map2srccfrm:cfrm
  115. % Determine a possible source coframing for map x by
  116. % inspecting the rhs of each rule.
  117. !*sys2cfrm foreach p in x collect
  118. (1 .* simp!* cdr p .+ nil);
  119. symbolic procedure !*map2cotangent x;
  120. % x:map -> !*map2cotangent:{cob,map}
  121. % Differentiate map x and determine which cobasis elements are
  122. % eliminated (ambiguous for anholonomic frames). Also returns
  123. % differentiated map.
  124. begin scalar f,old,xl;
  125. foreach p in x do
  126. << f := xpows exdfk car p;
  127. if length f > 1 or car f neq {'d,car p} then xl := p . xl
  128. else old := car f . old >>;
  129. if xl then x := exdfmap(xl,x);
  130. old := append(old,for each p in x
  131. join if xdegree car p = 1 then {car p});
  132. edsdebug("Cobasis elements eliminated",old,'cob);
  133. return {old,x};
  134. end;
  135. symbolic procedure exdfmap(xl,x);
  136. % xl,x:map -> exdfmap:map
  137. % produce substitution for differentials in xl from those for scalars
  138. % x is the whole map, xl is usually only a subset
  139. begin scalar f,old,y,ok;
  140. ok := updkordl {};
  141. foreach p in xl do
  142. << f := exdfk car p;
  143. old := union(xpows f,old);
  144. if red f or lpow f neq {'d,car p} then
  145. f := pullbackpf(f,x);
  146. y := addpf(f,negpf pullbackpf(xpartitop{'d,cdr p},x)) . y >>;
  147. edsdebug("Possibilities for elimination",old,'cob);
  148. y := solvepfsys1(y,old);
  149. if cadr y then
  150. rerror(eds,000,"Cannot determine suitable coframe for pullback");
  151. setkorder ok;
  152. return
  153. append(x,
  154. foreach f in car y collect
  155. lpow f . mk!*sq !*pf2sq negpf xreorder!* red f);
  156. end;
  157. symbolic procedure pullbackdrv(d,x);
  158. % d:drv, x:map -> pullbackdrv:drv
  159. (foreach r in d collect
  160. {car r,cadr r,mk!*sq subsq(simp!* caddr r,x)})
  161. ; %%% where subfg!*=nil; %%% Why?
  162. symbolic procedure pullbackmap(p,x);
  163. % p:map, x:map -> pullbackmap:map
  164. % substitute map x into map p
  165. foreach s in p collect car s . mk!*sq subsq(simp!* cdr s,x);
  166. symbolic procedure pullback0(s,x);
  167. % s:eds, x:rmap -> pullback0:eds
  168. % restricts and pulls back s using rmap x
  169. if emptyedsp(s := pullback(s,car x)) then s
  170. else if cadr x then edscall restrict(s,{{},cadr x})
  171. else s;
  172. symbolic procedure pullback(s,x);
  173. % s:eds, x:map -> pullback:eds
  174. % Pulls back s using map x.
  175. begin scalar prl,cob,m;
  176. if null x then return s;
  177. % Get some information about s
  178. prl := prlkrns s; cob := edscob s;
  179. % Pullback coframing, and get cotangent space info
  180. m := pullbackcfrm1(eds_cfrm s,x);
  181. x := cadr m; m:= car m;
  182. % Setting coframe here reduces need to reorder later. If some
  183. % cobasis elements are eliminated, the forms in sys and ind may be
  184. % out of order, but this doesn't seem to matter since these will be
  185. % replaced anyway.
  186. setcfrm m;
  187. % Fix flags first (need to test using old sys/ind)
  188. s := purgeeds!* s; % copies s
  189. if not subsetp(cfrm_cob m,cob) then
  190. rempropeds(s,'jet0);
  191. if subsetp(car x,prl) and % try to avoid re-solving
  192. null xnp(prl,foreach f in pfaffpart eds_sys s join xpows f) and
  193. null xnp(prl,foreach f in eds_ind s join xpows f) then
  194. remtrueeds(s,'reduced)
  195. else
  196. remtrueeds(s,'solved);
  197. foreach f in {'solved,'pfaffian,'quasilinear,'closed} do
  198. remfalseeds(s,f);
  199. rempropeds(s,'involutive);
  200. % Form new eds
  201. eds_sys s := foreach f in eds_sys s join
  202. if f := pullbackpf(f,cadr x) then {f};
  203. eds_ind s := foreach f in eds_ind s join
  204. if f := pullbackpf(f,cadr x) then {f}
  205. else <<edsverbose(
  206. "Pullback inconsistent with independence condition",
  207. nil,nil);>>;
  208. cfrm_cob m := append(setdiff(cfrm_cob m,i),i) where i=indkrns s;
  209. eds_cfrm s := m;
  210. if not subsetp(cfrm_cob m,cob) then % probably need to reorder
  211. << setcfrm m;
  212. eds_sys s := xreordersys eds_sys s;
  213. eds_ind s := xreordersys eds_ind s; >>;
  214. remkrns s;
  215. return normaleds s;
  216. end;
  217. symbolic procedure pullbackpf(f,x);
  218. % f:pf, x:map -> pullbackpf:pf
  219. % pulls back f using map x
  220. % should watch out for partdf's
  221. % This version assumes x introduces no new xvars in coefficients.
  222. % Done using two routines to reduce subs2 checking.
  223. subs2pf pullbackpf1(f,x);
  224. symbolic procedure pullbackpf1(f,x);
  225. % f:pf, x:map -> pullbackpf1:pf
  226. if f then
  227. addpf(multpfsq(pullbackk(lpow f,x),subsq(lc f,x)),
  228. pullbackpf1(red f,x));
  229. symbolic procedure pullbackk(k,x);
  230. % k:lpow pf, x:map -> pullbackk:pf
  231. % need xreorder here because subf returns unordered wedge kernels
  232. xreorder xpartitsq subf(!*k2f k,x);
  233. symbolic procedure pullbacksq(q,x);
  234. % q:sq, x:map -> pullbacksq:pf
  235. xpartitsq subsq(q,x);
  236. endmodule;
  237. end;