crgensep.red 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. %*********************************************************************
  2. module gensep$
  3. %*********************************************************************
  4. % Routines for generalized separation of de's
  5. % Author: Andreas Brand, Thomas Wolf
  6. % 1990 1994 1997
  7. %
  8. % $Id: crgensep.red,v 1.7 1998/06/04 15:04:28 tw Exp tw $
  9. %
  10. symbolic procedure maxnoargs(fl,v)$
  11. % determines the maximal number of arguments of any of the
  12. % functions of fl
  13. begin scalar n,m;
  14. n:=0;
  15. for each f in fl do
  16. <<m:=fctargs f;
  17. m:=if m and not_included(v,m) then length m
  18. else 0;
  19. if n<m then n:=m
  20. >>;
  21. return n
  22. end$
  23. symbolic procedure get_gen_separ_pde(pdes)$
  24. % looking for a pde in pdes which can be indirectly separated
  25. % p ...the next equation that will be chosen
  26. % dw...whether p was already delt with
  27. % nv...maximal number of arguments of any of the functions of p
  28. % nf...min number of functions to be dropped before direct sep.
  29. % leng...length of p
  30. begin scalar p,nv,nf,dw,len,h1,h2,h3,h4$
  31. while pdes do <<
  32. if flagp(car pdes,'to_gensep) and
  33. % not too many terms:
  34. (gensep_ > (h1:=get(car pdes,'length)) ) and
  35. % no single function depending on all variables:
  36. (h3:=get(car pdes,'starde) ) and
  37. % Each time the equation is investigated and differentiated
  38. % wrt the first element of car h3, this element is dropped.
  39. % --> The equation should not already have been differentiated
  40. % wrt all variables:
  41. (not null car h3 ) and
  42. % If equations have been investigated by generalized
  43. % separation or if equations resulted from generalized
  44. % separation then they get the flag used_ to be solved
  45. % first, not to have too many unevaluated new functions
  46. % at a time
  47. ((h4:=flagp(car pdes,'used_) ) or
  48. (null dw) ) and
  49. % The variables in h3 are the ones wrt which direct separation
  50. % shall be achieved after differentiation, therefore functions
  51. % of these variables have to be thrown out. The remaining
  52. % functions shall be of as many as possible arguments to
  53. % make quick progress:
  54. ((null p ) or
  55. (nv < (h2:=maxnoargs(
  56. get(car pdes,'fcts),
  57. car h3 )) ) or
  58. ((null dw) and flagp(car pdes,'used_)) or
  59. (( nv = h2 ) and
  60. (( nf > cdr h3 ) or
  61. ((nf = cdr h3 ) and
  62. (len > h1 ) ) ) ) ) then
  63. <<p:=car pdes;
  64. nv:=if null nv then maxnoargs(get(p,'fcts),
  65. car h3) % first time
  66. else h2;
  67. if h4 then dw:=h4;
  68. nf:=cdr h3;
  69. len:=h1>>$
  70. pdes:=cdr pdes$
  71. >>;
  72. return p
  73. end$
  74. symbolic procedure gensep(p)$
  75. % generalized separation of pde p
  76. if zerop cdr get(p,'starde) then separate(p) % be dropped?
  77. else % e.g. a=((x y z).2)
  78. begin scalar ftem,ftem1,a,aa,q,l1,l2,ft,pl,x,vl,vl1,deno,starlist,
  79. f,nv,nv1,h,firsttime,ruli$
  80. % remflag1(p,'to_gensep)$
  81. ruli:=start_let_rules()$
  82. if print_ then <<terpri()$write "generalized separation of ",p>>$
  83. if tr_gensep then
  84. <<a:=get(p,'starde)$
  85. terpri()$write "de to be separated : "$
  86. typeeqlist list p$
  87. terpri()$write "variable list for separation : ",car a$
  88. terpri()$write "for each of these variables ",cdr a$
  89. if (cdr a)=1 then write" function does"
  90. else write" functions"$
  91. write" depend on it "
  92. >>$
  93. %--- so far only one DE p in the pool starlist of equations
  94. starlist:=list(list(get(p,'val), % expression
  95. get(p,'fcts), % functions
  96. get(p,'vars), % variables
  97. get(p,'starde), % separation charac.
  98. nil % history of divisions
  99. ));
  100. firsttime:=t;
  101. while starlist do <<
  102. %--- take first equation from starlist and
  103. %--- delete it from starlist
  104. l1:=car starlist; starlist:=cdr starlist;
  105. %--- the content of l1:
  106. q :=car l1; % the expression
  107. ftem:=cadr l1; % functions in the expression
  108. vl :=caddr l1; % variables in the expression
  109. a :=car cadddr l1; % the variables for direct separation
  110. l2 :=nth(l1,5); % history of divisions so far
  111. %--- ft: the list of functions to drop from q by differ.
  112. %--- to do a direct separation wrt x:
  113. % x:=car a$
  114. % x:=nth(a,1+random length a)$
  115. % x = any one variable in a on which a function with as
  116. % many as possible variables does not depend on
  117. ftem1:=ftem;
  118. nv:=0;
  119. while ftem1 do <<
  120. vl1:=fctargs car ftem1;
  121. nv1:=if vl1 then length vl1
  122. else 0;
  123. if nv1 > nv then <<
  124. h:=setdiff(a,vl1);
  125. if h then <<
  126. x:=car h;
  127. f:=car ftem1;
  128. nv:=nv1
  129. >>
  130. >>;
  131. ftem1:=cdr ftem1
  132. >>;
  133. if nv=0 then x:=car a; % so far no x had been found
  134. % f:=car ftem;
  135. % vl1:=fctargs f;
  136. % nv:=if vl1 then length vl1
  137. % else 0;
  138. %
  139. % for each x in cdr ftem do <<
  140. % vl2:=fctargs x;
  141. % if vl2 and (nv<length(vl2)) then <<
  142. % f:=x; nv:=length(vl2)
  143. % >>
  144. % >>;
  145. % x:=vl;
  146. % vl1:=fctargs f;
  147. % while member(car x,vl1) do x:=cdr x; % there must be one
  148. % x:=car x;
  149. %x:=car a;
  150. if firsttime then
  151. put(p,'starde,delete(x,car cadddr l1) . cdr cadddr l1);
  152. ft:=nil$
  153. for each f in ftem do
  154. if member(x,fctargs f) and not freeof(q,f) then ft:=cons(f,ft)$
  155. if tr_gensep then
  156. <<terpri()$write "to separate directly w.r.t. ",x$
  157. write " the expression : "$deprint list q$
  158. write "will be differentiated">>$
  159. ft:=fctsort reverse ft$ % sorting w.r.t. number of args
  160. %--- throwing out functions ft until ft=nil
  161. %--- or until the expression lost the *-property
  162. while ft do
  163. if (l1:=felim(q,car ft,ftem,vl,l2)) then <<
  164. q:=car l1$ % new expression
  165. l2:=cadr l1$ % extended history
  166. ftem:=smemberl(ftem,q); % functions still in q
  167. aa:=stardep(ftem,vl); % still *-expression?
  168. if not aa or zerop cdr aa then ft:=nil
  169. else ft:=smemberl(cdr ft,q)
  170. >> else ft:=nil$
  171. if null l1 then if tr_gensep then <<terpri()$
  172. write"felim gave nil!!"$terpri()$
  173. write"q=",q;terpri()
  174. >> else
  175. else
  176. <<if tr_gensep then <<
  177. terpri()$
  178. write"Now ready for direct separation."
  179. >>;
  180. %--- make denominator-free for direct separation
  181. if (pairp q) and (car q='QUOTIENT) then
  182. <<deno:=caddr q$
  183. q:=cadr q$
  184. ft:=smemberl(ftem,q)>> else ft:=nil$
  185. %--- prepare list of variables vl1 for direct separation
  186. if ft then <<
  187. vl1:=nil$
  188. for each y in vl do if my_freeof(ft,y) then vl1:=cons(y,vl1)
  189. >> else vl1:=vl$
  190. %--- direct separation if useful (i.e. if aa neq nil)
  191. if aa and zerop cdr aa and not (q=0) then
  192. <<if tr_gensep then
  193. <<terpri()$write "trying direct separation of "$
  194. deprint list q$
  195. write "Remaining variables: ",vl1>>$
  196. l1:=for each bb in separ(q,ftem,vl1) collect cdr bb$
  197. if tr_gensep then
  198. <<terpri()$
  199. write "The result of direct separation: "$deprint l1>>$
  200. if l1 and cdr l1 and tr_gensep then
  201. <<terpri()$
  202. write "direct separation yields ",length l1," equations">>
  203. >> else l1:=list q$
  204. %--- backintegration
  205. if tr_gensep then <<
  206. terpri()$
  207. write"Separation gave ",length l1," condition(s)"
  208. >>;
  209. fnew_:=nil$
  210. stop_let_rules(ruli)$ % because integration may not work properly
  211. while l1 do <<
  212. q:=car l1; l1:=cdr l1;
  213. if deno then q:=list('QUOTIENT,q,deno);
  214. ft:=smemberl(ftem,q);
  215. vl1:=argset(ft); % all other explicitly occuring variables
  216. % are gone through direct separation
  217. if (aa:=stardep(ft,vl1)) then
  218. starlist:=cons(list(q,ft,vl1,aa,l2),starlist)
  219. else
  220. pl:=union(list(backint(q,l2,union(fnew_,ftem),vl)),pl)
  221. >>;
  222. ruli:=start_let_rules()$
  223. ftem_:=reverse ftem_$
  224. for each f in reverse fnew_ do ftem_:=fctinsert(f,ftem_)$
  225. ftem_:=reverse ftem_$
  226. fnew_:=nil$
  227. >>$
  228. %if null l3 then << a:=cdr a$ q:=get(p,'val)>> else
  229. %a:=nil;
  230. %% Only if all possible separations should be done at once.
  231. %% Better to stop here and to do substitutions first.
  232. firsttime:=nil$
  233. >>$
  234. if pl then <<
  235. pl:=mkeqlist(pl,fctsort union(ftem_,get(p,'fcts)),get(p,'vars),
  236. cons('to_drop,allflags_),t,get(p,'orderings))$
  237. flag(list(p),'used_);
  238. flag(pl,'used_);
  239. if print_ then <<terpri()$
  240. a:=length pl$
  241. write "separation yields ",a," new equation"$
  242. if a > 1 then write"s"$ write" : "$
  243. if tr_gensep then typeeqlist pl
  244. else listprint pl
  245. >>
  246. >>$
  247. stop_let_rules(ruli)$
  248. return cons(p,pl)$
  249. end$
  250. symbolic procedure felim(q,f,ftem,vl,l2)$
  251. begin scalar a,b,l,l1,ft1,v,prflag$
  252. %--- getting rid of f through diff. wrt. v
  253. v:=car setdiff(vl,fctargs f)$
  254. %--- ft1 are all v-independent functions
  255. %--- In the call to separ one has to disregard v-dep. functions
  256. ft1:=nil$
  257. for each f in ftem do if my_freeof(f,v) then ft1:=cons(f,ft1)$
  258. %--- To run separ, functions ft1 should not be in the denominator
  259. %--- ?????? What if nonl. Problems?
  260. if not (pairp q and (car q='QUOTIENT) and smemberl(ft1,caddr q)) then
  261. <<prflag:=print_$print_:=nil$
  262. l:=desort separ(q,ft1,list v)$ % det. all lin. ind. factors with v
  263. if tr_gensep then
  264. <<terpri()$write "To get rid of ",f,
  265. " we differentiate w.r.t. : ",v>>$
  266. print_:=prflag$
  267. %--- l is a list of dotted pairs a each representing a term in q
  268. % where car(a) is the product of v-dep. factors and cdr(a) the
  269. % product of v-independent factors
  270. %--- A list l1 of car(a) is generated for which cdr(a) depends
  271. % on f. l1 is the list of divisions to be done before differen.
  272. l1:=nil$
  273. while l do
  274. <<a:=car l$
  275. b:=nil$
  276. if not freeof(cdr a,f) and (not zerop car a) then
  277. % if (pairp cdr a) and (cadr a='PLUS) then
  278. % <<for each c in cddr a do if not freeof(c,f) then b:=cons(c,b)$
  279. % if b then b:=cons('PLUS,b)>> else b:=cdr a$
  280. % if b then
  281. <<l1:=cons(car a,l1)$
  282. % q:=reval list('DIFFERENCE,q,list('times,b,car a))
  283. >>$
  284. l:=cdr l
  285. >>$
  286. if tr_gensep then
  287. <<terpri()$
  288. write v," - depending coefficients of terms containing ",f," : "$
  289. for each ss in l1 do eqprint ss>>$
  290. %--- Now the divisions and differentiations are done
  291. while l1 do
  292. <<b:=reval aeval car l1$ %--- b is the v-dep. coefficient
  293. l1:=cdr l1$
  294. %--- ????? If for non-linear Problems b includes ftem functions
  295. % then the extra case 0 = b has to be considered
  296. if not zerop b then
  297. <<a:=reval aeval list('QUOTIENT,q,b)$
  298. %--- for later backward integrations: extension of the history
  299. if new_gensep then %############## change:
  300. l:=cons(b . q ,l) %--- q is the equ. before division & diff.
  301. else
  302. l:=cons(b ,l)$
  303. % l will be returned later by felim
  304. %--- l1 has to be updated as the coefficients
  305. % change through division and differentiation
  306. l1:=for each c in l1 collect
  307. reval list('DF,list('QUOTIENT,c,b),v)$
  308. %--- the differentiation
  309. q:=reval list('DF,a,v)$
  310. if tr_gensep then
  311. <<write "The new equation: "$
  312. eqprint q$
  313. write "The remaining factors:"$
  314. for each ss in l1 do eqprint ss
  315. >>
  316. >>
  317. >>$
  318. if l then l2:=cons(list(v,l),l2)$
  319. %--- output
  320. if tr_gensep then
  321. <<terpri()$write "new expression (should not depend on ",f,") : "$
  322. eqprint q$>>$
  323. if tr_gensep and l2 then
  324. <<write "The list of multiplications and integrations ",
  325. "to go backwards after direct separation:"$
  326. for each ss in l2 do <<write "integr. wrt. ",car ss$ terpri()$
  327. write "multiply with "$
  328. for each aa in cadr ss do
  329. %--- print all collected factors
  330. eqprint aa>>
  331. >>$
  332. l1:=list(q,l2)
  333. >>$
  334. return l1
  335. %--- returns nil if not successful (quotient)
  336. % otherwise a list with 2 elements: the current equation and a history list
  337. % which is the input history list extended by the current run, each
  338. % run being represented by one element which itself is a list of the
  339. % differentiation variable and the list of factors
  340. end$
  341. symbolic procedure backint(s,l2,ftem,vl)$
  342. begin scalar fl,ft,q,l,v,v1,vf,s2,p,f2,fnew1$
  343. % factors should be dropped which do not depend on any integration
  344. % variable and not on any variable of the ftem functions but on other
  345. % variables of vl
  346. % But factors containing ftem functions should not be dropped.
  347. % It is assumed that all integration variables are argument to at
  348. % least one function of ftem
  349. ft:=smemberl(union(ftem,fnew_),s);
  350. v1:=argset ft;
  351. q:=t;
  352. l:=vl;
  353. while q and l do
  354. if freeof(v1,car l) and
  355. (not my_freeof(s,car l)) then q:=nil
  356. else l:=cdr l;
  357. if not q then s:=cadr extractfac(s,append(v1,ft),nil)$
  358. % start of the backintegration
  359. fnew1:=fnew_$
  360. fl:=q:=t$
  361. p:=s$
  362. while l2 and fl do
  363. <<l:=car l2$
  364. l2:=cdr l2$
  365. v:=car l$
  366. if tr_gensep then
  367. <<terpri()$
  368. write "backward integration w.r.t. ",v," of the expression : "$
  369. eqprint p>>$
  370. l:=cadr l$
  371. while l and q do
  372. <<ft:=smemberl(ftem,p)$
  373. %terpri()$write "vor int: p= "$eqprint p$
  374. fnew_:=nil$
  375. q:=integratepde(p,ft,v,nil,nil)$ % genflag:=nil, potflag=nil
  376. fnew1:=append(fnew_,fnew1)$
  377. if q then
  378. <<fl:=t$
  379. p:=reval list('TIMES,car l,car q)$
  380. % Substituting the new functions of integration by derivatives
  381. % of them such that back-integration can be made
  382. % hat fnew_ nur ein element, d.h. wird nur eine Integration gemacht
  383. % oder mehrere?
  384. for each f1 in fnew_ do
  385. <<f2:=f1$
  386. vf:=setdiff(vl,fctargs f1)$
  387. for each s1 in reverse l2 do
  388. <<v1:=car s1$
  389. if not my_freeof(f1,v1) then
  390. % only then integration makes difficulties
  391. <<s2:=reverse cadr s1$
  392. while s2 do
  393. <<if not smemberl(vf,car s2) then
  394. f2:=reval list('DF,list('QUOTIENT,f2,car s2),v1)$
  395. % actually only dividing through those factors of (car s2)
  396. % which depend on v1 and which do not contain variables
  397. % which f2 does not depent on.
  398. s2:=cdr s2
  399. >>
  400. >>
  401. >>$
  402. if f1 neq f2 then
  403. <<if tr_gensep then <<terpri()$
  404. write f1," is replaced by "$
  405. eqprint f2>>$
  406. p:=subst(f2,f1,p)$
  407. >>
  408. >>$
  409. ftem:=union(fnew_,ftem)
  410. >> else fl:=nil$
  411. l:=cdr l
  412. >>
  413. >>$
  414. if tr_gensep then if fl then <<terpri()$write "yields : "$
  415. eqprint p$>>
  416. else <<terpri()$
  417. write "was not successful.">>$
  418. fnew_:=union(fnew1,fnew_)$
  419. return if fl then p
  420. else s
  421. end$
  422. endmodule$
  423. end$