disjoin.red 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. module disjoin;
  2. % Convert a variety to a disjoint union of sub-coframings
  3. % Author: David Hartley
  4. fluid '(!*edsverbose !*edsdebug !*arbvars !*varopt !*groebopt
  5. !*solveinconsistent depl!* cfrmcrd!* cfrmrsx!* xvars!*
  6. !*edssloppy !*edsdisjoint);
  7. Comment. The edsdisjoin routines decompose a solution returned by
  8. eds*solve into a disjoint union of solutions (rmaps). The operations
  9. intersection and difference are somewhat slow, so the whole process is
  10. only performed automatically if the switch edsdisjoint is on.
  11. endcomment;
  12. symbolic operator disjoin;
  13. symbolic procedure disjoin u;
  14. (makelist foreach rm in
  15. edsdisjoin(foreach s in getrlist u collect !*a2rmap s) collect
  16. !*rmap2a rm) where !*edsdisjoint = t;
  17. symbolic procedure edsdisjoin u;
  18. % u:list of rmap -> edsdisjoin:list of rmap
  19. if !*edsdisjoint then reverse edsdisjoin1(u,{}) else u;
  20. symbolic procedure edsdisjoin1(u,v);
  21. % u,v:list of rmap -> edsdisjoin1:list of rmap
  22. % rmaps in v are disjoint already.
  23. if null u then v
  24. else edsdisjoin1(cdr u,edsdisjoin2(car u,v));
  25. symbolic procedure edsdisjoin2(x,v);
  26. % x:rmap, v:list of rmap -> edsdisjoin2:list of rmap
  27. % rmaps in v are disjoint already.
  28. if null v then {x}
  29. else
  30. begin scalar y,z;
  31. y := car v;
  32. return
  33. if z := rmapintersection(x,y) then
  34. append(rmapdifference(y,x),
  35. append(z,edsdisjoin1(rmapdifference(x,y),cdr v)))
  36. else
  37. y . edsdisjoin2(x,cdr v);
  38. end;
  39. symbolic procedure rmapintersection(x,y);
  40. % x,y:rmap -> rmapintersection:list of rmap
  41. begin scalar lhx,xl,z,rsx,rsy,mx,my;
  42. % First a simple check which may save us going into solve
  43. rsy := pullbackrsx(cadr y,car x);
  44. if 0 member rsy then return nil;
  45. rsx := pullbackrsx(cadr x,car y);
  46. if 0 member rsx then return nil;
  47. % Now just pile everything together and resolve
  48. return rmapeval {append(car x,car y),append(rsx,rsy)};
  49. end;
  50. symbolic procedure rmapdifference(x,z);
  51. % x,z:rmap -> rmapdifference:list of rmap
  52. % NO LONGER assumes z is a sub-coframing of x
  53. begin scalar m;
  54. m := foreach s in car z join
  55. if s := numr subsq(subtrsq(simp!* car s,simp!* cdr s),car x)
  56. then rmapeval {car x,addrsx(s,cadr x)};
  57. m := append(m,
  58. foreach s in cadr z join
  59. rmapeval {(0 . s) . car x,cadr x});
  60. return edsdisjoin purge m;
  61. end;
  62. symbolic procedure rmapeval x;
  63. % x:rmap -> rmapeval:list of rmap
  64. % Resolve a badly formed rmap into a disjoint list of rmaps.
  65. % The map part of x may include equations expr=expr.
  66. begin scalar xl,vl;
  67. % First resolve map part, solving for lhs variables where possible
  68. vl := purge foreach s in car x collect car s;
  69. vl := {intersection(cfrmcrd!*,vl),setdiff(cfrmcrd!*,vl)};
  70. xl := foreach s in car x collect
  71. subtrsq(simp!* car s,simp!* cdr s);
  72. return foreach s in edssolvegraded(xl,vl,cadr x) collect
  73. if car s then cdr s
  74. else
  75. << lprim "Could not resolve decomposition entirely";
  76. {foreach q in cdr s collect 0 . mk!*sq q,cadr x} >>;
  77. end;
  78. endmodule;
  79. end;