crdec.red 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. %********************************************************************
  2. module decoupling$
  3. %********************************************************************
  4. % Routines for decoupling de's
  5. % Author: Andreas Brand untill 1995,
  6. % updates and extensions by Thomas Wolf
  7. %
  8. symbolic procedure which_deriv(p,q)$
  9. % yields a list of variables and orders
  10. % such that one gets at least q by differentiating p w.r.t. the vars
  11. % p,q: lists of variables and orders
  12. begin scalar l,n,a$
  13. while q do
  14. if (a:=member(car q,p)) then
  15. <<q:=cdr q$
  16. if q and numberp(car q) then
  17. <<n:= car q$
  18. q:=cdr q>>
  19. else n:=1$
  20. n:=n-(if pairp cdr a and numberp cadr a then cadr a else 1)$
  21. if n>0 then
  22. <<l:=cons(car a,l)$
  23. if n>1 then l:=cons(n,l)>> >>
  24. else
  25. <<l:=cons(car q,l)$
  26. q:=cdr q$
  27. if q and numberp(car q) then
  28. <<l:=cons(car q,l)$
  29. q:=cdr q>> >>$
  30. return append(reverse l,q)$
  31. end$
  32. symbolic procedure dec_ld_info(p,q,simpp,simpq,f,vl,rl)$
  33. % gets leading derivatives of f in p and q wrt. vars order vl
  34. % and the lists of variables and orders for differentiation
  35. begin scalar s,l,l1,l1d,l2,l2d,vl1,vl2,d1,d2,ld1,ld2,wd1,wd2,
  36. caar_ld,found$
  37. %
  38. % if (p has more variables than q) or
  39. % (f is not leading function of p)
  40. % => simpp = t => p must be simplified with (deriv.s of) q
  41. % if (q has more variables than p) or
  42. % (f is not leading function of q)
  43. % => simpq = t => q must be simplified with (deriv.s of) p
  44. %
  45. % vl1 holds the list of _ordered_ variables of p
  46. % vl2 holds the list of _ordered_ variables of q
  47. %
  48. % list all powers of derivatives of f in p as l1 and in q as l2
  49. %
  50. if simpp and simpq then return nil$
  51. vl1:=intersection(vl,get(p,'vars))$
  52. vl2:=intersection(vl,get(q,'vars))$
  53. % collect all powers of all derivatives of f
  54. %
  55. for each a in get(p,'derivs) do if caar a=f then l1:=cons(a,l1)$
  56. l1:=sort_derivs(reverse l1,list f,vl1)$
  57. %
  58. % l1 is a list of _all_ derivatives of f in p _sorted_ stored as a
  59. % dotted pair, e.g. ((f x 2 y) . 5) would be f_{xxy}^5, or more
  60. % generally ((f_1 . power) (f_2 . power) ... )
  61. %
  62. %terpri()$write "l10=",l1$
  63. %
  64. % keep only highest power of each derivative in l1
  65. l:=nil$
  66. for each a in l1 do if not member(cdar a,l) then <<
  67. l:=cons(cdar a,l)$
  68. l1d:=cons(list(cdar a,absdeg(cdar a),cdr a),l1d)
  69. >>$
  70. %
  71. % cdar a is the list of derivatives so we are making sure that our
  72. % list l1 has no repetitions
  73. %
  74. l1 :=reverse l$ % e.g. l1 = ( (x 2 y) (x y 2) ...)
  75. l1d:=reverse l1d$ % e.g. l1d = (((x 2 y),3,1) ((x y 2),3,2) ...)
  76. %
  77. % The above now applies but with q and l2 instead of p and l1
  78. %
  79. % collect all powers of all derivatives of f
  80. %
  81. for each a in get(q,'derivs) do if caar a=f then l2:=cons(a,l2)$
  82. l2:=sort_derivs(reverse l2,list f,vl2)$
  83. %terpri()$write "l20=",l2$
  84. % keep only highest power of each derivative in l2
  85. l:=nil$
  86. for each a in l2 do if not member(cdar a,l) then <<
  87. l:=cons(cdar a,l)$
  88. l2d:=cons(list(cdar a,absdeg(cdar a),cdr a),l2d)
  89. >>$
  90. l2 :=reverse l$ % e.g. l2 = ( (x 2 y) (x y 2) ...)
  91. l2d:=reverse l2d$ % e.g. l2d = (((x 2 y),3,1) ((x y 2),3,2) ...)
  92. % At this point we have two lists, l1d and l2d resp. containing the
  93. % sorted list of all derivatives of the function f in p and q
  94. % together with their highest power
  95. % At first we note the leading derivative in l1d with its power
  96. % and check whether there is a derivative in l2d which has in no variable
  97. % a lower derivative or and either has a higher derivative in at least
  98. % one variable, or is not of lower degree.
  99. if not simpp then <<
  100. %p may be differentiated and q be substituted or new equ. added
  101. caar_ld:=caar l1d$
  102. d1:=cadar l1d$
  103. d2:=caddar l1d$
  104. l:=l2d$
  105. while l and ((d1<cadar l) or ((d1=cadar l) and (d2<=caddar l))) do
  106. <<s:=which_deriv(caar_ld,caar l)$
  107. %
  108. % which_deriv(a,b) takes two lists of derivatives and returns how
  109. % often you need to diff. a in order to get at least the
  110. % derivatives in b.
  111. % e.g. which_deriv((x 2 y), (x y 2)) returns y
  112. %
  113. if (absdeg s + d1)=cadar l then <<ld2:=caar l$ found:=t$ l:=nil>>
  114. % At this point we compare the degree of the highest
  115. % derivative of l1 + number of diff. in order to get the
  116. % leading deriv. of l2 (aliased to l)
  117. else l:=cdr l
  118. >>
  119. >>$
  120. if simpq and null found then return nil;
  121. % Now, either l is nil and ld2 = leading deriv. of l2 (i.e. highest
  122. % deriv. of f in q) [this is the case in which leading deriv. in l2
  123. % can be obtained by diff. of the leading deriv. in l1] OR
  124. % ld2 is nil and l contains the rest of the deriv. of l2 except the
  125. % leading one [in this case we _cannot_ obtain the leading deriv. in
  126. % l2 by diff. the leading deriv. in l1].
  127. if (not ld2) and (not simpq) then <<
  128. %
  129. % We cannot get to the leading deriv. in l2 by diff. of leading
  130. % deriv. in l1.
  131. % We now try the opposite way, we try to diff. something in l2 to
  132. % get into l1.
  133. %
  134. caar_ld:=caar l2d$
  135. d1:=cadar l2d$
  136. d2:=caddar l2d$
  137. l:=l1d$
  138. found:=nil$
  139. while l and ((d1<cadar l) or ((d1=cadar l) and (d2<=caddar l))) do
  140. <<s:=which_deriv(caar_ld,caar l)$
  141. if (absdeg s + d1)=cadar l then <<ld1:=caar l$ found:=t$ l:=nil>>
  142. else l:=cdr l
  143. >>
  144. >>$
  145. if simpp and null found then return nil;
  146. % We now have either ld2 non-nil, i.e. we can get to leading derv. in
  147. % l2 by differentiation of terms in l1 OR we have ld1 non-nil in
  148. % which case we have the opposite situation. If neither are non-nil
  149. % then we have to cross-differentiate to get the ld to match.
  150. %
  151. % What we return is
  152. %
  153. % ( (s ld(l1)) (nil ld(l2)) ) [ld2 non-nil] or
  154. % ( (nil ld(l1)) (s ld(l2)) ) [ld1 non-nil] or
  155. % ( (v ld(l1)) (w ld(l2)) ) [both ld1 _and_ ld2 nil]
  156. %
  157. % where v and w are the required diff. to get to ld2 and ld1 resp.
  158. % and s is the required diff. for the non-nil cases.
  159. %
  160. % It is to be interpreted as:
  161. %
  162. % Either "diff. ld(l1) by s to get ld(l2)" or
  163. % "diff. ld(l2) by s to get ld(l1)" or
  164. % "diff. ld(l1) by wd1 and ld(l2) by wd2 to get the
  165. % ld's to match".
  166. %
  167. return
  168. if ld2 then cons(cons(s,caar l1d),cons(nil,ld2)) else
  169. if ld1 then cons(cons(nil,ld1),cons(s,caar l2d)) else <<
  170. wd1:=which_deriv(caar l1d,caar l2d)$
  171. wd2:=which_deriv(caar l2d,caar l1d)$
  172. if (simpq and wd2) or
  173. (simpp and wd1) or
  174. (rl and wd1 and wd2) then nil
  175. else cons(cons(wd1,caar l1d),
  176. cons(wd2,caar l2d))
  177. >>
  178. end$
  179. symbolic procedure diffeq(f,sd,r)$
  180. % input of how often equation r is to be differentiated
  181. % sd is the resulting derivative that is to be substituted
  182. % with another equation, eg sd=(x,2,y)
  183. begin scalar rdif,rd,contradic,a,ad,b,bd,resu,must_be_subst$
  184. terpri()$
  185. write"How often is equation ",r," to be differentiated?"$
  186. terpri()$
  187. write"(just `;' for no differentiation or, for example, `x,y,2;' ): "$
  188. rdif:=termlistread()$
  189. rd:=get(r,'derivs)$
  190. while rd and null contradic do <<
  191. a:=caar rd; % only the differentiations, not the degree
  192. rd:=cdr rd$
  193. if f=car a then <<
  194. ad:=cdr a$
  195. if cdr a then a:=cons('DF,a)
  196. else a:=car a; % a is now the function/full derivative
  197. if null rdif then b:=a else
  198. b:=reval cons('DF,cons(a,rdif));
  199. if pairp b then bd:=cddr b
  200. else bd:=nil$
  201. % There must not result a derivative from differentiating
  202. % equation r which is a derivative of sd
  203. if zerop b then <<
  204. write "The function ",f," differentiated that way gives zero."$
  205. contradic:=t$
  206. >> else
  207. if (null which_deriv(bd,sd)) and
  208. which_deriv(sd,bd) then
  209. if null rdif then must_be_subst:=b
  210. else <<
  211. contradic:=t$ % sd,r,rdif are not compatible
  212. terpri()$
  213. write"This differentiation of equation ",r,
  214. " will generate a derivative ",b$
  215. terpri()$
  216. write" which is a derivative of the derivative to be eliminated."$
  217. terpri()$
  218. >> else
  219. if bd = sd then resu:={r,rdif,ad}
  220. >>
  221. >>$
  222. return if contradic or null resu then nil
  223. else resu . must_be_subst
  224. end$
  225. symbolic procedure read_sub_diff(p,q)$
  226. begin scalar ps,s,l0,l,m0,m1,f,sd,info_p,info_q,contradic,let_conflict$
  227. ps:=promptstring!*$
  228. promptstring!*:=""$
  229. terpri()$
  230. write"What is the derivative to be eliminated? "$
  231. write"(e.g. df(f,x,y,2); or f; ) "$terpri()$
  232. l0:=termxread()$
  233. l:=reval l0$
  234. % tests whether the input l is ok
  235. if null l then return nil else
  236. if not pairp l then if l0 neq l then let_conflict:=t else
  237. else % pairp l
  238. if car l neq 'DF then if car l0 neq 'DF then <<
  239. write"Not a derivative!"$ terpri()$
  240. return nil
  241. >> else let_conflict:=t
  242. else
  243. if cadr l neq cadr l0 then let_conflict:=t
  244. else <<
  245. m0:=cddr l0; m1:=cddr l;
  246. while m1 and null let_conflict do
  247. if fixp car m1 then m1:=cdr m1 else <<
  248. if no_of_v(car m1,m1) neq no_of_v(car m1,m0) then let_conflict:=t;
  249. m1:=cdr m1
  250. >>
  251. >>$
  252. if let_conflict then <<
  253. write "Due to a LET-rule in operation this elimination ",
  254. "is not possible."$terpri()$
  255. write "To delete a LET-rule use 'cr'."$terpri()$
  256. return nil
  257. >>$
  258. if pairp l then <<f:=cadr l;sd:=cddr l>>
  259. else <<f:=l;sd:=nil>>$
  260. info_p:=diffeq(f,sd,p)$
  261. if info_p then info_q:=diffeq(f,sd,q)$
  262. promptstring!*:=ps$
  263. return
  264. if info_p and info_q then <<
  265. if null cadar info_p and cadar info_q then s:=p else
  266. if null cadar info_q and cadar info_p then s:=q else
  267. if cadar info_p and cadar info_q then s:=nil else <<
  268. terpri()$
  269. write"Which equation is to be substituted? Input ",p," or ",q,": "$
  270. repeat
  271. s:=reval termread()
  272. until (s=p) or (s=q)
  273. >>$
  274. if s=p and cdr info_q then <<
  275. contradic:=t$
  276. terpri()$
  277. write"The derivative ",cdr info_q," would enter ",p$
  278. terpri()$
  279. write" which is a derivative of the derivative to be substituted."$
  280. >>$
  281. if s=q and cdr info_p then <<
  282. contradic:=t;
  283. terpri()$
  284. write"The derivative ",cdr info_p," would enter ",q$
  285. terpri()$
  286. write" which is a derivative of the derivative to be substituted."$
  287. >>$
  288. if contradic then nil
  289. else {car info_p,car info_q,l,s,nil} . 1
  290. % returns the same kind of result as dec_info
  291. >> else nil
  292. end$
  293. symbolic procedure dec_info(p,q,f,vl,rl,ordering)$
  294. % yields information for a decouple reduction step
  295. % i.e. ((info_1
  296. % info_2
  297. % deriv_to_eliminate
  298. % equ_to_be_subst
  299. % whether_one_equation_must_be_substituted % important for elim. techn.
  300. % ).num_value)
  301. % where num_value is a measure of cost, e.g.
  302. % result has form (((e4 (x 2 y) (y z))
  303. % (e5 (z) (x 2 y 2)) (df f x 2 y 2 z) nil nil) . num_value)
  304. % Criteria: a) the function f must depend on all vars
  305. % b) the function and all their derivatives must occur
  306. % polynomially
  307. begin scalar a,b,l,l1,info,m,n,fp,fq,fpmq,fqmp,s,lenp,lenq,dp,dq,
  308. simpp,simpq,let_conflict$
  309. %
  310. % 'length is the property containing the expression length
  311. %
  312. if expert_mode then return read_sub_diff(p,q)$
  313. lenp:=get(p,'length)$
  314. lenq:=get(q,'length)$
  315. if rl and ((lenp*lenq)>max_red_len) then return nil;
  316. a:=get(p,'vars); b:=get(q,'vars);
  317. simpp:=(null get(p,'allvarfcts)) or (f neq caaar get(p,'derivs))$
  318. simpq:=(null get(q,'allvarfcts)) or (f neq caaar get(q,'derivs))$
  319. % star-equn. or f is not leading function
  320. l:=dec_ld_info(p,q,simpp,simpq,f,vl,rl)$
  321. if not l then <<
  322. add_both_dec_with(ordering,p,q,rl)$
  323. return nil
  324. >>$
  325. %
  326. % l:= dec_ld_info(p,q,f,vl,rl) returns a list of lists, from which
  327. % a := caar l sets a to be the differentiations required to get
  328. % the ld(p) w.r.t. f to match that of ld(q) w.r.t. f,
  329. % b := caadr l sets b to be the differentiations required to get
  330. % the ld(q) w.r.t. f to match that of ld(q) w.r.t. f.
  331. %
  332. % l1 := cadadr l sets l1 to be the derivative in q which we
  333. % eliminate, similarly l is the derivative in p which we elim.
  334. %
  335. a:=caar l$ % a are the differentiations of p
  336. b:=cadr l$ % b are the differentiations of q
  337. if struc_eqn and
  338. ((a and b and (not freeof(algebraic struc_done,f))) or
  339. % no integrab. cond.s for functions in struc_done
  340. ((get(p,'no_derivs)>0) and (get(q,'no_derivs)=0)) or
  341. ((get(p,'no_derivs)=0) and (get(q,'no_derivs)>0))
  342. % not using algebr. conditions to simplify diff. cond.
  343. ) then return nil;
  344. l1:=cddr l$
  345. l:=cdar l$
  346. % Test whether there is a let-rule in operation which changes the
  347. % target derivative
  348. if (null a) and (null l) then
  349. if f neq reval f then let_conflict:=t
  350. else else <<
  351. m:=reval cons('DF,cons(f,append(l,a)));
  352. if (not pairp m) or
  353. (car m neq 'DF) or
  354. (cadr m neq f) then let_conflict:=t
  355. else <<
  356. m:=cddr m$
  357. while m and null let_conflict do
  358. if fixp car m then m:=cdr m else <<
  359. if (no_of_v(car m,a)+no_of_v(car m,l)) neq
  360. no_of_v(car m,m) then let_conflict:=t;
  361. m:=cdr m
  362. >>
  363. >>
  364. >>$
  365. if let_conflict then <<
  366. if print_ then <<
  367. write "Due to a let-rule in operation equations ",
  368. p,",",q," will not be paired."$terpri()$
  369. >>$
  370. add_both_dec_with(ordering,p,q,rl)$
  371. return nil
  372. >>$
  373. % s is the equation to be substituted
  374. if a and not b then s:=q % p will be diff.
  375. else if b and not a then s:=p % q will be diff.
  376. else if not (a or b) then % no diff., only reduction
  377. if struc_eqn and l and l1 then <<
  378. % 2 structural equations, both with one or more derivatives
  379. % --> equation with more derivatives is substituted
  380. % The case below would work, only this may need fewer substitutions
  381. m:=get(p,'no_derivs)$
  382. n:=get(q,'no_derivs)$
  383. if m>n then s:=p else
  384. if m<n then s:=q else
  385. % if cons(f,l ) neq caar get(q,'derivs) then s:=q else
  386. % if cons(f,l1) neq caar get(p,'derivs) then s:=p else
  387. if get(p,'length)>get(q,'length) then s:=p
  388. else s:=q
  389. >> else <<
  390. dp:=get(p,'derivs)$
  391. dq:=get(q,'derivs)$
  392. repeat <<
  393. s:=total_less_dfrel(car dp,car dq,ftem_,vl)$
  394. dp:=cdr dp$
  395. dq:=cdr dq
  396. >> until (s neq 0) or (null dp) or (null dq)$
  397. if (s=t) or ((null dp) and dq) then s:=q
  398. else s:=p
  399. >>$
  400. fp:=get(p,'allvarfcts)$ % functions of all vars in p
  401. fq:=get(q,'allvarfcts)$ % functions of all vars in q
  402. % If a pde will be replaced by a pde with more fcts of all vars
  403. % then this pairing will have a lowered priority
  404. fqmp:=length setdiff(fq,fp);
  405. fpmq:=length setdiff(fp,fq);
  406. if nil then
  407. if tr_decouple then << terpri()$
  408. write"p=",p," q=",q," s=",s," lfp=",length fp,
  409. " lfq=",length fq," lfu=",length union(fp,fq),
  410. " fqmp=",fqmp," fpmq=",fpmq
  411. >>$
  412. m:=(1.5^absdeg(a)*lenp+1.5^absdeg(b)*lenq)*
  413. (length union(fp,fq))**20$
  414. if nil then
  415. if tr_decouple then write" m2=",m;
  416. if s then <<
  417. % the equation s will be replaced by the new one
  418. % --> if (null struc_eqn) and fcteval(s,nil) then m:=m*10**7;
  419. % The above line has been commented out because fcteval takes
  420. % much time the first time it is called and substitutions
  421. % are to be done before decoupling anyway
  422. if (s=q) and (lenp>lenq) then m:=(m*lenp)/lenq else
  423. if (s=p) and (lenq>lenp) then m:=(m*lenq)/lenp;
  424. if (s=p) and (fqmp>0) then m:=m*10**(2*fqmp) else
  425. if (s=q) and (fpmq>0) then m:=m*10**(2*fpmq);
  426. if struc_eqn then
  427. if ((a and is_algebraic(p)) or
  428. (b and is_algebraic(q)) ) then m:=m*10**100 else
  429. if is_algebraic(p) and is_algebraic(q) then m:=m/10**5;
  430. >> else
  431. % Enlarge m because extra equation is generated (temp. idea)
  432. m:=m*10$
  433. % Non-linearity in largest derivative not taken care of.
  434. if nil then
  435. if tr_decouple then write" m3=",m;
  436. info:=cons(list(list(p,a,l),
  437. list(q,b,l1),
  438. if (null a) and
  439. (null l) then f
  440. else reval cons('DF,cons(f,append(l,a))),
  441. s,
  442. simpp or simpq
  443. ),
  444. m)$
  445. return info$
  446. end$
  447. %symbolic procedure dec_put_info(l,rl)$
  448. %% l has form ((e4 (x 2 y) (y z))
  449. %% (e5 (z) (x 2 y 2)) (df f x 2 y 2 z) nil)
  450. %% puts informations for decouple reduction step
  451. %% result: ((df f x 2 y 2 z) e4 e5 nil)
  452. %if l then
  453. %begin scalar f$
  454. % put(caar l,'dec_info,cadar l)$ % saves (x 2 y) for e4
  455. % put(caadr l,'dec_info,cadadr l)$ % saves (z) for e5
  456. % if (cadar l) and (cadadr l) then << % if both eq. are diff.
  457. % f:=caddr l;
  458. % if pairp f then f:=cadr f;
  459. % add_both_dec_with(f,caar l,caadr l,rl)$
  460. % >>$
  461. % return list(caddr l,caar l,caadr l,cadddr l)$
  462. %end$
  463. % symbolic procedure dec_put_info(f,l)$
  464. % % put informations for decouple reduction step
  465. % % result: (deriv_to_eliminate pde_1 pde_2)
  466. % if l then
  467. % begin scalar a,b$
  468. % put(caar l,'dec_info,cadar l)$
  469. % a:=get(caar l,'dec_with)$
  470. % b:=assoc(f,a)$
  471. % a:=delete(b,a)$
  472. % if b then b:=cons(f,cons(caadr l,cdr b))
  473. % else b:=list(f,caadr l)$
  474. % put(caar l,'dec_with,cons(b,a))$
  475. % put(caadr l,'dec_info,cadadr l)$
  476. % a:=get(caadr l,'dec_with)$
  477. % b:=assoc(f,a)$
  478. % a:=delete(b,a)$
  479. % if b then b:=cons(f,cons(caar l,cdr b))
  480. % else b:=list(f,caar l)$
  481. % put(caadr l,'dec_with,cons(b,a))$
  482. % return list(caddr l,caar l,caadr l)$
  483. % end$
  484. %% symbolic procedure dec_info_leq(p,q)$
  485. %% % relation "<=" for decouple informations
  486. %% if p and q then
  487. %% if not (cadar car p and cadadr car p) then
  488. %% if not (cadar car q and cadadr car q) then (cdr p<=cdr q)
  489. %% else p
  490. %% else if cadar car q and cadadr car q then (cdr p<=cdr q)
  491. %% else nil
  492. %% else p$
  493. symbolic procedure dec_info_leq(p,q)$
  494. % relation "<=" for decouple informations
  495. if p and q then (cdr p<=cdr q)
  496. else if p then p
  497. else q$
  498. symbolic procedure dec_and_fct_select(pdes,vl,rl,hp,ordering)$
  499. % select 2 pdes for decoupling
  500. % if rl then one pde must be simplified with the help of
  501. % another one and reduce its length
  502. % if hp then only high priority decouplings (eqns with max 3-4 functions)
  503. begin scalar min,f,l,l1,l2,done_pdes,car_pdes,len,
  504. d_car_pdes,val_car_pdes,val_p,d_p,w1,w2,rtn,f_in_flin,allvarfl$
  505. while pdes and null rtn do <<
  506. car_pdes:=car pdes;
  507. allvarfl:=get(car_pdes,'allvarfcts);
  508. if expert_mode or
  509. (flagp(car_pdes,'to_decoup) and allvarfl and
  510. ((null hp) or (length(allvarfl)<4)) ) then
  511. <<f:=caaar get(car_pdes,'derivs)$
  512. if not flin_ or (f_in_flin:=not freeof(flin_,f)) or
  513. ( homogen_ and (zerop car get(car_pdes,'hom_deg))) or
  514. (null homogen_ and freeoflist(get(car_pdes,'fcts),flin_)) then <<
  515. % initializations for the special case of car_pdes: 0=df(f,...)
  516. len:=get(car_pdes,'printlength)$
  517. if (null record_hist) and (len=1) then <<
  518. val_car_pdes:=get(car_pdes,'val);
  519. if (pairp val_car_pdes) and
  520. (car val_car_pdes = 'DF) and
  521. (cadr val_car_pdes = f) then
  522. d_car_pdes:=cddr val_car_pdes else
  523. if val_car_pdes=f then d_car_pdes:=nil
  524. else len:=1000
  525. >>$
  526. l:=assoc(ordering,get(car_pdes,'dec_with))$
  527. if rl then l:=append(l,assoc(ordering,get(car_pdes,'dec_with_rl)))$
  528. % unchecked pairings
  529. for each p in cdr pdes do
  530. % It should be possible that f is leading function in car_pdes but not
  531. % in others
  532. % if not flin_ or f_in_flin or
  533. % ( homogen_ and (zerop car get(p,'hom_deg))) or
  534. % (null homogen_ and freeoflist(get(p,'fcts),flin_)) then
  535. if expert_mode or
  536. (flagp(p,'to_decoup) and
  537. member(f,get(p,'rational)) and
  538. ((null hp) or
  539. (length(union(allvarfl,get(p,'allvarfcts)))<4)) and
  540. ((not member(p,l)) or
  541. ((not member(car_pdes,assoc(ordering,get(p,'dec_with)))) and
  542. ((null rl) or
  543. (not member(car_pdes,assoc(ordering,get(p,'dec_with_rl)))))
  544. )
  545. )
  546. )
  547. then
  548. % If both equations consist of a derivative of f only then
  549. % instant decision possible
  550. if (null record_hist) and (len=1) and (get(p,'printlength)=1) then <<
  551. val_p:=get(p,'val);
  552. d_p:=0$
  553. if (pairp val_p) and
  554. (car val_p = 'DF) and
  555. (cadr val_p = f) then
  556. d_p:=cddr val_p else
  557. if val_p=f then d_p:=nil$
  558. if not zerop d_p then <<
  559. w1:=which_deriv(d_p,d_car_pdes)$
  560. w2:=which_deriv(d_car_pdes,d_p)$
  561. if w1 and w2 then add_both_dec_with(ordering,car_pdes,p,rl) else
  562. % returns eg. ((e5 nil (x 2 y 2 z)) (e4 (x 2 y) (y z))
  563. % (df f x 2 y 2 z) e5)
  564. if null w1 then rtn:={{p,nil,d_p},{car_pdes,w2,d_car_pdes},
  565. val_p,p}
  566. else rtn:={{p,w1,d_p},{car_pdes,nil,d_car_pdes},
  567. val_car_pdes,car_pdes}
  568. >>
  569. >> else
  570. % The general case
  571. <<l1:=dec_info(car_pdes,p,f,vl,rl,ordering)$
  572. if expert_mode and null l1 then <<pdes:={nil};done_pdes:=nil;l2:=nil>>
  573. else
  574. if expert_mode or
  575. (quick_decoup and l1 and cadddr car l1 and
  576. ((null struc_eqn) or
  577. ((null is_algebraic(car_pdes)) and
  578. (null is_algebraic(p )) ) ))
  579. then rtn:=car l1
  580. else if l1 then l2:=cons(l1,l2)
  581. >>$
  582. % Check pairings where f is *not* the leading function in
  583. % car done_pdes. This has not been checked when this pairing
  584. % was tested before.
  585. if null rtn then
  586. for each p in done_pdes do
  587. % It should be possible that f is leading function in car_pdes but not
  588. % in others
  589. % if not flin_ or f_in_flin or
  590. % ( homogen_ and (zerop car get(p,'hom_deg))) or
  591. % (null homogen_ and freeoflist(get(p,'fcts),flin_)) then
  592. if flagp(p,'to_decoup) and
  593. member(f,get(p,'rational)) and
  594. ((null hp) or
  595. (length(union(allvarfl,get(p,'allvarfcts)))<4)) and
  596. ((not member(p,l)) or
  597. ((not member(car_pdes,assoc(ordering,get(p,'dec_with)))) and
  598. ((null rl) or
  599. (not member(car_pdes,assoc(ordering,get(p,'dec_with_rl)))))
  600. )
  601. ) and
  602. ((null get(p,'allvarfcts)) or
  603. (f neq car get(p,'allvarfcts)))
  604. then <<l1:=dec_info(car_pdes,p,f,vl,rl,ordering)$
  605. if expert_mode and null l1 then
  606. <<pdes:={nil};done_pdes:=nil;l2:=nil>>
  607. else
  608. if quick_decoup and l1 and cadddr car l1 and
  609. ((null struc_eqn) or
  610. ((null is_algebraic(car_pdes)) and
  611. (null is_algebraic(p )) ) )
  612. then rtn:=car l1
  613. else if l1 then l2:=cons(l1,l2)
  614. >>
  615. >>
  616. >>$
  617. done_pdes:=cons(car_pdes,done_pdes)$
  618. pdes:=cdr pdes
  619. >>$
  620. if rtn then return rtn$
  621. %--- l2 is the list of possible pairings of 2 equations
  622. %--- pick one of these pairings
  623. l1:=nil;
  624. %--- l1 is the list of equations which still can be reduced
  625. %--- and where f=car get(equ,'allvarfcts), i.e. equations
  626. %--- which must not be used for generating new equations
  627. %
  628. %--- each l in l2 has the form
  629. %--- (((e4 (x 2 y) (y z)) (e5 (z) (x 2 y 2))
  630. %--- (df f x 2 y 2 z) nil nil) . num_value)
  631. for each l in l2 do <<
  632. f:=caddar l;
  633. if pairp f then f:=cadr f;
  634. if (caaar l = cadddr car l) and % if caaar l will be subst.
  635. get(caaar l,'allvarfcts) and
  636. (f=car get(caaar l,'allvarfcts))
  637. then l1:=union(list(caaar l),l1);
  638. if (caadar l = cadddr car l) and % if caadar l will be subst.
  639. get(caadar l,'allvarfcts) and
  640. (f=car get(caadar l,'allvarfcts))
  641. then l1:=union(list(caadar l),l1);
  642. >>;
  643. %--- Test that no new equation will be generated from an
  644. %--- equation from which the leading derivative can still be
  645. %--- reduced
  646. for each l in l2 do
  647. if ((cadaar l = nil) or
  648. (cadr cadar l = nil) or
  649. (freeof(l1,caaar l) and freeof(l1,caadar l)) ) and
  650. dec_info_leq(l,min)
  651. then min:=l;
  652. if min then <<
  653. l:=car min$
  654. if (cadar l) and (cadadr l) then << % if both eq. are diff.
  655. f:=caddr l;
  656. if pairp f then f:=cadr f;
  657. add_both_dec_with(ordering,caar l,caadr l,rl)$
  658. >>$
  659. return l % dec_put_info(car min,rl)$
  660. >>
  661. end$
  662. symbolic procedure err_catch_elimin(p,ltp,dgp,q,ltq,dgq,x,once)$
  663. begin scalar h,bak,kernlist!*bak,kord!*bak,bakup_bak;
  664. bak:=max_gc_counter$ max_gc_counter:=my_gc_counter+max_gc_elimin;
  665. kernlist!*bak:=kernlist!*$
  666. kord!*bak:=kord!*$
  667. bakup_bak:=backup_;backup_:='max_gc_elimin$
  668. h:=errorset({'elimin,mkquote p,mkquote ltp,mkquote dgp,
  669. mkquote q,mkquote ltq,mkquote dgq,
  670. mkquote x,mkquote once},nil,nil)
  671. where !*protfg=t;
  672. kernlist!*:=kernlist!*bak$
  673. kord!*:=kord!*bak;
  674. erfg!*:=nil;
  675. max_gc_counter:=bak;
  676. backup_:=bakup_bak;
  677. return if errorp h then nil
  678. else car h
  679. end$
  680. symbolic procedure elimin(p,ltp,dgp,q,ltq,dgq,x,once)$
  681. % returns {resulting_eqn, multiplier_of_ddpcp, multiplier_of_ddqcp}
  682. begin
  683. scalar dgs,s,flg,quoti,lts,
  684. fcpp,fcqp,fcsp,
  685. fcpq,fcqq,fcsq$
  686. if dgp > dgq then << flg:=t; dgs:=dgq >>
  687. else dgs:=dgp$
  688. fcpp:=1; fcpq:=0;
  689. fcqq:=1; fcqp:=0;
  690. while dgs neq 0 do <<
  691. quoti:=reval{'QUOTIENT,ltp,ltq};
  692. s:=reval{'PLUS,{'TIMES,p,{'DEN,quoti}},
  693. {'MINUS,{'TIMES,q,{'NUM,quoti}}}}$
  694. lts:=reval{'LTERM,s,x}$
  695. dgs:=reval{'DEG,lts,x}$
  696. fcsp:=reval{'PLUS,{'TIMES,fcpp,{'DEN,quoti}},
  697. {'MINUS,{'TIMES,fcqp,{'NUM,quoti}}}}$
  698. fcsq:=reval{'PLUS,{'TIMES,fcpq,{'DEN,quoti}},
  699. {'MINUS,{'TIMES,fcqq,{'NUM,quoti}}}}$
  700. if flg=t then <<
  701. p:=s;
  702. ltp:=lts;
  703. dgp:=dgs;
  704. fcpp:=fcsp;
  705. fcpq:=fcsq;
  706. if dgq>dgp then flg:=nil
  707. >> else <<
  708. q:=s;
  709. ltq:=lts;
  710. dgq:=dgs;
  711. fcqp:=fcsp;
  712. fcqq:=fcsq;
  713. if dgp>dgq then flg:=t
  714. >>$
  715. if once then dgs:=0
  716. >>;
  717. quoti:=err_catch_gcd(fcsp,fcsq);
  718. return {reval{'QUOTIENT,s ,quoti},
  719. reval{'QUOTIENT,fcsp,quoti},
  720. reval{'QUOTIENT,fcsq,quoti} }
  721. end$ % elimin
  722. symbolic procedure dec_new_equation(l,rl)$
  723. % l has form ((e4 (x 2 y) (y z)) (e5 (z) (x 2 y 2)) (df f x 2 y 2 z) nil nil)
  724. % This means: e4 has df(f,y,z) and is differ. wrt. xxy
  725. % e5 has df(f,x,2,y,2) and is diff. wrt. z
  726. % to eliminate df(f,x,2,y,2,z),
  727. % nil is substituted,
  728. % substitution is not essential
  729. begin scalar ld,f,ip,iq,s,nvl,lcop,p,ddp,ddpcp,ldp,ltp,dgp,pfac,
  730. q,ddq,ddqcp,ldq,ltq,dgq,qfac,h,once$
  731. % ddpcp will be the name of the equation, e.g. e4
  732. % p at first the value of the equation, later df(p,ip)
  733. % ddp will be the history value of the equation
  734. % ip is a list of differentiations to be done with p
  735. % ldp is the leading derivative in p
  736. % ltp at first the lead. term of p then is the leading term in df(p,ip)
  737. % dgp at first highpow of ldp in p then highpow of df(ldp,ip) in ltp
  738. % lcop is the coefficient of ldp**dgp in ltp
  739. % pfac an overall factor of p that has been dropped but that may vanish
  740. % similar with q
  741. ld:=caddr l$
  742. f:=if pairp ld then cadr ld
  743. else ld$
  744. ip:=cadar l$
  745. iq:=cadadr l$
  746. s:=cadddr l$
  747. once:=car cddddr l$
  748. ddp:=caar l$ ddpcp:=ddp$
  749. ddq:=caadr l$ ddqcp:=ddq$
  750. p:=get(ddp,'val)$
  751. q:=get(ddq,'val)$
  752. if record_hist then <<
  753. nvl:=get(ddp,'nvars)$
  754. if get(ddq,'nvars)<nvl then nvl:=get(ddq,'nvars)$
  755. if s=ddp then ddp:=get(ddp,'histry_) else
  756. if s=ddq then ddq:=get(ddq,'histry_)
  757. >>$
  758. if print_ and ((null rl and tr_decouple) or
  759. ( rl and tr_redlength) ) then
  760. <<terpri()$write " first pde ",caar l,": "$
  761. typeeq caar l$
  762. if ip then write "is diff. wrt. ",ip,","
  763. else write "is not differentiated,"$
  764. write " second pde ",caadr l,": "$
  765. typeeq caadr l$
  766. if iq then write "is diff. wrt. ",iq," "
  767. else write "is not differentiated, "$
  768. write"to eliminate "$mathprint ld$
  769. >>$
  770. if atom ld then ldp:=ld else <<
  771. ldp:=cadr ld;
  772. if caddar l then ldp:=cons('DF,cons(ldp,caddar l))
  773. >>;
  774. ltp:=reval{'LTERM,p,ldp};
  775. dgp:=reval{'DEG,ltp,ldp};
  776. pfac:=1:
  777. if ip then <<
  778. lcop:=reval{'QUOTIENT,ltp,{'EXPT,ldp,dgp}}$
  779. if (dgp=1) and (not fixp lcop) then <<
  780. p:=reval cons('DF,cons({'QUOTIENT,{'DIFFERENCE,p,ltp},lcop},ip));
  781. if record_hist then
  782. ddp:=reval cons('DF,cons({'QUOTIENT,ddp,lcop},ip));
  783. h:=reval{'DEN,p}$ % the new lcop
  784. pfac:=reval {'QUOTIENT,lcop,h}$
  785. if may_vanish(pfac) and (s=ddqcp) then s:=nil;
  786. ltp:={'TIMES,ld,h}$
  787. p:=reval{'PLUS,ltp,{'NUM,p}}$
  788. if record_hist then ddp:=reval {'TIMES,ddp,h}$
  789. >> else <<
  790. % p:=cons('DF,cons(p,ip));
  791. if record_hist then
  792. ddp:=cons('DF,cons(ddp,ip));
  793. % ltp:=cons('DF,cons(ltp,ip))
  794. dgp:=1;
  795. ltp:={'TIMES,{'DF,p,ldp},cons('DF,cons(ldp,ip))};
  796. p:=cons('DF,cons(p,ip));
  797. >>
  798. >>$
  799. if atom ld then ldq:=ld else <<
  800. ldq:=cadr ld;
  801. if caddar cdr l then ldq:=cons('DF,cons(ldq,caddar cdr l))
  802. >>;
  803. ltq:=reval{'LTERM,q,ldq};
  804. dgq:=reval{'DEG,ltq,ldq};
  805. qfac:=1:
  806. if iq then <<
  807. lcop:=reval{'QUOTIENT,ltq,{'EXPT,ldq,dgq}}$
  808. if (dgq=1) and (not fixp lcop) then <<
  809. q:=reval cons('DF,cons({'QUOTIENT,{'DIFFERENCE,q,ltq},lcop},iq));
  810. if record_hist then
  811. ddq:=cons('DF,cons({'QUOTIENT,ddq,lcop},iq));
  812. h:=reval{'DEN,q}$ % the new lcop
  813. qfac:=reval {'QUOTIENT,lcop,h}$
  814. if may_vanish(qfac) and (s=ddpcp) then s:=nil;
  815. ltq:={'TIMES,ld,h}$
  816. q:=reval{'PLUS,ltq,{'NUM,q}}$
  817. if record_hist then ddq:=reval {'TIMES,ddq,h}$
  818. >> else <<
  819. % q:=cons('DF,cons(q,iq));
  820. if record_hist then
  821. ddq:=cons('DF,cons(ddq,iq));
  822. % ltq:=cons('DF,cons(ltq,iq))
  823. dgq:=1;
  824. ltq:={'TIMES,{'DF,q,ldq},cons('DF,cons(ldq,iq))};
  825. q:=cons('DF,cons(q,iq));
  826. >>
  827. >>$
  828. % l:=list(caar l,caadr l)$
  829. % if iq then q:=simplifypde(reval cons('DF,cons(q,iq)),ftem,nil,nil (?))$
  830. % if ip then p:=simplifypde(reval cons('DF,cons(p,ip)),ftem,nil,nil (?))$
  831. % h:=reval !*q2a simpresultant list(p,q,ld)$
  832. return if (l:=err_catch_elimin(p,ltp,dgp,q,ltq,dgq,ld,once)) then
  833. list(l,s,ddpcp,ddqcp,ddp,ddq,ld,pfac,qfac) else nil$
  834. end$ % of dec_new_equation
  835. symbolic procedure dec_reduction(h,pdes,ftem,%forg,
  836. vl,rl,ordering)$
  837. % do a reduction step or a cross differentiation either
  838. % h is the result of dec_new_equation() and has the structure
  839. % list(elimin(p,ltp,dgp,q,ltq,dgq,ld),s,ddpcp,ddqcp,ddp,ddq,ld,pfac,qfac)$
  840. % if rl then one pde must be simplified with the help of
  841. % another one and reduce its length
  842. begin scalar %p,q,ld,a,s,ip,iq,f,dwsa,dwla,dwlb,el,h,
  843. %ldp,ldq,ltp,ltq,dgp,dgq,lcop,ddp,ddq,ddpcp,ddqcp,len,nvl$
  844. s,p,q,ddp,ddq,ld,len,a,ip,iq,pfac,qfac$
  845. s:=cadr h$
  846. p:=caddr h$
  847. q:=cadddr h$
  848. ddp:=nth(h,5)$
  849. ddq:=nth(h,6)$
  850. ld:=nth(h,7)$
  851. pfac:=nth(h,8)$
  852. qfac:=nth(h,9)$
  853. h:=car h$
  854. % If an equation is to be substituted then the new system must
  855. % be sufficient after replacing one equations through another one.
  856. % --> the replaced equation must not have been multiplied with
  857. % possibly vanishing factors
  858. if s and (null rl) and % (sufficient_decouple) and
  859. % for rl=t already checked
  860. (((s=p) and may_vanish(cadr h)) or
  861. ((s=q) and may_vanish(caddr h)) ) then s:=nil$
  862. % tracing comments
  863. if (null rl and tr_decouple) or
  864. ( rl and tr_redlength) then <<
  865. terpri()$
  866. write p," (resp its derivative) is multiplied with"$terpri()$
  867. algebraic write lisp if qfac=1 then cadr h
  868. else {'TIMES,qfac,cadr h}$
  869. write q," (resp its derivative) is multiplied with"$terpri()$
  870. algebraic write lisp if pfac=1 then caddr h
  871. else {'TIMES,pfac,caddr h}$
  872. >>$
  873. % If an equation is used for a substitution of a derivative which is
  874. % not a leading derivative and the length of the equation is
  875. % increased then drop the new equation
  876. if (null rl) and % for rl=t the length comparison is already done
  877. (null expert_mode) and % not explicitly ordered by user
  878. (car h) and s and ((null struc_eqn) or (atom ld))
  879. then <<
  880. len:=no_of_terms(car h);
  881. if pairp(ld) and (car ld = 'DF) then ld:=cdr ld
  882. else ld:=list ld;
  883. if ((s=p) and
  884. (ld neq caar get(p,'derivs)) and
  885. (len>get(p,'terms))) or
  886. ((s=q) and
  887. (ld neq caar get(q,'derivs)) and
  888. (len>get(q,'terms))) then
  889. return <<
  890. if print_ then <<
  891. write"The tried reduction of a non-leading derivative"$terpri()$
  892. write"would have only increased the equation's length."$terpri()
  893. >>$
  894. add_both_dec_with(ordering,p,q,rl);
  895. list(nil)
  896. >>;
  897. if cdr ld then ld:=cons('DF,ld)
  898. else ld:=car ld;
  899. >>$
  900. % the case of a resulting identity 0=0
  901. if car h then
  902. if zerop car h and null rl then <<
  903. % for rl=t the case that the multipliers contain ftem_ has already
  904. % been checked
  905. if print_ then <<terpri()$write" An identity 0=0 results.">>$
  906. if null ip and null iq and null s and
  907. % if s<>nil then multipliers can not be ftem_ dependent
  908. (!*batch_mode or
  909. (batchcount_>=stepcounter_)) then << % i.e. only if batch_mode
  910. a:=proc_list_;
  911. % Have already all normal factorizations be tried?
  912. while a and (car a neq 8) and (car a neq 30) do a:=cdr a;
  913. if a and car a = 8 then
  914. to_do_list:=cons(list('factorize_any,%pdes,forg,vl_,
  915. list <<a:=get(p,'val);
  916. if (pairp a) and (car a = 'TIMES) then p
  917. else q
  918. >>),
  919. to_do_list);
  920. a:=nil;
  921. >>;
  922. add_both_dec_with(ordering,p,q,rl);
  923. >> else <<
  924. a:=mkeq(if pfac neq 1 then if qfac neq 1 then {'TIMES,pfac,qfac,car h}
  925. else {'TIMES,pfac, car h}
  926. else if qfac neq 1 then {'TIMES, qfac,car h}
  927. else car h ,
  928. ftem,vl,allflags_,t,list(0),
  929. reval {'PLUS,{'TIMES,cadr h,ddp},
  930. {'TIMES,caddr h,ddq} },pdes)$
  931. if print_ and ((null rl and tr_decouple ) or
  932. ( rl and tr_redlength) ) then
  933. <<terpri()$mathprint reval {'EQUAL,a,get(a,'histry_)}>>
  934. >>$
  935. if record_hist and
  936. (car h) and (zerop car h) then
  937. new_idty({'PLUS,{'TIMES,cadr h,ddp},{'TIMES,caddr h,ddq} }, pdes, t);
  938. % also if car h is not identical 0 but with less variables.
  939. % It still can be the case that some functions of fewer variables
  940. % still depend on all the differentiation variables of the divergence
  941. % Then integration of the curl is not done(possible?)
  942. % The following lines have been commented out 9.9.2001 as the
  943. % cycle-test with dec_hist_list is too crude. It is necessary to
  944. % record which method (decoupling or length-reduction-decoupling or
  945. % shortening) leads to a repetition, or better just to check only
  946. % when doing length-reduction because straightforward decoupling
  947. % should be done anyway.
  948. %if a and (null s) and member(get(a,'val),dec_hist_list) then <<
  949. % drop_pde(a,nil,nil)$
  950. % add_both_dec_with(ordering,car l,cadr l,rl);
  951. % if print_ and tr_decouple then <<
  952. % terpri()$write "the resulting pde would lead to a cycle"$
  953. % >>
  954. %>> else <<
  955. if print_ then <<
  956. write"Eliminate "$
  957. mathprint ld$
  958. write"from ",if ip then cons('DF,cons(p,ip))
  959. else p, " and ",
  960. if iq then cons('DF,cons(q,iq))
  961. else q, ". "$
  962. if a then <<
  963. if s then <<
  964. write s,": "$terpri()$
  965. typeeq s;
  966. write"is replaced by ",a,": "
  967. >> else write a," is added: "$
  968. terpri()$
  969. typeeq a
  970. >> else
  971. if s then <<write s," is deleted.";terpri()>>$
  972. >>$
  973. if null s then add_both_dec_with(ordering,p,q,rl)
  974. else << % reduction, s is the equation to be replaced
  975. % The following was commented out as in_cycle() is to take care of
  976. % preventing cycles, l had the value which is now the input of
  977. % dec_new_equation()
  978. %
  979. % l:=delete(s,l)$
  980. %
  981. % if not (ip or iq) then <<
  982. % % The equations wrt which s has already been decoupled
  983. % % are to be listed under dec_with wrt to the equation
  984. % % of both that is kept which is car l
  985. % % purpose: These decouplings should not be done again
  986. % % with car l as this may result in a cycle
  987. % dwsa:=get( s,'dec_with)$
  988. % dwla:=get(car l,'dec_with)$
  989. % for each el in dwsa do <<
  990. % % el are the different orderings, if more than one are
  991. % % in use then something must be changed probably
  992. % dwlb:=assoc(car el,dwla)$
  993. % dwla:=delete(dwlb,dwla)$
  994. % if dwlb then dwlb:=cons(car el,union(cdr el,cdr dwlb))
  995. % else dwlb:=el$
  996. % dwla:=cons(dwlb,dwla)
  997. % >>$
  998. % put(car l,'dec_with,dwla)$
  999. % >>$
  1000. % The following was taken out some time ago (now 9.9.2001)
  1001. % because it probably prevented a complete computation
  1002. % % If other than the leading derivatives are reduced then
  1003. % % the new equ. a must inherit 'dec_with from equ. s
  1004. % if a and get(a,'derivs) and
  1005. % (car get(a,'derivs) = car get(s,'derivs)) then <<
  1006. % dwsa:=get(s,'dec_with)$
  1007. % put(a,'dec_with,dwsa)$
  1008. % >>$
  1009. % The following has been taken out with the dec_hist_list test above
  1010. % if dec_hist>0 then <<
  1011. % if length dec_hist_list>dec_hist then
  1012. % dec_hist_list:=cdr dec_hist_list$
  1013. % dec_hist_list:=reverse cons(get(s,'val),reverse dec_hist_list)$
  1014. % >>$
  1015. drop_pde(s,if a then cons(a,pdes) else pdes,nil)
  1016. >>$
  1017. %>>$ commented out together with code from above
  1018. return list(a)
  1019. % a is either a new equation or nil if s has beed reduced to an identity
  1020. end$ % of dec_reduction
  1021. symbolic procedure dec_fct_check(a,l)$
  1022. % checks, if a function occurs in only one pde
  1023. begin scalar ft,n$
  1024. ft:=get(a,'fcts)$
  1025. while ft and l do
  1026. <<if flagp(car l,'to_decoup) then
  1027. ft:=setdiff(ft,get(car l,'fcts))$
  1028. l:=cdr l>>$
  1029. n:=get(a,'nvars)$
  1030. while ft and (n<=length fctargs(car ft)) do ft:=cdr ft$
  1031. if ft then remflag1(a,'to_decoup)$
  1032. return ft$
  1033. end$
  1034. symbolic procedure check_cases_for_symbol(l)$
  1035. % l has form ((e4 (x 2 y) (y z)) (e5 (z) (x 2 y 2)) (df f x 2 y 2 z) nil nil)
  1036. % This means: e4 has df(f,y,z) and is differ. wrt. xxy
  1037. % e5 has df(f,x,2,y,2) and is diff. wrt. z
  1038. % to eliminate df(f,x,2,y,2,z),
  1039. % nil is substituted,
  1040. % substitution is not essential
  1041. begin scalar s,h,lde,sy$
  1042. % Is a case-distinction to be made about whether the symbol
  1043. % is zero or non-zero?
  1044. s:=cadddr l;
  1045. if lin_problem or (null s) or
  1046. (not pairp caddr l) or
  1047. (null flagp(if s=caar l then caadr l
  1048. else caar l,'to_symbol))
  1049. then return nil % no case-distinction
  1050. else <<
  1051. if s=caar l then h:=cadr l else h:=car l$ % h are the data of the lower
  1052. % priority (e.g. order) equation
  1053. if null cadr h then return nil else << % lower order equ. is not diff.
  1054. remflag1(car h,'to_symbol)$
  1055. lde:=if null caddr h then cadr caddr l % lead. deriv. is algebraic
  1056. else cons('DF,cons(cadr caddr l,caddr h));
  1057. % lde is the leading derivative in the lower priority equation
  1058. sy:=reval {'DF,get(car h,'val),lde};
  1059. return
  1060. if freeofzero(sy,get(car h,'fcts),get(car h,'vars),get(car h,'nonrational))
  1061. % if not may_vanish(sy)
  1062. then nil
  1063. else <<to_do_list:=cons(list('split_into_cases,sy),to_do_list);
  1064. if print_ then <<
  1065. write"To reduce the leading derivative"$terpri()$
  1066. mathprint caddr l$
  1067. write"in ",s," using ",car h," a case distinction will be made."$terpri()
  1068. >>$
  1069. t
  1070. >>
  1071. >>
  1072. >>
  1073. end$
  1074. symbolic procedure dec_one_step(pdes,ftem,%forg,
  1075. vl,hp,ordering)$
  1076. % do one decouple step for 2 pdes from l, differentiate them
  1077. % and add the new pde or replace an original one
  1078. begin scalar l0,l1,l2,l,ruli$ %,f$
  1079. l:=pdes;
  1080. if not expert_mode then l0:=l
  1081. else <<
  1082. l0:=selectpdes(l,2)$
  1083. drop_dec_with(car l0,cadr l0,nil)$
  1084. drop_dec_with(cadr l0,car l0,nil)$
  1085. >>$
  1086. ruli:=start_let_rules()$
  1087. again:
  1088. l1:=dec_and_fct_select(l0,vl,nil,hp,ordering)$
  1089. if null l1 then l:=nil else
  1090. if check_cases_for_symbol(l1) then return l else
  1091. % i.e. dec_one_step was successful even if nothing
  1092. % happened just to continue with to_do
  1093. if null (l2:=dec_new_equation(l1,nil)) then
  1094. <<l:=nil; % e.g. elimin too slow --> err_catch
  1095. add_both_dec_with(ordering,caar l1,caadr l1,nil)$
  1096. goto again
  1097. >> else
  1098. if null (l2:=dec_reduction(l2,pdes,ftem,%forg,
  1099. vl,nil,ordering)) then l:=nil else <<
  1100. for each a in cdddr l1 do
  1101. if get(a,'val)=nil then l:=delete(a,l)$
  1102. for each a in l2 do if a then <<
  1103. l:=eqinsert(a,l)$
  1104. % % equations which are added and are still to be reduced and still
  1105. % % contain the function to be decoupled shall not be integrated:
  1106. % if null cadddr l1 then <<% no equation was reduced only a new one is added
  1107. % f:=if pairp caddr l1 then cadr caddr l1 % leading deriv. was a deriv
  1108. % else caddr l1; % leading deriv. was a function
  1109. % if not freeof(get(a,'fcts),f) then <<
  1110. % remflag1(a,'to_int)$
  1111. % remflag1(a,'to_fullint)
  1112. % >>$
  1113. >>
  1114. % the following breaks the ordering
  1115. % for each a in l2 do dec_fct_check(a,l)$
  1116. >>$
  1117. stop_let_rules(ruli);
  1118. % if anything has changed then l must be the new pde-list
  1119. return l$
  1120. end$
  1121. symbolic procedure dec_try_to_red_len(pdes_to_choose_from,vl,ordering)$
  1122. begin scalar l1,l2,p,q,s$
  1123. again:
  1124. l1:=dec_and_fct_select(pdes_to_choose_from,vl,t,nil,ordering)$
  1125. if l1 then <<
  1126. if in_cycle({27,get(caar l1,'printlength),get(caadr l1,'printlength),
  1127. caddr l1,get(cadddr l1,'printlength),
  1128. length get(cadddr l1,'fcts)}) then <<
  1129. add_both_dec_with(ordering,caar l1,caadr l1,t)$
  1130. goto again;
  1131. >>;
  1132. l2:=dec_new_equation(l1,t)$
  1133. % possible length measures to use:
  1134. % put(equ,'length,pdeweight(val,ftem))$
  1135. % put(equ,'printlength,delength val)$
  1136. % put(equ,'terms,no_of_terms(val))$
  1137. p:=caar l1$
  1138. q:=caadr l1$
  1139. s:=cadddr l1$
  1140. % if ( no_of_terms(caar l2) >
  1141. % get(cadddr l1,'terms) ) or % * length_inc
  1142. % disadvantage of 'terms: a big product is one term
  1143. if (null l2) or
  1144. ( pdeweight(caar l2,ftem_) >
  1145. get(cadddr l1,'length) ) or % * length_inc
  1146. ((s=p) and may_vanish( cadar l2)) or
  1147. ((s=q) and may_vanish(caddar l2)) then <<
  1148. l2:=nil;
  1149. add_both_dec_with(ordering,p,q,t);
  1150. last_steps:=cdr last_steps; % last_steps had already been updated
  1151. % in add_to_last_steps() in in_cycle()
  1152. goto again
  1153. >>
  1154. >>;
  1155. return l2
  1156. end$
  1157. symbolic procedure err_catch_red_len(a1,a2,a3)$
  1158. begin scalar h,bak,kernlist!*bak,kord!*bak,bakup_bak;
  1159. bak:=max_gc_counter$ max_gc_counter:=my_gc_counter+max_gc_red_len;
  1160. kernlist!*bak:=kernlist!*$
  1161. kord!*bak:=kord!*$
  1162. bakup_bak:=backup_;backup_:='max_gc_red_len$
  1163. h:=errorset({'dec_try_to_red_len,mkquote a1,mkquote a2,mkquote a3},nil,nil)
  1164. where !*protfg=t;
  1165. kernlist!*:=kernlist!*bak$
  1166. kord!*:=kord!*bak;
  1167. erfg!*:=nil;
  1168. max_gc_counter:=bak;
  1169. backup_:=bakup_bak;
  1170. return if errorp h then nil
  1171. else car h
  1172. end$
  1173. symbolic procedure dec_and_red_len_one_step(pdes,ftem,%forg,
  1174. vl,ordering)$
  1175. % do one length-reducing decouple step for 2 pdes from l,
  1176. % differentiate at most one and replace the other one which must
  1177. % become shorter, the one replaced must not be multiplied with a
  1178. % potentially zero factor
  1179. begin scalar l,l1,l2,l3,ruli$ %,f$
  1180. l:=pdes;
  1181. if not expert_mode then l1:=l
  1182. else <<
  1183. l1:=selectpdes(l,2)$
  1184. drop_dec_with(car l1,cadr l1,t)$
  1185. drop_dec_with(cadr l1,car l1,t)$
  1186. >>$
  1187. ruli:=start_let_rules()$
  1188. again:
  1189. l2:=err_catch_red_len(l1,vl,ordering)$
  1190. if null l2 then return nil;
  1191. if (l3:=dec_reduction(l2,pdes,ftem,%forg,
  1192. vl,t,ordering)) then <<
  1193. l:=delete(cadr l2,l)$
  1194. for each a in l3 do if a then <<
  1195. l:=eqinsert(a,l)$
  1196. % % equations which are added and are still to be reduced and still
  1197. % % contain the function to be decoupled shall not be integrated:
  1198. % if null cadddr l1 then <<% no equation was reduced only a new one is added
  1199. % f:=if pairp caddr l1 then cadr caddr l1 % leading deriv. was a deriv
  1200. % else caddr l1; % leading deriv. was a function
  1201. % if not freeof(get(a,'fcts),f) then <<
  1202. % remflag1(a,'to_int)$
  1203. % remflag1(a,'to_fullint)
  1204. % >>$
  1205. % >>
  1206. >>$
  1207. % the following breaks the ordering
  1208. % for each a in l3 do dec_fct_check(a,l)$
  1209. >> else
  1210. <<last_steps:=cdr last_steps;
  1211. if not expert_mode then <<l1:=l;goto again>>
  1212. >>;
  1213. stop_let_rules(ruli);
  1214. % if anything has changed then l must be the new pde-list
  1215. return l$
  1216. end$
  1217. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1218. % procedures for decoupling of similar pde %
  1219. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1220. %symbolic procedure rel_length_diff(p,q)$
  1221. %% print length difference in pro cent
  1222. %(abs(get(p,'length)-get(q,'length))*100)/
  1223. % (get(p,'length)+get(q,'length))$
  1224. %symbolic procedure nearly_same(p,q)$
  1225. %begin scalar lp,lq$
  1226. % lp:=get(p,'fcts)$
  1227. % lq:=get(q,'fcts)$
  1228. % if null setdiff(get(p,'allvarfcts),get(q,'allvarfcts)) and
  1229. % null setdiff(get(q,'allvarfcts),get(p,'allvarfcts)) and
  1230. % ((length setdiff(lp,lq)+length setdiff(lq,lp))*100<
  1231. % (length lp+length lq)*same_fcts) then
  1232. % <<lp:=get(p,'derivs)$
  1233. % lq:=get(q,'derivs)$
  1234. % if (length setdiff(lp,lq)+length setdiff(lq,lp))*100<
  1235. % (length lp+length lq)*same_derivs then return t>>$
  1236. %end$
  1237. %symbolic procedure get_same_pdes(pdes)$
  1238. %begin scalar l,n,res$
  1239. % while pdes do
  1240. % <<l:=cdr pdes$
  1241. % while l do
  1242. % if (n:=rel_length_diff(car pdes,car l))<=same_length then
  1243. % if nearly_same(car pdes,car l) then
  1244. % <<res:=list(car pdes,car l)$
  1245. % l:=nil>>
  1246. % else l:=cdr l
  1247. % else if n>5*same_length then l:=nil
  1248. % else l:=cdr l$
  1249. % if res then pdes:=nil
  1250. % else pdes:=cdr pdes
  1251. % >>$
  1252. % return res$
  1253. %end$
  1254. endmodule$
  1255. end$