crutil.red 130 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114
  1. %********************************************************************
  2. module utilities$
  3. %********************************************************************
  4. % Routines for finding leading derivatives and others
  5. % Author: Andreas Brand 1990 1994
  6. % Thomas Wolf since 1994
  7. %%%%%%%%%%%%%%%%%%%%%%%%%
  8. % properties of pde's %
  9. %%%%%%%%%%%%%%%%%%%%%%%%%
  10. symbolic procedure drop_dec_with(de1,de2,rl)$
  11. % drop de1 from the 'dec_with or 'dec_with_rl list of de2
  12. % currently for all orderings
  13. begin scalar a,b,c$
  14. a:=if rl then get(de2,'dec_with_rl)
  15. else get(de2,'dec_with)$
  16. for each b in a do << % for each ordering b
  17. b:=delete(de1,b);
  18. if length b>1 then c:=cons(b,c);
  19. >>;
  20. if rl then put(de2,'dec_with_rl,c)
  21. else put(de2,'dec_with ,c)
  22. end$
  23. symbolic procedure add_dec_with(ordering,de1,de2,rl)$
  24. % add (ordering de1) to 'dec_with or 'dec_with_rl of de2
  25. begin scalar a,b$
  26. a:=if rl then get(de2,'dec_with_rl)
  27. else get(de2,'dec_with)$
  28. b:=assoc(ordering,a)$
  29. a:=delete(b,a)$
  30. if b then b:=cons(ordering,cons(de1,cdr b))
  31. else b:=list(ordering,de1)$
  32. if rl then put(de2,'dec_with_rl,cons(b,a))
  33. else put(de2,'dec_with ,cons(b,a))$
  34. end$
  35. symbolic procedure add_both_dec_with(ordering,de1,de2,rl)$
  36. % add (ordering de1) to 'dec_with or 'dec_with_rl of de2 and
  37. % add (ordering de2) to 'dec_with or 'dec_with_rl of de1
  38. begin
  39. add_dec_with(ordering,de1,de2,rl)$
  40. add_dec_with(ordering,de2,de1,rl)$
  41. end$
  42. symbolic procedure drop_rl_with(de1,de2)$
  43. % drop de1 from the 'rl_with list of de2
  44. put(de2,'rl_with,delete(de1,get(de2,'rl_with)))$
  45. symbolic procedure add_rl_with(de1,de2)$
  46. % add de1 to 'rl_with of de2 and vice versa
  47. <<put(de2,'rl_with,cons(de1,get(de2,'rl_with)))$
  48. put(de1,'rl_with,cons(de2,get(de1,'rl_with)))>>$
  49. symbolic procedure prevent_simp(v,de1,de2)$
  50. % it is df(de1,v) = de2
  51. % add dec_with such that de2
  52. % will not be simplified to 0=0
  53. begin scalar a,b$
  54. % a:=get(de1,'fcts)$
  55. a:=list(0); % all orderings for which de1 is used (-->ord)
  56. for each b in a do if member(v,fctargs(b)) then
  57. <<add_dec_with(b,de2,de1,nil);add_dec_with(b,de2,de1,t)>>;
  58. % a:=get(de2,'fcts)$
  59. a:=list(0); % all orderings for which de2 is used (-->ord)
  60. for each b in a do if member(v,fctargs(b)) then
  61. <<add_dec_with(b,de1,de2,nil);add_dec_with(b,de1,de2,t)>>;
  62. end$
  63. symbolic procedure termread$
  64. begin scalar val, !*echo; % Don't re-echo tty input
  65. if not null old_history then <<
  66. val:=car old_history$
  67. if print_ then <<write"old input: ",val$terpri()>>$
  68. old_history:=cdr old_history
  69. >> else <<
  70. rds nil; wrs nil$ % Switch I/O to terminal
  71. val := read()$
  72. if ifl!* then rds cadr ifl!*$ % Resets I/O streams
  73. if ofl!* then wrs cdr ofl!*$
  74. >>$
  75. history_:=cons(val,history_)$
  76. return val
  77. end$
  78. symbolic procedure termxread$
  79. begin scalar val, !*echo; % Don't re-echo tty input
  80. if not null old_history then <<
  81. val:=car old_history$
  82. if print_ then <<write"old input: ",val$terpri()>>$
  83. old_history:=cdr old_history
  84. >> else <<
  85. rds nil; wrs nil$ % Switch I/O to terminal
  86. val := xread(nil)$
  87. if ifl!* then rds cadr ifl!*$ % Resets I/O streams
  88. if ofl!* then wrs cdr ofl!*$
  89. >>$
  90. % history_:=cons(compress(append(explode val,list('$))),history_)$
  91. history_:=cons(val,history_)$
  92. return val
  93. end$
  94. symbolic procedure termlistread()$
  95. begin scalar l;
  96. l:=termxread()$
  97. if (not null l) and
  98. ((atom l) or
  99. (pairp l and (car l neq '!*comma!*)))
  100. then l:=list('!*comma!*,l);
  101. if l and ((not pairp l) or (car l neq '!*comma!*)) then
  102. <<terpri()$write"Error: not a legal list of elements.";terpri()$
  103. l:=nil>>
  104. else if pairp l then l:=cdr l; % dropping '!*comma!*
  105. return l
  106. end$
  107. symbolic procedure mkeqlist(vallist,ftem,vl,flaglist,simp_flag,orderl,pdes)$
  108. % make a list of equations
  109. % vallist: list of expressions
  110. % ftem: list of functions
  111. % vl: list of variables
  112. % flaglist: list of flags
  113. % orderl: list of orderings where the equations are valid
  114. % pdes: list of all equations by name to update inequalities
  115. % within update()
  116. begin scalar l1$
  117. for each a in vallist do
  118. l1:=eqinsert(mkeq(a,ftem,vl,flaglist,simp_flag,orderl,
  119. nil,append(l1,pdes)),l1)$
  120. return l1
  121. end$
  122. symbolic procedure mkeq(val,ftem,vl,flaglist,simp_flag,orderl,hist,pdes)$
  123. % make a new equation
  124. % val: expression
  125. % ftem: list of functions
  126. % vl: list of variables
  127. % flaglist: list of flags
  128. % orderl: list of orderings where the equation is valid
  129. % hist: the history of val
  130. % pdes: list of all equations by name to update inequalities
  131. % within update()
  132. % If the new equation to be made is only to exist temporarily then
  133. % call mkeq with pdes=nil to avoid lasting effects of the temprary pde.
  134. %
  135. begin scalar s$
  136. s:=new_pde()$
  137. if record_hist and hist then put(s,'histry_,reval hist)$
  138. for each a in flaglist do flag1(s,a)$
  139. if not update(s,val,ftem,vl,simp_flag,orderl,pdes) then
  140. <<drop_pde(s,nil,nil)$
  141. s:=nil>>$
  142. if record_hist and null hist and s then put(s,'histry_,s)$
  143. return s
  144. end$
  145. symbolic procedure no_of_derivs(equ)$
  146. begin scalar h,dl;
  147. h:=0;
  148. dl:=get(equ,'derivs);
  149. while dl do <<
  150. if (pairp caar dl) and (cdaar dl) then h:=add1 h;
  151. dl:=cdr dl
  152. >>;
  153. return h
  154. end$
  155. symbolic procedure update(equ,val,ftem,vl,simp_flag,orderl,pdes)$
  156. % update the properties of a pde
  157. % equ: pde
  158. % val: expression
  159. % ftem: list of functions
  160. % vl: list of variables
  161. % orderl: list of orderings where the equation is valid
  162. % pdes: to call addineq at end
  163. % *** important ***:
  164. % call afterwards also drop_pde_from_idties(p,pdes,pval) and
  165. % drop_pde_from_properties()
  166. % if this is now a new equation
  167. begin scalar l$
  168. if val and not zerop val then <<
  169. %ftem:=reverse union(smemberl(ftem,val),nil)$
  170. ftem:=sort_according_to(smemberl(ftem,val),ftem_)$
  171. put(equ,'terms,no_of_terms(val))$
  172. if simp_flag then <<
  173. % the following test to avoid factorizing big equations
  174. val:=% if get(equ,'terms)>max_factor then simplifypde(val,ftem,nil,equ)
  175. % else
  176. simplifypde(val,ftem,t,equ)$
  177. if val and not zerop val then <<
  178. ftem:=reverse union(smemberl(ftem,val),nil)$
  179. put(equ,'terms,no_of_terms(val))$
  180. >>
  181. >>$
  182. >>$
  183. depl!*:=delete(assoc(reval equ,depl!*),depl!*)$
  184. if val and not zerop val then <<
  185. put(equ,'val,val)$
  186. put(equ,'fcts,ftem)$
  187. for each v in vl do
  188. if not my_freeof(val,v) then l:=cons(v,l)$
  189. vl:=sort_according_to(l,vl_);
  190. put(equ,'vars,vl)$
  191. if vl then
  192. depl!*:=cons(cons(equ,vl),depl!*)$ % needed in expressions in idnties_
  193. put(equ,'nvars,length vl)$
  194. put(equ,'level,level_)$
  195. put(equ,'derivs,sort_derivs(all_deriv_search(val,ftem),ftem,vl))$
  196. if struc_eqn then put(equ,'no_derivs,no_of_derivs(equ));
  197. put(equ,'fcteval_lin,nil)$
  198. put(equ,'fcteval_nca,nil)$
  199. put(equ,'fcteval_nli,nil)$
  200. put(equ,'fct_nli_lin,nil)$
  201. put(equ,'fct_nli_nca,nil)$
  202. put(equ,'fct_nli_nli,nil)$
  203. put(equ,'fct_nli_nus,nil)$
  204. % put(equ,'terms,no_of_terms(val))$
  205. put(equ,'length,pdeweight(val,ftem))$
  206. put(equ,'printlength,delength val)$
  207. put(equ,'rational,nil)$
  208. put(equ,'nonrational,nil)$
  209. put(equ,'allvarfcts,nil)$
  210. put(equ,'orderings,orderl)$ % Orderings !
  211. for each f in reverse ftem do
  212. if rationalp(val,f) then
  213. <<put(equ,'rational,cons(f,get(equ,'rational)))$
  214. if fctlength f=get(equ,'nvars) then
  215. put(equ,'allvarfcts,cons(f,get(equ,'allvarfcts)))>>
  216. else put(equ,'nonrational,cons(f,get(equ,'nonrational)))$
  217. % put(equ,'degrees, % too expensive
  218. % if linear_pr then cons(1,for each l in get(equ,'rational)
  219. % collect (l . 1))
  220. % else fct_degrees(val,get(equ,'rational)) )$
  221. put(equ,'partitioned,nil)$
  222. put(equ,'starde,stardep(ftem,vl))$
  223. flag1(equ,'to_eval)$
  224. if (l:=get(equ,'starde)) then
  225. <<%remflag1(equ,'to_eval)$
  226. remflag1(equ,'to_int)$
  227. remflag1(equ,'to_fullint)$
  228. if simp_flag and (zerop cdr l) then flag1(equ,'to_sep)$
  229. % remflag1(equ,'to_diff)
  230. >>
  231. else remflag1(equ,'to_gensep)$
  232. if get(equ,'starde) and
  233. (zerop cdr get(equ,'starde) ) % or (get(equ,'length)<=gensep_))
  234. then
  235. else remflag1(equ,'to_sep)$
  236. if get(equ,'nonrational) then
  237. <<%remflag1(equ,'to_decoup)$
  238. if not freeoflist(get(equ,'allvarfcts),get(equ,'nonrational)) then
  239. remflag1(equ,'to_eval)>>$
  240. % if not get(equ,'allvarfcts) then remflag1(equ,'to_eval)$
  241. if (not get(equ,'rational)) or
  242. ((l:=get(equ,'starde)) and (cdr l = 0)) then remflag1(equ,'to_eval)$
  243. if homogen_ then <<
  244. l:=cdr algebraic find_hom_deg(lisp val);
  245. put(equ,'hom_deg,l)$
  246. % if car l=1 then << % i.e. linear in flin_
  247. % l:=get(equ,'derivs);
  248. % while l and (null linf or (length linf < 3)) do <<
  249. % if not freeoflist(car l,flin_) then <<
  250. % linf:=cons(car l,linf);
  251. % if member(car l,ineq_) then fd1:=car l
  252. % >>;
  253. % l:=cdr l
  254. % >>;
  255. % if linf and (length linf = 2) and fd1 then <<<<
  256. % if NON-ZERO(coeffn(get(equ,'val),fd1,1)) then <<
  257. % fd2:=car delete(fd1,linf);
  258. % braucht pdes, was nicht vorhanden ist
  259. % addineq(pdes,fd2);
  260. % addineq(pdes,coeffn(get(equ,'val),fd2,1))
  261. % >>
  262. % >>
  263. % >>
  264. >>$
  265. put(equ,'split_test,nil)$
  266. put(equ,'linear_,if lin_problem then t
  267. else lin_check(val,ftem))$
  268. new_ineq_from_pde(equ,pdes);
  269. return equ
  270. >>
  271. end$
  272. symbolic procedure new_ineq_from_pde(equ,pdes)$
  273. % currently only effective for equations with 2 terms
  274. % If one term of the equation is non-zero then the sum of the
  275. % remaining terms has to be non-zero too
  276. if pdes and null lin_problem and (get(equ,'terms)=2) % >1)
  277. then begin scalar valu;
  278. valu:=get(equ,'val);
  279. if not (pairp valu and (car valu='PLUS)) then valu:=reval valu;
  280. if not (pairp valu and (car valu='PLUS)) then write"err in update"
  281. else
  282. % for each l in cdr valu do
  283. % if null may_vanish l then addineq(pdes,reval{'DIFFERENCE,valu,l})
  284. if null may_vanish cadr valu then addineq(pdes,caddr valu) else
  285. if null may_vanish caddr valu then addineq(pdes,cadr valu)
  286. end$
  287. symbolic procedure fct_degrees(pv,ftem)$
  288. % ftem are to be the rational functions
  289. begin
  290. scalar f,l,ll,h,degs$
  291. if den pv then pv:=num pv$
  292. for each f in ftem do <<
  293. l:=gensym()$
  294. ll:=cons((f . l),ll)$
  295. pv:=subst({'TIMES,l,f},f,pv)$
  296. >>$
  297. pv:=reval pv$
  298. for each l in ll do <<
  299. degs:=cons((car l . deg(pv,cdr l)),degs)$
  300. >>;
  301. h:=cdar ll$
  302. for each l in cdr ll do pv:=subst(h,cdr l,pv)$
  303. pv:=reval pv$
  304. return cons(deg(pv,h),degs)
  305. end$
  306. symbolic procedure pde_degree(pv,ftem)$
  307. % ftem are to be the rational functions
  308. begin
  309. scalar f,h$
  310. if den pv neq 1 then pv:=num pv$
  311. h:=gensym()$
  312. for each f in ftem do pv:=subst({'TIMES,h,f},f,pv)$
  313. pv:=reval pv$
  314. return deg(pv,h)
  315. end$
  316. symbolic procedure dfsubst_update(f,der,equ)$
  317. % miniml update of some properties of a pde
  318. % equ: pde
  319. % der: derivative
  320. % f: f new function
  321. begin scalar l$
  322. for each d in get(equ,'derivs) do
  323. if not member(cadr der,car d) then l:=cons(d,l)
  324. else
  325. <<l:=cons(cons(cons(f,df_int(cdar d,cddr der)),cdr d),l)$
  326. put(equ,'val,
  327. subst(reval cons('DF,caar l),reval cons('DF,car d),
  328. get(equ,'val)))>>$
  329. put(equ,'fcts,subst(f,cadr der,get(equ,'fcts)))$
  330. put(equ,'allvarfcts,subst(f,cadr der,get(equ,'allvarfcts)))$
  331. if get(equ,'allvarfcts) then flag(list equ,'to_eval)$
  332. % This would reactivate equations which resulted due to
  333. % substitution of derivative by a function.
  334. % 8.March 98: change again: the line 3 lines above has been reactivated
  335. put(equ,'rational,subst(f,cadr der,get(equ,'rational)))$
  336. put(equ,'nonrational,subst(f,cadr der,get(equ,'nonrational)))$
  337. put(equ,'derivs,sort_derivs(l,get(equ,'fcts),get(equ,'vars)))$
  338. return equ
  339. end$
  340. symbolic procedure eqinsert(s,l)$
  341. % l is a sorted list
  342. if not (s or get(s,'val)) or zerop get(s,'length) or member(s,l) then l
  343. else if not l then list s
  344. else begin scalar l1,n$
  345. l1:=proddel(s,l)$
  346. if car l1 then
  347. <<n:=get(s,'length)$
  348. l:=cadr l1$
  349. l1:=nil$
  350. while l and (n>get(car l,'length)) do
  351. <<l1:=cons(car l,l1)$
  352. l:=cdr l>>$
  353. l1:=append(reverse l1,cons(s,l))$
  354. >>
  355. else if l1 then l1:=cadr l1 % or reverse of it
  356. else l1:=l$
  357. return l1$
  358. end$
  359. symbolic procedure not_included(a,b)$
  360. % meaning: not_all_a_in_b = setdiff(a,b)
  361. % Are all elements of a also in b? If yes then return nil else t
  362. % This could be done with setdiff(a,b), only setdiff
  363. % copies expressions and needs extra memory whereas here we only
  364. % want to know one bit (included or not)
  365. begin scalar c$
  366. c:=t;
  367. while a and c do <<
  368. c:=b;
  369. while c and ((car a) neq (car c)) do c:=cdr c;
  370. % if c=nil then car a is not in b
  371. a:=cdr a;
  372. >>;
  373. return if c then nil
  374. else t
  375. end$
  376. symbolic procedure proddel(s,l)$
  377. % delete all pdes from l with s as factor
  378. % delete s if it is a consequence of any known pde from l
  379. begin scalar l1,l2,l3,n,lnew,pdes,s_hist$
  380. if pairp(lnew:=get(s,'val)) and (car lnew='TIMES) then lnew:=cdr lnew
  381. else lnew:=list lnew$
  382. n:=length lnew$
  383. pdes:=l$
  384. while l do <<
  385. if pairp(l1:=get(car l,'val)) and (car l1='TIMES) then l1:=cdr l1
  386. else l1:=list l1$
  387. if n<length l1 then % s has less factors than car l
  388. if not_included(lnew,l1) then
  389. l2:=cons(car l,l2) % car l is not a consequ. of s
  390. else
  391. <<l3:=cons(car l,l3); % car l is a consequ. of s
  392. drop_pde(car l,nil,{'QUOTIENT,{'TIMES,s,get(car l,'val)},get(s,'val)})
  393. >>
  394. else <<
  395. if null not_included(l1,lnew) then % s is a consequence of car l
  396. <<if print_ then <<terpri()$write s," is a consequence of ",car l,".">>$
  397. % one could stop here but continuation can still be useful
  398. if null s_hist then s_hist:={'QUOTIENT,
  399. {'TIMES,car l,get(s,'val)},
  400. get(car l,'val) }$
  401. >>$
  402. % else
  403. if null l3 or (car l3 neq car l) then l2:=cons(car l,l2)$
  404. >>;
  405. l:=cdr l
  406. >>$
  407. if print_ and l3 then <<
  408. listprint l3$
  409. if cdr l3 then write " are consequences of ",s
  410. else write " is a consequence of ",s;
  411. terpri()$
  412. >>$
  413. if s_hist then <<drop_pde(s,nil,s_hist);s:=nil>>$
  414. return list(s,reverse l2)$
  415. end$
  416. symbolic procedure myprin2l(l,trenn)$
  417. if l then
  418. <<if pairp l then
  419. while l do
  420. <<write car l$
  421. l:=cdr l$
  422. if l then write trenn>>
  423. else write l>>$
  424. symbolic procedure print_stars(s)$
  425. begin scalar b,star,pv$
  426. pv:=get(s,'val)$
  427. if (pairp pv) and (car pv='TIMES) then pv:=t else pv:=nil$
  428. star:=get(s,'starde)$
  429. if star or pv then <<
  430. write "("$
  431. if pv then write"#"$
  432. if star then for b:=1:(1+cdr star) do write"*"$
  433. write")"$
  434. >>$
  435. end$
  436. symbolic procedure typeeq(s)$
  437. % print equation
  438. if (null print_) or (get(s,'printlength)>print_) then begin scalar a,b$
  439. print_stars(s);
  440. write " ",(a:=get(s,'terms))," terms"$
  441. if a neq (b:=get(s,'length)) then write", ",b," factors"$
  442. write", with derivatives"$
  443. if get(s,'starde) then <<
  444. write": "$ terpri()$
  445. print_derivs(s,nil)$
  446. >> else <<
  447. write" of functions of all variables: "$ terpri()$
  448. print_derivs(s,t)$
  449. >>
  450. end else
  451. mathprint list('EQUAL,0,get(s,'val))$
  452. symbolic procedure print_derivs(p,allvarf)$
  453. begin scalar a,d,dl,avf;
  454. dl:=get(p,'derivs)$
  455. if allvarf then <<
  456. avf:=get(p,'allvarfcts);
  457. for each d in dl do
  458. if not freeoflist(d,avf) then a:=cons(d,a);
  459. dl:=reverse a
  460. >>$
  461. dl:=for each d in dl collect <<
  462. a:=if null cdar d then caar d
  463. else cons('DF,car d);
  464. if cdr d=1 then a else {'EXPT,a,cdr d}
  465. >>$
  466. mathprint cons('! ,dl)
  467. end$
  468. symbolic procedure typeeqlist(l)$
  469. % print equations and their property lists
  470. <<terpri()$
  471. for each s in l do
  472. <<terpri()$
  473. write s," : "$
  474. if not print_all then typeeq(s)
  475. else
  476. if (null print_) or (get(s,'printlength)>print_) then
  477. <<write get(s,'terms)," terms"$terpri()>> else
  478. mathprint list('EQUAL,0,get(s,'val))$
  479. if print_all then
  480. << write " derivs : "$
  481. terpri()$print_derivs(s,nil)$
  482. % if struc_eqn then <<
  483. % terpri()$write " no_derivs : ",get(s,'no_derivs)$
  484. % >>$
  485. write " terms : ",get(s,'terms)$
  486. terpri()$write " fcts : ",get(s,'fcts)$
  487. terpri()$write " vars : ",get(s,'vars)$
  488. terpri()$write " nvars : ",get(s,'nvars)$
  489. terpri()$write " length : ",get(s,'length)$
  490. terpri()$write " printlength: ",get(s,'printlength)$
  491. terpri()$write " level : ",get(s,'level)$
  492. terpri()$write " allvarfcts : ",get(s,'allvarfcts)$
  493. terpri()$write " rational : ",get(s,'rational)$
  494. terpri()$write " nonrational: ",get(s,'nonrational)$
  495. terpri()$write " degrees : ",get(s,'degrees)$
  496. terpri()$write " starde : ",get(s,'starde)$
  497. terpri()$write " fcteval_lin: ",get(s,'fcteval_lin)$
  498. terpri()$write " fcteval_nca: ",get(s,'fcteval_nca)$
  499. terpri()$write " fcteval_nli: ",get(s,'fcteval_nli)$
  500. terpri()$write " fct_nli_lin: ",get(s,'fct_nli_lin)$
  501. terpri()$write " fct_nli_nca: ",get(s,'fct_nli_nca)$
  502. terpri()$write " fct_nli_nli: ",get(s,'fct_nli_nli)$
  503. terpri()$write " fct_nli_nus: ",get(s,'fct_nli_nus)$
  504. terpri()$write " rl_with : ",get(s,'rl_with)$
  505. terpri()$write " dec_with : ",get(s,'dec_with)$
  506. terpri()$write " dec_with_rl: ",get(s,'dec_with_rl)$
  507. % terpri()$write " dec_info : ",get(s,'dec_info)$
  508. terpri()$write " to_int : ",flagp(s,'to_int)$
  509. terpri()$write " to_fullint : ",flagp(s,'to_fullint)$
  510. terpri()$write " to_sep : ",flagp(s,'to_sep)$
  511. terpri()$write " to_gensep : ",flagp(s,'to_gensep)$
  512. terpri()$write " to_decoup : ",flagp(s,'to_decoup)$
  513. terpri()$write " to_drop : ",flagp(s,'to_drop)$
  514. terpri()$write " to_eval : ",flagp(s,'to_eval)$
  515. terpri()$write " to_diff : ",flagp(s,'to_diff)$
  516. terpri()$write " to_under : ",flagp(s,'to_under)$
  517. terpri()$write " to_symbol : ",flagp(s,'to_symbol)$
  518. terpri()$write " not_to_eval: ",get(s,'not_to_eval)$
  519. terpri()$write " used_ : ",flagp(s,'used_)$
  520. terpri()$write " orderings : ",get(s,'orderings)$
  521. terpri()$write " histry_ : ",get(s,'histry_)$
  522. terpri()$write " partitioned: ",if get(s,'partitioned) then
  523. "not nil" else
  524. "nil"$
  525. terpri()$write " split_test : ",get(s,'split_test)$
  526. terpri()$write " linear_ : ",get(s,'linear_)$
  527. if homogen_ then <<
  528. terpri()$write " hom_deg : ",get(s,'hom_deg)
  529. >>$
  530. terpri()>>
  531. >> >>$
  532. symbolic procedure rationalp(p,f)$
  533. % tests if p is rational in f and its derivatives
  534. not pairp p
  535. or
  536. ((car p='QUOTIENT) and
  537. polyp(cadr p,f) and polyp(caddr p,f))
  538. or
  539. ((car p='EQUAL) and
  540. rationalp(cadr p,f) and rationalp(caddr p,f))
  541. or
  542. polyp(p,f)$
  543. symbolic procedure ratexp(p,ftem)$
  544. if null ftem then t
  545. else if rationalp(p,car ftem) then ratexp(p,cdr ftem)
  546. else nil$
  547. symbolic procedure polyp(p,f)$
  548. % tests if p is a polynomial in f and its derivatives
  549. % p: expression
  550. % f: function
  551. if my_freeof(p,f) then t
  552. else
  553. begin scalar a$
  554. if atom p then a:=t
  555. else
  556. if member(car p,list('EXPT,'PLUS,'MINUS,'TIMES,'QUOTIENT,'DF)) then
  557. % erlaubte Funktionen
  558. <<if (car p='PLUS) or (car p='TIMES) then
  559. <<p:=cdr p$
  560. while p do
  561. if a:=polyp(car p,f) then p:=cdr p
  562. else p:=nil>>
  563. else if (car p='MINUS) then
  564. a:=polyp(cadr p,f)
  565. else if (car p='QUOTIENT) then
  566. <<if freeof(caddr p,f) then a:=polyp(cadr p,f)>>
  567. else if car p='EXPT then % Exponent
  568. <<if (fixp caddr p) then
  569. if caddr p>0 then a:=polyp(cadr p,f)>>
  570. else if car p='DF then % Ableitung
  571. if (cadr p=f) or freeof(cadr p,f) then a:=t>>
  572. else a:=(p=f)$
  573. return a
  574. end$
  575. symbolic procedure starp(ft,n)$
  576. % yields T if all functions from ft have less than n arguments
  577. begin scalar b$
  578. while not b and ft do % searching a fct of all vars
  579. if fctlength car ft=n then b:=t
  580. else ft:=cdr ft$
  581. return not b
  582. end$
  583. symbolic procedure stardep(ftem,vl)$
  584. % yields: nil, if a function (from ftem) in p depends
  585. % on all variables (from vl)
  586. % cons(v,n) otherwise, with v being the list of variables
  587. % which occur in a minimal number of n functions
  588. begin scalar b,v,n$
  589. if starp(ftem,length vl) then
  590. <<n:=sub1 length ftem$
  591. while vl do % searching var.s on which depend a
  592. % minimal number of functions
  593. <<if n> (b:=for each h in ftem sum
  594. if member(car vl,fctargs h) then 1
  595. else 0)
  596. then <<n:=b$v:=list car vl>> % a new minimum
  597. else if b=n then v:=cons(car vl,v)$
  598. vl:=cdr vl>> >>$
  599. return if v then cons(v,n) % on each varible from v depend n
  600. % functions
  601. else nil
  602. end$
  603. %symbolic procedure no_of_sep_var(ftem)$
  604. %% assuming ftem are all functions from an ise
  605. %% How many are there indirectly separable variables?
  606. %% If just two then the new indirect separation is possible
  607. %begin scalar v,vs$
  608. % vl:=argset(ftem);
  609. % for each f in ftem do
  610. % vs:=union(setdiff(vl,fctargs f),vs)$
  611. % return vs
  612. %end$
  613. symbolic operator parti_fn$
  614. symbolic procedure parti_fn(fl,el)$
  615. % fl ... alg. list of functions, el ... alg. list of equations
  616. % partitions fl such that all functions that are somehow dependent on
  617. % each other through equations in el are grouped in lists,
  618. % returns alg. list of these lists
  619. begin
  620. scalar f1,f2,f3,f4,f5,e1,e2;
  621. fl:=cdr fl;
  622. el:=cdr el;
  623. while fl do <<
  624. f1:=nil; % f1 is the sublist of functions depending on each other
  625. f2:=list car fl; % f2 ... func.s to be added to f1, not yet checked
  626. fl:=cdr fl;
  627. while f2 and fl do <<
  628. f3:=car f2; f2:=cdr f2;
  629. f1:=cons(f3,f1);
  630. for each f4 in
  631. % smemberl will be all functions not registered yet that occur in
  632. % an equation in which the function f3 occurs
  633. smemberl(fl, % fl ... the remaining functions not known yet to depend
  634. <<e1:=nil; % equations in which f3 occurs
  635. for each e2 in el do
  636. if smember(f3,e2) then e1:=cons(e2,e1);
  637. e1
  638. >>
  639. ) do <<
  640. f2:=cons(f4,f2);
  641. fl:=delete(f4,fl)
  642. >>
  643. >>;
  644. if f2 then f1:=append(f1,f2);
  645. f5:=cons(cons('LIST,f1),f5)
  646. >>;
  647. return cons('LIST,f5)
  648. end$
  649. symbolic procedure plot_dependencies(pdes)$
  650. begin scalar ps,fl$
  651. ps:=promptstring!*$ promptstring!*:=""$
  652. fl:=ftem_;
  653. if flin_ and yesp
  654. "Shall only functions from the linear list flin_ be considered? "
  655. then fl:=setdiff(fl,setdiff(fl,flin_))$
  656. promptstring!*:=ps$
  657. plot_dep_matrix(pdes,fl)
  658. end$
  659. symbolic procedure plot_dep_matrix(pdes,allf)$
  660. begin scalar f,ml,lf,fl,h,lh,lc,n,m,h;
  661. terpri()$
  662. write "Horizontally: function names (each vertical), ",
  663. "Vertically: equation indices"$
  664. terpri()$
  665. ml:=0; % the maximal length of all variable names
  666. lf:=length allf$
  667. for each f in reverse allf do <<
  668. h:=explode f;
  669. lh:=length h;
  670. if lh>ml then ml:=lh;
  671. lc:=cons(h,lc);
  672. >>$
  673. % print the variable names
  674. for n:=1:ml do <<
  675. terpri()$ write" "$
  676. for m:=1:lf do write <<
  677. h:=nth(lc,m);
  678. if n>length h then " "
  679. else nth(nth(lc,m),n)
  680. >>
  681. >>$
  682. m:=add1 add1 ml;
  683. terpri()$terpri()$
  684. for each p in pdes do
  685. if m>=0 then <<
  686. h:=explode p;
  687. for n:=3:length h do write nth(h,n);
  688. for n:=(sub1 length(h)):5 do write" "$
  689. fl:=get(p,'fcts);
  690. if (not get(p,'fcteval_lin)) and
  691. (not get(p,'fcteval_nca)) and
  692. (not get(p,'fcteval_nli)) then fcteval(p,nil)$ % for writing "s"
  693. for each f in allf do
  694. if freeof(fl,f) then write" " else
  695. if solvable_case(p,f,'fcteval_lin) or
  696. solvable_case(p,f,'fcteval_nca) then write"s"
  697. else write"+"$
  698. terpri()$
  699. m:=add1 m$
  700. if m=23 then if not yesp "Continue ?" then m:=-1
  701. else m:=0
  702. >>$
  703. end$
  704. symbolic procedure solvable_case(p,f,case)$
  705. begin scalar fe;
  706. fe:=get(p,case);
  707. while fe and (cdar fe neq f) do fe:=cdr fe$
  708. return fe
  709. end$
  710. %symbolic procedure lin_check(pde,fl)$
  711. %<<for each f in fl do pde:=subst({'TIMES,lin_test_const,f},f,pde);
  712. % freeof(reval {'QUOTIENT,pde,lin_test_const},lin_test_const)
  713. %>>$
  714. symbolic procedure lin_check(pde,fl)$
  715. % This needs pde to have prefix form.
  716. begin scalar a,f;
  717. a:=pde;
  718. for each f in fl do a:=err_catch_sub(f,0,a);
  719. return
  720. if a then <<
  721. for each f in fl do pde:=subst({'TIMES,lin_test_const,f},f,pde);
  722. freeof(reval {'QUOTIENT,{'DIFFERENCE,pde,a},lin_test_const},lin_test_const)
  723. >> else nil
  724. end$
  725. symbolic procedure plot_non0_coeff_ld(s)$
  726. begin scalar dv,dl,dlc,dr,fdl,avf;
  727. write " Leading derivatives with non-zero symbol: "$terpri()$
  728. dv:=get(s,'derivs);
  729. avf:=get(s,'allvarfcts);
  730. while dv do <<
  731. dr:=caar dv; dv:=cdr dv;
  732. if member(car dr,avf) then <<
  733. dlc:=dl;
  734. while dlc and ((caar dlc neq car dr) or
  735. which_deriv(car dlc,dr) ) do dlc:=cdr dlc;
  736. if null dlc then dl:=cons(dr,dl);
  737. % which_deriv(a,b) takes two lists of derivatives and returns how
  738. % often you need to diff. a in order to get at least the
  739. % derivatives in b. e.g. which_deriv((x 2 y), (x y 2)) returns y
  740. >>
  741. >>;
  742. for each dr in dl do <<
  743. dr:=if null cdr dr then car dr
  744. else cons('DF,dr);
  745. if get(s,'linear_) or
  746. freeofzero(reval {'DF,get(s,'val),dr},get(s,'fcts),
  747. get(s,'vars),get(s,'nonrational)) then
  748. fdl:=cons(dr,fdl)
  749. >>;
  750. mathprint cons('! ,fdl)
  751. end$
  752. %%%%%%%%%%%%%%%%%%%%%%%%%
  753. % leading derivatives %
  754. %%%%%%%%%%%%%%%%%%%%%%%%%
  755. symbolic procedure listrel(a,b,l)$
  756. % a>=b w.r.t list l; e.g. l='(a b c) -> a>=a, b>=c
  757. member(b,member(a,l))$
  758. symbolic procedure abs_dfrel(p,q,vl)$
  759. % returns t if derivative of p is lower than derivative of q
  760. % 0 " equal "
  761. % nil " higher "
  762. % p,q : derivatives or functions from ftem like ((f x 2 y z 3) . 2)
  763. % ftem : list of fcts
  764. % vl : list of vars
  765. begin scalar a$
  766. return
  767. if lex_df then dfrel2(p,q,vl) else
  768. if zerop (a:=absdeg(cdar p)-absdeg(cdar q)) then dfrel2(p,q,vl)
  769. else a<0$
  770. end$
  771. symbolic procedure mult_derivs(a,b)$
  772. % multiplies deriv. of a and b
  773. % a,b list of derivs of the form ((fct var1 n1 ...).pow)
  774. begin scalar l$
  775. return
  776. if not b then a
  777. else if not a then b
  778. else
  779. <<
  780. for each s in a do
  781. for each r in b do
  782. if car s=car r then l:=union(list cons(car r,plus(cdr r,cdr s)),l)
  783. else l:=union(list(r,s),l)$
  784. l>>$
  785. end$
  786. symbolic procedure all_deriv_search(p,ftem)$
  787. % yields all derivatives occuring polynomially in a pde p
  788. begin scalar a$
  789. if not pairp p then
  790. <<if member(p,ftem) then a:=list cons(list p,1)>>
  791. else
  792. <<if member(car p,'(PLUS QUOTIENT EQUAL)) then
  793. for each q in cdr p do
  794. a:=union(all_deriv_search(q,ftem),a)
  795. else if car p='MINUS then a:=all_deriv_search(cadr p,ftem)
  796. else if car p='TIMES then
  797. for each q in cdr p do
  798. a:=mult_derivs(all_deriv_search(q,ftem),a)
  799. else if (car p='EXPT) and numberp caddr p then
  800. for each b in all_deriv_search(cadr p,ftem) do
  801. <<if numberp cdr b then
  802. a:=cons(cons(car b,times(caddr p,cdr b)),a)>>
  803. else if (car p='DF) and member(cadr p,ftem) then a:=list cons(cdr p,1)
  804. >>$
  805. return a
  806. end$
  807. symbolic procedure abs_ld_deriv(p)$
  808. if get(p,'derivs) then reval cons('DF,caar get(p,'derivs))$
  809. symbolic procedure abs_ld_deriv_pow(p)$
  810. if get(p,'derivs) then cdar get(p,'derivs)
  811. else 0$
  812. symbolic procedure which_first(a,b,l)$
  813. if null l then nil else
  814. if a = car l then a else
  815. if b = car l then b else which_first(a,b,cdr l)$
  816. symbolic procedure total_less_dfrel(a,b,ftem,vl)$
  817. % = 0 if a=b, =t if a<b, = nil if a>b
  818. begin scalar fa,ad,al,bl$
  819. fa:=caar a$
  820. return
  821. if a=b then 0 else
  822. if lex_fc then % lex. order. of functions has highest priority
  823. if fa=caar b then
  824. if (ad:=abs_dfrel(a,b,vl))=0 then % power counts
  825. if cdr a < cdr b then t
  826. else nil
  827. else
  828. if ad then t
  829. else nil
  830. else
  831. if fa=which_first(fa,caar b,ftem) then nil
  832. else t
  833. else % order. of deriv. has higher priority than fcts.
  834. % number of variables of functions has still higher priority
  835. if (al:=fctlength fa) > (bl:=fctlength caar b) then nil
  836. else
  837. if bl>al then t
  838. else
  839. if (ad:=abs_dfrel(a,b,vl))=0 then
  840. if fa=caar b then
  841. if cdr a < cdr b then t
  842. else nil
  843. else
  844. if fa=which_first(fa,caar b,ftem) then nil
  845. else t
  846. else
  847. if ad then t
  848. else nil
  849. end$
  850. symbolic procedure sort_derivs(l,ftem,vl)$
  851. % yields a sorted list of all derivatives in l
  852. begin scalar l1,l2,a$
  853. return
  854. if null l then nil
  855. else <<
  856. a:=car l$
  857. l:=cdr l$
  858. while l do <<
  859. if total_less_dfrel(a,car l,ftem,vl) then l1:=cons(car l,l1)
  860. else l2:=cons(car l,l2)$
  861. l:=cdr l
  862. >>$
  863. append(sort_derivs(l1,ftem,vl),cons(a,sort_derivs(l2,ftem,vl)))>>
  864. end$
  865. symbolic procedure dfmax(p,q,vl)$
  866. % yields the higher derivative
  867. % vl list of variables e.g. p=((x 2 y 3 z).2), q=((x y 4 z).1)
  868. % df(f,x,2,y,3,z)^2, df(f,x,y,4,z)
  869. if dfrel(p,q,vl) then q
  870. else p$
  871. symbolic procedure dfrel(p,q,vl)$
  872. % the relation "p is lower than q"
  873. % vl list of vars e.g. p=((x 2 y 3 z).2), q=((x y 4 z).1)
  874. if cdr p='infinity then nil
  875. else if cdr q='infinity then t
  876. else begin scalar a$
  877. return
  878. if lex_df then dfrel1(p,q,vl) else
  879. if zerop(a:=absdeg(car p)-absdeg(car q)) then dfrel1(p,q,vl)
  880. else if a<0 then t
  881. else nil
  882. end$
  883. symbolic procedure diffrelp(p,q,v)$
  884. % gives t when p "<" q
  885. % nil when p ">" q
  886. % 0 when p = q
  887. % p, q Paare (liste.power), v Liste der Variablen
  888. % liste Liste aus Var. und Ordn. der Ableit. in Diff.ausdr.,
  889. % power Potenz des Differentialausdrucks
  890. if cdr p='infinity then nil
  891. else if cdr q='infinity then t
  892. else dfrel1(p,q,v)$
  893. symbolic procedure dfrel1(p,q,v)$
  894. % p,q like ((f x 2 y z 3) . 2)
  895. if null v then
  896. % if cdr p = t then if cdr q = t then 0 else nil
  897. % else if cdr q = t then t else
  898. if cdr p>cdr q then nil else % same derivatives,
  899. if cdr p<cdr q then t else 0 % considering powers
  900. % for termorderings of non-linear problems the last 2 lines
  901. % have to be extended
  902. else begin
  903. scalar a,b$
  904. a:=dfdeg(car p, car v)$
  905. b:=dfdeg(car q, car v)$
  906. return if a<b then t
  907. else if b<a then nil
  908. else dfrel1(p,q,cdr v) % same derivative w.r.t car v
  909. end$
  910. symbolic procedure dfrel2(p,q,v)$
  911. % p,q like ((f x 2 y z 3) . 2)
  912. if null v then 0
  913. else begin
  914. scalar a,b$
  915. a:=dfdeg(car p, car v)$
  916. b:=dfdeg(car q,car v)$
  917. return if a<b then t
  918. else if b<a then nil
  919. else dfrel2(p,q,cdr v) % same derivative w.r.t car v
  920. end$
  921. symbolic procedure absdeg(p)$
  922. if null p then 0
  923. else eval cons('PLUS,for each v in p collect if fixp(v) then sub1(v)
  924. else 1)$
  925. symbolic procedure maxderivs(numberlist,deriv,varlist)$
  926. if null numberlist then
  927. for each v in varlist collect dfdeg(deriv,v)
  928. else begin scalar l$
  929. for each v in varlist do
  930. <<l:=cons(max(car numberlist,dfdeg(deriv,v)),l)$
  931. numberlist:=cdr numberlist>>$
  932. return reverse l
  933. end$
  934. symbolic procedure dfdeg(p,v)$
  935. % yields order of deriv. wrt. v$
  936. % e.g p='(x 2 y z 3), v='x --> 2
  937. if null(p:=member(v,p)) then 0
  938. else if null(cdr p) or not fixp(cadr p)
  939. then 1 % v without order
  940. else cadr p$ % v with order
  941. symbolic procedure lower_deg(p,v)$
  942. % reduces the order of the derivative p wrt. v by one
  943. % e.g p='(x 2 y z 3), v='z --> p='(x 2 y z 2)
  944. % e.g p='(x 2 y z 3), v='y --> p='(x 2 z 3)
  945. % returns nil if no v-derivative
  946. begin scalar newp$
  947. while p and (car p neq v) do <<newp:=cons(car p,newp);p:=cdr p>>$
  948. if p then
  949. if null(cdr p) or not fixp(cadr p) then p:=cdr p
  950. else <<
  951. newp:=cons(sub1 cadr p,cons(car p,newp));
  952. p:=cddr p
  953. >> else newp:=nil;
  954. while p do <<newp:=cons(car p,newp);p:=cdr p>>$
  955. return reverse newp
  956. end$
  957. symbolic procedure df_int(d1,d2)$
  958. begin scalar n,l$
  959. return
  960. if d1 then
  961. if d2 then
  962. <<n:=dfdeg(d1,car d1)-dfdeg(d2,car d1)$
  963. l:=df_int(if cdr d1 and numberp cadr d1 then cddr d1
  964. else cdr d1 ,d2)$
  965. if n<=0 then l
  966. else if n=1 then cons(car d1,l)
  967. else cons(car d1,cons(n,l))
  968. >>
  969. else d1$
  970. end$
  971. symbolic procedure linear_fct(p,f)$
  972. begin scalar l$
  973. l:=ld_deriv(p,f)$
  974. return ((car l=f) and (cdr l=1))
  975. end$
  976. % not used anymore:
  977. %
  978. %symbolic procedure dec_ld_deriv(p,f,vl)$
  979. %% gets leading derivative of f in p wrt. vars order vl
  980. %% result: derivative , e.g. '(x 2 y 3 z)
  981. %begin scalar l,d,ld$
  982. % l:=get(p,'derivs)$
  983. % vl:=intersection(vl,get(p,'vars))$
  984. % while caaar l neq f do l:=cdr l$
  985. % ld:=car l$l:=cdr l$
  986. % % --> if lex_df then dfrel1() else
  987. % d:=absdeg(cdar ld)$
  988. % while l and (caaar l=f) and (d=absdeg cdaar l) do
  989. % <<if dfrel1(ld,car l,vl) then ld:=car l$
  990. % l:=cdr l>>$
  991. % return cdar ld$
  992. %end$
  993. symbolic procedure ld_deriv(p,f)$
  994. % gets leading derivative of f in p
  995. % result: derivative + power , e.g. '((DF f x 2 y 3 z) . 3)
  996. begin scalar l$
  997. return if l:=get(p,'derivs) then
  998. <<while caaar l neq f do l:=cdr l$
  999. if l then cons(reval cons('DF,caar l),cdar l)>>
  1000. else cons(nil,0)$
  1001. end$
  1002. symbolic procedure ldiffp(p,f)$
  1003. % liefert Liste der Variablen + Ordnungen mit Potenz
  1004. % p Ausdruck in LISP - Notation, f Funktion
  1005. ld_deriv_search(p,f,fctargs f)$
  1006. symbolic procedure ld_deriv_search(p,f,vl)$
  1007. % gets leading derivative of function f in expr. p w.r.t
  1008. % list of variables vl
  1009. begin scalar a$
  1010. if p=f then a:=cons(nil,1)
  1011. else
  1012. <<a:=cons(nil,0)$
  1013. if pairp p then
  1014. if member(car p,'(PLUS TIMES QUOTIENT EQUAL)) then
  1015. <<p:=cdr p$
  1016. while p do
  1017. <<a:=dfmax(ld_deriv_search(car p,f,vl),a,vl)$
  1018. if cdr a='infinity then p:=nil
  1019. else p:=cdr p
  1020. >>
  1021. >>
  1022. else if car p='MINUS then a:=ld_deriv_search(cadr p,f,vl)
  1023. else if car p='EXPT then
  1024. <<a:=ld_deriv_search(cadr p,f,vl)$
  1025. if numberp cdr a then
  1026. if numberp caddr p
  1027. then a:=cons(car a,times(caddr p,cdr a))
  1028. else if not zerop cdr a
  1029. then a:=cons(nil,'infinity)
  1030. else if not my_freeof(caddr p,f)
  1031. then a:=cons(nil,'infinity)
  1032. >>
  1033. else if car p='DF then
  1034. if cadr p=f then a:=cons(cddr p,1)
  1035. else if my_freeof(cadr p,f)
  1036. then a:=cons(nil,0) % a constant
  1037. else a:=cons(nil,'infinity)
  1038. else if my_freeof(p,f) then a:=cons(nil,0)
  1039. else a:=cons(nil,'infinity)
  1040. >>$
  1041. return a
  1042. end$
  1043. symbolic procedure lderiv(p,f,vl)$
  1044. % fuehrende Ableitung in LISP-Notation mit Potenz (als dotted pair)
  1045. begin scalar l$
  1046. l:=ld_deriv_search(p,f,vl)$
  1047. return cons(if car l then cons('DF,cons(f,car l))
  1048. else if zerop cdr l then nil
  1049. else f
  1050. ,cdr l)
  1051. end$
  1052. symbolic procedure splitinhom(q,ftem,vl)$
  1053. % Splitting the equation q into the homogeneous and inhom. part
  1054. % returns dotted pair qhom . qinhom
  1055. begin scalar qhom,qinhom,denm;
  1056. vl:=varslist(q,ftem,vl)$
  1057. if pairp q and (car q = 'QUOTIENT) then
  1058. if starp(smemberl(ftem,caddr q),length vl) then
  1059. <<denm:=caddr q; q:=cadr q>> else return (q . 0)
  1060. else denm:=1;
  1061. if pairp q and (car q = 'PLUS) then q:=cdr q
  1062. else q:=list q;
  1063. while q do <<
  1064. if starp(smemberl(ftem,car q),length vl) then qinhom:=cons(car q,qinhom)
  1065. else qhom :=cons(car q,qhom);
  1066. q:=cdr q
  1067. >>;
  1068. if null qinhom then qinhom:=0
  1069. else
  1070. if length qinhom > 1 then qinhom:=cons('PLUS,qinhom)
  1071. else qinhom:=car qinhom;
  1072. if null qhom then qhom:=0
  1073. else
  1074. if length qhom > 1 then qhom:=cons('PLUS,qhom)
  1075. else qhom:=car qhom;
  1076. if denm neq 1 then <<qhom :=list('QUOTIENT, qhom,denm);
  1077. qinhom:=list('QUOTIENT,qinhom,denm)>>;
  1078. return qhom . qinhom
  1079. end$
  1080. symbolic procedure search_den(l)$
  1081. % get all denominators and arguments of LOG,... anywhere in a list l
  1082. begin scalar l1$
  1083. if pairp l then
  1084. if car l='quotient then
  1085. l1:=union(cddr l,union(search_den(cadr l),search_den(caddr l)))
  1086. else if member(car l,'(log ln logb log10)) then
  1087. if pairp cadr l and (caadr l='QUOTIENT) then
  1088. l1:=union(list cadadr l,search_den(cadr l))
  1089. else l1:=union(cdr l,search_den(cadr l))
  1090. else for each s in l do l1:=union(search_den(s),l1)$
  1091. return l1$
  1092. end$
  1093. symbolic procedure zero_den(l,ftem,vl)$
  1094. begin scalar cases$
  1095. l:=search_den(l)$
  1096. while l do <<
  1097. if not freeofzero(car l,ftem,vl,ftem) then cases:=cons(car l,cases);
  1098. l:=cdr l
  1099. >>$
  1100. return cases
  1101. end$
  1102. symbolic procedure forg_int(forg,fges)$
  1103. for each ex in forg collect
  1104. if pairp ex and pairp cadr ex then forg_int_f(ex,smemberl(fges,ex))
  1105. else ex$
  1106. symbolic procedure forg_int_f(ex,fges)$
  1107. % try to integrate expr. ex of the form df(f,...)=expr.
  1108. begin scalar p,h,f$
  1109. p:=caddr ex$
  1110. f:=cadadr ex$
  1111. if pairp p and (car p='PLUS)
  1112. then p:=reval cons('PLUS,cons(list('MINUS,cadr ex),cdr p))
  1113. else p:=reval list('DIFFERENCE,p,cadr ex)$
  1114. p:=integratepde(p,cons(f,fges),nil,nil,nil)$
  1115. if p and (car p) and not cdr p then
  1116. <<h:=car lderiv(car p,f,fctargs f)$
  1117. p:=reval list('PLUS,car p,h)$
  1118. for each ff in fnew_ do
  1119. if not member(ff,ftem_) then ftem_:=fctinsert(ff,ftem_)$
  1120. ex:=list('EQUAL,h,p)>>$
  1121. return ex
  1122. end$
  1123. symbolic operator total_alg_mode_deriv$
  1124. symbolic procedure total_alg_mode_deriv(f,x)$
  1125. begin scalar tdf$ %,u,uli,v,vli$
  1126. tdf:={'DF,f,x}$
  1127. % explicit program for chain rule of differentiation which is not used
  1128. % as currently f=f(u), u=u(x) gives df(f**2,x)=2*f*df(f,x)
  1129. %
  1130. % for each u in depl!* do
  1131. % if not freeof(cdr u,x) then uli:=cons(car u,uli)$
  1132. % for each u in uli do <<
  1133. % vli:=nil$
  1134. % for each v in depl!* do
  1135. % if not freeof(cdr v,u) then vli:=cons(car v,vli)$
  1136. % algebraic ( tdf:=tdf+df(f,v)*df(v,u)*df(u,x) )$
  1137. % >>$
  1138. return reval tdf
  1139. end$
  1140. symbolic procedure no_of_v(v,l)$
  1141. % v is a variable name, l a list of derivatives like (x 2 y z 3)
  1142. % it returns the order of v-derivatives
  1143. <<while l and car l neq v do l:=cdr l;
  1144. if null l then 0 else
  1145. if null cdr l or not fixp cadr l or (cadr l = 1) then 1 else
  1146. cadr l
  1147. >>$
  1148. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1149. % general purpose procedures %
  1150. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1151. symbolic procedure memberl(a,b)$
  1152. % member for a list
  1153. if a and b then
  1154. if member(car a,b) then cons(car a,memberl(cdr a,b))
  1155. else memberl(cdr a,b)$
  1156. symbolic procedure smemberl(fl,ex)$
  1157. % smember for a list
  1158. if fl and ex then
  1159. if smember(car fl,ex) then cons(car fl,smemberl(cdr fl,ex))
  1160. else smemberl(cdr fl,ex)$
  1161. symbolic operator my_freeof$
  1162. symbolic procedure my_freeof(u,v)$
  1163. % a patch for FREEOF in REDUCE 3.5
  1164. not(smember(v,u)) and freeofdepl(depl!*,u,v)$
  1165. lisp flag('(my_freeof),'BOOLEAN)$
  1166. symbolic procedure freeoflist(l,m)$
  1167. % liefert t, falls kein Element aus m in l auftritt
  1168. if null m then t
  1169. else if freeof(l,car m) then freeoflist(l,cdr m)
  1170. else nil$
  1171. symbolic procedure freeofdepl(de,u,v)$
  1172. if null de then t
  1173. else if smember(v,cdar de) and smember(caar de,u) then nil
  1174. else freeofdepl(cdr de,u,v)$
  1175. symbolic procedure fctins(f,flen,ftem)$
  1176. if null ftem then list f else
  1177. if fctlength car ftem < flen then cons(f,ftem)
  1178. else cons(car ftem,fctinsert(f,cdr ftem))$
  1179. symbolic procedure fctinsert(f,ftem)$
  1180. % isert a function f in the function list ftem
  1181. if freeof(ftem,f) then fctins(f,fctlength f,ftem)
  1182. else ftem$
  1183. symbolic procedure newfct(id,l,nfct)$
  1184. begin scalar f$
  1185. % Only in the top level function names may be recycled otherwise
  1186. % name clashes occur when passing back solutions with new functions
  1187. % of integration but old used names
  1188. if (null level_) and (id=fname_) and recycle_fcts then <<
  1189. f:=car recycle_fcts$
  1190. recycle_fcts:=cdr recycle_fcts
  1191. >> else
  1192. f:=mkid(id,nfct)$
  1193. depl!*:=delete(assoc(f,depl!*),depl!*)$
  1194. %put(f,'simpfn,'simpiden)$
  1195. %if pairp l then f:=cons(f,l)$
  1196. if pairp l then depl!*:=cons(cons(f,l),depl!*)$
  1197. if print_ then
  1198. <<terpri()$
  1199. if pairp l then
  1200. <<write "new function: "$
  1201. fctprint list f>>
  1202. else
  1203. write "new constant: ",f>>$
  1204. return f$
  1205. end$
  1206. symbolic procedure drop_fct(f)$
  1207. % check before that f is not one of the forg functions!
  1208. % check dropping f also from ftem_
  1209. <<if do_recycle_fnc then recycle_fcts:=f . recycle_fcts$
  1210. depl!*:=delete(assoc(reval f,depl!*),depl!*)$
  1211. >>$
  1212. symbolic procedure varslist(p,ftem,vl)$
  1213. begin scalar l$
  1214. ftem:=argset smemberl(ftem,p)$
  1215. for each v in vl do
  1216. if not my_freeof(p,v) or member(v,ftem) then l:=cons(v,l)$
  1217. return reverse l$
  1218. end$
  1219. symbolic procedure var_list(pdes,forg,vl)$
  1220. begin scalar l,l1$
  1221. for each p in pdes do l:=union(get(p,'vars),l)$
  1222. for each v in vl do
  1223. if member(v,l) or not my_freeof(forg,v) then l1:=cons(v,l1)$
  1224. return reverse l1$
  1225. end$
  1226. symbolic procedure fctlist(ftem,pdes,forg)$
  1227. begin scalar fges,l$
  1228. for each p in pdes do l:=union(get(p,'fcts),l)$
  1229. for each f in ftem do
  1230. if not freeof(forg,f) or member(f,l) then fges:=fctinsert(f,fges)$
  1231. for each f in forg do
  1232. if not pairp f and not member(f,fges) then fges:=fctinsert(f,fges)$
  1233. for each f in l do
  1234. if not member(f,fges) then fges:=fctinsert(f,fges)$
  1235. l:=setdiff(ftem,fges);
  1236. for each f in l do drop_fct(f)$
  1237. return fges$
  1238. end$
  1239. symbolic operator fargs$
  1240. symbolic procedure fargs f$
  1241. cons('LIST,fctargs f)$
  1242. symbolic procedure fctargs f$
  1243. % arguments of a function
  1244. if (f:=assoc(f,depl!*)) then cdr f$
  1245. symbolic procedure fctlength f$
  1246. % number of arguments
  1247. length fctargs f$
  1248. symbolic procedure fctsort(l)$
  1249. % list sorting
  1250. begin scalar l1,l2,l3,m,n$
  1251. return
  1252. if null l then nil
  1253. else
  1254. <<n:=fctlength car l$
  1255. l2:=list car l$
  1256. l:=cdr l$
  1257. while l do
  1258. <<m:=fctlength car l$
  1259. if m<n then l1:=cons(car l,l1)
  1260. else if m>n then l3:=cons(car l,l3)
  1261. else l2:=cons(car l,l2)$
  1262. l:=cdr l>>$
  1263. append(fctsort reverse l3,append(reverse l2,fctsort reverse l1))>>
  1264. end$
  1265. symbolic procedure listprint(l)$
  1266. % print elements of a lisp list
  1267. if pairp l then <<
  1268. write car l$
  1269. for each v in cdr l do <<write ",",v>>
  1270. >>$
  1271. symbolic procedure fctprint1(f)$
  1272. % print a function
  1273. begin scalar vl;
  1274. if f then
  1275. if pairp f then <<
  1276. write car f$
  1277. if pairp cdr f then <<
  1278. for each a in vl_ do
  1279. if not freeof(cdr f,a) then vl:=cons(a,vl);
  1280. write "("$
  1281. % listprint cdr f$
  1282. listprint append(setdiff(cdr f,vl),reverse vl)$
  1283. write ")">>
  1284. >>
  1285. else write f$
  1286. end$
  1287. symbolic procedure fctprint(fl)$
  1288. % Ausdrucken der Funktionen aus fl
  1289. begin scalar l,f,a,n,nn$
  1290. n:=0$
  1291. while fl do <<
  1292. f:=car fl$
  1293. fl:=cdr fl$
  1294. if pairp f then
  1295. if car f='EQUAL then
  1296. <<n:=no_of_terms caddr f$
  1297. if (null print_) or (n>print_) then
  1298. <<terpri()$write cadr f,"= expr. with ",n," terms"$
  1299. if (l:=get(cadr f,'fcts)) then
  1300. <<write " in "$
  1301. myprin2l(l,", ")>>$
  1302. terpri()>>
  1303. else mathprint f$
  1304. n:=0>>
  1305. else
  1306. <<if n = 4 then
  1307. <<terpri()$n:=0>>$
  1308. fctprint1 f$
  1309. if fl then write ", "$
  1310. n:=add1 n>>
  1311. else <<
  1312. nn:=reval {'PLUS,4,length explode f,
  1313. for each a in fctargs f sum add1 length explode a};
  1314. if nn+n > 79 then <<terpri()$n:=0>>$
  1315. l:=assoc(f,depl!*)$
  1316. fctprint1 if l then l
  1317. else f$
  1318. if fl then write ", "$
  1319. n:=nn+n>>
  1320. >>$
  1321. end$
  1322. symbolic procedure deprint(l)$
  1323. % Ausdrucken der Gl. aus der Liste l
  1324. if l and print_ then for each x in l do eqprint list('EQUAL,0,x)$
  1325. symbolic procedure eqprint(e)$
  1326. % Ausdrucken der Gl. e
  1327. if print_ then
  1328. begin scalar n$
  1329. n:=delength e$
  1330. if n>print_ then
  1331. <<write %"expr. with ",
  1332. n," factors in ",
  1333. no_of_terms(e)," terms"$
  1334. terpri()
  1335. >>
  1336. else
  1337. mathprint e$
  1338. end$
  1339. symbolic procedure print_level(neu)$
  1340. if print_ and level_ then <<
  1341. terpri()$
  1342. if neu then write "New level : "
  1343. else write "Current level : "$
  1344. for each m in reverse level_ do write m,"."$
  1345. >>$
  1346. symbolic procedure print_statistic(pdes,fcts)$
  1347. if print_ then begin
  1348. integer j,k,le,r,s$
  1349. scalar n,m,p,el,fl,vl,pl$
  1350. %--- printing the stats of equations:
  1351. if pdes then <<
  1352. terpri()$write "number of equations : ",length pdes$
  1353. terpri()$write "total no of terms : ",
  1354. j:=for each p in pdes sum get(p,'terms)$
  1355. k:=for each p in pdes sum get(p,'length)$
  1356. if k neq j then <<terpri()$write "total no of factors : ",k>>$
  1357. while pdes do <<
  1358. j:=0;
  1359. el:=nil;
  1360. for each p in pdes do <<
  1361. vl:=get(p,'vars);
  1362. if vl then le:=length vl
  1363. else le:=0;
  1364. if ((j=0) and null vl) or
  1365. (j=le) then el:=cons(p,el)
  1366. else if j<le then <<
  1367. j:=le;
  1368. el:=list(p)
  1369. >>
  1370. >>;
  1371. pdes:=setdiff(pdes,el);
  1372. if el then <<
  1373. n:=length el$
  1374. terpri()$write n," equation"$
  1375. if n>1 then write"s"$write" in ",j," variable"$
  1376. if j neq 1 then write"s"$
  1377. write": "$
  1378. if struc_eqn then el:=sort_deriv_pdes(el)$
  1379. repeat <<
  1380. if struc_eqn then <<
  1381. pl:=first el; el:=cdr el;
  1382. terpri()$
  1383. write length cdr pl," equations with ",car pl," derivative",
  1384. if car pl = 1 then ":" else "s:"$
  1385. pl:=cdr pl
  1386. >> else <<pl:=el;el:=nil>>;
  1387. terpri()$
  1388. k:=0;
  1389. while pl do <<
  1390. if (k geq 70) then <<k:=0;terpri()>>$
  1391. k:=k+4+length explode car pl + length explode get(car pl,'terms)$
  1392. write car pl,"(",get(car pl,'terms)$
  1393. r:=get(car pl,'val)$
  1394. if (s:=get(car pl,'starde)) then <<
  1395. for r:=1:(1+cdr s) do write"*"$
  1396. k:=k+1+cdr s;
  1397. >>$
  1398. if (pairp r) and (car r='TIMES) then write"#"$
  1399. if flin_ and freeoflist(r,flin_) then write"a"$
  1400. write")"$
  1401. pl:=cdr pl$
  1402. if pl then write","$
  1403. >>;
  1404. >> until null el;
  1405. >>$
  1406. j:=add1 j;
  1407. >>
  1408. >>
  1409. else <<terpri()$write "no equations">>$
  1410. %--- printing the stats of functions:
  1411. for each f in fcts do if not pairp f then fl:=cons(f,fl)$
  1412. if fl then <<
  1413. fl:=fctsort reverse fl$
  1414. m:=fctlength car fl$
  1415. while m>=0 do <<
  1416. n:=0$
  1417. el:=nil;
  1418. while fl and (fctlength car fl=m) do <<
  1419. n:=add1 n$
  1420. el:=cons(car fl,el)$
  1421. fl:=cdr fl
  1422. >>$
  1423. if n>0 then
  1424. if m>0 then <<
  1425. terpri()$
  1426. write n," function"$
  1427. if n>1 then write"s"$
  1428. write" with ",m," argument",if m>1 then "s : "
  1429. else " : "
  1430. >> else <<
  1431. terpri()$
  1432. write n," constant"$
  1433. if n>1 then write"s"$
  1434. write" : "
  1435. >>$
  1436. k:=0;
  1437. while el do <<
  1438. if k=10 then <<k:=0;terpri()>>
  1439. else k:=add1 k$
  1440. write car el$
  1441. el:=cdr el$
  1442. if el then write","$
  1443. >>$
  1444. m:=if fl then fctlength car fl
  1445. else -1
  1446. >>
  1447. >> else <<terpri()$write "no functions or constants">>$
  1448. terpri()$
  1449. end$
  1450. symbolic procedure get_statistic(pdes,fcts)$
  1451. % returns: {time(),
  1452. % stepcounter_,
  1453. % number of pdes,
  1454. % number of terms,
  1455. % length of pdes,
  1456. % {{no of eq, no of var in eq}, ...}
  1457. % {{no of fc, no of var in fc}, ...}
  1458. % }
  1459. if contradiction_ then "contradiction" else
  1460. begin
  1461. integer j,le$
  1462. scalar n,p,el,fl,vl,li,stats$
  1463. stats:={for each p in pdes sum get(p,'length),
  1464. for each p in pdes sum get(p,'terms),
  1465. length pdes,
  1466. stepcounter_,
  1467. time()}$
  1468. %--- the statistics of equations:
  1469. while pdes do <<
  1470. % j is number of variables and el the list of equations
  1471. j:=0;
  1472. el:=nil;
  1473. for each p in pdes do <<
  1474. vl:=get(p,'vars);
  1475. if vl then le:=length vl
  1476. else le:=0;
  1477. if ((j=0) and null vl) or
  1478. (j=le) then el:=cons(p,el)
  1479. else if j<le then <<
  1480. j:=le;
  1481. el:=list(p)
  1482. >>
  1483. >>;
  1484. pdes:=setdiff(pdes,el);
  1485. li:=cons({length el,j},li)
  1486. % length el equations in j variables
  1487. >>;
  1488. stats:=cons(li,stats)$
  1489. li:=nil;
  1490. %--- the statistics of functions:
  1491. for each f in fcts do if not pairp f then fl:=cons(f,fl)$
  1492. if fl then <<
  1493. fl:=fctsort reverse fl$
  1494. j:=fctlength car fl$
  1495. while j>=0 do <<
  1496. n:=0$
  1497. while fl and (fctlength car fl=j) do <<n:=add1 n$ fl:=cdr fl>>$
  1498. li:=cons({n,j},li)$
  1499. % n functions of j variables
  1500. j:=if fl then fctlength car fl
  1501. else -1
  1502. >>
  1503. >>$
  1504. return reverse cons(li,stats)
  1505. end$
  1506. symbolic procedure sort_deriv_pdes(pdes)$
  1507. begin scalar max_no_deri,cp,pl,res$
  1508. max_no_deri:=0;
  1509. cp:=pdes;
  1510. while cp do <<
  1511. if get(car cp,'no_derivs)>max_no_deri then
  1512. max_no_deri:=get(car cp,'no_derivs);
  1513. cp:=cdr cp
  1514. >>;
  1515. repeat <<
  1516. pl:=nil;
  1517. cp:=pdes;
  1518. while cp do <<
  1519. if get(car cp,'no_derivs)=max_no_deri then pl:=cons(car cp,pl);
  1520. cp:=cdr cp
  1521. >>$
  1522. if pl then res:=cons(cons(max_no_deri,reverse pl),res)$
  1523. pdes:=setdiff(pdes,pl);
  1524. max_no_deri:=if zerop max_no_deri then nil
  1525. else sub1(max_no_deri);
  1526. >> until (null max_no_deri) or (null pdes);
  1527. return res
  1528. end$
  1529. symbolic procedure print_pdes(pdes)$
  1530. % print all pdes up to some size
  1531. begin scalar pl,ps,n,pdecp$
  1532. terpri()$
  1533. if pdes then <<
  1534. if (null !*batch_mode) and
  1535. (batchcount_<stepcounter_) and
  1536. (cdr pdes) then << % if more than one pde
  1537. write"What is the maximal number of terms of equations to be shown? "$
  1538. ps:=promptstring!*$
  1539. promptstring!*:=""$
  1540. terpri()$n:=termread()$
  1541. promptstring!*:=ps$
  1542. for each pl in pdes do
  1543. if get(pl,'terms)<=n then pdecp:=cons(pl,pdecp);
  1544. pdecp:=reverse pdecp;
  1545. >> else pdecp:=pdes$
  1546. write "equations : "$
  1547. if struc_eqn then <<
  1548. pl:=sort_deriv_pdes(pdecp)$
  1549. while pl do <<
  1550. terpri()$
  1551. write length cdar pl," equations with ",caar pl," derivatives:"$
  1552. typeeqlist(cdar pl)$
  1553. pl:=cdr pl
  1554. >>
  1555. >> else typeeqlist(pdecp)
  1556. >> else <<write "no equations"$ terpri()>>$
  1557. end$
  1558. symbolic procedure print_ineq(ineqs)$
  1559. % print all ineqs
  1560. begin scalar a,b,c$
  1561. terpri()$
  1562. if ineqs then <<
  1563. terpri()$write "non-vanishing expressions: "$
  1564. for each a in ineqs do if pairp a then c:=cons(a,c)
  1565. else b:=cons(a,b);
  1566. listprint b;terpri()$
  1567. for each a in c do eqprint a
  1568. >>
  1569. end$
  1570. symbolic procedure print_fcts2(pdes,fcts)$
  1571. % print all fcts and vars
  1572. begin scalar dflist,dfs,f,p,cp,h,hh,ps,showcoef$
  1573. for each h in fcts do if not pairp h then hh:=cons(h,hh);
  1574. ps:=promptstring!*$ promptstring!*:=""$
  1575. % write "Which function out of "$terpri()$
  1576. % listprint(hh)$
  1577. % write"? "$terpri()$
  1578. % write"Enter the function name only or ; for all functions."$terpri()$
  1579. %
  1580. % h:=termread();
  1581. % if h neq '!; and not_included(list h,hh) then <<
  1582. % write"This is not a function in the list."$
  1583. % terpri();
  1584. % h:=nil
  1585. % >>;
  1586. % if null h then return nil;
  1587. % if h='!; then fcts:=hh
  1588. % else fcts:=list h;
  1589. fcts:=select_from_list(hh,nil)$
  1590. pdes:=select_from_list(pdes,nil)$
  1591. write"Do you want to see the coefficients of all derivatives in all equations"$
  1592. terpri()$
  1593. write"in factorized form which may take relatively much time? y/n"$
  1594. terpri()$
  1595. repeat
  1596. h:=termread()
  1597. until (h='y) or (h='n);
  1598. if h='n then showcoef:=nil else showcoef:=t;
  1599. promptstring!*:=ps$
  1600. while fcts do
  1601. if pairp car fcts then fcts:=cdr fcts
  1602. else <<
  1603. f:=car fcts; fcts:=cdr fcts;
  1604. dflist:=nil;
  1605. for each p in pdes do if not freeof(get(p,'fcts),f) then <<
  1606. dfs:=get(p,'derivs);
  1607. while dfs do <<
  1608. if caaar dfs=f then <<
  1609. cp:=dflist;
  1610. while cp and (caar cp neq caar dfs) do cp:=cdr cp;
  1611. if cdaar dfs then h:=cons('DF,caar dfs)
  1612. else h:=caaar dfs;
  1613. if showcoef then
  1614. if null cp then dflist:=cons({caar dfs,{'LIST,p,
  1615. factorize coeffn(get(p,'val),h,1)}},
  1616. dflist)
  1617. else rplaca(cp,cons(caar cp,
  1618. cons({'LIST,p,
  1619. factorize coeffn(get(p,'val),h,1)},
  1620. cdar cp)))
  1621. else
  1622. if null cp then dflist:=cons({caar dfs,p},dflist)
  1623. else rplaca(cp,cons(caar cp,cons(p,cdar cp)))
  1624. >>;
  1625. dfs:=cdr dfs
  1626. >>;
  1627. >>;
  1628. while dflist do <<
  1629. dfs:=car dflist;dflist:=cdr dflist;
  1630. if cdar dfs then h:=cons('DF,car dfs)
  1631. else h:=caar dfs;
  1632. if showcoef then algebraic <<write h,": ",lisp cons('LIST,cdr dfs)>>
  1633. else <<write h,": "$ print cdr dfs$ terpri()>>
  1634. >>;
  1635. >>;
  1636. end$
  1637. symbolic procedure print_fcts(fcts,vl)$
  1638. % print all fcts and vars
  1639. <<if fcts then
  1640. <<terpri()$write "functions : "$
  1641. fctprint(fcts);
  1642. terpri()$write "with ",
  1643. for each p in fcts sum no_of_terms(p)," terms">>$
  1644. if vl then
  1645. <<terpri()$write "variables : "$
  1646. fctprint(vl)>>$
  1647. >>$
  1648. symbolic procedure print_pde_fct_ineq(pdes,ineqs,fcts,vl)$
  1649. % print all pdes, ineqs and fcts
  1650. if print_ then begin$
  1651. print_pdes(pdes)$
  1652. print_ineq(ineqs)$
  1653. print_fcts(fcts,vl)$
  1654. print_statistic(pdes,fcts)
  1655. end$
  1656. symbolic procedure no_of_terms(d)$
  1657. if not pairp d then if (null d) or (zerop d) then 0
  1658. else 1 else
  1659. if car d='PLUS then length d - 1 else
  1660. if car d='EQUAL then no_of_terms(cadr d) +
  1661. no_of_terms(caddr d) else
  1662. if (car d='MINUS) or (car d='QUOTIENT) then
  1663. no_of_terms(cadr d) else
  1664. if car d='EXPT then
  1665. if (not fixp caddr d) or (caddr d < 2) then 1 else
  1666. % number of terms of (a1+a2+..+an)**r = n+r-1 over r
  1667. begin scalar h,m,q$
  1668. m:=no_of_terms(cadr d)-1;
  1669. h:=1;
  1670. for q:=1:caddr d do h:=h*(m+q)/q;
  1671. return h
  1672. end else
  1673. if car d='TIMES then begin scalar h,r;
  1674. h:=1;
  1675. for each r in cdr d do h:=h*no_of_terms(r);
  1676. return h
  1677. end else 1$
  1678. symbolic procedure delength(d)$
  1679. % Laenge eines Polynoms in LISP - Notation
  1680. if not pairp d then
  1681. if d then 1
  1682. else 0
  1683. else
  1684. if (car d='PLUS) or (car d='TIMES) or (car d='QUOTIENT)
  1685. or (car d='MINUS) or (car d='EQUAL)
  1686. then for each a in cdr d sum delength(a)
  1687. else 1$
  1688. symbolic procedure pdeweight(d,ftem)$
  1689. % Laenge eines Polynoms in LISP - Notation
  1690. if not smemberl(ftem,d) then 0
  1691. else if not pairp d then 1
  1692. else if (car d='PLUS) or (car d='TIMES) or (car d='EQUAL)
  1693. or (car d='QUOTIENT) then
  1694. for each a in cdr d sum pdeweight(a,ftem)
  1695. else if (car d='EXPT) then
  1696. if numberp caddr d then
  1697. caddr d*pdeweight(cadr d,ftem)
  1698. else
  1699. pdeweight(caddr d,ftem)+pdeweight(cadr d,ftem)
  1700. else if (car d='MINUS) then pdeweight(cadr d,ftem)
  1701. else 1$
  1702. symbolic procedure desort(l)$
  1703. % sort expressions hat are the elements of the list l by size
  1704. for each a in idx_sort for each b in l collect cons(delength b,b)
  1705. collect cdr a$
  1706. symbolic procedure idx_sort(l)$
  1707. % All elements of l have a numerical first element and are sorted
  1708. % by that number
  1709. begin scalar l1,l2,l3,m,n$
  1710. return
  1711. if null l then nil
  1712. else
  1713. <<n:=caar l$
  1714. l2:=list car l$
  1715. l:=cdr l$
  1716. while l do
  1717. <<m:=caar l$
  1718. if m<n then l1:=cons(car l,l1)
  1719. else if m>n then l3:=cons(car l,l3)
  1720. else l2:=cons(car l,l2)$
  1721. l:=cdr l>>$
  1722. append(idx_sort(l1),append(l2,idx_sort(l3)))>>
  1723. end$
  1724. symbolic procedure rat_idx_sort(l)$
  1725. % All elements of l have a rational number first element
  1726. % and are sorted by that number
  1727. % The rational number has to be reval-ed !
  1728. begin scalar l1,l2,l3,m,n$
  1729. return
  1730. if null l then nil
  1731. else
  1732. <<n:=caar l$
  1733. l2:=list car l$
  1734. l:=cdr l$
  1735. while l do
  1736. <<m:=caar l$
  1737. if rational_less(m,n) then l1:=cons(car l,l1)
  1738. else if rational_less(n,m) then l3:=cons(car l,l3)
  1739. else l2:=cons(car l,l2)$
  1740. l:=cdr l>>$
  1741. append(rat_idx_sort(l1),append(l2,rat_idx_sort(l3)))>>
  1742. end$
  1743. symbolic procedure argset(ftem)$
  1744. % List of arguments of all functions in ftem
  1745. if ftem then union(reverse fctargs car ftem,argset(cdr ftem))
  1746. else nil$
  1747. symbolic procedure no_fnc_of_v$
  1748. begin scalar vl,v,nofu,f,nv$
  1749. % How many functions do depend on each variable?
  1750. vl:=argset(ftem_)$
  1751. for each v in vl do <<
  1752. nofu:=0; % the number of functions v occurs in
  1753. for each f in ftem_ do
  1754. if not freeof(fctargs f,v) then nofu:=add1 nofu$
  1755. nv:=cons((v . nofu),nv)$
  1756. >>$
  1757. return nv
  1758. end$
  1759. procedure push_vars(liste)$
  1760. for each x in liste collect
  1761. if not boundp x then x else eval x$ % valuecell x$
  1762. symbolic procedure backup_pdes(pdes,forg)$
  1763. % make a backup of all pdes
  1764. begin scalar allfl$
  1765. return
  1766. list(push_vars glob_var,
  1767. for each p in pdes collect
  1768. list(p,
  1769. for each q in prop_list collect cons(q,get(p,q)),
  1770. <<allfl:=nil;
  1771. for each q in allflags_ do
  1772. if flagp(p,q) then allfl:=cons(q,allfl);
  1773. allfl>>),
  1774. for each f in forg collect
  1775. if pairp f then cons(f,get(cadr f,'fcts))
  1776. else cons(f,get( f,'fcts)),
  1777. for each id in idnties_ collect
  1778. list(id,get(id,'val),flagp(id,'to_int),flagp(id,'to_subst))
  1779. )
  1780. end$
  1781. %symbolic procedure backup_pdes(pdes,forg)$
  1782. %% make a backup of all pdes
  1783. %begin scalar cop$
  1784. % cop:=list(nequ_,
  1785. % for each p in pdes collect
  1786. % list(p,
  1787. % for each q in prop_list collect cons(q,get(p,q)),
  1788. % for each q in allflags_ collect if flagp(p,q) then q),
  1789. % for each f in forg collect
  1790. % if pairp f then cons(cadr f,get(cadr f,'fcts))
  1791. % else cons(f,get(f,'fcts)),
  1792. % ftem_,
  1793. % ineq_,
  1794. % recycle_ens,
  1795. % recycle_fcts)$
  1796. % return cop
  1797. %end$
  1798. symbolic procedure pop_vars(liste,altewerte)$
  1799. foreach x in liste do <<set (x,car altewerte);
  1800. altewerte := cdr altewerte>>$
  1801. symbolic procedure restore_pdes(bak)$
  1802. % restore all data: glob_var, pdes, forg
  1803. begin scalar pdes,forg$
  1804. % recover values of global variables
  1805. pop_vars(glob_var,car bak)$
  1806. % recover the pdes
  1807. for each c in cadr bak do <<
  1808. pdes:=cons(car c,pdes)$
  1809. for each s in cadr c do put(car c,car s,cdr s)$
  1810. for each s in caddr c do flag1(car c,s)
  1811. >>$
  1812. % recover the properties of forg
  1813. for each c in caddr bak do <<
  1814. forg:=cons(car c,forg)$
  1815. if pairp car c then put(cadar c,'fcts,cdr c)
  1816. >>$
  1817. % recover the properties of idnties_
  1818. if cdddr bak then
  1819. for each c in cadddr bak do <<
  1820. put(car c,'val,cadr c);
  1821. if caddr c then flag1(car c,'to_int)
  1822. else if flagp(car c,'to_int) then remflag(car c,'to_int);
  1823. if caddr c then flag1(car c,'to_subst)
  1824. else if flagp(car c,'to_subst) then remflag(car c,'to_subst);
  1825. >>$
  1826. return {reverse pdes,reverse forg}$
  1827. end$
  1828. %symbolic procedure restore_pdes(cop)$
  1829. %% restore the pde list cop
  1830. %% first element must be the old value of nequ_
  1831. %% the elements must have the form (p . property_list_of_p)
  1832. %begin scalar pdes$
  1833. % % delete all new produced pdes
  1834. % for i:=car cop:sub1 nequ_ do setprop(mkid(eqname_,i),nil)$
  1835. % nequ_:=car cop$
  1836. % for each c in cadr cop do
  1837. % <<pdes:=cons(car c,pdes)$
  1838. % for each s in cadr c do
  1839. % put(car c,car s,cdr s)$
  1840. % for each s in caddr c do
  1841. % if s then flag1(car c,s)$
  1842. % >>$
  1843. % for each c in caddr cop do
  1844. % put(car c,'fcts,cdr c)$
  1845. % ftem_:=cadddr cop$
  1846. % ineq_:=car cddddr cop$
  1847. % recycle_eqns:= cadr cddddr cop$
  1848. % recycle_fcts:= caddr cddddr cop$
  1849. % return reverse pdes$
  1850. %end$
  1851. %symbolic procedure copy_from_backup(copie)$
  1852. %% restore the pde list copie
  1853. %% first element must be the old value of nequ_
  1854. %% the elements must have the form (p . property_list_of_p)
  1855. %% at least recycle_eqns should not work with this procedure
  1856. %begin scalar l,pdes,cop$
  1857. % cop:=cadr copie$
  1858. % l:=cop$
  1859. % for i:=1:length cop do
  1860. % <<pdes:=cons(mkid(eqname_,nequ_),pdes)$
  1861. % setprop(car pdes,nil)$
  1862. % nequ_:=add1 nequ_>>$
  1863. % pdes:=reverse pdes$
  1864. % for each p in pdes do
  1865. % <<cop:=subst(p,caar l,cop)$
  1866. % l:=cdr l>>$
  1867. % for each c in cop do
  1868. % <<for each s in cadr c do
  1869. % put(car c,car s,cdr s)$
  1870. % for each s in caddr c do
  1871. % if s then flag1(car c,s)$
  1872. % >>$
  1873. % for each c in caddr copie do
  1874. % put(car c,'fcts,cdr c)$
  1875. % ftem_:=cadddr copie$
  1876. % return pdes$
  1877. %end$
  1878. symbolic procedure deletepde(pdes)$
  1879. begin scalar s,l,ps$
  1880. ps:=promptstring!*$
  1881. promptstring!*:=""$
  1882. terpri()$
  1883. write "Equations to be deleted: "$
  1884. l:=select_from_list(pdes,nil)$
  1885. promptstring!*:=ps$
  1886. for each s in l do
  1887. if member(s,pdes) then pdes:=drop_pde(s,pdes,nil)$
  1888. return pdes
  1889. end$
  1890. symbolic procedure new_pde()$
  1891. begin scalar s$
  1892. if null car recycle_eqns then <<
  1893. s:=mkid(eqname_,nequ_)$
  1894. nequ_:=add1 nequ_$
  1895. >> else <<
  1896. s:=caar recycle_eqns$
  1897. recycle_eqns:=(cdar recycle_eqns) . (cdr recycle_eqns)
  1898. >>$
  1899. setprop(s,nil)$
  1900. return s
  1901. end$
  1902. symbolic procedure drop_pde_from_properties(p,pdes)$
  1903. begin
  1904. for each q in pdes do if q neq p then <<
  1905. drop_dec_with(p,q,t)$
  1906. drop_dec_with(p,q,nil)$
  1907. drop_rl_with(p,q)
  1908. >>
  1909. end$
  1910. symbolic procedure drop_pde_from_idties(p,pdes,pval)$
  1911. % to be used whenever the equation p is dropped or changed and
  1912. % afterwards newly characterized in update,
  1913. % pval is the new value of p in terms of the previous value,
  1914. % if this is unknown then pval=nil
  1915. % to be done before setprop(p,nil)
  1916. begin scalar q,newidval,idnt$
  1917. for each q in pdes do if q neq p then
  1918. if not freeof(get(q,'histry_),p) then
  1919. put(q,'histry_, if null pval then q
  1920. else subst(pval,p,get(q,'histry_)))$
  1921. if record_hist and (getd 'show_id) then <<
  1922. idnt:=idnties_$
  1923. while idnt do <<
  1924. if not freeof(get(car idnt,'val),p) then
  1925. if null pval then drop_idty(car idnt)
  1926. else <<
  1927. % Once pdes_ is available as global variable then simplify 'val
  1928. % before put()
  1929. newidval:=reval subst(pval,p,get(car idnt,'val))$
  1930. if trivial_idty(pdes,newidval) then drop_idty(car idnt)
  1931. else <<
  1932. put(car idnt,'val,newidval);
  1933. flag1(car idnt,'to_subst)$
  1934. flag1(car idnt,'to_int)
  1935. >>
  1936. >>;
  1937. idnt:=cdr idnt
  1938. >>;
  1939. if pval and not zerop pval and (p neq get(p,'histry_)) then <<
  1940. idnt:=reval num reval {'PLUS,get(p,'histry_),{'MINUS,pval}}$
  1941. if not zerop idnt then
  1942. new_idty(idnt,pdes,if pdes then t else nil)
  1943. >>
  1944. >>
  1945. end$
  1946. symbolic procedure drop_pde(p,pdes,pval)$
  1947. % pval is the value of p in terms of other equations,
  1948. % if pval=nil then unknown
  1949. % pdes should be a list of all currently used pde-names
  1950. begin
  1951. if do_recycle_eqn then
  1952. recycle_eqns:=(car recycle_eqns) . union({p},cdr recycle_eqns)$
  1953. depl!*:=delete(assoc(reval p,depl!*),depl!*)$
  1954. drop_pde_from_idties(p,pdes,pval)$
  1955. setprop(p,nil)$
  1956. return delete(p,pdes)
  1957. end$
  1958. symbolic procedure change_pde_flag(pdes)$
  1959. begin scalar p,ty,h$
  1960. repeat <<
  1961. terpri()$
  1962. write "From which PDE do you want to change a ",
  1963. "flag or property, e.g. e_23?"$
  1964. terpri()$
  1965. p:=termread()$
  1966. >> until not freeof(pdes,p)$
  1967. terpri()$
  1968. write"Type in one of the following flags that is to be flipped "$
  1969. terpri()$
  1970. write"(e.g. to_int <ENTER>): "$
  1971. terpri()$terpri()$
  1972. write allflags_;
  1973. terpri()$terpri()$
  1974. write"or type in one of the following properties that is to be changed"$
  1975. terpri()$
  1976. write"(e.g. vars <ENTER>): "$
  1977. terpri()$terpri()$
  1978. write prop_list;
  1979. terpri()$terpri()$
  1980. ty:=termread()$
  1981. if member(ty,allflags_) then <<
  1982. if flagp(p,ty) then remflag1(p,ty)
  1983. else flag1(p,ty)$
  1984. write"The new value of ",ty,": ",flagp(p,ty)$
  1985. >> else
  1986. if member(ty,prop_list) then <<
  1987. terpri()$
  1988. write"current value: ",get(p,ty)$
  1989. terpri()$
  1990. write"new value (e.g. (x y z) ENTER): "$
  1991. terpri()$
  1992. h:=termread()$
  1993. put(p,ty,h)$
  1994. write"The new value of ",ty,": ",get(p,ty)$
  1995. >> else write"Input not recognized."$
  1996. terpri()$
  1997. end$
  1998. symbolic procedure restore_backup_from_file(pdes,forg,nme)$
  1999. begin scalar ps,s,p,echo_bak$
  2000. if nme=t then <<
  2001. ps:=promptstring!*$
  2002. promptstring!*:=""$
  2003. terpri()$
  2004. write"Please give the name of the file in double quotes"$terpri()$
  2005. write"without `;' : "$
  2006. s:=termread()$
  2007. >> else
  2008. if nme then s:=nme
  2009. else s:=level_string(session_)$
  2010. % infile s$
  2011. echo_bak:=!*echo; semic!*:='!$; in s$ !*echo:=echo_bak;
  2012. %-- cleaning up:
  2013. for each p in pdes do setprop(p,nil)$
  2014. for each p in forg do if pairp p then put(cadr p,'fcts,nil)$
  2015. %-- assigning the new values:
  2016. promptstring!*:=ps$
  2017. size_hist :=car backup_; backup_:=cdr backup_;
  2018. stepcounter_:=car backup_; backup_:=cdr backup_;
  2019. level_ :=car backup_; backup_:=cdr backup_;
  2020. nfct_ :=car backup_; backup_:=cdr backup_;
  2021. time_limit :=car backup_; backup_:=cdr backup_;
  2022. limit_time :=car backup_; backup_:=cdr backup_;
  2023. history_ :=car backup_; backup_:=cdr backup_;
  2024. s:=restore_pdes(backup_)$
  2025. backup_:=nil;
  2026. orderings_:=car orderings_;
  2027. return s
  2028. end$
  2029. symbolic procedure level_string(s)$
  2030. << for each m in reverse level_ do s := if s then bldmsg("%w%d.",s,m)
  2031. else bldmsg("%d.",m );
  2032. s>>;
  2033. symbolic procedure backup_to_file(pdes,forg,nme)$
  2034. begin scalar s,ps$ %,levelcp$
  2035. if nme=t then <<
  2036. ps:=promptstring!*$
  2037. promptstring!*:=""$
  2038. terpri()$
  2039. write"Please give the name of the file in double quotes"$terpri()$
  2040. write"without `;' : "$
  2041. s:=termread()$
  2042. promptstring!*:=ps$
  2043. >> else
  2044. if nme then s:=nme
  2045. else s:=level_string(session_)$
  2046. out s;
  2047. off nat$
  2048. orderings_:=list orderings_;
  2049. write"off echo$"$
  2050. write "backup_:='"$terpri()$
  2051. print cons(size_hist,cons(stepcounter_,cons(level_,cons(nfct_,
  2052. cons(time_limit,cons(limit_time,cons(history_,
  2053. backup_pdes(pdes,forg))))))))$
  2054. write"$"$terpri()$
  2055. write "end$"$terpri()$
  2056. shut s;
  2057. on nat;
  2058. end$
  2059. symbolic procedure delete_backup$
  2060. begin scalar s$
  2061. s:=level_string(session_);
  2062. delete!-file s;
  2063. end$
  2064. symbolic procedure restore_and_merge(soln,pdes,forg)$
  2065. % pdes, forg are cleaned up
  2066. % one could just use restore_pdes without assigning bak
  2067. % but then it would not be stored in a file, such that
  2068. % rb can reload the file
  2069. begin scalar bak,newfdep,sol,f,h$
  2070. % store ongoing global values in bak
  2071. newfdep:=nil$
  2072. for each sol in soln do
  2073. if sol then <<
  2074. for each f in caddr sol do
  2075. if h:=assoc(f,depl!*) then newfdep:=cons(h,newfdep);
  2076. >>;
  2077. bak:=append(list(size_hist,stepcounter_,level_,nfct_,
  2078. time_limit,limit_time,history_),
  2079. newfdep);
  2080. h:=restore_backup_from_file(pdes,forg,nil)$
  2081. size_hist :=car bak; bak:=cdr bak;
  2082. stepcounter_:=car bak; bak:=cdr bak;
  2083. level_ :=car bak; bak:=cdr bak;
  2084. nfct_ :=car bak; bak:=cdr bak;
  2085. time_limit :=car bak; bak:=cdr bak;
  2086. limit_time :=car bak; bak:=cdr bak;
  2087. history_ :=car bak; bak:=cdr bak;
  2088. depl!* :=append(depl!*,bak);
  2089. return h
  2090. end$
  2091. symbolic procedure write_in_file(pdes,forg)$
  2092. begin scalar p,pl,s,h,ps,wn,vl,ftem$
  2093. ps:=promptstring!*$
  2094. promptstring!*:=""$
  2095. terpri()$
  2096. write "Enter a list of equations, like e2,e5,e35; from: "$terpri()$
  2097. listprint(pdes)$
  2098. terpri()$write "To write all equations just enter ; "$terpri()$
  2099. repeat <<
  2100. s:=termlistread()$
  2101. h:=s;
  2102. if s=nil then pl:=pdes else <<
  2103. pl:=nil;h:=nil$
  2104. if (null s) or pairp s then <<
  2105. for each p in s do
  2106. if member(p,pdes) then pl:=cons(p,pl);
  2107. h:=setdiff(pl,pdes);
  2108. >> else h:=s;
  2109. >>;
  2110. if h then <<write "These are no equations: ",h," Try again."$terpri()>>$
  2111. >> until null h$
  2112. write"Shall the name of the equation be written? (y/n) "$
  2113. repeat s:=termread()
  2114. until (s='y) or (s='Y) or (s='n) or (s='N)$
  2115. if (s='y) or (s='Y) then wn:=t$
  2116. write"Please give the name of the file in double quotes"$terpri()$
  2117. write"without `;' : "$
  2118. s:=termread()$
  2119. out s;
  2120. off nat$
  2121. write"load crack$"$terpri()$
  2122. write"lisp(nfct_:=",nfct_,")$"$terpri()$
  2123. if wn then write"lisp(nequ_:=",nequ_,")$"$terpri()$
  2124. write"off batch_mode$"$terpri()$
  2125. for each p in pl do <<h:=get(p,'vars);if h then vl:=union(h,vl)>>$
  2126. write"list_of_variables:="$
  2127. algebraic write lisp cons('LIST,vl)$
  2128. for each p in pl do <<h:=get(p,'fcts);if h then ftem:=union(h,ftem)>>$
  2129. write"list_of_functions:="$
  2130. algebraic write lisp cons('LIST,ftem)$
  2131. for each h in ftem do
  2132. if assoc(h,depl!*) then <<
  2133. p:=pl;
  2134. while p and freeof(get(car p,'val),h) do p:=cdr p;
  2135. if p then <<
  2136. write "depend ",h$
  2137. for each v in cdr assoc(h,depl!*) do <<
  2138. write ","$print v
  2139. >>$
  2140. write "$"$terpri()$
  2141. % for each v in cdr assoc(h,depl!*) do
  2142. % algebraic write "depend ",lisp h,",",lisp v$
  2143. >>
  2144. >>$
  2145. if wn then <<
  2146. for each h in pl do algebraic (write h,":=",lisp (get(h,'val)))$
  2147. write"list_of_equations:="$
  2148. algebraic write lisp( cons('LIST,pl) )
  2149. >> else <<
  2150. write"list_of_equations:="$
  2151. algebraic write lisp( cons('LIST,
  2152. for each h in pl collect get(h,'val)) )$
  2153. >>$
  2154. write"list_of_inequalities:="$
  2155. algebraic write lisp( cons('LIST,ineq_))$
  2156. terpri()$ write"solution_:=crack(list_of_equations,"$
  2157. terpri()$ write" list_of_inequalities,"$
  2158. terpri()$ write" list_of_functions,"$
  2159. terpri()$ write" list_of_variables)$"$
  2160. terpri()$
  2161. for each h in forg do <<
  2162. terpri()$
  2163. if pairp h and (car h = 'EQUAL) then
  2164. algebraic
  2165. write lisp(cadr h)," := sub(second first solution_,",
  2166. lisp(caddr h),")"
  2167. >>$
  2168. terpri()$
  2169. write"end$"$terpri()$terpri()$
  2170. write"These data were produced with the following input:"$terpri()$terpri()$
  2171. write"lisp( old_history := "$terpri()$
  2172. write"'",reverse history_,")$"$terpri()$
  2173. shut s;
  2174. on nat;
  2175. promptstring!*:=ps$
  2176. end$
  2177. symbolic procedure give_low_priority(pdes,f)$
  2178. % It assumes that f is element of ftem_.
  2179. % It assumes that if f is element of flin_ then flin_ functions
  2180. % come first in each group of functions with the same number
  2181. % of independent variables.
  2182. % If f is element of flin_ then f is put at the end of the flin_
  2183. % functions with equally many variables but before the first functions
  2184. % that occur in ineq_ in order to change ftem_ as little as possible
  2185. % not to invalidate previous decoupling.
  2186. begin scalar ftemcp,ano,h,s,fli$
  2187. ftemcp:=ftem_$
  2188. while ftemcp and (car ftemcp neq f) do <<
  2189. h:=cons(car ftemcp,h)$
  2190. ftemcp:=cdr ftemcp
  2191. >>$
  2192. % Is there an element of the remaining ftemcp with the same no of
  2193. % variables and that is not in ineq_ ?
  2194. if ftemcp then <<
  2195. ftemcp:=cdr ftemcp;
  2196. ano:=fctlength f$
  2197. if member(f,flin_) then fli:=t$
  2198. while ftemcp do
  2199. if (ano > (fctlength car ftemcp)) or
  2200. (fli and (not member(car ftemcp,flin_))) then ftemcp:=nil else <<
  2201. h:=cons(car ftemcp,h)$
  2202. ftemcp:=cdr ftemcp$
  2203. if not member(car h,ineq_) then <<
  2204. while ftemcp and
  2205. (ano = (fctlength car ftemcp)) and
  2206. (not member(car ftemcp,ineq_)) and
  2207. ((not fli) or member(car ftemcp,flin_)) do <<
  2208. h:=cons(car ftemcp,h)$
  2209. ftemcp:=cdr ftemcp
  2210. >>$
  2211. if print_ or tr_orderings then <<
  2212. write"The lexicographical ordering of unknowns is changed"$
  2213. terpri()$
  2214. write"because ",f," has to be non-zero, giving ",f," a low priority."$
  2215. terpri()$
  2216. write "Old ordering: "$
  2217. s:=ftem_;
  2218. while s do <<write car s$ s:=cdr s$ if s then write",">>$
  2219. terpri()$
  2220. write "New ordering: "$
  2221. s:=append(reverse h,cons(f,ftemcp));
  2222. while s do <<write car s$ s:=cdr s$ if s then write",">>$
  2223. terpri()$
  2224. >>$
  2225. change_fcts_ordering(append(reverse h,cons(f,ftemcp)),pdes,vl_)$
  2226. ftemcp:=nil
  2227. >> % of not member(car h,ineq_)
  2228. >> % of ano > (fctlength car ftemcp)
  2229. >> % of ftemcp
  2230. end$
  2231. symbolic procedure addineq(pdes,newineq)$
  2232. % it assumes newineq involves functions of ftem_
  2233. begin scalar h1,h2,h3$
  2234. newineq:=simp_ineq(newineq);
  2235. h1:=cdr err_catch_fac(newineq)$ % h1 is a lisp list of factors
  2236. if null cdr h1 then <<
  2237. h2:=signchange(car h1); % only one factor
  2238. if not member(h2,ineq_) then <<ineq_:=cons(h2,ineq_);h3:=cons(h2,h3)>>
  2239. >> else for each h2 in h1 do <<
  2240. h2:=signchange(h2);
  2241. if (not freeoflist(h2,ftem_)) and
  2242. (not member(h2,ineq_)) then <<ineq_:=cons(h2,ineq_);h3:=cons(h2,h3)>>
  2243. >>$
  2244. if print_ and h3 then <<
  2245. write"The list of inequalities got extended."$terpri()
  2246. >>$
  2247. % h3 is the list of all new non-zero expressions
  2248. % if any one of these expressions is an element of ftem_ then it
  2249. % should get a low priority in the lexicographical ordering for
  2250. % non-linear problems
  2251. if flin_ and null lin_problem then % maybe also for flin_=nil
  2252. for each h2 in h3 do
  2253. if atom h2 and member(h2,ftem_) then give_low_priority(pdes,h2);
  2254. % h2 gets a low priority so that it is eliminated late in decoupling
  2255. % to be available as non-zero coefficient as long as possible to
  2256. % allow substitutions of other functions without case-distinctions
  2257. if pdes then for each h2 in h3 do update_fcteval(pdes,h2);
  2258. % If one term of the equation is non-zero then the sum of the
  2259. % remaining terms has to be non-zero too
  2260. if h3 and pdes then for each h2 in pdes do
  2261. if get(h2,'terms)=2 then new_ineq_from_pde(h2,pdes)
  2262. end$
  2263. % symbolic procedure drop_factor(h,pro)$
  2264. % % This procedure drops a factor h or its negative from an expression pro
  2265. % begin scalar hs,newpro,mi;
  2266. % hs:=signchange(h);
  2267. % if pairp pro and (car pro='MINUS) then <<pro:=cadr pro; mi:=t>>;
  2268. % if pro = h then newpro:= 1 else
  2269. % if pro = hs then newpro:=-1 else
  2270. % if pairp pro and (car pro = 'TIMES) then
  2271. % if member(h ,pro) then newpro:=reval delete(h ,pro) else
  2272. % if member(hs,pro) then newpro:=reval list('MINUS,delete(hs,pro));
  2273. % if mi and newpro then newpro:=reval list('MINUS,newpro)
  2274. % return newpro
  2275. % end$
  2276. symbolic procedure update_fcteval(pdes,newineq)$
  2277. begin scalar p,pv,ps,hist,h1,h2$
  2278. for each p in pdes do <<
  2279. pv:=get(p,'val)$
  2280. if pairp pv and (car pv='TIMES) and member(newineq,pv) then <<
  2281. pv:=reval {'QUOTIENT,pv,newineq};
  2282. if record_hist then hist:=reval {'QUOTIENT,get(p,'histry_),newineq}$
  2283. update(p,pv,get(p,'fcts),get(p,'vars),t,list(0),pdes)$
  2284. drop_pde_from_idties(p,pdes,hist)$
  2285. drop_pde_from_properties(p,pdes)
  2286. >> else <<
  2287. ps:=get(p,'fcteval_nli)$
  2288. while ps and
  2289. <<h1:=caar ps;
  2290. h2:=signchange(h1);
  2291. (not ((newineq=h1 ) or
  2292. (pairp h1 and
  2293. (car h1 = 'TIMES) and
  2294. member(newineq,h1) ) )) and
  2295. (not ((newineq=h2 ) or
  2296. (pairp h2 and
  2297. (car h2 = 'TIMES) and
  2298. member(newineq,h2) ) ))
  2299. >> do ps:=cdr ps;
  2300. if ps then << % We would have to check whether apart from the
  2301. % new non-zero factor, the other factors can vanish for
  2302. % specific values of ftem_ or not. Instead of programming
  2303. % this again here we simply change flags to re-compute all
  2304. % fct... properties later when a substitution is to be done.
  2305. flag1(p,'to_eval)$
  2306. put(p,'fcteval_lin,nil)$
  2307. put(p,'fcteval_nca,nil)$
  2308. put(p,'fcteval_nli,nil)$
  2309. put(p,'fct_nli_lin,nil)$
  2310. put(p,'fct_nli_nca,nil)$
  2311. put(p,'fct_nli_nli,nil)$
  2312. put(p,'fct_nli_nus,nil)$
  2313. >>
  2314. >>
  2315. >>$
  2316. end$
  2317. symbolic procedure addfunction(ft)$
  2318. begin scalar f,ff,l,ps,ok$
  2319. ps:=promptstring!*$
  2320. promptstring!*:=""$
  2321. ff:=mkid(fname_,nfct_)$
  2322. repeat <<
  2323. ok:=t;
  2324. terpri()$
  2325. write "What is the name of the new function?"$
  2326. terpri()$
  2327. write "If the name is ",fname_,"+digits then use ",ff,". Terminate with <ENTER>: "$
  2328. f:=termread()$
  2329. if f=ff then nfct_:=add1 nfct_
  2330. else if member(f,ft) then <<
  2331. terpri()$
  2332. write"Choose another name. ",f," is already in use."$
  2333. ok:=nil
  2334. >>$
  2335. >> until ok;
  2336. depl!*:=delete(assoc(f,depl!*),depl!*)$
  2337. terpri()$
  2338. write "Give a list of variables ",f," depends on, for example x,y,z; "$
  2339. terpri()$
  2340. write "For constant ",f," input a `;' "$
  2341. l:=termxread()$
  2342. if (pairp l) and (car l='!*comma!*) then l:=cdr l;
  2343. if pairp l then depl!*:=cons(cons(f,l),depl!*) else
  2344. if l then depl!*:=cons(list(f,l),depl!*)$
  2345. ft:=fctinsert(f,ft)$
  2346. ftem_:=fctinsert(f,ftem_)$
  2347. promptstring!*:=ps$
  2348. return (ft . f)
  2349. end$
  2350. symbolic procedure newinequ(pdes)$
  2351. begin scalar ps,ex$
  2352. ps:=promptstring!*$
  2353. promptstring!*:=""$
  2354. write "Input of a value for the new non-vanishing expression."$
  2355. terpri()$
  2356. write "You can use names of pds, e.g. 3*e_12 - df(e_13,x) + 8; "$
  2357. terpri()$
  2358. write "Terminate the expression with ; or $ : "$
  2359. terpri()$
  2360. ex:=termxread()$
  2361. for each a in pdes do ex:=subst(get(a,'val),a,ex)$
  2362. terpri()$
  2363. promptstring!*:=ps$
  2364. addineq(pdes,ex)$
  2365. end$
  2366. symbolic procedure replacepde(pdes,ftem,vl)$
  2367. begin scalar p,q,ex,ps,h,newfct,again$
  2368. ps:=promptstring!*$ promptstring!*:=""$
  2369. repeat <<
  2370. terpri()$
  2371. write "Is there a"$
  2372. if again then write" further"$
  2373. write" new function in the changed/new PDE that"$
  2374. terpri()$
  2375. write "is to be calculated (y/n)? "$
  2376. p:=termread()$
  2377. if (p='y) or (p='Y) then <<
  2378. h:=addfunction(ftem)$
  2379. ftem:=car h$
  2380. if cdr h then newfct:=cons(cdr h,newfct)
  2381. >>;
  2382. again:=t
  2383. >> until (p='n) or (p='N)$
  2384. terpri()$
  2385. write "If you want to replace a pde then type its name, e.g. e_23 <ENTER>."$
  2386. terpri()$
  2387. write "If you want to add a pde then type `new_pde' <ENTER>. "$
  2388. p:=termread()$
  2389. if (p='NEW_PDE) or member(p,pdes) then
  2390. <<terpri()$write "Input of a value for "$
  2391. if p='new_pde then write "the new pde."
  2392. else write p,"."$
  2393. terpri()$
  2394. write "You can use names of other pds, e.g. 3*e_12 - df(e_13,x); "$
  2395. terpri()$
  2396. write "Terminate the expression with ; or $ : "$
  2397. terpri()$
  2398. ex:=termxread()$
  2399. for each a in pdes do ex:=subst(get(a,'val),a,ex)$
  2400. terpri()$
  2401. write "Do you want the equation to be"$terpri()$
  2402. % write "- left completely unchanged"$
  2403. % terpri()$
  2404. % write " (e.g. to keep the structure of a product to "$
  2405. % terpri()$
  2406. % write " investigate subcases) (1)"$
  2407. % terpri()$
  2408. write "- simplified (e.g. e**log(x) -> x) without"$
  2409. terpri()$
  2410. write " dropping non-zero factors and denominators"$
  2411. terpri()$
  2412. write " (e.g. to introduce integrating factors) (1)"$
  2413. terpri()$
  2414. write "- simplified completely (2) "$
  2415. h:=termread()$
  2416. % if h=2 then ex:=reval ex$
  2417. % if h<3 then h:=nil
  2418. % else h:=t$
  2419. if h=1 then <<ex:=reval ex$h:=nil>>
  2420. else h:=t$
  2421. if p neq 'NEW_PDE then
  2422. pdes:=drop_pde(p,pdes,{'QUOTIENT,{'TIMES,p,ex},get(p,'val)})$
  2423. q:=mkeq(ex,ftem,vl,allflags_,h,list(0),nil,pdes)$
  2424. % A new equation with a new function appearing linear and only
  2425. % algebraically can only have the purpose of a transformation
  2426. % in which case the new equation should not be solved for the
  2427. % new function as this would just mean dropping the new equation:
  2428. if (p='NEW_PDE) and newfct then
  2429. put(q,'not_to_eval,newfct)$
  2430. terpri()$write q$
  2431. if p='NEW_PDE then write " is added"
  2432. else write " replaces ",p$
  2433. pdes:=eqinsert(q,pdes)>>
  2434. else <<terpri()$
  2435. write "A pde ",p," does not exist! (Back to previous menu)">>$
  2436. promptstring!*:=ps$
  2437. return list(pdes,ftem)
  2438. end$
  2439. symbolic procedure select_from_list(liste,n)$
  2440. begin scalar ps,s$
  2441. ps:=promptstring!*$
  2442. promptstring!*:=""$
  2443. terpri()$
  2444. if n then write"Pick ",n," from this list:"
  2445. else write"Pick from this list"$
  2446. terpri()$
  2447. listprint(liste)$write";"$terpri()$
  2448. if null n then <<
  2449. write"a sublist and input it in the same form. Enter ; to choose all."$
  2450. terpri()$
  2451. >>$
  2452. s:=termlistread()$
  2453. if n and n neq length s then <<
  2454. write "Wrong number picked."$terpri()$
  2455. s:=nil;
  2456. >> else
  2457. if null s then s:=liste else
  2458. if not_included(s,liste) then <<
  2459. write setdiff(s,liste)," is not allowed."$terpri()$
  2460. s:=nil;
  2461. >>;
  2462. promptstring!*:=ps$
  2463. return s
  2464. end$
  2465. symbolic procedure selectpdes(pdes,n)$
  2466. % interactive selection of n pdes
  2467. % n may be an integer or nil. If nil then the
  2468. % number of pdes is free.
  2469. if pdes then
  2470. begin scalar l,s,ps,m$
  2471. ps:=promptstring!*$
  2472. promptstring!*:=""$
  2473. terpri()$
  2474. if null n then <<
  2475. write "How many equations do you want to select? "$terpri()$
  2476. write "(number <ENTER>) : "$terpri()$
  2477. n:=termread()$
  2478. >>$
  2479. write "Please select ",n," equation"$
  2480. if n>1 then write "s"$write " from: "$
  2481. write pdes$ % fctprint pdes$
  2482. terpri()$
  2483. m:=0$
  2484. s:=t$
  2485. while (m<n) and s do
  2486. <<m:=add1 m$
  2487. if n>1 then write m,". "$
  2488. write "pde: "$
  2489. s:=termread()$
  2490. while not member(s,pdes) do
  2491. <<write "Error!!! Please select a pde from: "$
  2492. write pdes$ % fctprint pdes$
  2493. terpri()$if n>1 then write m,". "$
  2494. write "pde: "$
  2495. s:=termread()>>$
  2496. if s then
  2497. <<pdes:=delete(s,pdes)$
  2498. l:=cons(s,l)>> >>$
  2499. promptstring!*:=ps$
  2500. return reverse l$
  2501. end$
  2502. symbolic operator nodepnd$
  2503. symbolic procedure nodepnd(fl)$
  2504. for each f in cdr fl do
  2505. depl!*:=delete(assoc(reval f,depl!*),depl!*)$
  2506. symbolic procedure err_catch_readin$
  2507. begin scalar h,mode_bak,echo_bak$
  2508. mode_bak:=!*mode; % as the _stop_ file has to start with 'lisp;'
  2509. echo_bak:=!*echo; semic!*:='!$;
  2510. h:= errorset({'in,mkquote {"_stop_"}},nil,nil)
  2511. where !*protfg=t;
  2512. !*echo:=echo_bak; semic!*:='!; ;
  2513. erfg!*:=nil; !*mode:=mode_bak$
  2514. return not errorp h
  2515. end$
  2516. symbolic procedure err_catch_solve(eqs,fl)$
  2517. % fl='(LIST x y z); eqs='(LIST expr1 expr2 .. )
  2518. begin scalar h$
  2519. h:=errorset({'solveeval,mkquote{eqs, fl}},nil,nil)
  2520. where !*protfg=t;
  2521. erfg!*:=nil;
  2522. return if errorp h then nil
  2523. else cdar h % cdr for deleting 'LIST
  2524. end$
  2525. symbolic operator err_catch_sub$
  2526. symbolic procedure err_catch_sub(h2,h6,h3)$
  2527. % do sub(h2=h6,h3) with error catching
  2528. begin scalar h4,h5;
  2529. h4 := list('EQUAL,h2,h6);
  2530. h5:=errorset({'subeval,mkquote{reval h4,
  2531. reval h3 }},nil,nil)
  2532. where !*protfg=t;
  2533. erfg!*:=nil;
  2534. return if errorp h5 then nil
  2535. else car h5
  2536. end$
  2537. symbolic operator err_catch_int$
  2538. symbolic procedure err_catch_int(h2,h3)$
  2539. % do int(h2,h3) with error catching
  2540. begin scalar h5;
  2541. h5:=errorset({'simpint,mkquote{reval h2,
  2542. reval h3 }},nil,nil)
  2543. where !*protfg=t;
  2544. erfg!*:=nil;
  2545. return if errorp h5 then nil
  2546. else
  2547. if not freeof(car h5,'INT) then nil
  2548. else prepsq car h5
  2549. end$
  2550. symbolic procedure beforegcsystemhook()$
  2551. my_gc_counter:=add1 my_gc_counter$
  2552. symbolic procedure aftergcsystemhook()$
  2553. if my_gc_counter > max_gc_counter then <<
  2554. if print_ % and print_more (User must know that not all is computed.)
  2555. then <<
  2556. write "Stop of a subroutine."$terpri()$
  2557. write "Number of garbage collections exceeds ",backup_,".";
  2558. terpri()$
  2559. >>$
  2560. rederr "Heidadeife "
  2561. >>$
  2562. symbolic operator err_catch_fac$
  2563. symbolic procedure err_catch_fac(a)$
  2564. begin scalar h,bak,kernlist!*bak,kord!*bak,bakup_bak;
  2565. bak:=max_gc_counter;
  2566. max_gc_counter:=my_gc_counter+max_gc_fac;
  2567. kernlist!*bak:=kernlist!*$
  2568. kord!*bak:=kord!*$
  2569. bakup_bak:=backup_;backup_:='max_gc_fac$
  2570. h:=errorset({'reval,list('FACTORIZE,mkquote a)},nil,nil)
  2571. where !*protfg=t;
  2572. kernlist!*:=kernlist!*bak$
  2573. kord!*:=kord!*bak;
  2574. erfg!*:=nil;
  2575. max_gc_counter:=bak;
  2576. backup_:=bakup_bak;
  2577. return if errorp h then {'LIST,a}
  2578. else car h
  2579. end$
  2580. symbolic operator err_catch_gcd$
  2581. symbolic procedure err_catch_gcd(a,b)$
  2582. begin scalar h,bak,kernlist!*bak,kord!*bak,bakup_bak;
  2583. bak:=max_gc_counter;
  2584. max_gc_counter:=my_gc_counter+max_gc_fac;
  2585. kernlist!*bak:=kernlist!*$
  2586. kord!*bak:=kord!*$
  2587. bakup_bak:=backup_;backup_:='max_gc_fac$
  2588. h:=errorset({'reval,list('GCD,mkquote a,mkquote b)},nil,nil)
  2589. where !*protfg=t;
  2590. kernlist!*:=kernlist!*bak$
  2591. kord!*:=kord!*bak;
  2592. erfg!*:=nil;
  2593. max_gc_counter:=bak;
  2594. backup_:=bakup_bak;
  2595. return if errorp h then 1
  2596. else car h
  2597. end$
  2598. %symbolic operator err_catch_fac$
  2599. %symbolic procedure err_catch_fac(a)$
  2600. %begin scalar h,bak,bakup_bak;
  2601. % bak:=max_gc_counter;
  2602. % max_gc_counter:=my_gc_counter+max_gc_fac;
  2603. % bakup_bak:=backup_;backup_:='max_gc_fac$
  2604. % h:=errorset({'reval,list('FACTORIZE,mkquote a)},nil,nil)
  2605. % where !*protfg=t;
  2606. % erfg!*:=nil;
  2607. % max_gc_counter:=bak;
  2608. % backup_:=bakup_bak;
  2609. % return if errorp h then {'LIST,a}
  2610. % else car h
  2611. %end$
  2612. symbolic procedure factored_form(a)$
  2613. % a is expected to be in prefix form
  2614. begin scalar b;
  2615. if (pairp a) and (car a = 'PLUS) then <<
  2616. b:=err_catch_fac a$
  2617. if b and (length b > 2) then a:=cons('TIMES,cdr b)
  2618. >>;
  2619. return a
  2620. end$
  2621. symbolic lispeval '(putd 'countids 'expr
  2622. '(lambda nil (prog (nn) (setq nn 0)
  2623. (mapobl (function (lambda (x) (setq nn (plus2 nn 1)))))
  2624. (return nn))))$
  2625. symbolic operator low_mem$
  2626. % if garbage collection recovers only 500000 cells then backtrace
  2627. % to be used only on workstations, not PCs i.e. under LINUX, Windows
  2628. symbolic procedure newreclaim()$
  2629. <<oldreclaim();
  2630. if (known!-free!-space() < 500000 ) then backtrace()
  2631. >>$
  2632. symbolic procedure low_mem()$
  2633. if not( getd 'oldreclaim) then <<
  2634. copyd('oldreclaim,'!%reclaim);
  2635. copyd('!%reclaim,'newreclaim);
  2636. >>$
  2637. symbolic operator polyansatz$
  2638. symbolic procedure polyansatz(ev,iv,fn,degr,homo)$
  2639. % ev, iv are algebraic mode lists
  2640. % generates a polynomial in the variables ev of degree degr
  2641. % with functions of the variables iv
  2642. % if homo then a homogeneous polynomial
  2643. begin scalar a,fi,el1,el2,f,fl,p,pr;
  2644. a:=reval list('EXPT,cons('PLUS,if homo then cdr ev
  2645. else cons(1,cdr ev)),degr)$
  2646. a:=reverse cdr a$
  2647. fi:=0$
  2648. iv:=cdr iv$
  2649. for each el1 in a collect <<
  2650. if (not pairp el1) or
  2651. (car el1 neq 'TIMES) then el1:=list el1
  2652. else el1:=cdr el1;
  2653. f:=newfct(fn,iv,fi);
  2654. fi:=add1 fi;
  2655. fl:=cons(f,fl)$
  2656. pr:=list f$
  2657. for each el2 in el1 do
  2658. if not fixp el2 then pr:=cons(el2,pr);
  2659. if length pr>1 then pr:=cons('TIMES,pr)
  2660. else pr:=car pr;
  2661. p:=cons(pr,p)
  2662. >>$
  2663. p:=reval cons('PLUS,p)$
  2664. return list('LIST,p,cons('LIST,fl))
  2665. end$
  2666. symbolic operator polyans$
  2667. symbolic procedure polyans(ordr,dgr,x,y,d_y,fn)$
  2668. % generates a polynom
  2669. % for i:=0:dgr sum fn"i"(x,y,d_y(1),..,d_y(ordr-1))*d_y(ordr)**i
  2670. % with fn as the function names and d_y as names or derivatives of y
  2671. % w.r.t. x
  2672. begin scalar ll,fl,a,i,f$
  2673. i:=sub1 ordr$
  2674. while i>0 do
  2675. <<ll:=cons(list(d_y,i),ll)$
  2676. i:=sub1 i>>$
  2677. ll:=cons(y,ll)$
  2678. ll:=reverse cons(x,ll)$
  2679. fl:=nil$
  2680. i:=0$
  2681. while i<=dgr do
  2682. <<f:=newfct(fn,ll,i)$
  2683. fl:=(f . fl)$
  2684. a:=list('PLUS,list('TIMES,f,list('EXPT,list(d_y,ordr),i)),a)$
  2685. i:=add1 i>>$
  2686. return list('list,reval a,cons('list,fl))
  2687. end$ % of polyans
  2688. symbolic operator sepans$
  2689. symbolic procedure sepans(kind,v1,v2,fn)$
  2690. % Generates a separation ansatz
  2691. % v1,v2 = lists of variables, fn = new function name + index added
  2692. % The first variable of v1 occurs only in one sort of the two sorts of
  2693. % functions and the remaining variables of v1 in the other sort of
  2694. % functios.
  2695. % The variables of v2 occur in all functions.
  2696. % Returned is a sum of products of each one function of both sorts.
  2697. % form: fn1(v11;v21,v22,v23,..)*fn2(v12,..,v1n;v21,v22,v23,..)+...
  2698. % the higher "kind", the more general and difficult the ansatz is
  2699. % kind = 0 is the full case
  2700. begin scalar n,vl1,vl2,h1,h2,h3,h4,fl$
  2701. if cdr v1 = nil then <<vl1:=cdr v2$vl2:=cdr v2>>
  2702. else <<vl1:=cons(cadr v1,cdr v2)$
  2703. vl2:=append(cddr v1,cdr v2)>>$
  2704. return
  2705. if kind = 0 then <<vl1:=append(cdr v1,cdr v2)$
  2706. h1:=newfct(fn,vl1,'_)$
  2707. list('LIST,h1,list('LIST,h1))>>
  2708. else
  2709. if kind = 1 then <<h1:=newfct(fn,vl1,1)$
  2710. list('LIST,h1,list('LIST,h1))>>
  2711. else
  2712. if kind = 2 then <<h1:=newfct(fn,vl2,1)$
  2713. list('LIST,h1,list('LIST,h1))>>
  2714. else
  2715. if kind = 3 then <<h1:=newfct(fn,vl1,1)$
  2716. h2:=newfct(fn,vl2,2)$
  2717. list('LIST,reval list('PLUS,h1,h2),
  2718. list('LIST,h1,h2))>>
  2719. else
  2720. if kind = 4 then <<h1:=newfct(fn,vl1,1)$
  2721. h2:=newfct(fn,vl2,2)$
  2722. list('LIST,reval list('TIMES,h1,h2),
  2723. list('LIST,h1,h2))>>
  2724. else
  2725. if kind = 5 then <<h1:=newfct(fn,vl1,1)$
  2726. h2:=newfct(fn,vl2,2)$
  2727. h3:=newfct(fn,vl1,3)$
  2728. list('LIST,reval list('PLUS,list('TIMES,h1,h2),h3),
  2729. list('LIST,h1,h2,h3))>>
  2730. else
  2731. if kind = 6 then <<h1:=newfct(fn,vl1,1)$
  2732. h2:=newfct(fn,vl2,2)$
  2733. h3:=newfct(fn,vl2,3)$
  2734. list('LIST,reval list('PLUS,list('TIMES,h1,h2),h3),
  2735. list('LIST,h1,h2,h3))>>
  2736. else
  2737. if kind = 7 then <<h1:=newfct(fn,vl1,1)$
  2738. h2:=newfct(fn,vl2,2)$
  2739. h3:=newfct(fn,vl1,3)$
  2740. h4:=newfct(fn,vl2,4)$
  2741. list('LIST,reval list('PLUS,
  2742. list('TIMES,h1,h2),h3,h4),
  2743. list('LIST,h1,h2,h3,h4))>>
  2744. else
  2745. % ansatz of the form FN = FN1(v11,v2) + FN2(v12,v2) + ... + FNi(v1i,v2)
  2746. if kind = 8 then <<n:=1$ vl1:=cdr v1$ vl2:=cdr v2$
  2747. fl:=()$
  2748. while vl1 neq () do <<
  2749. h1:=newfct(fn,cons(car vl1,vl2),n)$
  2750. vl1:=cdr vl1$
  2751. fl:=cons(h1, fl)$
  2752. n:=n+1
  2753. >>$
  2754. list('LIST, cons('PLUS,fl), cons('LIST,fl))>>
  2755. else
  2756. <<h1:=newfct(fn,vl1,1)$
  2757. h2:=newfct(fn,vl2,2)$
  2758. h3:=newfct(fn,vl1,3)$
  2759. h4:=newfct(fn,vl2,4)$
  2760. list('LIST,reval list('PLUS,list('TIMES,h1,h2),
  2761. list('TIMES,h3,h4)),
  2762. list('LIST,h1,h2,h3,h4))>>
  2763. end$ % of sepans
  2764. %
  2765. % Orderings support!
  2766. %
  2767. % change_derivs_ordering(pdes,fl,vl) changes the ordering of the
  2768. % list of derivatives depending on the current ordering (this
  2769. % is detected "automatically" by sort_derivs using the lex_df flag to
  2770. % toggle between total-degree and lexicographic.
  2771. %
  2772. symbolic procedure change_derivs_ordering(pdes,fl,vl)$
  2773. begin scalar p, dl;
  2774. for each p in pdes do <<
  2775. if tr_orderings then <<
  2776. terpri()$
  2777. write "Old: ", get(p,'derivs)$
  2778. >>$
  2779. dl := sort_derivs(get(p,'derivs),fl,vl)$
  2780. if tr_orderings then <<
  2781. terpri()$
  2782. write "New: ", dl$
  2783. >>$
  2784. put(p,'derivs,dl)$
  2785. put(p,'dec_with,nil)$ % only if orderings are not
  2786. % investigated in parallel (-->ord)
  2787. put(p,'dec_with_rl,nil) % only if orderings are not ..
  2788. >>$
  2789. return pdes
  2790. end$
  2791. symbolic procedure sort_according_to(r,s)$
  2792. % all elements in r that are in s are sorted according to their order in s
  2793. begin scalar ss,h;
  2794. for each ss in s do
  2795. if member(ss,r) then h:=cons(ss,h);
  2796. return reverse h
  2797. end$
  2798. symbolic procedure change_fcts_ordering(newli,pdes,vl)$
  2799. begin scalar s$
  2800. ftem_ := newli$
  2801. for each s in pdes do put(s,'fcts,sort_according_to(get(s,'fcts),ftem_))$
  2802. pdes := change_derivs_ordering(pdes,ftem_,vl)$
  2803. if tr_orderings then <<
  2804. terpri()$
  2805. write "New functions list: ", ftem_$
  2806. >>
  2807. end$
  2808. symbolic procedure check_history(pdes)$
  2809. begin scalar p,q,h$
  2810. for each p in pdes do <<
  2811. h:=get(p,'histry_);
  2812. for each q in pdes do
  2813. h:=subst(get(q,'val),q,h)$
  2814. if algebraic((lisp(get(p,'val)) - h) neq 0) then <<
  2815. write"The history value of ",p," is not correct!"$
  2816. terpri()
  2817. >>
  2818. >>
  2819. end$
  2820. symbolic procedure check_globals$
  2821. % to check validity of global variables at start of CRACK
  2822. begin scalar flag, var$
  2823. % The integer variables
  2824. foreach var in global_list_integer do
  2825. if not fixp eval(var) then <<
  2826. terpri()$
  2827. write var, " needs to be an integer: ", eval(var)," is invalid"$
  2828. flag := var
  2829. >>$
  2830. % Now for integer variables allowed to be nil
  2831. foreach var in global_list_ninteger do
  2832. if not fixp eval(var) and eval(var) neq nil then <<
  2833. terpri()$
  2834. write var, " needs to be an integer or nil: ",
  2835. eval(var)," is invalid"$
  2836. flag := var
  2837. >>$
  2838. % Finally variables containing any number
  2839. foreach var in global_list_number do
  2840. if not numberp eval(var) then <<
  2841. terpri()$
  2842. write var, " needs to be a number: ", eval(var)," is invalid"$
  2843. flag := var
  2844. >>$
  2845. return flag
  2846. end$
  2847. symbolic procedure search_li(l,care)$
  2848. % Find the cadr of all sublists which have 'care' as car (no nesting)
  2849. if pairp l then
  2850. if car l = care then {cadr l}
  2851. else begin
  2852. scalar a,b,resul;
  2853. for each a in l do
  2854. if b:=search_li(a,care) then resul:=union(b,resul);
  2855. return resul
  2856. end$
  2857. symbolic procedure search_li2(l,care)$
  2858. % Find all sublists which have 'care' as car (no nesting)
  2859. if pairp l then
  2860. if car l = care then list l
  2861. else begin
  2862. scalar a,b,resul;
  2863. for each a in l do
  2864. if b:=search_li2(a,care) then resul:=union(b,resul);
  2865. return resul
  2866. end$
  2867. symbolic operator backup_reduce_flags$
  2868. symbolic procedure backup_reduce_flags$
  2869. % !*nopowers = t to have output of FACTORIZE like in Reduce 3.6
  2870. % !*allowdfint = t moved here from crintfix, to enable simplification
  2871. % of derivatives of integrals
  2872. begin
  2873. !*dfprint_bak := cons(!*dfprint,!*dfprint_bak)$
  2874. !*exp_bak := cons(!*exp,!*exp_bak)$
  2875. !*ezgcd_bak := cons(!*ezgcd,!*ezgcd_bak)$
  2876. !*fullroots_bak := cons(!*fullroots,!*fullroots_bak)$
  2877. !*gcd_bak := cons(!*gcd,!*gcd_bak)$
  2878. !*mcd_bak := cons(!*mcd,!*mcd_bak)$
  2879. !*ratarg_bak := cons(!*ratarg,!*ratarg_bak)$
  2880. !*rational_bak := cons(!*rational,!*rational_bak)$
  2881. if null !*dfprint then algebraic(on dfprint)$
  2882. if null !*exp then algebraic(on exp)$
  2883. if null !*ezgcd then algebraic(on ezgcd)$
  2884. if null !*fullroots then algebraic(on fullroots)$
  2885. if !*gcd then algebraic(off gcd)$
  2886. if null !*mcd then algebraic(on mcd)$
  2887. if null !*ratarg then algebraic(on ratarg)$
  2888. if null !*rational then algebraic(on rational)$
  2889. !#if (neq version!* "REDUCE 3.6")
  2890. !*nopowers_bak := cons(!*nopowers,!*nopowers_bak)$
  2891. !*allowdfint_bak := cons(!*allowdfint,!*allowdfint_bak)$
  2892. if null !*nopowers then algebraic(on nopowers)$
  2893. if null !*allowdfint then algebraic(on allowdfint)$
  2894. !#endif
  2895. end$
  2896. symbolic operator recover_reduce_flags$
  2897. symbolic procedure recover_reduce_flags$
  2898. begin
  2899. if !*dfprint neq car !*dfprint_bak then
  2900. if !*dfprint then algebraic(off dfprint) else algebraic(on dfprint)$
  2901. !*dfprint_bak:= cdr !*dfprint_bak$
  2902. if !*exp neq car !*exp_bak then
  2903. if !*exp then algebraic(off exp) else algebraic(on exp)$
  2904. !*exp_bak:= cdr !*exp_bak$
  2905. if !*ezgcd neq car !*ezgcd_bak then
  2906. if !*ezgcd then algebraic(off ezgcd) else algebraic(on ezgcd)$
  2907. !*ezgcd_bak:= cdr !*ezgcd_bak$
  2908. if !*fullroots neq car !*fullroots_bak then
  2909. if !*fullroots then algebraic(off fullroots) else algebraic(on fullroots)$
  2910. !*fullroots_bak:= cdr !*fullroots_bak$
  2911. if !*gcd neq car !*gcd_bak then
  2912. if !*gcd then algebraic(off gcd) else algebraic(on gcd)$
  2913. !*gcd_bak:= cdr !*gcd_bak$
  2914. if !*mcd neq car !*mcd_bak then
  2915. if !*mcd then algebraic(off mcd) else algebraic(on mcd)$
  2916. !*mcd_bak:= cdr !*mcd_bak$
  2917. if !*ratarg neq car !*ratarg_bak then
  2918. if !*ratarg then algebraic(off ratarg) else algebraic(on ratarg)$
  2919. !*ratarg_bak:= cdr !*ratarg_bak$
  2920. if !*rational neq car !*rational_bak then
  2921. if !*rational then algebraic(off rational) else algebraic(on rational)$
  2922. !*rational_bak:= cdr !*rational_bak$
  2923. !#if (neq version!* "REDUCE 3.6")
  2924. if !*nopowers neq car !*nopowers_bak then
  2925. if !*nopowers then algebraic(off nopowers) else algebraic(on nopowers)$
  2926. !*nopowers_bak:= cdr !*nopowers_bak$
  2927. if !*allowdfint neq car !*allowdfint_bak then
  2928. if !*allowdfint then algebraic(off allowdfint) else algebraic(on allowdfint)$
  2929. !*allowdfint_bak:= cdr !*allowdfint_bak$
  2930. !#endif
  2931. end$
  2932. algebraic procedure maklist(ex)$
  2933. % making a list out of an expression if not already
  2934. if lisp(atom algebraic ex) then {ex} else
  2935. if lisp(car algebraic ex neq 'LIST) then ex:={ex}
  2936. else ex$
  2937. symbolic procedure add_to_last_steps(h)$
  2938. if length last_steps < 20 then last_steps:=cons(h,last_steps) else
  2939. last_steps:=cons(h,reverse cdr reverse last_steps)$
  2940. symbolic procedure same_steps(a,b)$
  2941. if (car a = car b ) and
  2942. ((a = b) or
  2943. ((car a neq 'subst) and
  2944. (car a neq 27 ) and
  2945. (car a neq 11 ) )) then t
  2946. else nil$
  2947. symbolic procedure in_cycle(h)$
  2948. begin scalar cpls1,cpls2,n,cycle;
  2949. cpls1:=last_steps$
  2950. if car h='subst then <<
  2951. n:=0$
  2952. while cpls1 do <<
  2953. if same_steps(h,car cpls1) then n:=add1 n;
  2954. cpls1:=cdr cpls1
  2955. >>$
  2956. cycle:=
  2957. if n>2 then << % the subst. had been done already >=3 times
  2958. write"A partial substitution has been repeated too often."$ terpri()$
  2959. write"It will now be made rigorously."$ terpri()$
  2960. t
  2961. >> else nil
  2962. % add_to_last_steps(h) is done outside for substitutions as it is not
  2963. % clear at this stage whether the substitution will be performed
  2964. >> else <<
  2965. n:=1$
  2966. while cpls1 and (not same_steps(h,car cpls1)) do
  2967. <<n:=add1 n;cpls1:=cdr cpls1>>$
  2968. if null cpls1 or
  2969. ((reval {'PLUS,n,n})>length last_steps) then cycle:=nil
  2970. else <<
  2971. cpls1:=cdr cpls1;
  2972. cpls2:=last_steps$
  2973. while (n>0) and same_steps(car cpls2,car cpls1) do
  2974. <<cpls1:=cdr cpls1;cpls2:=cdr cpls2;n:=sub1 n>>$
  2975. if (n=0) and print_ then <<
  2976. write if car h = 11 then "An algebraic length reduction" else
  2977. if car h = 27 then "A length reducing simplification" else
  2978. "A step",
  2979. " was prevented"$ terpri()$
  2980. write"to avoid a cycle."$ terpri()$
  2981. >>$
  2982. cycle:=if n>0 then nil else t
  2983. >>;
  2984. if null cycle then add_to_last_steps(h)$
  2985. >>;
  2986. return cycle
  2987. end$
  2988. endmodule$
  2989. %********************************************************************
  2990. module solution_handling$
  2991. %********************************************************************
  2992. % Routines for storing, retrieving, merging and displaying solutions
  2993. % Author: Thomas Wolf Dec 2001
  2994. symbolic procedure save_solution(eqns,assigns,freef,ineq,file_name)$
  2995. % input data are algebraic mode
  2996. % eqns .. list of remaining unsolved equations
  2997. % assigns .. list of computed assignments of the form `function = expression'
  2998. % freef .. list of list of functiones either free or in eqns
  2999. % ineq .. list of inequalities
  3000. begin scalar s,levelcp,h,p,conti$
  3001. if file_name then s:=file_name
  3002. else <<
  3003. s:=session_;
  3004. levelcp:=reverse level_;
  3005. while levelcp do <<setq(s,bldmsg("%w%d.",s,car levelcp));
  3006. levelcp:=cdr levelcp>>;
  3007. s:=explode s;
  3008. s:=compress cons(car s,cons('s,cons('o,cdddr s)))$
  3009. >>$
  3010. sol_list:=union(list s,sol_list)$
  3011. out s;
  3012. write"off echo$ "$
  3013. write"backup_:='("$terpri()$
  3014. for each h in freef do
  3015. if p:=assoc(h,depl!*) then conti:=cons(p,conti);
  3016. % The first sub-list is a list of dependencies, like ((f x y) (g x))
  3017. write"% A list of dependencies, like ((f x y) (g x))"$terpri()$
  3018. print conti$write" "$terpri()$
  3019. % The next sublist is a list of unsolved equations
  3020. write"% A list of unsolved equations"$terpri()$
  3021. print eqns$write" "$terpri()$
  3022. % The next sublist is a list of assignments
  3023. write"% A list of assignments"$terpri()$
  3024. print assigns$write" "$terpri()$
  3025. % The next sublist is a list of free or unresolved functions
  3026. write"% A list of free or unresolved functions"$terpri()$
  3027. print freef$write" "$terpri()$
  3028. % The next sublist is a list of non-vanishing expressions
  3029. write"% A list of non-vanishing expressions"$terpri()$
  3030. print ineq$terpri()$
  3031. write")$"$
  3032. % shorter but less clear: print list(conti,eqns,freef,ineq)$
  3033. write "end$"$terpri()$
  3034. shut s;
  3035. return s
  3036. end$
  3037. symbolic procedure print_indexed_list(li)$
  3038. begin scalar a,h$
  3039. terpri()$
  3040. h:=0$
  3041. for each a in li do <<
  3042. h:=add1 h;
  3043. write"[",h,"]";terpri()$
  3044. mathprint a
  3045. >>
  3046. end$
  3047. symbolic procedure merge_two(s1,sol1,s2,sol2,absorb)$
  3048. % Is sol1 a special case of sol2 ?
  3049. % If yes, return the new generalized solution sol2 with one less inequality.
  3050. % If absorb then modify s2 and sol2 if s1 can be absorbed
  3051. begin scalar eli_2,singular_eli,regular_eli,a,b,cond2,sb,remain_sb,
  3052. singular_sb,regular_sb,c2,remain_c2,remain_num_c2,h,
  3053. try_to_sub,try_to_sub_cp,num_sb,num_sb_quo,singular_ex,
  3054. singular_ex_cp,ineq2,ine,ineqnew,ineqdrop,tr_merge,
  3055. extra_par_in_s1,gauge_of_s2,gauge_of_s2_cp,did_trafo,n,
  3056. remain_c2_cp,dropped_assign_in_s2,new_assign_in_s2$
  3057. % tr_merge:=t$
  3058. if tr_merge then <<write"s1=",s1$terpri()$
  3059. write"s2=",s2$terpri()$
  3060. write"*** sol1 ***:"$print_indexed_list(caddr sol1)$
  3061. write"*** sol2 ***:"$print_indexed_list(caddr sol2)$
  3062. write"free param in sol1: ",cadddr sol1$terpri()$
  3063. write"free param in sol2: ",cadddr sol2$terpri()>>$
  3064. % At first we list all lhs y_i in assignments y_i=... in sol2
  3065. eli_2:=setdiff(for each a in caddr sol2 collect cadr a,cadddr sol2);
  3066. % We use setdiff because of assignments, like a6=a6 in sol2
  3067. % where a6 is a free parameter.
  3068. % writing assignments of solution 2 as expressions to vanish
  3069. cond2:=for each a in caddr sol2
  3070. collect {'PLUS,cadr a,{'MINUS,caddr a}};
  3071. % Do all substitutions a=... from sol1 for which
  3072. % there is an assignment a=... in sol2 and
  3073. % collecting the others as remain_sb
  3074. cond2:=cons('LIST,cond2);
  3075. sb:=caddr sol1; % all assignments of solution 1
  3076. while sb do <<
  3077. a:=car sb; sb:=cdr sb;
  3078. if member(cadr a,eli_2) then <<
  3079. eli_2:=delete(cadr a,eli_2)$
  3080. cond2:=err_catch_sub(cadr a,caddr a,cond2)
  3081. >> else remain_sb:=cons(a,remain_sb)
  3082. >>$
  3083. eli_2:=append(eli_2,cadddr sol2)$
  3084. % eli_2 is now the list of new sol2 parameters
  3085. % At this stage any sol2 conditions either become singular or zero.
  3086. % The singular ones are collected in remain_c2.
  3087. % The same again, now taking only numerators
  3088. remain_c2:=cond2;
  3089. cond2:=cdr cond2;
  3090. c2:=nil$
  3091. h:=0$
  3092. while cond2 and (null c2 or zerop c2) do <<
  3093. c2:=car cond2;
  3094. h:=add1 h;
  3095. if tr_merge then <<write"[",h,"]"$terpri()$mathprint c2>>$
  3096. % Is the numerator of c2 fulfilled by assignments of solution 1?
  3097. sb:=remain_sb; % all remaining assignments of solution 1
  3098. while sb and c2 and not zerop c2 do <<
  3099. a:=car sb; sb:=cdr sb;
  3100. c2:=algebraic(num(lisp(c2)));
  3101. if tr_merge then b:=c2;
  3102. c2:=err_catch_sub(cadr a,caddr a,c2);
  3103. if tr_merge and (b neq c2) then <<
  3104. write"Sub: ";mathprint a$
  3105. if c2 then <<write"c2="$mathprint c2>>
  3106. else <<write"singular result"$terpri()>>
  3107. >>
  3108. >>$
  3109. if null c2 then remain_num_c2:=cons(car cond2,remain_num_c2);
  3110. cond2:=cdr cond2
  3111. >>$
  3112. if c2 and not zerop c2 then return nil; % sol1 is not special case of sol2
  3113. if remain_num_c2 then << % can only occur if there were singular subst.
  3114. write"Even substitutions in the numerator is giving "$terpri()$
  3115. write"singularities like for log(0)."$ terpri()$
  3116. return nil
  3117. >>$
  3118. write"Substitutions in numerators give all zero"$terpri()$
  3119. % At this stage in the program either all is satisfied (remain_c2 = nil)
  3120. % or only singular solution 2 assignments remain (remain_c2 <> nil)
  3121. % but which vanish if numerators are taken.
  3122. % We now want to find a different order of substitutions, especially
  3123. % substituting for the free parameter functions of solution 2
  3124. % based on remain_sb to be done in remain_c2.
  3125. % At first we sort all solution 1 assignments into regular_sb and singular_sb.
  3126. % remain_c2 is not changed in this
  3127. cond2:=remain_c2;
  3128. sb:=remain_sb; % all remaining assignments of solution 1
  3129. while sb do <<
  3130. a:=car sb; sb:=cdr sb;
  3131. h:=err_catch_sub(cadr a,caddr a,cond2);
  3132. if null h then singular_sb:=cons(a,singular_sb)
  3133. else regular_sb:=cons(a,regular_sb)
  3134. >>$
  3135. if tr_merge then <<terpri()$
  3136. write"regular_sb: "$mathprint cons('LIST,regular_sb)>>$
  3137. if tr_merge then <<write"singular_sb: "$mathprint cons('LIST,singular_sb)>>$
  3138. if singular_sb then <<
  3139. write"Substitutions lead to singularities."$terpri()$
  3140. write"Solution ",s2," has to be transformed."$terpri()
  3141. >>$
  3142. % We now make a list of vanishing expressions based on singular_sb
  3143. % which when replaced by 0 in remain_c2 give singularities
  3144. singular_ex:=for each a in singular_sb
  3145. collect reval {'PLUS,cadr a,{'MINUS,caddr a}};
  3146. if tr_merge then <<
  3147. write"The following are expressions which vanish due to sol1 and"$
  3148. terpri()$
  3149. write"which lead to singularities when used for substitutions in sol2"$
  3150. terpri()$
  3151. mathprint cons('LIST,singular_ex)
  3152. >>$
  3153. if tr_merge then <<
  3154. write"The following are all free parameters in sol2 for which there are"$
  3155. terpri()$
  3156. write"substitutions in sol1"$ terpri()$
  3157. >>$
  3158. singular_eli:=for each a in singular_sb collect cadr a;
  3159. regular_eli:=for each a in regular_sb collect cadr a;
  3160. if tr_merge then <<terpri()$
  3161. write"singular_eli: "$mathprint cons('LIST,singular_eli)>>;
  3162. if tr_merge then <<write"regular_eli: "$mathprint cons('LIST,regular_eli)>>;
  3163. % Before continuing we want to check whether the supposed to be more special
  3164. % solution sol1 has free parameters which are not free parameters in the more
  3165. % general solution sol2. That can cause problems, i.e. division through 0
  3166. % and non-includedness when in fact sol1 is included in sol2.
  3167. extra_par_in_s1:=setdiff(cadddr sol1,cadddr sol2);
  3168. if tr_merge then <<write"Param in sol1 and not in sol2: ",extra_par_in_s1;
  3169. terpri()>>$
  3170. for each a in extra_par_in_s1 do <<
  3171. h:=caddr sol2$
  3172. while h and cadar h neq a do h:=cdr h;
  3173. if null h then write"ERROR, there must be an assignment of a in sol2!"
  3174. else <<
  3175. if tr_merge then <<
  3176. write"Assignment in ",s2," of a variable that is a free parameter in ",
  3177. s1," :"$
  3178. terpri()$
  3179. mathprint car h$
  3180. >>$
  3181. dropped_assign_in_s2:=cons(car h,dropped_assign_in_s2);
  3182. gauge_of_s2:=cons(algebraic(num(lisp({'PLUS,cadr car h,
  3183. {'MINUS,caddr car h}}))),
  3184. gauge_of_s2)
  3185. >>
  3186. >>$
  3187. gauge_of_s2:=cons('LIST,gauge_of_s2);
  3188. if tr_merge then <<write"gauge_of_s2="$mathprint gauge_of_s2>>$
  3189. % We should not do all regular substitutions in gauge_of_s2 (tried that)
  3190. % because some of them may set variables to zero which limits the
  3191. % possibilities of doing transformations of remain_c2
  3192. % We now search for a substitution based on one of the equations
  3193. % gauge_of_s2. The substitution is to be performed on remain_c2.
  3194. % One sometimes has to solve for regular_eli as singular_eli
  3195. % might appear only non-linearly.
  3196. % try_to_sub:=append(regular_eli,singular_eli);
  3197. try_to_sub:=append(singular_eli,regular_eli);
  3198. n:=1;
  3199. repeat <<
  3200. did_trafo:=nil;
  3201. gauge_of_s2_cp:=cdr gauge_of_s2;
  3202. while gauge_of_s2_cp do <<
  3203. sb:=reval car gauge_of_s2_cp$
  3204. gauge_of_s2_cp:=cdr gauge_of_s2_cp$
  3205. if not zerop sb then <<
  3206. try_to_sub_cp:=try_to_sub;
  3207. if tr_merge then <<write"next relation to be used: 0="$mathprint sb$
  3208. write"try_to_sub=",try_to_sub$terpri()>>$
  3209. h:=err_catch_fac(sb);
  3210. if h then <<
  3211. sb:=nil;
  3212. h:=cdr h;
  3213. while h do <<
  3214. if pairp cadar h then sb:=cons(cadar h,sb);
  3215. h:=cdr h;
  3216. >>
  3217. >>$
  3218. % From the next condition 0=sb we drop all factors which are
  3219. % single variables which set to zero would be a limitation
  3220. if tr_merge then <<write"After dropping single variable factors ",
  3221. length sb," factor(s) remain"$terpri()>>$
  3222. sb:=reval cons('TIMES,cons(1,sb));
  3223. if tr_merge then <<write"New relation used for substitution: sb="$
  3224. mathprint sb$terpri()>>$
  3225. while try_to_sub_cp do <<
  3226. a:=car try_to_sub_cp; try_to_sub_cp:=cdr try_to_sub_cp;
  3227. if tr_merge then <<write"try to sub next: ",a$terpri()>>$
  3228. if not freeof(sb,a) and lin_check(sb,{a}) then <<
  3229. num_sb:=reval {'DIFFERENCE, sb,{'TIMES,a,coeffn(sb,a,1)}};
  3230. if tr_merge then <<write"num_sb="$mathprint num_sb>>$
  3231. singular_ex_cp:=singular_ex;
  3232. while singular_ex_cp do <<
  3233. if tr_merge then <<write"car singular_ex_cp=",car singular_ex_cp$
  3234. terpri()>>$
  3235. % Search for an expression causing a singular substitution
  3236. % which is a factor of the substituted expression for a
  3237. num_sb_quo:=reval {'QUOTIENT,num_sb,car singular_ex_cp};
  3238. if tr_merge then <<write"num_sb_quo="$mathprint num_sb_quo>>$
  3239. % if (not pairp num_sb_quo) or
  3240. % (car num_sb_quo neq 'QUOTIENT) then <<
  3241. if t then <<
  3242. eli_2:=delete(a,eli_2);
  3243. % i.e. num_sb is a multiple of one of members of singular_ex, HURRAY!
  3244. % Do the substitution in remain_c2
  3245. b:=cadr solveeval list(sb,a)$
  3246. h:=err_catch_sub(cadr b,caddr b,remain_c2);
  3247. if tr_merge and null h then <<
  3248. write"Trafo "$mathprint b$write" was singular."$ terpri()
  3249. >>$
  3250. if h then <<
  3251. gauge_of_s2:=err_catch_sub(cadr b,caddr b,gauge_of_s2);
  3252. gauge_of_s2:=cons('LIST, for each gauge_of_s2_cp in cdr gauge_of_s2
  3253. collect algebraic(num(lisp(gauge_of_s2_cp))));
  3254. gauge_of_s2_cp:=nil$
  3255. new_assign_in_s2:=cons(b,new_assign_in_s2);
  3256. did_trafo:=t$
  3257. write"In order to avoid a singularity when doing substitutions"$
  3258. terpri()$
  3259. write"the supposed to be more general solution was transformed using:"$
  3260. terpri()$
  3261. mathprint b$
  3262. if tr_merge then <<write"The new gauge_of_s2: "$
  3263. mathprint gauge_of_s2>>$
  3264. remain_c2:=h;
  3265. h:=append(regular_sb,singular_sb);
  3266. while h and a neq cadar h do h:=cdr h;
  3267. if h then remain_c2:=append(remain_c2,list {'DIFFERENCE,caddar h,caddr b});
  3268. if tr_merge then <<write"remain_c2="$print_indexed_list(cdr remain_c2)>>$
  3269. singular_ex_cp:=nil;
  3270. try_to_sub:=delete(a,try_to_sub);
  3271. try_to_sub_cp:=nil;
  3272. n:=n+1
  3273. >> else singular_ex_cp:=cdr singular_ex_cp
  3274. >> else singular_ex_cp:=cdr singular_ex_cp
  3275. >> % while singular_ex_cp
  3276. >> % if car try_to_sub_cp passes first test
  3277. >>$ % while try_to_sub_cp
  3278. >> % if not zerop sb
  3279. >>$ % while gauge_of_s2_cp
  3280. >> until (did_trafo=nil)$
  3281. if tr_merge then <<
  3282. write"After completing the trafo the new list of parameters of"$
  3283. terpri()$
  3284. write"sol2 is: ",eli_2$terpri()$
  3285. write"sol1 has free parameters: ",cadddr sol1$terpri()
  3286. >>$
  3287. if not_included(cadddr sol1,eli_2) then return <<
  3288. write"Something seems wrong in merge_sol(): after the transformation of"$
  3289. terpri()$
  3290. write"sol2, all free parameters of sol1 should be free parameters of sol2."$
  3291. terpri();
  3292. nil
  3293. >> else <<
  3294. if tr_merge then <<
  3295. write"All free parameters of sol1 are free parameters of sol2"$
  3296. terpri()
  3297. >>
  3298. >>$
  3299. % Now all in remain_c2 has to become zero by using first substitutions
  3300. % from regular_sb and substituting parameters from sol2 such that
  3301. % the substituted expression has one of the singular_ex as factor.
  3302. % We seek global substitutions, i.e. substitutions based on sol1
  3303. % which satisfy all sol2 conditions and not for each sol2 condition a
  3304. % different set of sol1 based substitutions. Therefore substitutions
  3305. % are done in the whole remain_c2.
  3306. % try_to_sub are free parameters in sol2 that are contained in
  3307. % regular_eli and which are therefore not in singular_eli and not free
  3308. % parameters in sol1. They are to be substituted next because sol1 is
  3309. % obviously singularity free, so we have to express sol2 in the same
  3310. % free parameters, so we have to substitute for the free parameters fo
  3311. % sol2 which are not free parameters of sol1. But we must not use the
  3312. % same substitutions regular_sb which substitute for them as they lead
  3313. % to singular substitutions afterwards.
  3314. % try_to_sub:=memberl(cadddr sol2,regular_eli);
  3315. %
  3316. % write"try_to_sub=",try_to_sub$terpri()$
  3317. %
  3318. % % We now search for a substitution in regular_sb which leads to a
  3319. % % substitution of a member of try_to_sub, say p, ...
  3320. % b:=regular_sb;
  3321. % for each sb in b do <<
  3322. % sb_cp:=algebraic(num(lisp({'PLUS,cadr sb,{'MINUS,caddr sb}})));
  3323. % try_to_sub_cp:=delete(cadr sb,try_to_sub); % ... but the substitution
  3324. % % does not originally
  3325. % % have the form p=... .
  3326. % while try_to_sub_cp do <<
  3327. % a:=car try_to_sub_cp; try_to_sub_cp:=cdr try_to_sub_cp;
  3328. % if not freeof(sb_cp,a) and lin_check(sb_cp,{a}) then <<
  3329. % num_sb:={'DIFFERENCE, sb_cp,{'TIMES,a,coeffn(sb_cp,a,1)}};
  3330. %
  3331. % singular_ex_cp:=singular_ex;
  3332. % while singular_ex_cp do <<
  3333. % % Search for an expression causing a singular substitution
  3334. % % which is a factor of the substituted expression for a
  3335. % num_sb_quo:=reval {'QUOTIENT,num_sb,car singular_ex_cp};
  3336. % if (not pairp num_sb_quo) or
  3337. % (car num_sb_quo neq 'QUOTIENT) then <<
  3338. % % i.e. num_sb is a multiple of one of members of singular_ex, HURRAY!
  3339. % % Do the substitution in remain_c2
  3340. % h:=err_catch_sub(cadr sb,caddr sb,remain_c2);
  3341. % if h then <<
  3342. % write"In order to avoid a singularity when doing substitutions"$
  3343. % terpri()$
  3344. % write"the supposed to be more general solution was transformed:"$
  3345. % terpri()$
  3346. % mathprint sb$
  3347. % remain_c2:=h;
  3348. % singular_ex_cp:=nil;
  3349. % regular_sb:=delete(sb,regular_sb);
  3350. % try_to_sub:=delete(a,try_to_sub);
  3351. % try_to_sub_cp:=nil;
  3352. % >> else singular_ex_cp:=cdr singular_ex_cp
  3353. % >> else singular_ex_cp:=cdr singular_ex_cp
  3354. % >> % while singular_ex_cp
  3355. % >> % if car try_to_sub_cp passes first test
  3356. % >>$ % while try_to_sub_cp
  3357. % >>$ % for each sb
  3358. % Do the remaining regular_sb
  3359. sb:=append(regular_sb,singular_sb); % all remaining assignments of solution 1
  3360. while sb and remain_c2 do <<
  3361. a:=car sb; sb:=cdr sb;
  3362. remain_c2_cp:=remain_c2$
  3363. remain_c2:=err_catch_sub(cadr a,caddr a,remain_c2);
  3364. if tr_merge then
  3365. if null remain_c2 then
  3366. <<write"The following subst. was singular: "$mathprint a>>
  3367. else <<
  3368. write"Remaining substitution: ";mathprint a$
  3369. %write"remain_c2="$mathprint remain_c2
  3370. >>
  3371. >>$
  3372. if null remain_c2 then remain_c2:=remain_c2_cp
  3373. else remain_c2_cp:=remain_c2;
  3374. % Drop all zeros.
  3375. remain_c2_cp:=cdr remain_c2_cp$
  3376. while remain_c2_cp and zerop car remain_c2_cp do
  3377. remain_c2_cp:=cdr remain_c2_cp;
  3378. if remain_c2_cp then << % s1 is NOT a special case of s2
  3379. remain_c2_cp:=remain_c2$
  3380. if tr_merge then <<write"remain_c2="$
  3381. print_indexed_list(cdr remain_c2_cp)>>$
  3382. % Is there a contradiction of the type that the equivalence of two
  3383. % assignments, a8=A (from sol1), a8=B (from sol2) requires 0=A-B
  3384. % which got transformed into an expression C which is built only
  3385. % from free parameters of sol1 and therefore should not vanish?
  3386. h:=cadddr sol1; % all free parameters in sol1
  3387. while h and <<
  3388. if tr_merge then write"Substitution of ",car h," by: "$
  3389. repeat << % find a random integer for the free parameter
  3390. a:=1+random(10000); % that gives a regular substitution
  3391. if tr_merge then <<write a$terpri()>>$
  3392. a:=err_catch_sub(car h,a,remain_c2_cp)
  3393. >> until a;
  3394. remain_c2_cp:=a;
  3395. while a and ((not numberp car a) or (zerop car a)) do a:=cdr a;
  3396. not a
  3397. >> do h:=cdr h;
  3398. if h then return <<
  3399. write"In the following S1 stands for ",s1,"and S2 stands for ",s2," . ",
  3400. "Solution S1 fulfills all conditions of solution S2 when conditions",
  3401. "are made denominator free. But, after rewriting solution S2 so that",
  3402. "all free parameters of solution S1 are also free parameters of S2",
  3403. "then the new solution S2 now requires the vanishing of an expression",
  3404. "in these free parameters which is not allowed by S1. Therefore S1",
  3405. "is not a special case of S2."$
  3406. nil
  3407. >>$
  3408. if tr_merge and remain_c2_cp then
  3409. <<write"remain_c2_cp after subst = "$mathprint cons('LIST,remain_c2)>>$
  3410. write"Solution ",s1," is not less restrictive than solution"$terpri()$
  3411. write s2," and fulfills all conditions of solution ",s2," ."$terpri()$
  3412. write"But it was not possible for the program to re-formulate solution "$
  3413. terpri()$ write s2," to include both solutions in a single set of"$terpri()$
  3414. write"assignments without vanishing denominators. :-( "$
  3415. terpri()$
  3416. return nil
  3417. >> else return << % return the new s2 as s1 IS a special case of s2
  3418. % Which inequality is to be dropped?
  3419. ineq2:=car cddddr sol2$
  3420. while ineq2 do <<
  3421. ine:=car ineq2;
  3422. % ine should not have denominators, so no extra precautions for substitution:
  3423. for each a in caddr sol1 do ine:=reval(subst(caddr a,cadr a,ine));
  3424. if not zerop reval ine then ineqnew:=cons(car ineq2,ineqnew)
  3425. else ineqdrop:=cons(car ineq2,ineqdrop)$
  3426. ineq2:=cdr ineq2
  3427. >>$
  3428. if absorb then <<
  3429. % delete the redundant solution
  3430. sol_list:=delete(s1,sol_list); % system bldmsg ("rm %s",s1);
  3431. % transform the general solution if that was necessary and
  3432. % updating the list of free parameters
  3433. h:=cons('LIST,caddr sol2);
  3434. b:=cadddr sol2;
  3435. if tr_merge then <<
  3436. write"h0="$print_indexed_list(h)$
  3437. write"dropped_assign_in_s2="$print_indexed_list(dropped_assign_in_s2)$
  3438. write"new_assign_in_s2="$print_indexed_list(new_assign_in_s2)$
  3439. >>$
  3440. for each a in dropped_assign_in_s2 do
  3441. <<h:=delete(a,h);b:=cons(reval cadr a,b)>>$
  3442. if tr_merge then <<write"h1="$print_indexed_list(h)>>$
  3443. for each a in reverse new_assign_in_s2 do if h then <<
  3444. b:=delete(reval cadr a,b)$
  3445. if tr_merge then <<write"a=",a$terpri()$write"h2="$print_indexed_list(h)>>$
  3446. h:=err_catch_sub(cadr a,caddr a,h);
  3447. if h then h:=reval append(h,list a)
  3448. >>$
  3449. if null h then
  3450. write"A seemingly successful transformation of ",s2,
  3451. "went singular when performing the transformation ",
  3452. "finally on the whole solution."
  3453. else % save the generalized solution
  3454. save_solution(cadr sol2,cdr h,b,ineqnew,s2)$
  3455. >>;
  3456. if absorb and null h then nil
  3457. else <<
  3458. % report the merging
  3459. if null ineqdrop then <<
  3460. write"Strange: merging ",s1," and ",s2," without dropping inequalities!"$
  3461. terpri()$
  3462. write"Probably ",s2," had already been merged with ",s1,
  3463. " or similar before."$ terpri()
  3464. >> else
  3465. if print_ then <<
  3466. write"Solution ",s2," includes ",s1," by dropping "$
  3467. if length ineqdrop = 1 then write"inequality"
  3468. else write"inequalities"$terpri()$
  3469. for each ine in ineqdrop do mathprint ine
  3470. >>;
  3471. s2 % the more general solution
  3472. >>
  3473. >>
  3474. end$
  3475. symbolic operator merge_sol$
  3476. symbolic procedure merge_sol$
  3477. begin scalar s,sol_cp,sl1,sl2,s1,s2,s3,sol1,sol2,echo_bak$
  3478. if null session_ then ask_for_session() else <<
  3479. write "Do you want to merge solutions computed in this session,"$
  3480. terpri()$
  3481. if not yesp "i.e. since loading CRACK the last time? " then
  3482. ask_for_session()
  3483. >>$
  3484. % reading in sol_list
  3485. setq(s,bldmsg("%w%w",session_,"sol_list"));
  3486. in s;
  3487. % % At fist sort sol_list by the number of free unknowns
  3488. % for each s1 in sol_list do <<
  3489. % in s1;
  3490. % s2:=if null cadddr backup_ then 0 else length cadddr backup_;
  3491. % if cadr backup_ then s2:=s2 - length cadr backup_;
  3492. % sol_cp:=cons((s2 . s1),sol_cp)
  3493. % >>$
  3494. % sol_cp:=idx_sort(sol_cp)$
  3495. % while sol_cp do <<sl1:=cons(cdar sol_cp,sl1);sol_cp:=cdr sol_cp>>$
  3496. sol_cp:=sol_list$
  3497. sl1:=sol_cp$
  3498. if sl1 then
  3499. while sl1 and cdr sl1 do <<
  3500. s1:=car sl1; sl1:=cdr sl1;
  3501. %infile s1;
  3502. echo_bak:=!*echo; semic!*:='!$; in s1$ !*echo:=echo_bak;
  3503. sol1:=backup_;
  3504. if print_ then <<write"Comparing ",s1," with:"$terpri()>>$
  3505. sl2:=sl1;
  3506. while sl2 do <<
  3507. s2:=car sl2; sl2:=cdr sl2;
  3508. %infile s2$
  3509. echo_bak:=!*echo; semic!*:='!$; in s2$ !*echo:=echo_bak;
  3510. sol2:=backup_;
  3511. if print_ then <<write" ",s2$terpri()>>$
  3512. if (null car sol1) and (null car sol2) then % algebraic problem
  3513. if length cadddr sol1 <
  3514. length cadddr sol2 then s3:=merge_two(s1,sol1,s2,sol2,t) else
  3515. if length cadddr sol1 >
  3516. length cadddr sol2 then s3:=merge_two(s2,sol2,s1,sol1,t) else
  3517. <<s3:=merge_two(s1,sol1,s2,sol2,t)$
  3518. if s3 then <<
  3519. write"Strange: ",s1," is contained in ",s2$terpri()$
  3520. write"but both have same number of free unknowns!"$terpri()$
  3521. write"One of them has probably undergone earlier merging"$
  3522. terpri()$
  3523. >>
  3524. >> else
  3525. if null (s3:=merge_two(s1,sol1,s2,sol2,t)) then
  3526. s3:=merge_two(s2,sol2,s1,sol1,t);
  3527. if s3=s1 then sl1:=delete(s2,sl1) else % not to pair s2 later
  3528. if s3=s2 then sl2:=nil % to continue with next element in sl1
  3529. >>
  3530. >>;
  3531. save_sol_list()
  3532. end$
  3533. symbolic procedure save_sol_list$
  3534. begin scalar s$
  3535. setq(s,bldmsg("%w%w",session_,"sol_list"));
  3536. out s;
  3537. write"off echo$ "$ terpri()$
  3538. write"sol_list:='"$
  3539. print sol_list$write"$"$terpri()$
  3540. write "end$"$terpri()$
  3541. shut s
  3542. end$
  3543. symbolic procedure ask_for_session$
  3544. begin scalar ps$
  3545. ps:=promptstring!*$
  3546. promptstring!*:="Name of the session in double quotes: "$
  3547. terpri()$session_:=termread()$
  3548. promptstring!*:=ps
  3549. end$
  3550. symbolic operator pri_sol$
  3551. symbolic procedure pri_sol(sin,assgn,crout,html,solcount,fname,prind)$
  3552. % print the single solution sin
  3553. begin scalar a,b,sout$
  3554. in sin$
  3555. if html then <<
  3556. setq(sout,bldmsg("%w%w%d%w",fname,"-s",solcount,".html"));
  3557. out sout;
  3558. write"<html>"$terpri()$
  3559. terpri()$
  3560. write"<head>"$terpri()$
  3561. write"<meta http-equiv=""Content-Type"" content=""text/html;"$terpri()$
  3562. write"charset=iso-8859-1"">"$terpri()$
  3563. write"<title>Solution ",solcount," to problem ",prind,"</title>"$terpri()$
  3564. write"</head>"$terpri()$
  3565. terpri()$
  3566. write"<BODY TEXT=""#000000"" BGCOLOR=""#FFFFFF"">"$terpri()$
  3567. terpri()$
  3568. write"<CENTER><H2>Solution ",solcount," to problem ",prind,"</H2>"$terpri()$
  3569. write"<HR>"$terpri()$
  3570. if cadr backup_ then <<write"<A HREF=""#1"">Remaining equations</A> | "$
  3571. terpri()>>$
  3572. write"<A HREF=""#2"">Expressions</A> | "$terpri()$
  3573. write"<A HREF=""#3"">Parameters</A> | "$terpri()$
  3574. write"<A HREF=""#4"">Relevance</A> | "$terpri()$
  3575. write"<A HREF=",prind,".html>Back to problem ",prind,"</A> "$
  3576. write"</CENTER>"$terpri()$
  3577. terpri()
  3578. >>$
  3579. for each a in car backup_ do
  3580. for each b in cdr a do
  3581. algebraic(depend(lisp(car a),lisp b));
  3582. backup_:=cdr backup_;
  3583. terpri()$
  3584. if html then write"<!-- "$
  3585. write">>>=======>>> SOLUTION ",sin," <<<=======<<<"$
  3586. if html then write" --> "$
  3587. terpri()$terpri()$
  3588. if assgn or html then <<
  3589. if car backup_ then <<
  3590. if html then <<
  3591. write"<HR><A NAME=""1""></A><H3>Equations</H3>"$terpri()$
  3592. write"The following unsolved equations remain:"$terpri()$
  3593. write"<pre>"$
  3594. >> else write"Equations:"$
  3595. for each a in car backup_ do mathprint {'EQUAL,0,a}$
  3596. if html then <<write"</pre>"$terpri()>>
  3597. >>$
  3598. if html then <<
  3599. write"<HR><A NAME=""2""></A><H3>Expressions</H3>"$terpri()$
  3600. write"The solution is given through the following expressions:"$terpri()$
  3601. write"<pre>"$terpri()$
  3602. for each a in cadr backup_ do mathprint a$
  3603. write"</pre>"$terpri()
  3604. >> else <<
  3605. b:=nil;
  3606. for each a in cadr backup_ do
  3607. if not zerop caddr a then b:=cons(a,b);
  3608. print_fcts(b,nil)$
  3609. >>$
  3610. terpri()$
  3611. if html then <<
  3612. write"<HR><A NAME=""3""></A><H3>Parameters</H3>"$terpri()$
  3613. write"Apart from the condition that they must not vanish to give"$terpri()$
  3614. write"a non-trivial solution and a non-singular solution with"$terpri()$
  3615. write"non-vanishing denominators, the following parameters are free:"$terpri()$
  3616. write"<pre> "$
  3617. fctprint caddr backup_;
  3618. write"</pre>"$terpri()
  3619. >> else <<
  3620. write length caddr backup_," free unknowns: "$ listprint caddr backup_;
  3621. print_ineq(cadddr backup_)$
  3622. >>
  3623. >>$
  3624. if html then <<
  3625. write"<HR><A NAME=""4""></A><H3>Relevance for the application:</H3>"$
  3626. terpri()$
  3627. % A text for the relevance should be generated in crack_out()
  3628. % write"The solution given above tells us that the system {u_s, v_s}"$
  3629. % terpri()$
  3630. % write"is a higher order symmetry for the lower order system {u_t,v_t}"$
  3631. % terpri()$
  3632. % write"where u=u(t,x) is a scalar function, v=v(t,x) is a vector"$
  3633. % terpri()$
  3634. % write"function of arbitrary dimension and f(..,..) is the scalar"$
  3635. % terpri()$
  3636. % write"product between two such vectors:"$
  3637. % terpri()$
  3638. write"<pre>"
  3639. >>$
  3640. if crout or html then <<
  3641. algebraic (
  3642. crack_out(lisp cons('LIST,car backup_),
  3643. lisp cons('LIST,cadr backup_),
  3644. lisp cons('LIST,caddr backup_),
  3645. lisp cons('LIST,cadddr backup_) ))$
  3646. >>$
  3647. if html then <<
  3648. write"</pre>"$terpri()$
  3649. write"<HR>"$terpri()$
  3650. write"</body>"$terpri()$
  3651. write"</html>"$terpri()$
  3652. shut sout
  3653. >>
  3654. end$
  3655. symbolic operator print_all_sol$
  3656. symbolic procedure print_all_sol$
  3657. begin scalar s,a,assgn,crout,natbak,print_more_bak,fname,solcount,
  3658. html,prind,ps$
  3659. write"This is a reminder for you to read in any file CRACK_OUT.RED"$
  3660. terpri()$
  3661. write"with a procedure CRACK_OUT() in case that is necessary to display"$
  3662. terpri()$
  3663. write"results following from solutions to be printed."$
  3664. terpri()$ terpri()$
  3665. if null session_ then ask_for_session() else <<
  3666. write "Do you want to print solutions computed in this session,"$
  3667. terpri()$
  3668. if not yesp "i.e. since loading CRACK the last time? " then
  3669. ask_for_session()$
  3670. terpri()
  3671. >>$
  3672. % reading in sol_list
  3673. setq(s,bldmsg("%w%w",session_,"sol_list"));
  3674. in s;
  3675. natbak:=!*nat$ print_more_bak:=print_more$ print_more:=t$
  3676. if yesp "Do you want to generate an html file for each solution? "
  3677. then <<
  3678. html:=t$
  3679. solcount:=0$
  3680. terpri()$
  3681. write "What is the file name (including the path)"$
  3682. terpri()$
  3683. write "that shall be used (in double quotes) ? "$
  3684. terpri()$
  3685. write "(A suffix '-si' will be added for each solution 'i'.) "$
  3686. ps:=promptstring!*$
  3687. promptstring!*:=""$
  3688. fname:=termread()$terpri()$
  3689. write "What is a short name for the problem? "$
  3690. prind:=termread()$
  3691. promptstring!*:=ps$
  3692. terpri()$
  3693. >> else <<
  3694. if yesp "Do you want to see the computed value of each function? "
  3695. then assgn:=t$
  3696. if yesp "Do you want procedure `crack_out' to be called? " then <<
  3697. crout:=t;
  3698. if flin_ and homogen_ then
  3699. if yesp "Do you want to print less (e.g. no symmetries)? "
  3700. then print_more:=nil$
  3701. if not yesp
  3702. "Do you want natural output (no if you want to paste and copy)? "
  3703. then !*nat:=nil$
  3704. >>$
  3705. >>$
  3706. for each a in sol_list do <<
  3707. if html then solcount:=add1 solcount$
  3708. pri_sol(a,assgn,crout,html,solcount,fname,prind)$
  3709. >>$
  3710. !*nat:=natbak;
  3711. print_more:=print_more_bak
  3712. end$
  3713. symbolic procedure sol_in_list(set1,set2,sol_list2)$
  3714. begin scalar set2cp,s1,s2,found,sol1,sol2,same_sets,echo_bak$
  3715. while set1 do <<
  3716. s1:=car set1; set1:=cdr set1;
  3717. %infile s1;
  3718. echo_bak:=!*echo; semic!*:='!$; in s1$ !*echo:=echo_bak;
  3719. sol1:=backup_;
  3720. set2cp:=set2$
  3721. found:=nil$
  3722. while set2cp and not found do <<
  3723. s2:=car set2cp; set2cp:=cdr set2cp;
  3724. %infile s2;
  3725. echo_bak:=!*echo; semic!*:='!$; in s2$ !*echo:=echo_bak;
  3726. sol2:=backup_;
  3727. found:=merge_two(s1,sol1,s2,sol2,nil)$
  3728. >>;
  3729. if not found then <<
  3730. same_sets:=nil;
  3731. if print_ then <<
  3732. write"Solution ",s1," is not included in ",sol_list2$
  3733. terpri()
  3734. >>
  3735. >>
  3736. >>$
  3737. return same_sets
  3738. end$
  3739. symbolic operator same_sol_sets$
  3740. symbolic procedure same_sol_sets$
  3741. begin scalar session_bak,set1,set2,sol_list1,sol_list2,echo_bak$
  3742. session_bak:=session_;
  3743. write"Two sets of solutions are compared whether they are identical."$
  3744. write"What is the name of the session that produced the first set of solutions?"$
  3745. terpri()$
  3746. write"(CRACK will look for the file `sessionname'+`sol_list'.)"$terpri()$
  3747. ask_for_session()$
  3748. % reading in sol_list
  3749. setq(sol_list1,bldmsg("%w%w",session_,"sol_list"));
  3750. %infile sol_list1;
  3751. echo_bak:=!*echo; semic!*:='!$; in sol_list1$ !*echo:=echo_bak;
  3752. set1:=sol_list$
  3753. write"What is the name of the session that produced the second set of solutions?"$
  3754. terpri()$
  3755. ask_for_session()$
  3756. % reading in sol_list
  3757. setq(sol_list2,bldmsg("%w%w",session_,"sol_list"));
  3758. %infile sol_list2;
  3759. echo_bak:=!*echo; semic!*:='!$; in sol_list2$ !*echo:=echo_bak;
  3760. set2:=sol_list$
  3761. session_:=session_bak$
  3762. % 1. Check that all solutions in set1 are included in set2.
  3763. sol_in_list(set1,set2,sol_list2)$
  3764. sol_in_list(set2,set1,sol_list1)$
  3765. end$
  3766. % some PSL specific hacks
  3767. !#if (memq 'psl lispsystem!*)
  3768. symbolic procedure delete!-file(fi);
  3769. if memq('unix,lispsystem!*) then
  3770. system bldmsg("rm '%s'",fi) else
  3771. system bldmsg("del ""%s""",fi);
  3772. !#endif
  3773. endmodule$
  3774. end$