conlaw0.red 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. % CONLAW file with subroutines for CONLAW1/2/3/4
  2. % by Thomas Wolf, September 1997
  3. %----------------------------------------------------------------------
  4. symbolic fluid '(reducefunctions_ print_)$
  5. algebraic procedure print_claw(eqlist,qlist,plist,xlist)$
  6. begin scalar n$
  7. n:=length eqlist$
  8. while qlist neq {} do <<
  9. if length qlist < n then write "+"$
  10. write"( ",first qlist," ) * ( ",first eqlist," )"$
  11. qlist:=rest qlist; eqlist:=rest eqlist
  12. >>$
  13. write" = "$
  14. n:=length xlist$
  15. while plist neq {} do <<
  16. if length plist < n then write "+"$
  17. write"df( ",first plist,", ",first xlist," )"$
  18. plist:=rest plist;
  19. xlist:=rest xlist
  20. >>
  21. end$
  22. symbolic operator lhsli$
  23. symbolic procedure lhsli(eqlist)$
  24. % lhslist1 will be a list of all those lhs's which are a derivative or
  25. % a power of a derivative which is used to fix dependencies
  26. % of q_i or p_j
  27. % lhslist2 will be a list of all lhs's of all equations in their
  28. % order with those lhs's set to 0 which can not be used
  29. % for substitutions
  30. begin scalar lhslist1,lhslist2,h1,flg1,flg2$
  31. for each h1 in cdr eqlist do <<
  32. flg1:=nil$ % no assignment to lhslist1 done yet
  33. if (pairp h1) and (car h1 = 'EQUAL) then <<
  34. h1:=reval cadr h1;
  35. if (pairp h1) and
  36. (car h1='EXPT) and
  37. (numberp caddr h1) then <<flg2:=nil;h1:=cadr h1>>
  38. else flg2:=t;
  39. if (not numberp h1) and
  40. ((atom h1) or ((car h1='DF) and (atom cadr h1) )) then
  41. <<lhslist1:=cons(h1,lhslist1)$
  42. if flg2 then <<lhslist2:=cons(h1,lhslist2)$
  43. flg1:=t>>
  44. >>
  45. >>;
  46. if null flg1 then lhslist2:=cons(0,lhslist2);
  47. >>$
  48. return list('LIST,cons('LIST,lhslist1),cons('LIST,lhslist2))
  49. end$
  50. symbolic operator chksub$
  51. symbolic procedure chksub(eqlist,ulist)$
  52. % eqlist is a list of equations df(f,x,2,y) = ...
  53. % this procedure tests whether
  54. % - for any equation a derivative on the rhs is equal or a derivative of
  55. % the lhs?
  56. % - any lhs is equal or the derivative of any other lhs
  57. begin scalar h1,h2,derili,complaint$
  58. derili:=for each e1 in cdr eqlist collect
  59. cons( all_deriv_search(cadr e1,cdr ulist), % lhs
  60. all_deriv_search(caddr e1,cdr ulist) ); % rhs
  61. %--- Is for any equation a derivative on the rhs equal or a derivative of
  62. %--- the lhs?
  63. for each e1 in derili do
  64. if car e1 then <<
  65. h1:=caaar e1; % e.g. h1 = (f x 2 y)
  66. for each h2 in cdr e1 do
  67. if (car h1 = caar h2) and null which_deriv(cdar h2,cdr h1) then <<
  68. complaint:=t;
  69. write "The left hand side ",
  70. if length h1 = 1 then car h1
  71. else cons('DF,h1)$terpri()$
  72. write " is not a leading derivative in its equation!"$ terpri()
  73. >>
  74. >>$
  75. %--- Is any lhs equal or the derivative of any other lhs?
  76. if derili then
  77. while cdr derili do <<
  78. if caar derili then <<
  79. h1:=caaaar derili$
  80. for each h2 in cdr derili do
  81. if (car h2) and
  82. (car h1=caaaar h2) and
  83. ((null which_deriv(cdr h1,cdaaar h2)) or
  84. (null which_deriv(cdaaar h2,cdr h1)) ) then <<
  85. complaint:=t;
  86. write"--> One left hand side (lhs) contains a derivative which"$
  87. terpri()$
  88. write"is equal or a derivative of a derivative on another lhs!"$
  89. terpri()$
  90. >>$
  91. >>$
  92. derili:=cdr derili
  93. >>;
  94. if complaint then terpri()$
  95. end$
  96. %==== Procedures as in LIEPDE:
  97. symbolic procedure comparedif1(u1l,u2l)$
  98. % checks whether u2l has more or at least equally many 1's, 2's, ...
  99. % contained as u1l.
  100. % returns a list of 1's, 2's, ... which are in excess in u2l
  101. % compared with u1l. The returned value is 0 if both are identical
  102. begin
  103. scalar ul;
  104. if u2l=nil then if u1l neq nil then return nil
  105. else return 0
  106. else if u1l=nil then return u2l
  107. else % both are non-nil
  108. if car u1l < car u2l then return nil else
  109. if car u1l = car u2l then return comparedif1(cdr u1l,cdr u2l) else <<
  110. ul:=comparedif1(u1l,cdr u2l);
  111. return if not ul then nil else
  112. if zerop ul then list car u2l else
  113. cons(car u2l,ul)
  114. >>
  115. end$ % of comparedif1
  116. %-------------
  117. symbolic procedure comparedif2(u1,u1list,du2)$
  118. % checks whether du2 is a derivative of u1 differentiated
  119. % wrt. u1list
  120. begin
  121. scalar u2l;
  122. u2l:=combidif(du2)$ % u2l=(u2, 1, 1, ..)
  123. if car u2l neq u1 then return nil else
  124. return comparedif1(u1list, cdr u2l)
  125. end$ % of comparedif2
  126. %-------------
  127. symbolic procedure listdifdif1(du1,deplist)$
  128. % lists all elements of deplist which are *not* derivatives
  129. % of du1
  130. begin
  131. scalar u1,u1list,res,h$
  132. h:=combidif(du1);
  133. u1:=car h;
  134. u1list:=cdr h;
  135. for each h in deplist do
  136. if not comparedif2(u1,u1list,h) then res:=cons(h,res);
  137. return res
  138. end$ % of listdifdif1
  139. %-------------
  140. symbolic operator listdifdif2$
  141. symbolic procedure listdifdif2(lhslist,deplist)$
  142. % lists all elements of deplist which are *not* derivatives
  143. % of any element of lhslist
  144. begin
  145. scalar h;
  146. deplist:=cdr reval deplist;
  147. lhslist:=cdr reval lhslist;
  148. for each h in lhslist do
  149. deplist:=listdifdif1(h,deplist);
  150. return cons('LIST,deplist)
  151. end$ % of listdifdif2
  152. %-------------
  153. symbolic operator totdeg$
  154. symbolic procedure totdeg(p,f)$
  155. % Ordnung (total) der hoechsten Ableitung von f im Ausdruck p
  156. eval(cons('PLUS,ldiff1(car ldifftot(reval p,reval f),fctargs reval f)))$
  157. %-------------
  158. % symbolic operator totordpot$
  159. % symbolic procedure totordpot(p,f)$
  160. % % Ordnung (total) der hoechsten Ableitung von f im Ausdruck p
  161. % % und hoechste Potenz der hoechsten Ableitung
  162. % % currently not used
  163. % begin scalar a;
  164. % a:=ldifftot(reval p,reval f);
  165. % return
  166. % cons(eval(cons('PLUS,ldiff1(car a,fctargs reval f))), cdr a)
  167. % end$
  168. %-------------
  169. symbolic procedure diffdeg(p,v)$
  170. % liefert Ordnung der Ableitung von p nach v$
  171. % p Liste Varible+Ordnung der Ableitung, v Variable (Atom)
  172. if null p then 0 % alle Variable bearbeitet ?
  173. else if car p=v then % v naechste Variable ?
  174. if cdr p then
  175. if numberp(cadr p) then cadr p % folgt eine Zahl ?
  176. else 1
  177. else 1
  178. else diffdeg(cdr p,v)$ % weitersuchen
  179. %-------------
  180. symbolic procedure ldiff1(l,v)$
  181. % liefert Liste der Ordnungen der Ableitungen nach den Variablen aus v
  182. % l Liste (Variable + Ordnung)$ v Liste der Variablen
  183. if null v then nil % alle Variable abgearbeitet ?
  184. else cons(diffdeg(l,car v),ldiff1(l,cdr v))$
  185. % Ordnung der Ableitung nach
  186. % erster Variable anhaengen
  187. %-------------
  188. symbolic procedure ldifftot(p,f)$
  189. % leading derivative total degree ordering
  190. % liefert Liste der Variablen + Ordnungen mit Potenz
  191. % p Ausdruck in LISP - Notation, f Funktion
  192. ldifftot1(p,f,fctargs f)$
  193. %-------------
  194. symbolic procedure ldifftot1(p,f,vl)$
  195. % liefert Liste der Variablen + Ordnungen mit Potenz
  196. % p Ausdruck in LISP - Notation, f Funktion, lv Variablenliste
  197. begin scalar a$
  198. a:=cons(nil,0)$
  199. if not atom p then
  200. % if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,
  201. % 'QUOTIENT,'DF,'EQUAL)) then
  202. if member(car p,REDUCEFUNCTIONS_) then
  203. % erlaubte Funktionen
  204. <<if (car p='PLUS) or (car p='TIMES) or
  205. (car p='QUOTIENT) or (car p='EQUAL) then
  206. <<p:=cdr p$
  207. while p do
  208. <<a:=diffreltot(ldifftot1(car p,f,vl),a,vl)$
  209. p:=cdr p
  210. >>
  211. >> else
  212. if car p='MINUS then a:=ldifftot1(cadr p,f,vl) else
  213. if car p='EXPT then % Exponent
  214. % if numberp caddr p then
  215. % <<a:=ldifftot1(cadr p,f,vl)$
  216. % a:=cons(car a,times(caddr p,cdr a))
  217. % >> else a:=cons(nil,0)
  218. <<a:=ldifftot1(cadr p,f,vl)$
  219. if (numberp caddr p) and
  220. (numberp cdr a) then a:=cons(car a,times(caddr p,cdr a))
  221. else a:=cons(car a,10000)
  222. >>
  223. % Potenz aus Basis wird mit
  224. % Potenz multipliziert
  225. else
  226. if car p='DF then % Ableitung
  227. if cadr p=f then a:=cons(cddr p,1)
  228. % f wird differenziert?
  229. else a:=cons(nil,0)
  230. else % any other non-linear function
  231. <<p:=cdr p$
  232. while p do
  233. <<a:=diffreltot(ldifftot1(car p,f,vl),a,vl)$
  234. p:=cdr p
  235. >>;
  236. a:=cons(car a,10000)
  237. >>
  238. >> else % sonst Konstante bzgl. f
  239. if p=f then a:=cons(nil,1) % Funktion selbst
  240. else a:=cons(nil,0) % alle uebrigen Fkt. werden
  241. else if p=f then a:=cons(nil,1)$ % wie Konstante behandelt
  242. return a
  243. end$
  244. %-------------
  245. symbolic procedure diffreltot(p,q,v)$
  246. % liefert komplizierteren Differentialausdruck$
  247. if diffreltotp(p,q,v) then q
  248. else p$
  249. %-------------
  250. symbolic procedure diffreltotp(p,q,v)$
  251. % liefert t, falls p einfacherer Differentialausdruck, sonst nil
  252. % p, q Paare (liste.power), v Liste der Variablen
  253. % liste Liste aus Var. und Ordn. der Ableit. in Diff.ausdr.,
  254. % power Potenz des Differentialausdrucks
  255. begin scalar n,m$
  256. m:=eval(cons('PLUS,ldiff1(car p,v)))$
  257. n:=eval(cons('PLUS,ldiff1(car q,v)))$
  258. return
  259. if m<n then t
  260. else if n<m then nil
  261. else diffrelp(p,q,v)$
  262. end$
  263. %-------------
  264. algebraic procedure subdif1(xlist,ylist,ordr)$
  265. % A list of lists of derivatives of one order for all functions
  266. begin
  267. scalar allsub,revx,i,el,oldsub,newsub;
  268. revx:=reverse xlist;
  269. allsub:={};
  270. oldsub:= for each y in ylist collect y=y;
  271. for i:=1:ordr do % i is the order of next substitutions
  272. <<oldsub:=for each el in oldsub join nextdy(revx,xlist,el);
  273. allsub:=cons(oldsub,allsub)
  274. >>;
  275. return allsub
  276. end$
  277. %-------------
  278. algebraic procedure nextdy(revx,xlist,dy)$
  279. % generates all first order derivatives of lhs dy
  280. % revx = reverse xlist; xlist is the list of variables;
  281. % dy the old derivative
  282. begin
  283. scalar x,n,ldy,rdy,ldyx,sublist;
  284. x:=first revx; revx:=rest revx;
  285. sublist:={};
  286. ldy:=lhs dy;
  287. rdy:=rhs dy;
  288. while lisp(not member(prepsq simp!* algebraic x,
  289. prepsq simp!* algebraic ldy))
  290. and (revx neq {}) do
  291. <<x:=first revx; revx:=rest revx>>;
  292. n:=length xlist;
  293. if revx neq {} then % dy is not the function itself
  294. while first xlist neq x do xlist:=rest xlist;
  295. xlist:=reverse xlist;
  296. % New higher derivatives
  297. while xlist neq {} do
  298. <<x:=first xlist;
  299. ldyx:=df(ldy,x);
  300. sublist:=cons((lisp reval algebraic ldyx)=
  301. mkid(mkid(rdy,!`),n), sublist);
  302. n:=n-1;
  303. xlist:=rest xlist
  304. >>;
  305. return sublist
  306. end$
  307. %-------------
  308. symbolic procedure combidif(s)$
  309. % extracts the list of derivatives from s: % u`1`1`2 --> (u, 1, 1, 2)
  310. begin scalar temp,ans,no,n1;
  311. s:=reval s; % to guarantee s is in true prefix form
  312. temp:=reverse explode s;
  313. while not null temp do
  314. <<n1:=<<no:=nil;
  315. while (not null temp) and (not eqcar(temp,'!`)) do
  316. <<no:=car temp . no;temp:=cdr temp>>;
  317. compress no
  318. >>;
  319. if (not fixp n1) then n1:=intern n1;
  320. ans:=n1 . ans;
  321. if eqcar(temp,'!`) then <<temp:=cdr temp; temp:=cdr temp>>;
  322. >>;
  323. return ans
  324. end$
  325. %-------------
  326. symbolic operator dif$
  327. symbolic procedure dif(s,n)$
  328. % e.g.: dif(fnc!`1!`3!`3!`4, 3) --> fnc!`1!`3!`3!`3!`4
  329. begin scalar temp,ans,no,n1,n2,done;
  330. s:=reval s; % to guarantee s is in true prefix form
  331. temp:=reverse explode s;
  332. n2:=reval n;
  333. n2:=explode n2;
  334. while (not null temp) and (not done) do
  335. <<n1:=<<no:=nil;
  336. while (not null temp) and (not eqcar(temp,'!`)) do
  337. <<no:=car temp . no;temp:=cdr temp>>;
  338. compress no
  339. >>;
  340. if (not fixp n1) or ((fixp n1) and (n1 leq n)) then
  341. <<ans:=nconc(n2,ans); ans:='!` . ans; ans:='!! . ans; done:=t>>;
  342. ans:=nconc(no,ans);
  343. if eqcar(temp,'!`) then <<ans:='!` . ans; ans:='!! . ans;
  344. temp:=cdr temp; temp:=cdr temp>>;
  345. >>;
  346. return intern compress nconc(reverse temp,ans);
  347. end$
  348. %-------------
  349. algebraic procedure depnd(y,xlist)$
  350. for each xx in xlist do
  351. for each x in xx do depend y,x$
  352. %==== Other procedures:
  353. symbolic operator totdif$
  354. symbolic procedure totdif(s,x,n,dylist)$
  355. % total derivative of s(x,dylist) w.r.t. x which is the n'th variable
  356. begin
  357. scalar tdf,el1,el2;
  358. tdf:=simpdf {s,x};
  359. <<dylist:=cdr dylist;
  360. while dylist do
  361. <<el1:=cdar dylist;dylist:=cdr dylist;
  362. while el1 do
  363. <<el2:=car el1;el1:=cdr el1;
  364. tdf:=addsq(tdf ,multsq( simp!* dif(el2,n), simpdf {s,el2}))
  365. >>
  366. >>
  367. >>;
  368. return prepsq tdf
  369. end$
  370. %-------------
  371. algebraic procedure simppl(pllist,ulist,tt,xx)$
  372. begin
  373. scalar pl,hh,td,xd,lulist,ltt,lxx,ltd,dv,newtd,e1,deno,ok,
  374. newpllist,contrace;
  375. % contrace:=t;
  376. lisp <<
  377. lulist:=cdr reval algebraic ulist;
  378. lxx:=reval algebraic xx;
  379. ltt:=reval algebraic tt;
  380. >>;
  381. newpllist:={};
  382. for each pl in pllist do <<
  383. td:=first pl;
  384. xd:=second pl;
  385. repeat <<
  386. lisp <<
  387. ltd:=reval algebraic td;
  388. if contrace then <<write"ltd1=",ltd;terpri()>>$
  389. dv:=nil;
  390. newtd:=nil;
  391. deno:=nil;
  392. if (pairp ltd) and (car ltd='QUOTIENT) and
  393. my_freeof(caddr ltd,ltt) and
  394. my_freeof(caddr ltd,lxx)
  395. then <<deno:=caddr ltd;ltd:=cadr ltd>>;
  396. ok:=t;
  397. if (pairp ltd) and (car ltd = 'PLUS) then ltd:= cdr ltd else
  398. if (pairp ltd) and (car ltd neq 'TIMES) then ok:=nil
  399. else ltd:=list ltd;
  400. if contrace then <<write"ltd2=",ltd;terpri()>>$
  401. if ok then <<
  402. for each e1 in ltd do <<
  403. hh:=intpde(e1, lulist, list(lxx,ltt), lxx, t);
  404. if null hh then hh:=list(nil,e1);
  405. dv :=cons(car hh,dv);
  406. newtd:=cons(cadr hh,newtd);
  407. >>;
  408. dv :=reval cons('PLUS,dv);
  409. newtd:=reval cons('PLUS,newtd);
  410. if deno then <<newtd:=list('QUOTIENT,newtd,deno);
  411. dv :=list('QUOTIENT,dv ,deno) >>;
  412. if contrace then <<write"newtd=",newtd;terpri();
  413. write"dv=",dv ;terpri() >>$
  414. td:=newtd;
  415. if contrace then <<write"td=",td;terpri()>>$
  416. if (dv neq 0) and (dv neq nil) then <<
  417. xd:=reval(list('PLUS,xd,list('DF,dv,tt)));
  418. if contrace then <<write"xd=",xd;terpri()>>$
  419. %algebraic mode:
  420. %hh:=lisp gensym()$
  421. %sbb:=absorbconst({td*hh,xd*hh},{hh})$
  422. %if (sbb neq nil) and (sbb neq 0) then
  423. %<<td:=sub(sbb,td*hh)/hh; xd:=sub(sbb,xd*hh)/hh>>;
  424. % cllist would have to be scaled as well
  425. >>
  426. >>
  427. >>
  428. >>
  429. until lisp(dv)=0;
  430. newpllist:=cons({td,xd}, newpllist);
  431. >>;
  432. return reverse newpllist
  433. end$ % simppl
  434. %-------------
  435. symbolic operator fdepterms$
  436. symbolic procedure fdepterms(td,f)$
  437. % fdepterms regards td as a fraction where f occurs only in the
  438. % numerator. It determines all terms of the numerator in
  439. % which f occurs divided through the denominator.
  440. begin
  441. scalar nu,de,e1,sm;
  442. td:=reval td;
  443. if pairp td then
  444. if car td='QUOTIENT then <<nu:=cadr td;de:=caddr td>>;
  445. if null nu then nu:=td;
  446. if not pairp nu then if freeof(nu,f) then sm:=0
  447. else sm:=nu
  448. else <<
  449. if car nu = 'PLUS then nu:=cdr nu
  450. else nu:=list nu;
  451. for each e1 in nu do
  452. if not freeof(e1,f) then sm:=cons(e1,sm);
  453. if null sm then sm:=0 else
  454. if length sm = 1 then sm:=car sm
  455. else sm:=cons('PLUS,sm)
  456. >>;
  457. if de then sm:=list('QUOTIENT,sm,de);
  458. return sm
  459. end$ % of fdepterms
  460. %-------------
  461. symbolic procedure subtract_diff(d1,d2)$
  462. % assumes d1,d2 to be equally long lists of numbers (at least one)
  463. % that are orders of derivatives (which may be 0),
  464. % These lists ca be produced using the procedure maxderivs(),
  465. % returns nil if any number in d2 is bigger than the corresponding
  466. % number in d1, returns list of differences otherwise
  467. begin scalar d;
  468. return
  469. if car d2 > car d1 then nil else
  470. if null cdr d1 then {car d1 - car d2} else
  471. if d:=subtract_diff(cdr d1,cdr d2) then cons(car d1 - car d2,d)
  472. else nil
  473. end$
  474. %-------------
  475. symbolic procedure transfer_fctrs(h,flist)$
  476. begin scalar fctrs;
  477. %algebraic write"begin: caar h=",lisp caar h," cdar h =",lisp cdar h;
  478. if (pairp cdar h) and (cadar h='MINUS) then
  479. rplaca(h,cons(reval {'MINUS,caar h},cadr cdar h));
  480. if (pairp cdar h) and (cadar h='TIMES) then
  481. for each fc in cddar h do
  482. if freeoflist(fc,flist) then fctrs:=cons(fc,fctrs);
  483. if fctrs then <<
  484. if cdr fctrs then fctrs:=cons('TIMES,fctrs)
  485. else fctrs:=car fctrs;
  486. rplaca(h,cons(reval {'TIMES ,caar h,fctrs},
  487. reval {'QUOTIENT,cdar h,fctrs} ))
  488. >>
  489. %;algebraic write"end: caar h=",lisp caar h," cdar h =",lisp cdar h;
  490. end$
  491. %-------------
  492. symbolic operator partintdf$
  493. symbolic procedure partintdf(eqlist,qlist,plist,xlist,flist,jlist,sb)$
  494. % eqlist ... list of equations
  495. % qlist ... list of characteristic functions
  496. % plist ... list of components of conserved current
  497. % xlist ... list of independent variables
  498. % flist ... list of the arbitrary function occuring in this conservation law
  499. % jlist ... list of all jet-variables
  500. % eqlist and qlist are in order.
  501. % plist and xlist are in order.
  502. % The aim is to remove all derivatives of f in the conservation law
  503. % At first terms with derivatives of f in qlist are partially integrated.
  504. % Then terms with derivatives of f in plist are partially integrated.
  505. begin scalar f,n,d,deltali,subli,lhs,rhs,cof,x,y,cpy,newpl,lowd,su,vle,
  506. idty,idtysep,sbrev,dno,lsb,h0,h1,h2,h3,h4,h5,h6,h7,ldh1,ldh2,
  507. reductions_to_do,ld1,ld2,h0_changed;
  508. % 0. check that plist is homogeneous in flist
  509. algebraic <<
  510. cpy:=plist$
  511. for each f in flist do cpy:=sub(f=0,cpy)$
  512. while (cpy neq {}) and (first cpy = 0) do cpy:=rest cpy$
  513. >>$
  514. if cpy neq {'LIST} then return nil$
  515. eqlist:=cdr eqlist$
  516. qlist :=cdr qlist$
  517. plist :=cdr plist$
  518. xlist :=cdr xlist$
  519. flist :=cdr flist$
  520. jlist :=cdr jlist$
  521. % 0. check that flist functions do only depend on xlist variables
  522. d:=t;
  523. for each f in flist do
  524. if not_included(fctargs f,xlist) then d:=nil$
  525. if null d then return nil$
  526. terpri()$
  527. write"An attempt to factor out linear differential operators:"$terpri()$
  528. n:=0;
  529. while eqlist do <<
  530. n:=add1 n;
  531. su:=print_;print_:=nil;
  532. d:=newfct('eq_,xlist,n);
  533. print_:=su;
  534. deltali:=cons(d,deltali);
  535. algebraic write d,":=",lisp car eqlist$
  536. subli:=cons({'EQUAL,d,car eqlist},subli)$
  537. lhs:=cons({'TIMES,car qlist,d % car eqlist
  538. },lhs);
  539. eqlist:=cdr eqlist;
  540. qlist:=cdr qlist
  541. >>;
  542. lhs:=reval cons('PLUS,lhs)$
  543. subli:=cons('LIST,subli)$
  544. for each f in flist do <<
  545. f:=reval f$
  546. % removing f-derivatives from the lhs
  547. repeat <<
  548. d:=car ldiffp(lhs,f)$ % liefert Liste der Variablen + Ordnungen mit Potenz
  549. if d then <<
  550. % correcting plist
  551. cpy:=d;
  552. while cpy and ((numberp car cpy) or freeof(xlist,car cpy)) do cpy:=cdr cpy;
  553. if null cpy then d:=nil
  554. else <<
  555. cof:=coeffn(lhs,cons('DF,cons(f,d)),1);
  556. lhs:=reval {'DIFFERENCE,lhs,cons('DF,cons({'TIMES,cof,f},d))}$
  557. x:=car cpy;
  558. lowd:=lower_deg(d,x)$ % the derivative d reduced by one
  559. su:=if lowd then cons('DF,cons({'TIMES,cof,f},lowd))
  560. else {'TIMES,cof,f}$
  561. cpy:=xlist;
  562. newpl:=nil;
  563. while cpy and (x neq car cpy) do <<
  564. newpl:=cons(car plist,newpl);
  565. plist:=cdr plist;
  566. cpy:=cdr cpy
  567. >>;
  568. plist:=cons({'DIFFERENCE,car plist,su},cdr plist);
  569. while newpl do <<
  570. plist:=cons(car newpl,plist)$
  571. newpl:=cdr newpl
  572. >>
  573. >>
  574. >>
  575. >> until null d; % until no derivative of f occurs
  576. plist:=cdr algebraic(sub(subli,lisp cons('LIST,plist)))$
  577. % Now we add trivial conservation laws in order to get rid of
  578. % derivatives of f in the conserved current
  579. repeat <<
  580. newpl:=nil;
  581. cpy:=xlist;
  582. while plist and null(d:=car ldiffp(car plist,f)) do <<
  583. newpl:=cons(car plist,newpl);
  584. plist:=cdr plist;
  585. cpy:=cdr cpy
  586. >>;
  587. if d and (car d neq car cpy) then << % otherwise infinte loop
  588. cof:=coeffn(car plist,cons('DF,cons(f,d)),1);
  589. x:=car d;
  590. lowd:=lower_deg(d,x)$ % the derivative d reduced by one
  591. su:=if lowd then {'TIMES,cof,cons('DF,cons(f,lowd))}
  592. else {'TIMES,cof, f }$
  593. plist:=cons(reval reval {'DIFFERENCE,car plist,{'DF,su,x}},cdr plist);
  594. while newpl do <<
  595. plist:=cons(car newpl,plist)$
  596. newpl:=cdr newpl
  597. >>$
  598. % adding the correction to the other component of plist
  599. y:=car cpy;
  600. cpy:=xlist;
  601. while x neq car cpy do <<
  602. newpl:=cons(car plist,newpl);
  603. plist:=cdr plist;
  604. cpy:=cdr cpy
  605. >>$
  606. plist:=cons(reval reval {'PLUS,car plist,{'DF,su,y}},cdr plist);
  607. while newpl do <<
  608. plist:=cons(car newpl,plist)$
  609. newpl:=cdr newpl
  610. >>
  611. >> else <<d:=nil;plist:=append(reverse newpl,plist)>>
  612. >> until null d;
  613. >>;
  614. vle:=length xlist;
  615. newpl:=algebraic absorbconst(lisp cons('LIST,append(qlist,plist)),
  616. cons('LIST,flist))$
  617. if newpl then newpl:=cdadr newpl;
  618. % Now factorizing out a linear differential operator
  619. % 2. extend dependencies of functions from flist and add extra conditions
  620. for each f in flist do <<
  621. depl!*:=delete(assoc(f,depl!*),depl!*);
  622. depl!*:=cons(cons(f,xlist),depl!*);
  623. >>$
  624. % 3. compute coefficients of the conditions in the identity
  625. idty:=algebraic(sub(subli,lhs))$
  626. for n:=1:vle do
  627. if not zerop nth(plist,n) then
  628. idty:={'DIFFERENCE,idty,{'DF,nth(plist,n),nth(xlist,n)}}$
  629. % 4. separate idty into conditions with multiplicities
  630. sbrev:=cons('LIST,for each d in cdr sb collect {'EQUAL,caddr d,cadr d})$
  631. idty:=reval reval idty$
  632. dno:=algebraic den idty;
  633. if dno neq 1 then idty:=algebraic num idty$
  634. idty:=algebraic(sub(sbrev,idty))$
  635. su:=print_;print_:=nil;
  636. idtysep:=separ(reval idty,flist,jlist,nil)$
  637. print_:=su;
  638. idtysep:=for each d in idtysep collect
  639. cons(algebraic(sub(sb,lisp car d)),cdr d);
  640. % 5. integrations of cdr of the elements of idty have to be done:
  641. % - sufficiently often so that there are not more conditions
  642. % than functions in flist
  643. % - as few as possible to have factored out afterall an as
  644. % high as possible operator
  645. reductions_to_do:=length idtysep - length flist;
  646. if reductions_to_do>0 then <<
  647. h0:=idtysep;
  648. while h0 do <<
  649. rplaca(h0,cons(reval caar h0, reval cdar h0));
  650. transfer_fctrs(h0,flist); h0:=cdr h0
  651. >>$
  652. %write"Separation gives:"$terpri()$
  653. %for each d in idtysep do
  654. %algebraic write "0 = (",lisp car d,") * (",lisp cdr d,")"$
  655. h0:=idtysep;
  656. repeat << % check whether cdar h0 is a derivative of another condition
  657. h0_changed:=nil;
  658. h1:=cdar h0;
  659. %algebraic write"caar h0=",lisp caar h0," cdar h0 =",lisp cdar h0;
  660. % find a function appearing in h1 and its leading derivative
  661. cpy:=flist;
  662. while cpy and freeof(h1,car cpy) do cpy:=cdr cpy;
  663. % if null cpy then error!
  664. ld1:=car ldiffp(h1,car cpy)$
  665. ldh1:=maxderivs(nil,ld1,xlist)$
  666. ld1:=if null ld1 then car cpy
  667. else cons('DF,cons(car cpy,ld1))$
  668. h2:=idtysep;
  669. while h2 do
  670. % is h1 a derivative of car h2 or car h2 a derivative of h1?
  671. if (h2 eq h0) or freeof(cdar h2,car cpy) then h2:=cdr h2
  672. else <<
  673. %algebraic write"caar h2=",lisp caar h2," cdar h2 =",lisp cdar h2;
  674. ld2:=car ldiffp(cdar h2,car cpy)$
  675. ldh2:=maxderivs(nil,ld2,xlist)$
  676. ld2:=if null ld2 then car cpy
  677. else cons('DF,cons(car cpy,ld2))$
  678. % is h1 a derivative of car h2?
  679. h3:=subtract_diff(ldh1,ldh2);
  680. if null h3 then h2:=cdr h2
  681. else <<
  682. % the leading derivative in h1 is a derivative of
  683. % the leading derivative in cdar h2
  684. h4:=cdar h2;
  685. %write"h4=",h4;terpri()$
  686. if pairp h4 and (car h4 = 'PLUS) then <<
  687. for n:=1:vle do if not zerop nth(h3,n) then
  688. h4:={'DF,h4,nth(xlist,n),nth(h3,n)};
  689. if null freeoflist(h5:=algebraic(h1/h4),flist) then h2:=cdr h2
  690. else <<
  691. % h1 = h5 * derivative of (cdar h2)
  692. h6:={'TIMES,caar h0,reval h5};
  693. for n:=1:vle do <<
  694. h7:=nth(h3,n);
  695. if not zerop h7 then
  696. h6:={'TIMES,{'EXPT,-1,h7},{'DF,h6,nth(xlist,n),h7}};
  697. >>;
  698. rplaca(h2,cons(reval {'PLUS,caar h2,h6},cdar h2));
  699. rplaca(h0,cons(0,0));
  700. %algebraic write"Change(1):"$
  701. %algebraic write"caar h2=",lisp caar h2," cdar h2 =",lisp cdar h2;
  702. %algebraic write"caar h0=",lisp caar h0," cdar h0 =",lisp cdar h0;
  703. reductions_to_do:=sub1 reductions_to_do;
  704. h2:=nil
  705. >>
  706. >> else <<
  707. % Update of car h2
  708. h6:=algebraic(lisp(caar h0)*coeffn(h1,ld1,1));
  709. for n:=1:vle do <<
  710. h7:=nth(h3,n);
  711. if not zerop h7 then
  712. h6:={'TIMES,{'EXPT,-1,h7},{'DF,h6,nth(xlist,n),h7}};
  713. >>;
  714. rplaca(h2,cons(reval {'PLUS,caar h2,h6},cdar h2));
  715. %;algebraic write"Change(2):"$
  716. %algebraic write"caar h2=",lisp caar h2," cdar h2 =",lisp cdar h2;
  717. % Update of car h0
  718. h1:=reval {'DIFFERENCE,h1,{'TIMES,coeffn(h1,ld1,1),ld1}}$
  719. if zerop h1 then <<rplaca(h0,cons(0,0));h2:=nil;
  720. reductions_to_do:=sub1 reductions_to_do;>>
  721. else <<rplaca(h0,cons(caar h0,h1));
  722. transfer_fctrs(h0,flist);
  723. h1:=cdar h0;
  724. cpy:=flist;
  725. while cpy and freeof(h1,car cpy) do cpy:=cdr cpy;
  726. ld1:=car ldiffp(h1,car cpy)$
  727. ldh1:=maxderivs(nil,ld1,xlist)$
  728. ld1:=if null ld1 then car cpy
  729. else cons('DF,cons(car cpy,ld1))$
  730. h2:=cdr h2;h0_changed:=t>>
  731. %;algebraic write"caar h0=",lisp caar h0," cdar h0 =",lisp cdar h0;
  732. >>
  733. >>
  734. >>;
  735. if (null h0_changed) or (zerop caar h0) then h0:=cdr h0
  736. >> until (reductions_to_do=0) or (null h0);
  737. %write"After correction the separation gives:"$terpri()$
  738. %for each d in idtysep do
  739. %if not zerop car d then
  740. %algebraic write "0 = (",lisp car d,") * (",lisp cdr d,")"$
  741. >>$
  742. % Now the number of f in flist should be equal the number of conditions
  743. % or as low as possible
  744. n:=0;
  745. rhs:=nil;
  746. for each d in idtysep do
  747. if not zerop car d then << % for each condition
  748. n:=add1 n;
  749. su:=print_;print_:=nil;
  750. x:=newfct('l_,xlist,n);
  751. print_:=su;
  752. su:=if dno=1 then car d
  753. else reval {'QUOTIENT,car d,dno}$
  754. algebraic write x,":=",su$
  755. lsb:=cons({'EQUAL,x,su},lsb);
  756. % 5. for each condition integrate all terms
  757. y:=cdr d;
  758. cpy:=flist;
  759. while y and not zerop y do <<
  760. repeat <<
  761. d:=ldiffp(y,car cpy)$
  762. if zerop cdr d then
  763. if null cpy then <<write"The backintegration is faulty."$terpri()>>
  764. else cpy:=cdr cpy
  765. >> until not zerop cdr d;
  766. if car d = nil then <<
  767. cof:=coeffn(y,car cpy,1);
  768. rhs:={'PLUS,{'TIMES,x,cof,car cpy},rhs};
  769. y:=reval reval {'DIFFERENCE,y,{'TIMES,cof,car cpy}}
  770. >> else <<
  771. cof:=coeffn(y,cons('DF,cons(car cpy,car d)),1);
  772. rhs:=reval {'PLUS,rhs,{'TIMES,cons('DF,cons({'TIMES,x,cof},car d)),
  773. car cpy,{'EXPT,{'MINUS,1},absdeg(car d)}}};
  774. y:=reval reval {'DIFFERENCE,y,{'TIMES,cof,cons('DF,cons(car cpy,car d))}}
  775. >>
  776. >>
  777. >>$
  778. lsb:=cons('LIST,lsb)$
  779. flist:=cons('LIST,flist)$
  780. algebraic <<
  781. d:=gcd(den lhs,den rhs);
  782. lhs:=lhs*d; rhs:=rhs*d;
  783. %--- Correctness test
  784. d:=sub(subli,lhs)-sub(lsb,rhs);
  785. if d neq 0 then write "Not identically zero : ",d$
  786. for each f in flist do algebraic <<
  787. x:=coeffn(num lhs,f,1); y:=coeffn(num rhs,f,1);
  788. d:=gcd(x,y);
  789. algebraic write x/d/den lhs," = ",y/d/den rhs$
  790. >>
  791. >>$
  792. end$
  793. %-------------
  794. end$