crgensep.red 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343
  1. %*********************************************************************
  2. module gensep_lin$
  3. %*********************************************************************
  4. % Routines for generalized separation of de's
  5. % Author: Andreas Brand, Thomas Wolf 1990 1994 1997
  6. % Thomas Wolf since 1997
  7. symbolic procedure quick_gen_separation(arglist)$
  8. % Indirect separation of a pde
  9. if vl_ then % otherwise not possible --> save time
  10. begin scalar p,l,l1,pdes,stp$
  11. % pdes:=clean_up(car arglist)$
  12. % if pdes then l:=list(pdes,cadr arglist)$
  13. % because the bookeeping of to_drop is not complete instead:
  14. pdes:=car arglist$
  15. % to return the new list of pdes in case gensep is not successful
  16. if expert_mode then <<
  17. l1:=selectpdes(pdes,1);
  18. if get(car l1,'starde) then flag(l1,'to_gensep)
  19. >> else l1:=cadddr arglist$
  20. if (p:=get_gen_separ_pde(l1,t,t)) then % high priority
  21. <<l:=gensep(p,pdes)$
  22. pdes:=delete(p,pdes)$
  23. for each a in l do <<
  24. pdes:=eqinsert(a,pdes)$
  25. if member(a,pdes) and (stp:=get(a,'starde)) then
  26. to_do_list:=cons(list(if cdr stp=0 then 'separation
  27. else 'gen_separation,
  28. %pdes,cadr arglist,caddr arglist,
  29. list a),
  30. to_do_list)
  31. >>$
  32. l:=list(pdes,cadr arglist)>>$
  33. return l$
  34. end$
  35. symbolic procedure gen_separation(arglist)$
  36. % Indirect separation of a pde
  37. if vl_ then % otherwise not possible --> save time
  38. begin scalar p,l,l1,pdes,stp$
  39. % pdes:=clean_up(car arglist)$
  40. % if pdes then l:=list(pdes,cadr arglist)$
  41. % because the bookeeping of to_drop is not complete instead:
  42. pdes:=car arglist$
  43. % to return the new list of pdes in case gensep is not successful
  44. if expert_mode then <<
  45. l1:=selectpdes(pdes,1);
  46. if get(car l1,'starde) then flag(l1,'to_gensep)
  47. >> else l1:=cadddr arglist$
  48. if (p:=get_gen_separ_pde(l1,nil,t)) then % low priority
  49. <<l:=gensep(p,pdes)$
  50. pdes:=delete(p,pdes)$
  51. for each a in l do <<
  52. pdes:=eqinsert(a,pdes)$
  53. if member(a,pdes) and (stp:=get(a,'starde)) then
  54. to_do_list:=cons(list(if cdr stp=0 then 'separation
  55. else 'gen_separation,
  56. %pdes,cadr arglist,caddr arglist,
  57. list a),
  58. to_do_list)
  59. >>$
  60. l:=list(pdes,cadr arglist)>>$
  61. return l$
  62. end$
  63. symbolic procedure maxnoargs(fl,v)$
  64. % determines the maximal number of arguments of any of the
  65. % functions of fl
  66. begin scalar f,n,m;
  67. n:=0;
  68. for each f in fl do
  69. <<m:=fctargs f;
  70. m:=if m and not_included(v,m) then length m
  71. else 0;
  72. if n<m then n:=m
  73. >>;
  74. return n
  75. end$
  76. symbolic procedure get_gen_separ_pde(pdes,high_priority,lin)$
  77. % looking for a pde in pdes which can be indirectly separated
  78. % if lin then only a liner PDE
  79. % p ...the next equation that will be chosen
  80. % dw...whether p was already delt with
  81. % na...number of variables in the equation
  82. % nv...maximal number of arguments of any of the functions of p
  83. % nf...min number of functions to be dropped before direct sep.
  84. % leng...length of p
  85. begin scalar p,nv,nf,dw,len,h1,h2,h3,h4,nvmax$ %na,h5
  86. % ncmax:=nvmax$
  87. if high_priority then <<
  88. nvmax:=0;
  89. for each p in pdes do if (h1:=get(p,'nvars))>nvmax then nvmax:=h1;
  90. p:=nil
  91. >>$
  92. while pdes do <<
  93. if flagp(car pdes,'to_gensep) and
  94. (null lin or get(car pdes,'linear_)) and
  95. % not too many terms or enough terms
  96. <<h1:=get(car pdes,'length)$
  97. (null high_priority) or
  98. (get(car pdes,'nvars)=nvmax) or
  99. ( low_gensep>h1) or
  100. (high_gensep<h1)
  101. >> and
  102. % no single function depending on all variables:
  103. (h3:=get(car pdes,'starde) ) and
  104. % not directly separable:
  105. (cdr h3 neq 0 ) and
  106. % Each time the equation is investigated and differentiated
  107. % wrt the first element of car h3, this element is dropped.
  108. % --> The equation should not already have been differentiated
  109. % wrt all variables:
  110. (not null car h3 ) and
  111. % If equations have been investigated by generalized
  112. % separation or if equations resulted from generalized
  113. % separation then they get the flag used_ to be solved
  114. % first, not to have too many unevaluated new functions
  115. % at a time
  116. ((h4:=flagp(car pdes,'used_) ) or
  117. (null dw) ) and
  118. % The variables in h3 are the ones wrt which direct separation
  119. % shall be achieved after differentiation, therefore functions
  120. % of these variables have to be thrown out. The remaining
  121. % functions shall be of as many as possible arguments to
  122. % make quick progress:
  123. ((null p ) or
  124. (len > h1 ) or % neu
  125. ((len = h1) and ( % neu
  126. (nv < (h2:=maxnoargs(
  127. get(car pdes,'fcts),
  128. car h3 )) ) or
  129. ((nv = h2) and (
  130. % (na < (h5:=get(car pdes,'nvars)) ) or
  131. % ((na = h5) and (
  132. ((null dw) and flagp(car pdes,'used_)) or
  133. (( nf > cdr h3 ) or
  134. ((nf = cdr h3 ) and
  135. (len > h1 ) ) ) ) )))) then
  136. <<p:=car pdes;
  137. nv:=if (null nv) or (null h2) then maxnoargs(get(p,'fcts),car h3)
  138. else h2;
  139. % na:=if (null na) or (null h5) then get(car pdes,'nvars)
  140. % else h5;
  141. if h4 then dw:=h4;
  142. nf:=cdr h3;
  143. len:=h1>>$
  144. pdes:=cdr pdes$
  145. >>;
  146. return p
  147. end$
  148. %-----------------
  149. symbolic procedure gensep(p,pdes)$
  150. % generalized separation of pde p
  151. if zerop cdr get(p,'starde) then separate(p,pdes) % be dropped?
  152. else % e.g. a=((x y z).2)
  153. % POSSIBLE REASONS FOR FAILURE:
  154. % - After the sequence of divisions and differentiations in the direct
  155. % separation, if there explicit v-dependent coefficients are taken
  156. % out which also contain later integration variables, then the integrands
  157. % are not total derivatives anymore --> no backintegration is possible.
  158. % - This corresponds to the case when all variables occur explicitly but
  159. % in a non-product expression, like sin(x*y*z)
  160. begin scalar a,pl$
  161. if print_ then <<terpri()$write "generalized separation of ",p>>$
  162. if tr_gensep then
  163. <<a:=get(p,'starde)$
  164. terpri()$write "de to be separated : "$
  165. typeeqlist list p$
  166. terpri()$write "variable list for separation : ",car a$
  167. terpri()$write "for each of these variables ",cdr a$
  168. if (cdr a)=1 then write" function does"
  169. else write" functions"$
  170. write" depend on it "
  171. >>$
  172. %--- so far only one DE p in the pool starlist of equations
  173. pl:=partitn(get(p,'val), % expression
  174. nil, % history of divisions/diff so far
  175. get(p,'fcts), % functions
  176. get(p,'vars), % variables
  177. car get(p,'starde) % separation charac.
  178. );
  179. if pl then <<
  180. pl:=append(for each a in car pl collect cdr a,cadr pl);
  181. pl:=mkeqlist(pl,fctsort union(ftem_,get(p,'fcts)),get(p,'vars),
  182. cons('to_drop,allflags_),t,get(p,'orderings),pdes)$
  183. drop_pde(p,nil,nil);
  184. flag(pl,'used_);
  185. if print_ then <<terpri()$
  186. a:=length pl$
  187. write "separation yields ",a," new equation"$
  188. if a > 1 then write"s"$ write" : "$
  189. if tr_gensep then typeeqlist pl
  190. else listprint pl$
  191. terpri()
  192. >>
  193. >> else <<
  194. remflag1(p,'to_gensep)$
  195. pl:=list p
  196. >>$
  197. return pl$
  198. end$
  199. %-----------------
  200. symbolic procedure partitn(q,old_histy,ftem,vl,a)$
  201. % This procedure calls itself recursively!
  202. % q: a **-expression to be separated
  203. % old_histy: a list of elements {denom,v,{(divisor . expr_before),..}}
  204. % where a sequence of divisions through factors from the
  205. % list of divisors and differentiations wrt. v and
  206. % afterwards multiplication with denom resulted in q
  207. % ftem: functions in the expression
  208. % vl: variables in the expression
  209. % a: the variables for direct separation=car starp()
  210. %
  211. % RETURNS {{(c1.q1),(c2.q2),(c3.q3),..},{s1,s2,s3,..},{r1,r2,..},{f1,f2,..}}
  212. % where qi=0 are necessary consequences,
  213. % qi are not *-expressions,
  214. % sum_i ci*qi = q
  215. % si=0 are consistency conditions determining constants/functions
  216. % of integration
  217. % ri=0 are other cases to be checked --> case distinctions
  218. begin scalar histy,l1,l4,nv,vl1,nv1,h,x,f,ft,aa,bb,cc,y,
  219. ruli,extra_cond,par,cases,newf$
  220. %--- ft: the list of functions to drop from q by differentiation
  221. %--- to do a direct separation wrt x:
  222. % x = any one variable in a on which a function with as
  223. % many as possible variables does not depend on
  224. % Find such a function and variable x
  225. ft:=ftem;
  226. nv:=0;
  227. while ft do <<
  228. vl1:=fctargs car ft;
  229. nv1:=if vl1 then length vl1
  230. else 0;
  231. if nv1 > nv then <<
  232. h:=setdiff(a,vl1);
  233. if h then <<
  234. x:=car h;
  235. % if possible find an x occuring explicitly in q
  236. while h and freeof(q,car h) do h:=cdr h;
  237. if h then x:=car h;
  238. f:=car ft;
  239. nv:=nv1
  240. >>
  241. >>;
  242. ft:=cdr ft
  243. >>;
  244. if nv=0 then x:=car a; % no x was found
  245. if tr_gensep then
  246. <<terpri()$write "--- The aim is to separate directly w.r.t. ",x$
  247. write " the expression : "$deprint list q >>$
  248. % Find all functions ft in q depending on x
  249. ft:=nil$
  250. for each f in ftem do
  251. if member(x,fctargs f) and not freeof(q,f) then ft:=cons(f,ft)$
  252. ft:=fctsort reverse ft$ % sorting w.r.t. number of args
  253. ruli:=start_let_rules()$
  254. %--- throwing out functions ft until ft=nil
  255. %--- or until the expression lost the *-property
  256. while ft do % for each function to get rid of
  257. % (possibly each time a different diff variable)
  258. if null (l1:=felim(q,car ft,ftem,vl)) then ft:=nil % to stop
  259. else <<
  260. %prettyprint l1;
  261. for each h in cdadr l1 do % special extra cases
  262. if not freeoflist(car h,ftem) then cases:=cons(car h,cases);
  263. %write"cadr l1=",cadr l1$terpri()$
  264. if zerop car l1 then <<
  265. q:=reval {'QUOTIENT,cdr cadadr l1,car cadadr l1}; % new expression
  266. cc:=cons(car cadr l1,cddadr l1);
  267. >> else <<
  268. q:=car l1$ % new expression
  269. cc:=cadr l1;
  270. >>$
  271. if (pairp q) and (car q='QUOTIENT) then <<
  272. bb:=caddr q; % we take off the denimonator
  273. q:=cadr q
  274. >> else bb:=1$
  275. histy:=cons(cons(bb,cc),histy)$ % extended history
  276. %terpri()$write"q=",q$terpri()$
  277. %write"histy=",histy$terpri()$
  278. ftem:=smemberl(ftem,q)$ % functions still in q
  279. aa:=stardep(ftem,argset(ftem))$ % still *-expression?
  280. if not aa or
  281. zerop cdr aa then ft:=nil % to stop
  282. else ft:=smemberl(cdr ft,ftem) % remain. fcts of x
  283. >>$
  284. stop_let_rules(ruli)$
  285. if null l1 then if tr_gensep then <<terpri()$
  286. write"felim or newgensep gave nil!!"$terpri()$
  287. write"q=",q;terpri()
  288. >> else
  289. else
  290. RETURN <<
  291. if tr_gensep then <<
  292. terpri()$
  293. write"Now ready for direct separation."
  294. >>;
  295. %--- prepare list of variables vl1 for direct separation
  296. vl1:=nil$
  297. for each y in vl do if my_freeof(ftem,y) then vl1:=cons(y,vl1);
  298. %--- direct separation if useful (i.e. if aa(=stardep) neq nil)
  299. if vl1 and not (q=0) then
  300. <<if tr_gensep then
  301. <<terpri()$write "trying direct separation of "$
  302. deprint list q$
  303. write "Remaining variables: ",vl1>>$
  304. l1:=separ(q,ftem,vl1,nil)$ % direct separation of the numerator
  305. if tr_gensep then
  306. <<terpri()$
  307. write "The result of direct separation: "$
  308. deprint for each bb in l1 collect cdr bb>>$
  309. >> else l1:=list cons(1,q)$
  310. if tr_gensep then <<
  311. terpri()$
  312. write"Separation gave ",length l1," condition(s)"
  313. >>;
  314. % Although the vaiable x does not occur anymore
  315. % (each felim call removed one function of x
  316. % and direct separation removed explicit occurences of x)
  317. % the remaining expression may still be indirectly separable
  318. % --> recursive call of partitn
  319. % l4 becomes a list of pairs (sep_coefficient . sep_remainding_factor)
  320. for each h in l1 do <<
  321. ft:=smemberl(ftem,cdr h);
  322. vl1:=argset(ft)$
  323. if null (aa:=stardep(ft,vl1)) then l4:=cons(h,l4)
  324. else <<
  325. par:=partitn(cdr h, % expression
  326. append(histy, % history so far,
  327. old_histy), % needed to add new functions
  328. % of integration properly differentiated to be
  329. % able to integrate below
  330. ft, % functions
  331. vl1, % variables
  332. car aa % separation charac.
  333. );
  334. % RETURNS {{(c1.q1),(c2.q2),(c3.q3),..},{s1,s2,s3,..},
  335. % {r1,r2,..},{f1,f2,..} }
  336. % where qi=0 are necessary consequences,
  337. % qi are not *-expressions,
  338. % sum_i ci*qi = q
  339. % si=0 are consistency conditions determining constants/functions
  340. % of integration
  341. % ri=0 are other cases to be checked --> case distinctions
  342. l4:=append(l4,for each f in car par collect
  343. ({'TIMES,car h,car f} . cdr f));
  344. extra_cond:=append(extra_cond,cadr par); % collecting any
  345. % appearing conditions
  346. cases:=append(cases,caddr par);
  347. newf:=cadddr par;
  348. ftem:=append(ftem,newf);
  349. >>
  350. >>$
  351. %--- backintegration
  352. par:=backint(l4,old_histy,histy,ftem,vl)$
  353. extra_cond:=append(extra_cond,cadr par); % collecting any conditions
  354. {car par,extra_cond,cases,append(newf,caddr par)}
  355. >>
  356. end$
  357. %-----------
  358. symbolic procedure felim(q,f,ftem,vl)$
  359. % returns: nil if not successful (quotient) otherwise
  360. % {the expression after all the divisions and differentiations,
  361. % {diff variable, sequence of (factor . expression before)} }
  362. begin scalar a,b,l,l1,ft1,v,prflag$
  363. %--- getting rid of f through diff. wrt. v
  364. v:=car setdiff(vl,fctargs f)$
  365. %--- ft1 are all v-independent functions
  366. %--- In the call to separ one has to disregard v-dep. functions
  367. ft1:=nil$
  368. for each f in ftem do if my_freeof(f,v) then ft1:=cons(f,ft1)$
  369. %--- To run separ, functions ft1 should not be in the denominator
  370. %--- ?????? What if nonl. Problems?
  371. if not (pairp q and (car q='QUOTIENT) and smemberl(ft1,caddr q)) then
  372. % This exceptional case should not occure anymore
  373. <<prflag:=print_$print_:=nil$
  374. l:=separ(q,ft1,list v,nil)$ % det. all lin. ind. factors with v
  375. for each a in reverse idx_sort for each b in l
  376. collect cons(delength car b,b)
  377. collect cdr a$
  378. if tr_gensep then
  379. <<terpri()$write "To get rid of ",f,
  380. " we differentiate w.r.t. : ",v>>$
  381. print_:=prflag$
  382. %--- l is a list of dotted pairs a each representing a term in q
  383. % where car(a) is the product of v-dep. factors and cdr(a) the
  384. % product of v-independent factors
  385. %--- A list l1 of car(a) is generated for which cdr(a) depends
  386. % on f. l1 is the list of divisions to be done before differen.
  387. l1:=nil$
  388. while l do
  389. <<a:=car l$
  390. b:=nil$
  391. if not freeof(cdr a,f) and (not zerop car a) then
  392. l1:=cons(car a,l1)$
  393. l:=cdr l
  394. >>$
  395. if tr_gensep then
  396. <<terpri()$
  397. write v," - depending coefficients of terms containing ",f," : "$
  398. for each ss in l1 do eqprint ss>>$
  399. %--- Now the divisions and differentiations are done
  400. while l1 do
  401. <<b:=reval aeval car l1$ %--- b is the v-dep. coefficient
  402. l1:=cdr l1$
  403. %--- ????? If for non-linear Problems b includes ftem functions
  404. % then the extra case 0 = b has to be considered
  405. if not zerop b then
  406. <<a:=reval aeval list('QUOTIENT,q,b)$
  407. %--- for later backward integrations: extension of the history
  408. l:=cons(b . q ,l)$ %--- new: q is the equ. before division & diff.
  409. % formerly: l:=cons(b ,l)$
  410. % l will be returned later by felim
  411. %--- l1 has to be updated as the coefficients
  412. % change through division and differentiation
  413. l1:=for each c in l1 collect
  414. reval list('DF,list('QUOTIENT,c,b),v)$
  415. %--- the differentiation
  416. q:=reval list('DF,a,v)$
  417. if tr_gensep then
  418. <<write "The new equation: "$
  419. eqprint q$
  420. write "The remaining factors:"$
  421. for each ss in l1 do eqprint ss
  422. >>
  423. >>
  424. >>$
  425. %if l then part_histy:=cons(v,l)$
  426. %--- output
  427. if tr_gensep then
  428. <<terpri()$write "new expression (should not depend on ",f,") : "$
  429. eqprint q$>>$
  430. if tr_gensep and l then
  431. <<write"To invert the last steps one has to integr. wrt. ",v$
  432. terpri()$
  433. write "each time before multiplying with "$
  434. for each aa in l do eqprint car aa
  435. >>$
  436. l1:=list(q,cons(v,l))
  437. >>$
  438. return l1
  439. end$
  440. symbolic procedure backint(l4,old_histy,histy,ftem,vl)$
  441. % l4 is a list of pairs (sep_coefficient .
  442. % sep_remainding_factor_to_be_integrated)
  443. % old_histy, histy are lists of elements
  444. % {denom,v,{(divisor . expr_before),..}}
  445. % where a sequence of divisions through factors from the
  446. % list of divisors and differentiations wrt. v and
  447. % afterwards multiplication with denom resulted in q
  448. % Integrations should only be done inverting histy, but
  449. % in choosing functions of integration, both should be used
  450. %
  451. % returns {- integrated equivalent of l4 where the cdr of each element
  452. % is the integrated expression,
  453. % - a list of check_sum conditions,
  454. % - a list of new functions}
  455. begin scalar succ,ft,q,l,v,v1,vf,s1,s2,p,f1,f2,fctr,check_sum,
  456. allfnew,new_cond,denomi$
  457. % start of the backintegration
  458. succ:=t$
  459. while histy and succ do
  460. <<l:=car histy$ % l={diff variable, sequence of (factor . exp before)}
  461. histy:=cdr histy$
  462. denomi:=car l$
  463. v:=cadr l$
  464. l:=cddr l$
  465. % At first putting the denominator back in
  466. % l4 is a list of pairs (sep_coefficient . sep_remainding_factor)
  467. if denomi neq 1 then
  468. l4:=for each h in l4 collect (car h . {'QUOTIENT,cdr h,denomi});
  469. if tr_gensep then <<terpri()$ write "backward integration w.r.t. ",v>>$
  470. % Now the sequence of integrations wrt v
  471. % l is the list of (factor . expression before division & diff)
  472. while l do << % while l and q do
  473. fctr:=caar l;
  474. check_sum:=cdar l;
  475. l:=cdr l;
  476. if tr_gensep then
  477. <<terpri()$
  478. write "The integrals of the following partitioned subexpressions"$
  479. terpri()$
  480. write "added up should be equal the original expression: "$
  481. terpri()$
  482. eqprint check_sum
  483. >>$
  484. %write"l4="$
  485. %prettyprint l4;
  486. % l4 is a list of pairs (sep_coefficient . sep_remainding_factor)
  487. l4:=for each h in l4 collect if null car h then h % one integration
  488. % was not succ.ful
  489. else <<
  490. ft:=smemberl(ftem,cdr h)$
  491. fnew_:=nil$
  492. if tr_gensep then
  493. <<terpri()$
  494. write "Backintegration of: "$eqprint cdr h
  495. >>$
  496. q:=integratepde(cdr h,ft,v,nil,nil)$ % genflag:=nil, potflag=nil
  497. if null q then <<
  498. succ:=nil$
  499. if print_ then <<
  500. terpri()$
  501. write "#### Back integration of "$
  502. eqprint cdr h$
  503. write " wrt ",v," during generalized ",
  504. "separation was not successful ####."$
  505. terpri()$
  506. write "The coeff. dropped in direct separation was "$
  507. mathprint car h
  508. >>
  509. >> else <<
  510. q:=reval list('TIMES,fctr,car q)$
  511. % fctr is the next integrating factor
  512. % Neccessary: Substituting the new functions of integration by
  513. % derivatives of them such that back-integration can be made
  514. % hat fnew_ nur ein element, d.h. wird nur eine Integration gemacht
  515. % oder mehrere?
  516. for each f1 in fnew_ do
  517. <<f2:=f1$
  518. vf:=setdiff(vl,fctargs f1)$
  519. for each s1 in reverse append(histy,old_histy) do
  520. <<v1:=cadr s1$
  521. % The following also if not my_freeof(f1,v1)
  522. % The reason is that divisors may contain variables which
  523. % are later integration variables
  524. s2:=reverse cddr s1$
  525. while s2 do
  526. <<% only divisions through factors that can be swallowed by f1
  527. if not smemberl(vf,caar s2) then
  528. f2:=list('QUOTIENT,f2,caar s2)$
  529. if not my_freeof(f1,v1) then f2:=reval list('DF,f2,v1)$
  530. % actually only dividing through those factors of (caar s2)
  531. % which depend on v1 and which do not contain variables
  532. % which f2 does not depent on.
  533. s2:=cdr s2
  534. >>$
  535. if not smemberl(vf,car s1) then f2:=list('TIMES,f2,car s1)$
  536. >>$
  537. % the remaining integrations in the current element of histy
  538. if histy then <<
  539. s2:=reverse l$
  540. while s2 do
  541. <<if not smemberl(vf,caar s2) then f2:=list('QUOTIENT,f2,caar s2)$
  542. if not my_freeof(f1,v1) then f2:=reval list('DF,f2,v1)$
  543. s2:=cdr s2
  544. >>;
  545. >>;
  546. if f1 neq f2 then
  547. <<if tr_gensep then <<terpri()$
  548. write f1," is replaced by "$
  549. eqprint f2>>$
  550. q:=subst(f2,f1,q)$
  551. >>
  552. >>$
  553. allfnew:=append(fnew_,allfnew)$
  554. ftem:=union(fnew_,ftem);
  555. if succ then check_sum:={'DIFFERENCE,check_sum,{'TIMES,q,car h}};
  556. % car h is the coefficient dropped through direct separation
  557. >>$
  558. (car h . q) % the value to be collected to give the new l4
  559. >>;
  560. check_sum:=reval check_sum$
  561. if succ then new_cond:=cons(check_sum,new_cond)$
  562. if succ and tr_gensep then
  563. <<terpri()$
  564. write "Consistency condition: "$eqprint check_sum
  565. >>$
  566. >>
  567. >>$
  568. for each f in allfnew do ftem_:=fctinsert(f,ftem_)$
  569. if tr_gensep then if succ then <<terpri()$write "yields : "$
  570. eqprint p$>>
  571. else <<terpri()$
  572. write "was not successful.">>$
  573. fnew_:=nil$
  574. return {l4,new_cond,allfnew}
  575. end$
  576. endmodule$
  577. %*********************************************************************
  578. module gensep_non_lin$
  579. %*********************************************************************
  580. % Routines for generalized separation of de's
  581. % Author: Thomas Wolf since 1997
  582. symbolic procedure my_smemberl(p,vl)$
  583. begin scalar l,v;
  584. for each v in vl do
  585. if not my_freeof(p,v) then l:=cons(v,l);
  586. return reverse l
  587. end$
  588. %-----------
  589. symbolic procedure stripcond(conds)$
  590. begin scalar newconds,condi;
  591. newconds:=nil;
  592. while conds do <<
  593. condi:=cdar conds;
  594. conds:=cdr conds;
  595. if length condi=1 then condi:=car condi
  596. else condi:=cons('PLUS,condi);
  597. newconds:=cons(condi,newconds)
  598. >>;
  599. return newconds
  600. end$
  601. %-----------
  602. symbolic procedure checkli(exlist,condi)$
  603. begin
  604. scalar ok,isincondi,isinexli,excopy,n;
  605. ok:=t;
  606. while condi and ok do <<
  607. % all i in the condition car condi
  608. isincondi:=car condi; %smemberl(ilist,car condi);
  609. n:=length isincondi;
  610. % are all isincondi contained in one of the elements of exlist?
  611. excopy:=exlist;
  612. while excopy and ok do <<
  613. isinexli:=smemberl(isincondi,car excopy);
  614. if isinexli then
  615. if length(isinexli) = n then ok:=nil;
  616. excopy:=cdr excopy
  617. >>;
  618. condi:=cdr condi
  619. >>;
  620. return ok
  621. end$
  622. %-----------
  623. symbolic procedure longst(exlist)$
  624. % returns the element of exlist which (is a list and)
  625. % has the most elements
  626. begin
  627. scalar lo;
  628. while exlist do <<
  629. if not lo then lo:=car exlist else
  630. if length(lo)<length(car exlist) then lo:=car exlist;
  631. exlist:=cdr exlist
  632. >>;
  633. return lo
  634. end$
  635. %-----------
  636. symbolic procedure starequ(n,alindep,blindep)$
  637. % alindep is a list of lists of factors ai which are all non-zero and
  638. % are all linear independent from each other within such a list
  639. % blindep like alindep
  640. % generates all cases each with all conditions with _i representing
  641. % ai or bi, equations and new functions are not generated
  642. begin
  643. comment
  644. The equation to separate has the form 0 = sum_i ai*bi
  645. where the bi do not depend on some variable x. The
  646. procedure starequ generates cases:
  647. cases ... ( all cases )
  648. each case ... ( list of all a-conditions,
  649. list of all b-conditions)
  650. each condition ... ( the ai,bi contained in the condition
  651. with _i representing ai and bi )
  652. ;
  653. scalar i,j,cases,oldcases,case,ai,bi,ci,oldaconds,oldbconds,
  654. newaconds,newbcond,newbconds,newacond,
  655. ilist,cona,conb,unin,el,pri; % ,oldpri
  656. % Determine the longest union of two list, one, ai, being element of
  657. % alindep and one, bi, being from blindep
  658. %pri:=t;
  659. i:=0;
  660. if alindep then for each cona in alindep do
  661. if blindep then for each conb in blindep do
  662. if (j:=length union(cona,conb)) > i then <<ai:=cona;bi:=conb;i:=j>>
  663. else
  664. else % no blindep given
  665. if (j:=length cona) > i then <<ai:=cona;i:=j>>
  666. else
  667. else % no alindep given
  668. if blindep then for each conb in blindep do
  669. if (j:=length conb) > i then <<bi:=conb;i:=j>>;
  670. % ai, bi will now be determined
  671. % preparation of the sequence ilist of extensions
  672. ilist:=for i:=1:n collect i;
  673. if pri then <<write"222";terpri()>>$
  674. if i neq 0 then <<
  675. if ai then i:=length ai else i:=0;
  676. if bi then j:=length bi else j:=0;
  677. unin:=union(ai,bi);
  678. % extensions through bch should be done when elements from
  679. % bi are treated. This is coded in ilist through negative numbers
  680. ilist:=setdiff(ilist,unin);
  681. if i>j then <<
  682. for each el in setdiff(unin,ai) do ilist:=cons(-el,ilist);
  683. for each el in ai do ilist:=cons( el,ilist)
  684. >> else <<
  685. for each el in setdiff(unin,bi) do ilist:=cons( el,ilist);
  686. for each el in bi do ilist:=cons(-el,ilist)
  687. >>;
  688. ilist:=reverse ilist
  689. >>;
  690. % ilist is prepared now
  691. if pri then <<write"333 ilist=",ilist;terpri()>>$
  692. % `cases' is a list of cases, each is a dotted pair with
  693. % the car being the a-conditions and cdr being the b-conditions
  694. % The first two cases
  695. i:=car ilist;
  696. if i<0 then i:=-i;
  697. ci:=mkid('_,i);
  698. cases:=list(list(list(list(ci)), nil ),
  699. list( nil , list(list(ci))) );
  700. % oldpri:=print_;
  701. % print_:=nil;
  702. ilist:=cdr ilist;
  703. if pri then <<write"555";terpri()>>$
  704. while ilist do <<
  705. i:=car ilist;ilist:=cdr ilist;
  706. if pri then <<write"iii=",i;terpri()>>$
  707. if i>0 then ci:=mkid('_, i)
  708. else ci:=mkid('_,-i);
  709. if pri then <<
  710. write"666 car ilist=",i;
  711. terpri()
  712. >>$
  713. % if i>0 then the list of cases is extended with ai else with bi
  714. oldcases:=cases;
  715. cases:=nil;
  716. while oldcases do << % for each old case do:
  717. case:=car oldcases;
  718. if pri then <<write"old case:",case;terpri()>>$
  719. oldcases:=cdr oldcases;
  720. if i>0 then <<
  721. oldaconds:=car case;
  722. if pri then <<write"888 oldaconds=",oldaconds;terpri()>>$
  723. % at first add condition i=0 to the case
  724. cases:=cons(cons(cons(list(ci),oldaconds), cdr case) ,
  725. cases);
  726. if pri then <<write"999 new case=",car cases;terpri()>>$
  727. % then: - add to each a-condition i
  728. % - add one new b-condition with the first element `i'
  729. % and furtherelements which are the first elements of
  730. % the a-lists which have been extended
  731. newaconds:=nil;
  732. newbcond:=list(ci);
  733. while oldaconds do <<
  734. j:=caar oldaconds;
  735. newaconds:=cons(cons(j,cons(ci,cdar oldaconds)),
  736. newaconds);
  737. newbcond:=cons(j,newbcond);
  738. oldaconds:=cdr oldaconds
  739. >>;
  740. if pri then <<write"newaconds=",newaconds,
  741. " rev newbcond=",reverse newbcond;
  742. terpri()>>$
  743. cases:=cons(list(newaconds, cons(reverse newbcond,cadr case)) ,
  744. cases);
  745. if pri then <<write"000 new case=",car cases;terpri()>>$
  746. >> else <<
  747. oldbconds:=cadr case;
  748. if pri then <<write"888 oldbconds=",oldbconds;terpri()>>$
  749. % at first add condition bi=0 to the case
  750. cases:=cons(list(car case, cons(list(ci),oldbconds)),
  751. cases);
  752. if pri then <<write"999 new case=",car cases;terpri()>>$
  753. % then: - add to each b-condition i
  754. % - add one new a-condition with the first element `i'
  755. % and further elements which are the first elements of
  756. % the b-lists which have been extended
  757. newbconds:=nil;
  758. newacond:=list(ci);
  759. while oldbconds do <<
  760. j:=caar oldbconds;
  761. newbconds:=cons(cons(j,cons(ci,cdar oldbconds)),
  762. newbconds);
  763. newacond:=cons(j,newacond);
  764. oldbconds:=cdr oldbconds
  765. >>;
  766. cases:=cons(list(cons(reverse newacond,car case), newbconds),
  767. cases);
  768. if pri then <<write"000 new case=",car cases;terpri()>>$
  769. >>
  770. >>;
  771. >>;
  772. % Throwing out cases which are forbidden by alindep and blindep
  773. alindep:=for each ci in alindep collect
  774. for each i in ci collect mkid('_,i);
  775. blindep:=for each ci in blindep collect
  776. for each i in ci collect mkid('_,i);
  777. oldcases:=nil;
  778. % ilist:=for i:=1:n collect mkid('_,i);
  779. while cases do <<
  780. if checkli(alindep,caar cases%,ilist
  781. ) then
  782. if checkli(blindep,cadar cases%,ilist
  783. ) then
  784. oldcases:=cons(car cases,oldcases);
  785. cases:=cdr cases
  786. >>;
  787. % print_:=oldpri;
  788. return oldcases
  789. end$ % of starequ
  790. %-----------
  791. symbolic procedure pickfac(ex,indx)$
  792. % returns the n'th element of ex where indx has the form _n
  793. nth(ex,compress cdr explode indx)$
  794. %-----------
  795. symbolic procedure find_cond(bcons,ai)$
  796. % find the element of bcons with ai as (automatically first) element
  797. % (there must be an b-condition with ai as first element
  798. % if that has not already been dropped
  799. % because ai is not the first element of the a-condition)
  800. begin
  801. while (pairp bcons) and (caar bcons neq ai) do bcons:=cdr bcons;
  802. return if pairp bcons then car bcons
  803. else nil
  804. end$
  805. %-----------
  806. symbolic procedure starsep(exx,ex,ftem,vl,x)$
  807. % exx is the original expression to be separated
  808. % ex is a *-expression returned from SEPAR
  809. % vl are all variables which really occur in ex or
  810. % on which ex depends on
  811. % x is a variable on which the bi do not depend on
  812. %
  813. % RETURNS a list of cases, each case having the form
  814. % {{new constants/functions of integration},
  815. % eq1,eq2,eq3,...}
  816. % where eqi are a set of necc and suff conditions
  817. begin
  818. scalar cases,newcases,acons,bcons,acond,newca,alindep,blindep,aco,bco,
  819. ai,bi,ci,a1,avars,bvars,i,ili,cilist,ali,n,addex,bcopy,cntr,
  820. pri;
  821. % pri:=t;
  822. ili:=for i:=1:length ex collect mkid('_,i);
  823. n:=length vl;
  824. % at first determining lists of non-vanishing and linear independent
  825. % a-factors alindep and b-factors blindep
  826. % does so far only the obvious test which is useful essentially for
  827. % linear problems
  828. cntr:=0;
  829. for each ci in ex do <<
  830. cntr:=add1 cntr;
  831. if pri then <<
  832. write"a",cntr," = "$mathprint car ci$
  833. write"b",cntr," = "$mathprint cdr ci$
  834. >>$
  835. if null smemberl(ftem,car ci) then alindep:=cons(cntr,alindep)$
  836. if null smemberl(ftem,cdr ci) then blindep:=cons(cntr,blindep)$
  837. >>;
  838. if alindep then alindep:=list alindep$
  839. if blindep then blindep:=list blindep$
  840. % generation of all logical cases with the factors ai,bi
  841. % substituted by _i
  842. cases:=starequ(length ex,alindep,blindep);
  843. if pri then <<terpri()$write"Returned from STAREQU: ",cases>>;
  844. % newcases will be the new list of all cases
  845. newcases:=nil;
  846. while cases do <<
  847. % car cases is one case with alltogether n conditions which
  848. % The conditions for the a-factors are called below acons
  849. % and for the b-factors bcons.
  850. acons:= caar cases;
  851. bcons:=cadar cases;
  852. cases:= cdr cases;
  853. if pri then <<write"acons=",acons," bcons=",bcons;terpri()>>$
  854. % The case will now be formulated with the terms of the expression ex
  855. newca:=nil;
  856. cilist:=nil;
  857. addex:=nil;
  858. bcopy:=nil;
  859. % extract at first all b-conditions with only one term as they do not
  860. % need constants of integration and are used for any grade of ex
  861. while bcons do <<
  862. if length car bcons=1 then
  863. newca:=cons(cdr pickfac(ex,caar bcons),newca)
  864. else bcopy:=cons(car bcons,bcopy);
  865. bcons:=cdr bcons
  866. >>;
  867. bcons:=bcopy;
  868. % The a-factors may depend on all variables vl whereas the
  869. % b-factors do at least not depend on x.
  870. while acons do << % formulating all a-conditions
  871. aco:=car acons; % aco encodes one condition for a-factors
  872. acons:=cdr acons;
  873. if pri then <<write"aco=",aco;terpri()>>$
  874. a1:=car aco; % e.g. a1 = _7
  875. acond:=list car pickfac(ex,a1);
  876. if pri then <<write"acond=",acond;terpri()>>$
  877. % acond becomes a list of all a-factors encoded by aco
  878. % adding all a-conditions to the new case newca
  879. if (length aco)=1 then newca:=cons(car acond,newca)
  880. else <<
  881. ali:=for each i in aco collect car pickfac(ex,i);
  882. avars:=my_smemberl(ali,vl);
  883. if length avars neq n then <<
  884. % The progress in this case is that all new equations will
  885. % have less variables.
  886. % Now determination on which variables the constants of back-
  887. % integration would depend on. This is the intersection of all
  888. % variables avars in the a-condition and the variables bvars in
  889. % the b-condition in which the constant of integration occurs. The
  890. % a-condition is known, it will be made from acond. The relevant
  891. % b-condition is determined through the current index of aco
  892. % from which the coefficient is to be determined (which is not the
  893. % first index of aco)
  894. aco:=cdr aco; % a1 already in acond
  895. while aco do <<
  896. ai:=car aco;aco:=cdr aco;
  897. % find the list of variables bvers of the b-condition bco
  898. % which includes the b-factor corresponding to ai=car aco
  899. % disadvantage of this way: if bco has m elements then all
  900. % variables of bco are determined m-1 times.
  901. % determining bco as the b-condition which contains ai
  902. bco:=find_cond(bcopy,ai);
  903. % bcopy is used instead of bcons
  904. % the condition with ai may already have been dropped from
  905. % bcons because of ai depending on all variables, i.e. the
  906. % new functions in the b-conditions would depend on all
  907. % variables and be no help.
  908. if pri then <<write"bco=",bco;terpri()>>$
  909. % bcoli:=smemberl(ili,bco); % in case bco has already had subst.
  910. % determining bvars
  911. bvars:=nil;
  912. for each bi in bco do
  913. bvars:=union(my_smemberl(cdr pickfac(ex,bi),vl),bvars);
  914. if pri then <<write"bvars=",bvars$terpri()>>$
  915. % introducing new constants of integration
  916. ci:=newfct(fname_,intersection(avars,bvars),nfct_)$
  917. cilist:=cons(ci,cilist);
  918. nfct_:=nfct_+1;
  919. acond:=cons(list('MINUS,list('TIMES,ci,car pickfac(ex,ai))),acond);
  920. if pri then <<write"acond=",acond;terpri()>>$
  921. if bco:=find_cond(bcons,ai) then <<
  922. bcons:=subst(subst(list('TIMES,ci,a1),a1,bco),bco,bcons);
  923. if pri then <<write"bcons=",bcons;terpri()>>$
  924. >>
  925. >>;
  926. acond:=cons('PLUS,acond)
  927. >>
  928. else << % The condition aco is a *-condition
  929. % progress in this case is that new a-conditions
  930. % have less functions
  931. addex:=t;
  932. ali:=reverse ali;
  933. aco:=reverse aco;
  934. while length ali > 1 do <<
  935. if pri then <<write"ali1=",ali;terpri()>>$
  936. % Generate the a-condition
  937. if pri then <<write"###";terpri()>>$
  938. ali:=
  939. if not zerop car ali then
  940. for each i in cdr ali collect
  941. reval list('DF,list('QUOTIENT,i,car ali),x)
  942. else cdr ali;
  943. if pri then <<write"ali2=",ali;terpri()>>$
  944. % Drop that element from bcons which includes
  945. % car ali (as first element)
  946. if bco:=find_cond(bcons,car aco) then
  947. bcons:=setdiff(bcons,list bco);
  948. aco:=cdr aco
  949. >>;
  950. acond:=car ali;
  951. if (pairp acond) and (car acond = 'QUOTIENT) then
  952. acond:=cadr acond;
  953. >>;
  954. newca:=cons(acond,newca)
  955. >>;
  956. if pri then <<write"newca1=",newca;terpri()>>;
  957. >>; % all a-conditions have been dealt with
  958. if pri then <<write"newca2=",newca;terpri()>>;
  959. % completing all b-conditions
  960. for each bi in ili do bcons:=subst(cdr pickfac(ex,bi),bi,bcons);
  961. % adding all b-conditions to the new case newca
  962. while bcons do <<
  963. if length car bcons = 1 then newca:=cons(caar bcons,newca)
  964. else newca:=cons(cons('PLUS,car bcons),
  965. newca);
  966. bcons:=cdr bcons
  967. >>;
  968. % if ex is an *-expression with grade>1 then possibly b-conditions
  969. % had to be dropped, so ex must be added
  970. if addex then newca:=cons(exx,newca);
  971. if pri then <<write"newca3=",newca;terpri()>>;
  972. % adding the list of constants of integeration
  973. newca:=cons(cilist,newca);
  974. if pri then <<write"cilist=",cilist;terpri()>>;
  975. newcases:=cons(newca,newcases)
  976. >>;
  977. return newcases
  978. end$ % of starsep
  979. %-----------
  980. symbolic procedure separizable(p,ftem,vl)$
  981. begin scalar x,ft,f,ex,v,a,b,vlcp,allvarcaara,print_bak$
  982. vlcp:=vl;
  983. repeat <<
  984. x:=car vl; vl:=cdr vl;
  985. % Determining all x-dependent functions ft
  986. ft:=nil;
  987. for each f in ftem do
  988. if member(x,fctargs f) and
  989. not my_freeof(p,f) then ft:=cons(f,ft)$
  990. f:=car reverse fctsort ft$ % sorting w.r.t. number of args
  991. v:=car setdiff(vlcp,fctargs f)$ % getting rid of f by v-differen.
  992. % preparation of the separ-call, ft are now v-indep. functions
  993. ft:=nil$
  994. for each f in ftem do if my_freeof(f,v) then ft:=cons(f,ft)$
  995. % ex:=separ(p,ft,list v,nil)$ % det. all lin. ind. factors
  996. print_bak:=print_; print_:=nil;
  997. ex:=separ2(p,ft,list v)$ % det. all lin. ind. factors
  998. print_:=print_bak;
  999. a:=ex;
  1000. while a and <<
  1001. b:=vlcp;
  1002. while b and not my_freeof(caar a,car b) do b:=cdr b;
  1003. b
  1004. >> do a:=cdr a;
  1005. if a then allvarcaara:=cons(caar a,allvarcaara);
  1006. >> until (null a) or (null vl);
  1007. % if a then null vl then whatever x was, there is allways one
  1008. % element (car a) of ex such that car of this element (caar a)
  1009. % does depend on all variables --> no separability possible,
  1010. % new functions would depend on all variables
  1011. % if a then test whether separation would be possible by getting
  1012. % rid of functions through differentiation
  1013. % (this would not be the case if e.g. sin(all variables) would occur)
  1014. % --> use of smemberl
  1015. vl:=vlcp;
  1016. while allvarcaara and not not_included(vlcp,smemberl(vlcp,car allvarcaara)) do
  1017. <<allvarcaara:=cdr allvarcaara; vl:=cdr vl>>$
  1018. return if a and null allvarcaara then nil % no chance
  1019. else if a then {nil,car allvarcaara,car vl} % deleting functions first
  1020. else << % separation now possible
  1021. if tr_gensep then
  1022. <<terpri()$write "To separate directly wrt. ",x$
  1023. write " the expression : "$deprint list p$
  1024. write "will be differentiated wrt. ",v," to get rid of ",ft," ">>$
  1025. {ex,v}
  1026. >>
  1027. end$
  1028. %-----------
  1029. symbolic procedure newgensep(p,starpro,ftem,vl)$
  1030. % ftem, vl should be correct:
  1031. % ftem:=smemberl(ftem_,p)$
  1032. % vl:=varslist(p,ftem,vl)$
  1033. % starpro:=stardep(ftem,vl)$
  1034. % returns what starsep returns
  1035. begin
  1036. scalar pl,v,ex,a,b$
  1037. % ,gense,el1,el2,conds,newcali,l,clist$
  1038. % if pairp p and (car p = 'QUOTIENT) then <<casecheck(caddr p,vl)$
  1039. % p:=cadr p>>$
  1040. % ftem:=smemberl(ftem,p)$
  1041. % vl:=varslist(p,ftem,vl)$
  1042. % if not (starpro:=stardep(ftem,vl)) then % then no *-equation
  1043. % pl:=list list(nil,p) % one case, no new functions
  1044. % else % e.g. starpro=((x y z).2)
  1045. % if zerop cdr starpro then pl:=nil% ##############################
  1046. % %list cons(nil,separate(p,ftem,vl)) % direct sep
  1047. % else
  1048. % if delength(p) leq gensep_ then % generalized separation
  1049. % <<
  1050. if print_ then <<terpri()$write "generalized separation ">>$
  1051. if tr_gensep then
  1052. <<terpri()$write "de to be separated : "$
  1053. deprint list p$
  1054. terpri()$write "variable list for separation : ",car starpro$
  1055. terpri()$write "for each of these variables ",cdr starpro,
  1056. " function(s) depend(s) on it.">>$
  1057. for each v in car starpro do vl:=delete(v,vl);
  1058. vl:=append(car starpro,vl);
  1059. a:=separizable(p,ftem,vl)$
  1060. if null a then return nil else
  1061. if null car a then return <<
  1062. % functions to be deleted before separation are those in cadr a
  1063. % ft:=smemberl(ftem,cadr a);
  1064. if print_ then <<terpri()$
  1065. write"In order to be separable with this procedure at first"$terpri()$
  1066. write"one or more functions have to be eliminated through"$terpri()$
  1067. write"differentiation and algebraic elimination, for example,"$terpri()$
  1068. write"the functions: ",smemberl(ftem,cadr a)$terpri()$
  1069. >>;
  1070. nil
  1071. >> else <<ex:=car a;v:=cadr a>>$
  1072. for each a in
  1073. reverse idx_sort for each b in ex collect cons(delength car b,b)
  1074. collect cdr a$
  1075. if tr_gensep then
  1076. <<terpri()$write "Return from SEPAR: "$terpri()$prettyprint ex>>$
  1077. % with v and v-dep. functions as first factors in the terms in ex
  1078. pl:=starsep(p,ex,ftem,vl,v);
  1079. if tr_gensep then
  1080. <<terpri()$write "Return from STARSEP: "$terpri()$prettyprint pl>>$
  1081. % print_:=oldpri$
  1082. %%############################################################
  1083. % % l is a list of cases each (list of new fncts, cond1, cond2, ...)
  1084. % % for each condition (neq p) in all cases calling gensep again
  1085. % % if needed
  1086. % pl:=nil; % the final list of cases of only non-*-equ.
  1087. % while l do % checking all cases
  1088. % <<clist:=caar l; % list of new functions
  1089. % conds:=cdar l; % list of conditions
  1090. % l:=cdr l;
  1091. % newcali:=list list clist;
  1092. % % newcali will be the list of new cases which starts as
  1093. % % only one case and from this only the list of new functions
  1094. % % but no conditions
  1095. % while conds do % checking all conditions of one case
  1096. % <<
  1097. %% if car conds = ex then
  1098. %% % ex aready investigated, not again
  1099. %% % append ex to the conditions of all new cases
  1100. %% newcali:=for each el1 in newcali collect
  1101. %% cons(car el1,cons(ex,cdr el1))
  1102. %% else <<
  1103. % gense:=newgensep(car conds,append(ftem,clist),vl);
  1104. % newcali:=for each el1 in gense join
  1105. % for each el2 in newcali collect
  1106. % cons(append(car el1,car el2),
  1107. % append(cdr el1,cdr el2));
  1108. %% >>;
  1109. % conds:=cdr conds
  1110. % >>;
  1111. % pl:=append(newcali,pl)
  1112. % >>
  1113. % >>;
  1114. return pl
  1115. end$ % of newgensep
  1116. %-----------
  1117. symbolic procedure gen_separation2(arglist)$
  1118. % Indirect separation of a pde, 2nd version for non-linear PDEs
  1119. begin scalar p,h,fl,l,l1,pdes,forg,n,result,d,contrad,newpdes$%,newfdep,bak,sol
  1120. pdes:=car arglist$
  1121. forg:=cadr arglist$
  1122. if expert_mode then <<
  1123. l1:=selectpdes(pdes,1);
  1124. if get(car l1,'starde) then flag(l1,'to_gensep)
  1125. >> else l1:=pdes$
  1126. if (p:=get_gen_separ_pde(l1,nil,nil)) then
  1127. if l:=newgensep(get(p,'val),
  1128. get(p,'starde),
  1129. get(p,'fcts),
  1130. get(p,'vars)) then
  1131. if cdr l then <<
  1132. if print_ then <<
  1133. terpri()$
  1134. write"The indirect separation leads to ",length l," cases."$
  1135. %terpri()$
  1136. >>$
  1137. contrad:=t$
  1138. n:=0;
  1139. remflag1(p,'to_gensep)$
  1140. % bak:=backup_pdes(pdes,forg)$ % must come before drop_pde(...
  1141. backup_to_file(pdes,forg,nil)$
  1142. % newfdep:=nil$
  1143. while l do <<
  1144. d:=car l; l:=cdr l;
  1145. if not memberl(cdr d,ineq_) then << % non of the equations is an inequality
  1146. if n neq 0 then <<
  1147. h:=restore_and_merge(l1,pdes,forg)$
  1148. pdes:= car h;
  1149. forg:=cadr h; % was not assigned above as it has not changed probably
  1150. % h:=restore_pdes(bak);
  1151. % pdes:=car h; forg:=cadr h
  1152. >>;
  1153. n:=n+1$
  1154. level_:=cons(n,level_)$
  1155. if print_ then <<
  1156. print_level(t)$
  1157. terpri()$
  1158. write "CRACK is now called with the assumption : "$
  1159. deprint(cdr d)
  1160. >>$
  1161. % formulation of new equations
  1162. for each h in car d do ftem_:=fctinsert(h,ftem_);
  1163. fl:=append(get(p,'fcts),car d);
  1164. newpdes:=pdes$
  1165. for each h in cdr d do
  1166. newpdes:=eqinsert(mkeq(h,fl,vl_,allflags_,t,list(0),nil,newpdes),newpdes);
  1167. % further necessary step to call crackmain():
  1168. recycle_fcts:=nil$ % such that functions generated in the sub-call
  1169. % will not clash with existing functions
  1170. l1:=crackmain(newpdes,forg)$
  1171. % for each sol in l1 do
  1172. % if sol then <<
  1173. % for each f in caddr sol do
  1174. % if h:=assoc(f,depl!*) then newfdep:=cons(h,newfdep);
  1175. % >>;
  1176. if not contradiction_ then contrad:=nil$
  1177. if l1 and not contradiction_ then
  1178. result:=union(l1,result);
  1179. contradiction_:=nil$
  1180. >>
  1181. >>;
  1182. delete_backup()$
  1183. % % newfdep are additional dependencies of the new functions in l1
  1184. % depl!*:=append(depl!*,newfdep);
  1185. contradiction_:=contrad$
  1186. if contradiction_ then result:=nil$
  1187. if print_ then <<
  1188. terpri()$
  1189. write"This completes the investigation of all cases of an ",
  1190. "indirect separation."$
  1191. terpri()$
  1192. >>$
  1193. result:=list result % to tell crackmain that computation is completed
  1194. >> else << % only one case
  1195. l:=car l;
  1196. for each h in car l do ftem_:=fctinsert(h,ftem_);
  1197. fl:=append(get(p,'fcts),car l);
  1198. pdes:=drop_pde(p,pdes,nil)$
  1199. for each h in cdr l do
  1200. pdes:=eqinsert(mkeq(h,fl,vl_,allflags_,t,list(0),nil,pdes),pdes);
  1201. result:=list(pdes,forg)
  1202. >>$
  1203. return result$
  1204. end$
  1205. endmodule$
  1206. end$