desir.red 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936
  1. module desir; % Special case differential equation solver.
  2. algebraic;
  3. % ***************************************************************
  4. % * *
  5. % * DESIR *
  6. % * ===== *
  7. % * *
  8. % * SOLUTIONS FORMELLES D'EQUATIONS DIFFERENTIELLES *
  9. % * *
  10. % * LINEAIRES ET HOMOGENES *
  11. % * *
  12. % * AU VOISINAGE DE POINTS SINGULIERS REGULIERS ET IRREGULIERS *
  13. % * *
  14. % ***************************************************************
  15. %
  16. % Differential linear homogenous Equation Solutions in the
  17. % neighbourhood of Irregular and Regular points
  18. %
  19. % Version 3.3 - Novembre 1993
  20. %
  21. %
  22. % Groupe de Calcul Formel de Grenoble
  23. % laboratoire LMC
  24. %
  25. % E-mail: dicresc@imag.fr
  26. % This software enables the basis of formal solutions to be computed
  27. % for an ordinary homogeneous differential equation with polynomial
  28. % coefficients over Q of any order, in the neighbourhood of zero
  29. % (regular or irregular singular point, or ordinary point ).
  30. % Tools have been added to deal with equations with a polynomial
  31. % right-hand side, parameters and a singular point not to be found at
  32. % zero.
  33. %
  34. % This software can be used in two ways : * direct ( DELIRE procedure)
  35. % * interactive ( DESIR procedure)
  36. %
  37. % The basic procedure is the DELIRE procedure which enables the
  38. % solutions of a linear homogeneous differential equation to be
  39. % computed in the neighbourhood of zero.
  40. %
  41. % The DESIR procedure is a procedure without argument whereby DELIRE
  42. % can be called without preliminary treatment to the data, that is to
  43. % say, in an interactive autonomous way. This procedure also proposes
  44. % some transformations on the initial equation. This allows one to
  45. % start comfortably with an equation which has a non zero singular
  46. % point, a polynomial right-hand side and parameters.
  47. %
  48. % This document is a succint user manual. For more details on the
  49. % underlying mathematics and the algorithms used, the reader can refer
  50. % to :
  51. %
  52. % E. Tournier : Solutions formelles d'equations differentielles -
  53. % Le logiciel de calcul formel DESIR.
  54. % These d'Etat de l'Universite Joseph Fourier (Grenoble, Avr. 87).
  55. %
  56. % He will find more precision on use of parameters in :
  57. %
  58. % F. Richard-Jung : Representation graphique de solutions
  59. % d'equations differentielles dans le champ complexe.
  60. % These de l'Universite Louis Pasteur (Strasbourg - septembre 88).
  61. %
  62. % **************************
  63. % * *
  64. % * FORMS OF SOLUTIONS *
  65. % * *
  66. % **************************
  67. % We have tried to represent solutions in the simplest form possible.
  68. % For that, we have had to choose different forms according to the
  69. % complexity of the equation (parameters) and the later use we shall
  70. % have of these solutions.
  71. %
  72. % "general solution" = {......, { split_sol , cond },....}
  73. % ------------------
  74. %
  75. % cond = list of conditions or empty list (if there is no condition)
  76. % that parameters have to verify such that split_sol is in
  77. % the basis of solutions. In fact, if there are parameters,
  78. % basis of solutions can have different expressions according
  79. % to the values of parameters. ( Note : if cond={}, the list
  80. % "general solution" has one element only.
  81. %
  82. % split_sol = { q , ram , polysol , r }
  83. % ( " split solution " enables precise information on the
  84. % solution to be obtained immediately )
  85. %
  86. % The variable in the differential operator being x, solutions are
  87. % expressed with respect to a new variable xt, which is a fractional
  88. % power of x, in the following way :
  89. %
  90. % q : polynomial in 1/xt with complex coefficients
  91. % ram : xt = x**ram (1/ram is an integer)
  92. % polysol : polynomial in log(xt) with formal series in xt
  93. % coefficients
  94. % r : root of a complex coefficient polynomial ("indicial
  95. % equation").
  96. %
  97. %
  98. % qx r*ram
  99. % "standard solution" = e x polysolx
  100. % -----------------
  101. % qx and polysolx are q and polysol expressions in which xt has
  102. % been replaced by x**ram
  103. %
  104. % N.B. : the form of these solutions is simplified according to the
  105. % nature of the point zero.
  106. % - if 0 is a regular singular point : the series appearing in polysol
  107. % are convergent, ram = 1 and q = 0.
  108. % - if 0 is a regular point, we also have : polysol is constant in
  109. % log(xt) (no logarithmic terms).
  110. %
  111. % ***********************************
  112. % * *
  113. % * INTERACTIVE USE *
  114. % * *
  115. % ***********************************
  116. %
  117. %% Modification of the "deg" function in REDUCE 3.3.
  118. %
  119. %symbolic procedure deg(u,kern);
  120. % begin scalar x,y;
  121. % u := simp!* u;
  122. % y := denr u;
  123. % tstpolyarg(y,u);
  124. % u := numr u;
  125. % kern := !*a2k kern;
  126. % if domainp u then return 0
  127. % else if mvar u eq kern then return !*f2a ldeg u;
  128. % x := setkorder list kern;
  129. % u := reorder u;
  130. %% if not(mvar u eq kern) then u := nil else u := ldeg u;
  131. % if not(mvar u eq kern) then u := 0 else u := ldeg u;
  132. % setkorder x;
  133. % return !*f2a u
  134. % end;
  135. fluid '(!*trdesir);
  136. symbolic switch trdesir;
  137. global '(multiplicities!*);
  138. flag('(multiplicities!*),'share); % Since SOLVE not loaded when file
  139. % compiled.
  140. procedure desir ;
  141. %===============;
  142. %
  143. % Calcul des solutions formelles d'une equation differentielle lineaire
  144. % homogene de maniere interactive.
  145. % La variable dans cette equation est obligatoirement x.
  146. % -----------------
  147. % x et z doivent etre des variables atomiques.
  148. %
  149. % La procedure demande l'ordre et les coefficients de l'equation, le
  150. % nom des parametres s'il y en a, puis si l'on souhaite une
  151. % transformation de cette equation et laquelle ( par exemple, ramener
  152. % un point singulier a l'origine - voir les procedures changehom,
  153. % changevar, changefonc - ).
  154. %
  155. % Cette procedure ECRIT les solutions et RETOURNE une liste de terme
  156. % general { lcoeff, {....,{ solution_generale },....}}. Le nombre
  157. % d'elements de cette liste est lie au nombre de transformations
  158. % demandees :
  159. % * lcoeff : liste des coefficients de l'equation differentielle
  160. % * solution_generale : solution ecrite sous la forme generale
  161. begin
  162. scalar k,grille,repetition,lcoeff,param,n,ns,solutions,lsol ;
  163. integer j;
  164. if (repetition neq non ) and (repetition neq nonon ) then
  165. << write
  166. " ATTENTION : chaque donnee doit etre suivie de ; ou de $" ;
  167. repetition:=nonon ;
  168. >> ;
  169. solutions:={};
  170. lsol:={} ;
  171. % lecture des donnees ;
  172. lcoeff:= lectabcoef();
  173. param:=second lcoeff;
  174. lcoeff:=first lcoeff;
  175. continue:=oui;
  176. write "transformation ? (oui;/non;) ";
  177. ok:=xread(nil);
  178. while continue eq oui do
  179. <<
  180. if ok eq oui then <<lcoeff:=transformation(lcoeff,param);
  181. param:=second lcoeff;
  182. lcoeff:=first lcoeff;
  183. >>;
  184. write "nombre de termes desires pour la solution ?" ;
  185. k:=xread(nil) ;
  186. if k neq 0 then
  187. <<
  188. grille:=1 ;
  189. if repetition neq non and lisp !*trdesir then
  190. << write " ";
  191. write "a chaque etape le polygone NRM sera visualise par la ",
  192. "donnee des aretes modifiees , sous la forme :" ;
  193. write " " ;
  194. write
  195. " ARETE No i : coordonnees de l'origine gauche, pente,",
  196. " longueur " ;
  197. >> ;
  198. write " " ;
  199. on div ;
  200. on gcd ;
  201. solutions:= delire(x,k,grille,lcoeff,param);
  202. ns:=length solutions; n:=length lcoeff -1;
  203. if ns neq 0 then
  204. << write "LES ",ns," SOLUTIONS CALCULEES SONT LES SUIVANTES";
  205. j:=1;
  206. for each elt in solutions do
  207. << write " " ; write " ==============" ;
  208. write " SOLUTION No ",j ;
  209. write " ==============" ;
  210. sorsol(elt);
  211. j:=j+1;
  212. >> ;
  213. >>;
  214. off div ;
  215. if ns neq n then write n-ns," solutions n'ont pu etre calculees";
  216. repetition:=non ;
  217. lsol:= append(lsol,{{lcoeff,solutions}}) ;
  218. write "voulez-vous continuer ? ";
  219. write
  220. "'non;' : la liste des solutions calculees est affichee (sous";
  221. write " forme generalisee).";
  222. write "'non$' : cette liste n'est pas affichee.";
  223. continue:=xread(nil); ok:=oui;
  224. >>
  225. else
  226. continue:=non;
  227. >>;
  228. return lsol ;
  229. end;
  230. procedure solvalide(solutions,solk,k) ;
  231. %==================================== ;
  232. %
  233. % Verification de la validite de la solution numero solk dans la liste
  234. % solutions : {lcoeff,{....,{solution_generale},....}}.
  235. % On reporte la solution dans l'equation : le resultat a en facteur un
  236. % polynome en xt qui doit etre de degre > une valeur calculee en
  237. % fonction de k, nombre de termes demandes dans le developpement
  238. % asymptotique. Ne peut etre utilisee si la solution numero solk est
  239. % liee a une condition.
  240. %
  241. % ECRIT et RETOURNE l'evaluation de ce report.
  242. begin
  243. scalar z,lcoeff,sol,essai,qx,gri,r,coeff1,d,zz;
  244. integer j;
  245. lcoeff:=first solutions;
  246. sol:=part(second solutions,solk);
  247. if length sol > 1
  248. then write("presence de solutions conditionnelles :",
  249. " cette procedure ne peut pas etre appelee.")
  250. else
  251. << z:=first sol;
  252. essai:=first z; qx:=first essai;
  253. essai:=rest essai;
  254. gri:= first essai;
  255. sol:=second essai; r:=third essai;
  256. essai:=second z ;if length(essai)>0 then
  257. write "presence d'une condition : cette procedure ne peut pas etre
  258. appelee."
  259. else
  260. <<%calcul de la valuation theorique du polynome reste
  261. coeff1:=for each elt in lcoeff collect
  262. sub(x=xt**(1/gri),elt);
  263. if qx neq 0 then <<d:=solvireg(coeff1,qx,xt);
  264. coeff1:=changefonc(coeff1,xt,!&phi,e**qx*!&phi);
  265. >>;
  266. d:=altmin(coeff1,xt)-d;
  267. qx:=sub(xt=x**gri,qx);
  268. sol:=sub(lambd=r,sol);
  269. sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol);
  270. write "La solution numero ",solk," est ",sol;
  271. write "La partie reguliere du reste est de l'ordre de x**(",
  272. gri*(k+1+d+r),")";
  273. z:=0;
  274. for each elt in lcoeff do
  275. << z:=z+elt*df(sol,x,j);j:=j+1;>>;
  276. zz:=e**(-qx)*x**(-r*gri)*z;
  277. zz:=sub(x=xt**(1/gri),zz);
  278. on rational;
  279. write "Si on reporte cette solution dans l'equation, le terme ",
  280. "significatif du reste"," est : ",
  281. e**qx*x**(r*gri)*sub(xt=x**gri,valterm(zz,xt));
  282. off rational;
  283. return z ;
  284. >> ;
  285. >>;
  286. end;
  287. procedure solvireg(lcoeff,q,x);
  288. %=============================;
  289. begin scalar f;
  290. integer j,n;
  291. depend !&y,x;
  292. depend !&phi,x;
  293. l:=lcoeff;
  294. while l neq {} do
  295. <<f:=f+(first l)*df(!&y,x,j);j:=j+1;l:=rest l>>;
  296. n:=length(lcoeff);
  297. let !&y=e**q*!&phi;
  298. for j:=1:n do f:=sub(df(!&phi,x,j)=zz**j,f);
  299. f:=sub(!&phi=1,f);
  300. clear !&y;
  301. nodepend !&y,x;
  302. nodepend !&phi,x;
  303. return deg(den(f),x);
  304. end;
  305. procedure altmin(lcoeff,x);
  306. %=========================;
  307. begin
  308. integer j,min,d;
  309. min:=deg(valterm(first lcoeff,x),x);
  310. for each elt in rest lcoeff do <<
  311. j:=j+1;
  312. d:=deg(valterm(elt,x),x);
  313. if d-j<min then min:=d-j;>>;
  314. return min;
  315. end;
  316. procedure valterm(poly,x);
  317. %=========================;
  318. %retourne le terme de plus bas degre de poly;
  319. begin
  320. scalar l,elt;
  321. integer j;
  322. l:=coeff(poly,x);
  323. elt:=first l;
  324. while (elt=0) and (rest(l) neq {}) do
  325. <<j:=j+1;l:=rest l; elt:=first l>>;
  326. return elt*x**j;
  327. end;
  328. procedure standsol(solutions) ;
  329. %============================== ;
  330. %
  331. % PERMET d'avoir l'expression simplifiee de chaque solution a partir de
  332. % la liste des solutions {lcoeff,{....,{solution_generale},....}}, qui
  333. % est retournee par DELIRE ou qui est un des elements de la liste
  334. % retournee par DESIR.
  335. %
  336. % RETOURNE une liste de 3 elements : { lcoeff , solstand, solcond }
  337. % * lcoef = liste des coefficients de l'equation differentielle
  338. % * solstand = liste des solutions sous la forme standard
  339. % * solcond = liste des solutions conditionnelles n'ayant pu etre
  340. % mises sous la forme standard. Ces solutions restent
  341. % sous la forme generales
  342. %
  343. % Cette procedure n'a pas de sens pour les solutions "conditionnelles".
  344. % Pour celles-ci, il est indispensable de donner une valeur aux
  345. % parametres, ce que l'on peut faire, soit en appelant la procedure
  346. % SORPARAM, qui ecrit et retourne ces solutions dans la forme standard,
  347. % soit en appelant la procedure SOLPARAM qui les retourne dans la forme
  348. % generale.
  349. begin
  350. scalar z,lcoeff,sol,solnew,solcond,essai,qx,gri,r;
  351. integer j;
  352. solnew:={};
  353. solcond:= {} ;
  354. lcoeff:=first solutions;
  355. for each elt in second solutions do
  356. if length elt > 1 then solcond:=append(solcond,{elt})
  357. else
  358. << z:=first elt;
  359. essai:=first z;
  360. qx:=first essai;
  361. essai:=rest essai;
  362. gri:= first essai;
  363. qx:=sub(xt=x**gri,qx);
  364. sol:=second essai; r:=third essai;
  365. essai:=second z ;
  366. if length(essai)>0 then solcond:=append(solcond,{elt})
  367. else
  368. << sol:=sub(lambd=r,sol);
  369. sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol);
  370. solnew:=append(solnew,{sol});
  371. >> ;
  372. >>;
  373. return {lcoeff,solnew,solcond};
  374. end;
  375. procedure sorsol(sol);
  376. %=====================
  377. %
  378. % ecriture, sous forme standard, de la solution sol donnee sous la forme
  379. % generale, avec enumeration des differentes conditions (s'il y a lieu).
  380. %
  381. begin
  382. scalar essai,qx,gri,sol,r;
  383. nonnul:=" non nul";
  384. entnul:=" nul";
  385. nonent:=" non entier" ;
  386. entpos:= " entier positif" ;
  387. entneg:= " entier negatif" ;
  388. for each z in sol do
  389. << essai:=first z;
  390. qx:=first essai;
  391. essai:=rest essai;
  392. gri:= first essai;
  393. qx:=sub(xt=x**gri,qx);
  394. sol:=second essai;
  395. r:=third essai;
  396. essai:=second z ;
  397. sol:=sub(xt=x**gri,sol);
  398. if length(essai)>0 then
  399. <<if deg(num sol,lambd)=0 then
  400. <<write e**qx*x**(r*gri)*sol ;
  401. write "Si : ";
  402. for each w in essai do
  403. if (length(w)=2 or not lisp !*trdesir) then
  404. write first w,second w
  405. else
  406. << write (first w,second w,third w);
  407. w:=rest rest rest w;
  408. for each w1 in w do
  409. write (" +-",w1);
  410. >>
  411. >>
  412. >>
  413. else
  414. << sol:=sub(lambd=r,sol);
  415. write e**qx*x**(r*gri)*sol;
  416. >>;
  417. >>;
  418. clear nonnul,entnul,nonent,entpos,entneg;
  419. end;
  420. procedure changehom(lcoeff,x,secmembre,id);
  421. %========================================
  422. %
  423. % derivation d'une equation avec second membre.
  424. % * lcoeff : liste des coefficients de l'equation
  425. % * x : variable
  426. % * secmembre : second membre
  427. % * id : ordre de la derivation
  428. %
  429. % retourne la liste des coefficients de l'equation derivee
  430. % permet de transforme une equation avec second membre polynomial en une
  431. % equation homogene en derivant id fois, id = degre(secmembre) + 1.
  432. %
  433. begin scalar l,fct,cf,n;
  434. integer j;
  435. depend !&y,x;
  436. fct:=secmembre;
  437. l:=lcoeff;
  438. while l neq {} do
  439. <<fct:=fct+(first l)*df(!&y,x,j);j:=j+1;l:=rest l>>;
  440. fct:=df(fct,x,id);
  441. n:=length(lcoeff)+id;
  442. for j:=1:n do fct:=sub(df(!&y,x,j)=zz**j,fct);
  443. fct:=sub(!&y=1,fct);
  444. cf:=coeff(fct,zz);
  445. j:=0;
  446. if lisp !*trdesir then
  447. for each elt in cf do <<write "a(",j,") = ", elt;j:=j+1;>>;
  448. nodepend !&y,x;
  449. return cf;
  450. end;
  451. procedure changevar(lcoeff,x,v,fct);
  452. %=================================
  453. %
  454. % changement de variable dans l'equation homogene definie par la liste,
  455. % lcoeff, de ses coefficients :
  456. % l'ancienne variable x et la nouvelle variable v sont liees par la
  457. % relation x = fct(v)
  458. %
  459. % retourne la liste des coefficients en la variable v de la nouvelle
  460. % equation
  461. % Exemples d'utilisation :
  462. % - translation permettant de ramener une singularite rationnelle a
  463. % l'origine
  464. % - x = 1/v ramene l'infini en 0.
  465. %
  466. begin scalar f,cf;
  467. integer j,n;
  468. depend !&y,x;
  469. l:=lcoeff;
  470. while l neq {} do
  471. <<f:=f+(first l)*df(!&y,x,j);j:=j+1;l:=rest l>>;
  472. n:=length(lcoeff);
  473. f:=change(!&y,x,v,fct,f,n);
  474. for j:=1:n do f:=sub(df(!&y,v,j)=zz**j,f);
  475. f:=sub(!&y=1,f);
  476. cf:=coeff(num(f),zz);
  477. j:=0;
  478. if lisp !*trdesir then
  479. for each elt in cf do <<write "a(",j,") = ", elt;j:=j+1;>>;
  480. nodepend !&y,x;
  481. return cf;
  482. end;
  483. procedure changefonc(lcoeff,x,q,fct);
  484. %================================
  485. %
  486. % changement de fonction inconnue dans l'equation homogene definie par
  487. % la liste lcoeff de ses coefficients :
  488. % * lcoeff : liste des coefficients de l'equation initiale
  489. % * x : variable
  490. % * q : nouvelle fonction inconnue
  491. % * fct : y etant la fonction inconnue y = fct(q)
  492. %
  493. % retourne la liste des coefficients de la nouvelle equation
  494. %
  495. % Exemple d'utilisation : permet de calculer, au voisinage d'une
  496. % singularite irreguliere, l'equation reduite associee a l'une des
  497. % pentes (polygone de Newton ayant une pente nulle de longueur non
  498. % nulle). Cette equation fournit de nombreux renseignements sur la
  499. % serie divergente associee.
  500. %
  501. begin scalar f,cf;
  502. integer j,n;
  503. depend !&y,x;
  504. depend q,x;
  505. l:=lcoeff;
  506. while l neq {} do
  507. <<f:=f+(first l)*df(!&y,x,j);j:=j+1;l:=rest l>>;
  508. n:=length(lcoeff);
  509. let !&y=fct;
  510. for j:=1:n do f:=sub(df(q,x,j)=zz**j,f);
  511. f:=sub(q=1,f);
  512. cf:=coeff(num(f),zz); j:=1;
  513. if lisp !*trdesir then
  514. for each elt in cf do <<write "a(",j,") = ", elt;j:=j+1;>>;
  515. clear !&y;
  516. nodepend !&y,x;
  517. nodepend q,x;
  518. return cf;
  519. end;
  520. procedure sorparam(solutions,param);
  521. %==================================
  522. %
  523. % procedure interactive d'ecriture des solutions evaluees : la valeur
  524. % des parametres est demandee.
  525. % * solutions : {lcoeff,{....,{solution_generale},....}}
  526. % * param : liste des parametres;
  527. %
  528. % retourne la liste formee des 2 elements :
  529. % * liste des coefficients evalues de l'equation
  530. % * liste des solutions standards evaluees pour les valeurs des
  531. % parametres
  532. %
  533. begin
  534. scalar essai,sec,qx,gri,sol,sol1,sol2,r,solnew,coefnew,omega,omegac;
  535. integer j,iparam;
  536. solnew:={};
  537. iparam:=length param;
  538. if iparam=0
  539. then rederr "La liste des parametres est vide : utiliser STANDSOL";
  540. array parm(iparam),parmval(iparam);
  541. j:=1;
  542. for each elt in param do
  543. << write "donner la valeur du parametre ", elt;
  544. parm(j):=elt;parmval(j):=xread(nil);j:=j+1;
  545. >>;
  546. j:=1;
  547. for each elt in second solutions do
  548. << for each z in elt do
  549. << essai:=first z;
  550. qx:=first essai;
  551. essai:=rest essai;
  552. gri:= first essai;
  553. qx:=sub(xt=x**gri,qx);
  554. sol1:=second essai;
  555. r:=third essai;
  556. essai:=second z ;
  557. if essai ={} then
  558. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  559. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  560. >>
  561. else <<sol2:=sorparamcond(essai,iparam,qx,gri,r,sol1);
  562. if sol2 neq 0 then sol:=sol2; >>;
  563. >>;
  564. write " " ; write " ==============" ;
  565. write " SOLUTION No ",j ;
  566. write " ==============" ;
  567. if sol neq 0 then
  568. <<write sol; solnew:=append(solnew,{sol})>>
  569. else write "solution non calculee";
  570. j:=j+1;
  571. >> ;
  572. coefnew:= for each elt in first solutions collect
  573. begin scalar cof;
  574. cof:=elt ;
  575. for j:=1:iparam do cof:=sub(parm(j)=parmval(j),cof);
  576. return cof
  577. end;
  578. clear parm,parmval;
  579. return { coefnew, solnew };
  580. end;
  581. procedure sorparamcond(essai,iparam,qx,gri,r,sol1);
  582. %=================================================;
  583. begin
  584. scalar sol,sec,omega,omegac;
  585. essai:=first essai ;
  586. omega:=first essai;
  587. sec:= second essai ;
  588. for j:=1:iparam do omega:=sub(parm(j)=parmval(j),omega);
  589. omegac:=append(coeff(omega,i),{0});
  590. on rounded;
  591. if not numberp(first omegac) or not numberp(second omegac)
  592. then rederr list("Les valeurs donnees aux parametres ne",
  593. "permettent pas de choisir parmi les solutions conditionnelles.");
  594. off rounded;
  595. % il ne faut traiter qu'une seule fois la solution
  596. if sec=nonnul then
  597. if omega neq 0 then
  598. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  599. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  600. >>;
  601. if sec= entnul then
  602. if omega=0 then
  603. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  604. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  605. >>;
  606. if sec=nonent then
  607. if not fixp(omega) then
  608. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  609. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  610. >>;
  611. if sec=entpos then
  612. if fixp(omega) and (omega>0) then
  613. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  614. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  615. >>;
  616. if sec=entneg then
  617. if fixp(omega) and (omega<0) then
  618. << sol:=e**qx*x**(r*gri)*sub(xt=x**gri,sol1);
  619. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  620. >>;
  621. if deg(num sol,lambd) neq 0 then
  622. << sol:=sub(lambd=r,sol);
  623. for j:=1:iparam do sol:=sub(parm(j)=parmval(j),sol);
  624. >>;
  625. return sol;
  626. end;
  627. procedure solparam(solutions,param,valparam);
  628. %===========================================
  629. %
  630. % Cette procedure evalue, pour les valeurs des parametres donnees dans
  631. % valparam les solutions generalisees et les retourne sous forme
  632. % generalisee.
  633. %
  634. % * solutions : {lcoeff,{....,{solution_generale},....}}
  635. % * param : liste des parametres;
  636. % * valparam : liste des valeurs des parametres
  637. %
  638. % retourne la liste formee des 2 elements :
  639. % * liste des coefficients evalues de l'equation
  640. % * liste des solutions sous la forme generalisee evaluees pour les
  641. % valeurs des parametres
  642. %
  643. begin
  644. scalar essai,sol,sol1,solg,solnew, coefnew;
  645. integer j,iparam;
  646. solnew:={};
  647. iparam:=length param;
  648. if iparam=0
  649. then rederr "La liste des parametres est vide : utiliser STANDSOL";
  650. array parm(iparam),parmval(iparam);
  651. j:=1;
  652. for each elt in param do
  653. << parm(j):=elt ; j:=j+1 >>;
  654. j:=1;
  655. for each elt in valparam do
  656. << parmval(j):=elt ; j:=j+1 >>;
  657. for each elt in second solutions do
  658. << for each z in elt do
  659. << solg:=first z;
  660. essai:=second z ;
  661. if essai ={} then
  662. sol1:=solg
  663. else sol1:=solparamcond(essai,iparam,solg);
  664. if sol1 neq {} then
  665. << essai:=rest(rest(sol1)) ; r:=second essai;
  666. if deg(num(sol:=first(essai)),lambd) neq 0 then
  667. << sol:=sub(lambd=r,sol);
  668. for j:=1:iparam do
  669. sol:=sub(parm(j)=parmval(j),sol);
  670. >>;
  671. sol1:={first(sol1), second(sol1),sol,r};
  672. solnew:=append(solnew,{{{sol1,{}}}});
  673. >> ;
  674. >>;
  675. >> ;
  676. coefnew:= for each elt in first solutions collect
  677. begin scalar cof;
  678. cof:=elt ;
  679. for j:=1:iparam do cof:=sub(parm(j)=parmval(j),cof);
  680. return cof
  681. end;
  682. clear parm,parmval;
  683. return { coefnew, solnew };
  684. end;
  685. procedure solparamcond(essai,iparam,solg);
  686. %========================================;
  687. begin
  688. scalar sec,sol1,sol,omega,omegac;
  689. essai:=first essai ;
  690. omega:=first essai;
  691. sec:= second essai ;
  692. for j:=1:iparam do omega:=sub(parm(j)=parmval(j),omega);
  693. omegac:=append(coeff(omega,i),{0});
  694. on rounded;
  695. if not numberp(first omegac) or not numberp(second omegac)
  696. then rederr list("Les valeurs donnees aux parametres",
  697. "ne permettent pas de choisir parmi les solutions conditionnelles.");
  698. off rounded;
  699. % il ne faut traiter qu'une seule fois la solution
  700. sol1:={};
  701. if sec= nonnul then
  702. if omega neq 0 then
  703. sol1:= for each elem in solg collect
  704. begin
  705. sol:=elem ;
  706. for j:=1:iparam do
  707. sol:=sub(parm(j)=parmval(j),sol);
  708. return sol
  709. end ;
  710. if sec= entnul then
  711. if omega=0 then
  712. sol1:= for each elem in solg collect
  713. begin
  714. sol:=elem ;
  715. for j:=1:iparam do
  716. sol:=sub(parm(j)=parmval(j),sol);
  717. return sol
  718. end ;
  719. if sec=nonent then
  720. if not fixp(omega) then
  721. sol1:= for each elem in solg collect
  722. begin
  723. sol:=elem ;
  724. for j:=1:iparam do
  725. sol:=sub(parm(j)=parmval(j),sol);
  726. return sol
  727. end ;
  728. if sec=entpos then
  729. if fixp(omega) and (omega>0) then
  730. sol1:= for each elem in solg collect
  731. begin
  732. sol:=elem ;
  733. for j:=1:iparam do
  734. sol:=sub(parm(j)=parmval(j),sol);
  735. return sol
  736. end ;
  737. if sec=entneg then
  738. if fixp(omega) and (omega<0) then
  739. sol1:= for each elem in solg collect
  740. begin
  741. sol:=elem ;
  742. for j:=1:iparam do
  743. sol:=sub(parm(j)=parmval(j),sol);
  744. return sol
  745. end ;
  746. return sol1;
  747. end;
  748. procedure lectabcoef( ) ;
  749. %---------------------- ;
  750. % Lecture des coefficients de l'equation (dans l'ordre croissant des
  751. % derivations).
  752. % lecture de n : ordre de l'equation.
  753. % lecture des parametres (s'il apparait une variable differente de x
  754. % dans les coefficients).
  755. % les coefficients sont ranges dans la liste lcoeff (le tableau tabcoef
  756. % est utilise temporairement).
  757. % Retourne la liste { lcoeff , param } formee de la liste des
  758. % coefficients et de la liste des parametres (qui peut etre vide).
  759. %
  760. begin
  761. scalar n, ok,iparam,lcoeff,param ;
  762. write " " ;
  763. write " ***** INTRODUCTION DES DONNEES ***** ";
  764. write " " ;
  765. write " L' equation est de la forme";
  766. write " a(0)(x)d^0 + a(1)(x)d^1 + .... + a(n)(x)d^n = 0 " ;
  767. write " ordre de l'equation ? " ;
  768. n:=xread(nil) ;
  769. array tabcoef(n);
  770. write " Donner les coefficients a(j)(x), j = 0..n" ;
  771. for j:=0:n do tabcoef(j):=xread(nil);
  772. for j:=0:n do write "a(",j,") = ",tabcoef(j);
  773. write " " ;
  774. write "correction ? ( oui; / non; ) " ;
  775. ok:=xread(nil) ;
  776. while ok eq oui do
  777. << write "valeur de j :" ; j:=xread(nil) ;
  778. write "expression du coefficient :";tabcoef(j):=xread(nil);
  779. write "correction ?";ok:=xread(nil) ;
  780. >> ;
  781. lcoeff:={tabcoef(n)};
  782. for j:=n-1 step -1 until 0 do lcoeff:=tabcoef(j).lcoeff;
  783. if testparam(lcoeff,x) then
  784. <<write "nombre de parametres ? ";
  785. iparam:=xread(nil);
  786. if iparam neq 0 then
  787. <<param:={};
  788. if iparam=1 then write "donner ce parametre :"
  789. else write "donner ces parametres :";
  790. for i:=1:iparam do param:=xread(nil).param;
  791. >>;
  792. >> else param:={};
  793. clear tabcoef ;
  794. return {lcoeff,param};
  795. end;
  796. %
  797. % ***********************************
  798. % * *
  799. % * UTILISATION STANDARD *
  800. % * *
  801. % ***********************************
  802. %
  803. procedure delire(x,k,grille,lcoeff,param) ;
  804. %=========================================;
  805. %
  806. % cette procedure calcule les solutions formelles d'une equation
  807. % differentielle lineaire homogene, a coefficients polynomiaux sur Q et
  808. % d'ordre quelconque, au voisinage de l'origine, point singulier
  809. % regulier ou irregulier ou point regulier. En fait, elle initialise
  810. % l'appel de la procedure NEWTON qui est une procedure recursive
  811. % (algorithme de NEWTON-RAMIS-MALGRANGE)
  812. %
  813. % x : variable
  814. % k : nombre de termes desires dans le developpement asymptotique
  815. % grille : les coefficients de l'operateur differentiel sont des
  816. % polynomes en x**grille (en general grille=1)
  817. % lcoeff : liste des coefficients de l'operateur differentiel (par
  818. % ordre croissant)
  819. % param : liste des parametres
  820. %
  821. % RETOURNE la liste des solutions "generales".
  822. % -----
  823. %
  824. begin
  825. integer prof,ordremax,ns ;
  826. scalar n,l;
  827. n:=length lcoeff -1;
  828. array der(n),!&solution(n),!&aa(n) ;
  829. array gri(20),lu(20),qx(20),equ(20),cl(20,n),clu(20,n) ;
  830. array nbarete(20),xpoly(20,n),ypoly(20,n),ppoly(20,n),lpoly(20,n) ;
  831. array xsq(n+1),ysq(n+1),rxm(n+1) ;
  832. array ru(20,n) ,multi(20,n) ,nbracine(20) ;
  833. array rac(10),ordremult(10);
  834. array condprof(20),solparm(n); % liste des conditions dans Newton
  835. array solequ(n);
  836. on gcd ;
  837. % initialisation du tableau cl ;
  838. l:=lcoeff;
  839. for i:=0:n do
  840. << cl(0,i):= first l; l:=rest l;>>;
  841. % initialisation du tableau des parametres ;
  842. iparam:=length param;
  843. array parm(iparam);
  844. parm(0):=iparam;
  845. for i:=1:iparam do parm(i):=part(param,i);
  846. % initialisation de la grille : les coef de L sont des polynomes
  847. % en x**gri(0) ;
  848. gri(0):=grille ;
  849. % substitution de d/dx par ( d/dx - (&lamb*!&u)/x**(&lamb+1) ) ;
  850. der(0):=!&ff(x) ;
  851. for ik:=1:n do
  852. der(ik):=df(der(ik-1),x)-((!&lamb*!&u)/x**(!&lamb+1))*der(ik-1) ;
  853. % initialisation de l'exponentielle ;
  854. qx(0):=0 ;
  855. % l'appel initial de l'algorithme NEWTON se fait avec l'operateur
  856. % complet l'ordre maximum (ordremax) pour lequel on calcule le
  857. % polygone NRM est n;
  858. ordremax:=n ;
  859. % initialisation de prof : prof indique le nombre d'appels recursifs
  860. % de l'algorithme NEWTON ;
  861. prof:=1 ;
  862. condprof(0):={};
  863. % appel de l'algorithme NEWTON ;
  864. ns:=newton(prof,ordremax,n,x,k,0) ;
  865. l:=for i:=1:ns collect solequ(i);
  866. clear der,!&solution,!&aa,gri,lu,qx,equ,cl,clu,nbarete,xpoly,ypoly,
  867. ppoly,lpoly,xsq,ysq,rxm,tj,ru,multi,nbracine,parm ;
  868. clear rac,ordremult;
  869. clear condprof,solparm,solequ;
  870. return l ;
  871. end;
  872. procedure testparam(l,x);
  873. %-----------------------;
  874. % l : liste des coefficients;
  875. % retourne t si presence de parametres (variable differente de x);
  876. % nil sinon;
  877. begin
  878. scalar b,l1,l2;
  879. b:=nil; l1:=l;
  880. while b=nil and l1 neq{} do << l2:=coeffp({first l1},{x});
  881. for each elt in l2 do
  882. <<if not numberp elt then b:=true;>>;
  883. l1:=rest l1;>>;
  884. return b;
  885. end;
  886. procedure coeffp(poly,var);
  887. %-------------------------;
  888. % poly : liste des polynomes
  889. % var : liste des variables
  890. % retourne la liste des coefficients
  891. begin
  892. scalar l,l1 ;
  893. if var={} then return poly;
  894. l:={};
  895. for each elt in poly do <<l1:=coeff(elt,first var);
  896. for each el1 in l1 do if el1 neq 0 then
  897. l:=append(l,{el1})
  898. >>;
  899. return coeffp(l,rest var);
  900. end;
  901. procedure transformation(lcoeff,param);
  902. %-------------------------------------;
  903. % Entree : liste des coefficients de l'equation
  904. % liste des parametres
  905. % Sortie : liste des coefficients de l'equation transformee
  906. begin
  907. scalar f,id,fct,fct1,coeff1,lsor;
  908. ok:=oui;coeff1:=lcoeff;
  909. while ok eq oui do <<write "derivation : 1; ";
  910. write "changement de variable : 2; ";
  911. write "changement de fonction inconnue : 3;";
  912. write "substitution : 4;";
  913. ichoix:=xread(nil);
  914. if ichoix=1 then
  915. << write "donner le second membre : ";
  916. f:=xread(nil);
  917. write "donner le nombre de derivations : ";
  918. id:=xread(nil);
  919. coeff1:=changehom(coeff1,x,f,id) ;
  920. lsor:={coeff1,param}
  921. >>;
  922. if ichoix=2 then
  923. << write "valeur de x en fonction de la nouvelle variable v ? ";
  924. fct:=xread(nil);
  925. coeff1:=changevar(coeff1,x,v,fct);
  926. coeff1:=for each elt in coeff1 collect(sub(v=x,elt));
  927. lsor:={coeff1,param}
  928. >>;
  929. if ichoix=3 then
  930. << write
  931. "valeur de y en fonction de la nouvelle fonction inconnue q ?";
  932. fct:=xread(nil); coeff1:=changefonc(coeff1,x,q,fct);
  933. lsor:={coeff1,param}
  934. >>;
  935. if ichoix=4 then
  936. << write "donner la regle de substitution , ";
  937. write "le premier membre de l'{galit{ ,puis le second : ";
  938. fct:=xread(nil);
  939. fct1:=xread(nil);
  940. lsor:=subsfonc(coeff1,param,fct,fct1);
  941. coeff1:=first lsor;
  942. >>;
  943. write "transformation ? (oui;/non;) ";
  944. ok:=xread(nil); >>;
  945. return lsor;
  946. end;
  947. procedure subsfonc(lcoeff,param,fct,fct1);
  948. %----------------------------------------;
  949. % Effectue la substitution de fct par fct1
  950. begin
  951. scalar lsor,lsor1;integer j;
  952. lsor:= for each elt in lcoeff collect sub(fct=fct1,elt);
  953. for each elt in lsor do <<j:=j+1;write"a(",j,") = ",elt>>;
  954. lsor1:= for each elt in param do if fct neq elt then collect elt;
  955. if lsor1=0 then <<
  956. write "nouvelle liste de parametres : ",{};
  957. return {lsor,{}};>>
  958. else <<
  959. write "nouvelle liste de parametres : ",lsor1;
  960. return {lsor,lsor1};>>;
  961. end;
  962. procedure change(y,x,v,fct,exp,n);
  963. %---------------------------------
  964. % exp est une expression dependant de x, de y(x), et de ses derivees
  965. % d'ordre inferieur ou egal a n.
  966. % change retourne la meme expression apres avoir fait le changement de
  967. % variable x=fct(v).
  968. begin
  969. scalar !&exp;
  970. !&hp(xt):=1/df(sub(v=xt,fct),xt);
  971. !&exp:=exp;
  972. for i:=n step -1 until 0 do !&exp:=sub(df(y,x,i)=!&d(xt,i),!&exp);
  973. !&exp:=sub(x=fct,!&exp);
  974. depend y,v;
  975. for i:=n step -1 until 0 do
  976. !&exp:=sub(df(!&fg(xt),xt,i)=df(y,v,i),!&exp);
  977. return sub(xt=v,!&exp);
  978. end;
  979. %
  980. % +++++++++++++++++++++++++++++++++++++++++
  981. % + +
  982. % + ALGORITHME DE NEWTON +
  983. % + +
  984. % +++++++++++++++++++++++++++++++++++++++++
  985. %;
  986. operator !&ff,!&hp,!&fg ;
  987. procedure !&d(xt,n);
  988. begin
  989. if n=0 then return !&fg(xt)
  990. else if fixp n and (n>0) then return !&hp(xt)*df(!&d(xt,n-1),xt) ;
  991. end;
  992. procedure newton(prof,ordremax,n,x,k,ns) ;
  993. %======================================= ;
  994. % algorithme de NEWTON-RAMIS-MALGRANGE.
  995. % Cette procedure, recursive, est appelee par la procedure DELIRE.
  996. %
  997. % Elle NE PEUT PAS ETRE APPELEE SEULE car un certain nombre de tableaux
  998. % doivent etre declares et initialises.
  999. %
  1000. % prof : niveau de recursivite
  1001. % ordremax : ordre de l'operateur differentiel traite par cet appel
  1002. % x : variable de l'equation differentielle
  1003. % n : ordre de l'operateur differentiel initial
  1004. % k : nombre de terme du developpement asymptotique des solutions
  1005. % ns : nombre de solutions deja calculees lors de l'appel
  1006. %
  1007. % cette procedure retourne le nombre de solutions calculees ;
  1008. begin
  1009. integer nba, nadep, nbsol, q ;
  1010. scalar nbs,condit,sol,substitution ;
  1011. nbs:=ns ;
  1012. % construction du polygone N-R-M de l'operateur defini par
  1013. % cl(prof-1,i) avec i=0..ordremax ;
  1014. nba:=polygoneNRM(prof,ordremax,x) ;
  1015. % dessin ;
  1016. if lisp !*trdesir then for j:=1:nba do
  1017. write xpoly(prof,j)," ",ypoly(prof,j)," ",ppoly(prof,j)," ",
  1018. lpoly(prof,j) ;
  1019. % si la premiere arete a une pente nulle, on va calculer par FROBENIUS
  1020. % lpoly(prof,1) solutions en utilisant cl(prof-1,i) ,i=0..n et
  1021. % qx(prof-1) . ;
  1022. % nadep = numero de la premiere arete a traiter de pente non nulle ;
  1023. nadep:=1 ;
  1024. % si la 1ere pente est nulle : appel de frobenius et calcul des
  1025. % solutions;
  1026. if num(ppoly(prof,1)) = 0 then
  1027. << nbsol := lpoly(prof,1) ;
  1028. nouveauxaj(prof,n,x) ;
  1029. condl:=condprof(prof);
  1030. if lisp !*trdesir then
  1031. % <<depend !&y,xt;
  1032. <<write "Equation reduite : ";
  1033. for i:=n step -1 until 1 do
  1034. write " ",!&aa(i)," * DF(Y,XT,",i,") + ";
  1035. write " ",!&aa(0)," * Y">>;
  1036. % nodepend !&y,xt;>>;
  1037. nbsol:=frobenius (n,xt,k) ;
  1038. if nbsol neq 0 then
  1039. for i:=1:nbsol do
  1040. << solequ(nbs+i):={};
  1041. for each el in solparm(i) do
  1042. << if length(el) > 1 then condit:=second el else condit:={};
  1043. sol:=first el;
  1044. sol:=append({sub(x=xt**(1/gri(prof-1)),qx(prof-1)),
  1045. gri(prof-1)},sol);
  1046. solequ(nbs+i):=append (solequ(nbs+i),{{sol,condit}});
  1047. >> ;
  1048. >> ;
  1049. nbs:=nbs+nbsol ;
  1050. nadep:=2 ;
  1051. clear !&f,!&degrec ;
  1052. >> ;
  1053. % iteration sur le nombre d'aretes ;
  1054. for na:=nadep:nbarete(prof) do
  1055. nbs:=newtonarete(prof,na,n,x,k,nbs);
  1056. % iteration sur les aretes ;
  1057. return nbs ;
  1058. end ;
  1059. procedure newtonarete(prof,na,n,x,k,nbs);
  1060. %---------------------------------------;
  1061. begin scalar q,ordremax;
  1062. q:=den(ppoly(prof,na)) ;
  1063. if lisp !*trdesir then
  1064. write " ",xpoly(prof,na)," ",ypoly(prof,na)," ",
  1065. ppoly(prof,na)," ",lpoly(prof,na) ;
  1066. % calcul de la grille ;
  1067. if lpoly(prof,na)=1
  1068. then gri(prof):=gri(prof-1)
  1069. else gri(prof):=gcd(q,1/gri(prof-1))*gri(prof-1)/q ;
  1070. % substitution dans l'operateur defini par cl(prof-1,i),i=0..n;
  1071. lu(prof):= sub(!&lamb=ppoly(prof,na),cl(prof-1,0)*der(0)) ;
  1072. for ik:=1:n do
  1073. lu(prof):=lu(prof)+sub(!&lamb=ppoly(prof,na),
  1074. cl(prof-1,ik)*der(ik));
  1075. % decomposition de l'operateur lu ;
  1076. % selon les coefficients clu(prof,i) des derivees , i=0..n ;
  1077. % calcul de l'equation caracteristique ,equ(prof) :
  1078. % coefficient du terme constant de clu(prof,0) ;
  1079. decomplu(prof,n,x,na) ;
  1080. if lisp !*trdesir then
  1081. write "Equation caracteristique : ",equ(prof);
  1082. % calcul des racines de equ(prof) ;
  1083. racinesequ(prof,na) ;
  1084. % iteration sur les racines de l'equation caracteristique ;
  1085. for nk:=1:nbracine(prof) do
  1086. << % completer l'exponentielle ;
  1087. qx(prof):=qx(prof-1)+ru(prof,nk)/x**ppoly(prof,na) ;
  1088. % definition du nouvel operateur ;
  1089. for ik:=0:n do cl(prof,ik):=sub(!&u=ru(prof,nk),
  1090. clu(prof,ik));
  1091. % definition de l'ordre jusqu'auquel on calcule le nouveau
  1092. % polygone-nrm : ordremax ;
  1093. ordremax:=multi(prof,nk) ;
  1094. if lisp !*trdesir then
  1095. write "Racine eq. carac. : ",ru(prof,nk);
  1096. if prof <20 then nbs:=newton(prof+1,ordremax,n,x,k,nbs)
  1097. else write "la profondeur 20 est atteinte :",
  1098. " le calcul est arrete pour cette racine";
  1099. >> ; % fin de l'iteration sur les racines ;
  1100. return nbs;
  1101. end;
  1102. procedure squelette (prof,ordremax,x) ;
  1103. %------------------------------------ ;
  1104. % definition du squelette du polygone de NEWTON-R-M defini par
  1105. % cl(prof-1,i), avec i=0..ordremax ;
  1106. % retourne le nombre de minima ;
  1107. begin
  1108. scalar t00,tq,yi,cc ;
  1109. integer ik,nk,nbelsq,degden,degre, rxi ;
  1110. condprof(prof):=condprof(prof-1);
  1111. % base du squelette ;
  1112. % abscisse , numerotee de 1 a nbelsq ;
  1113. t00:=0 ;
  1114. for ik:=0 : ordremax do
  1115. if cl(prof-1,ik)neq 0 then << nk:=nk+1 ; xsq(nk):=ik >> ;
  1116. nbelsq:=nk ;
  1117. % ordonnee ;
  1118. for nk:=1:nbelsq do
  1119. <<tq:=sub(x=!&t**(1/gri(prof-1)),cl(prof-1,xsq(nk))) ;
  1120. degden:=deg(den(tq),!&t) ;
  1121. cc:=coeff(num(tq),!&t) ;
  1122. ik:=0 ;
  1123. while (first cc =0) do << ik:=ik+1 ; cc:= rest cc >>;
  1124. ysq(nk):=(ik-degden)*gri(prof-1)-xsq(nk) ;
  1125. trav1(nk):=first cc;
  1126. >> ;
  1127. % minima successifs ;
  1128. % le tableau rxm contiendra le rang de l'abscisse des minima successifs
  1129. % du squelette ;
  1130. % de 1 au nombre de minima ;
  1131. rxm(0):=0 ;
  1132. ik:=0 ;
  1133. while rxm(ik)< nbelsq do
  1134. <<rxi:=rxm(ik)+1 ;
  1135. yi:=ysq(rxi) ;
  1136. for j:=rxi+1 : nbelsq do
  1137. if num(ysq(j)-yi) <= 0 then << yi:=ysq(j) ; rxi:=j >> ;
  1138. ik:=ik+1 ;
  1139. rxm(ik):=rxi ;
  1140. >> ;
  1141. return ik ;
  1142. end ;
  1143. procedure polygoneNRM(prof,ordremax,x) ;
  1144. %------------------------------------- ;
  1145. % construction du polygone N-R-M de l'operateur defini par cl(prof-1,i),
  1146. % avec i=0..ordremax ;
  1147. %
  1148. % les aretes seront numerotees de 1 a nbarete(prof) ;
  1149. % i=nombre d'aretes deja construites ;
  1150. % l'arete i est definie par :
  1151. % xpoly(prof,i) abscisse du sommet gauche
  1152. % ypoly(prof,i) ordonnee du sommet gauche
  1153. % ppoly(prof,i) pente de l'arete
  1154. % lpoly(prof,i) "longueur" de l'arete : abscisse du sommet droite -
  1155. % abscisse du sommet gauche;
  1156. % retourne le nombre d'aretes ;
  1157. begin
  1158. scalar ydep,yfinal,pente ;
  1159. integer ik,imin,jmin,nbmin,rxmin,long,xfinal,xdep,deg1,rxi ;
  1160. array trav1(20);
  1161. nbmin:=squelette(prof,ordremax,x) ;
  1162. ik:=0 ;
  1163. xfinal:=xsq(rxm(1)) ;
  1164. yfinal:=ysq(rxm(1)) ;
  1165. xpoly(prof,1):=0 ;
  1166. ypoly(prof,1):=yfinal ;
  1167. ppoly(prof,1):=0 ;
  1168. rxi:=rxm(1);
  1169. for i:=1:parm(0) do
  1170. deg1:=deg1+deg(trav1(rxi),parm(i));
  1171. if deg1 neq 0 then
  1172. << if lisp !*trdesir
  1173. then write "Si : ",trav1(rxi)," non nul";
  1174. if (not membre({ trav1(rxi),nonnul },condprof(prof))) then
  1175. condprof(prof):=cons({ trav1(rxi),nonnul },condprof(prof));>>;
  1176. if xfinal neq 0 then << ik:=1 ; lpoly(prof,1):=xfinal >> ;
  1177. jmin:=1 ;
  1178. while xfinal <ordremax do
  1179. <<ik:=ik+1 ;
  1180. % initialisation de l'arete ik ;
  1181. xpoly(prof,ik):=xfinal ; xdep:=xfinal ;
  1182. ypoly(prof,ik):=yfinal ; ydep:=yfinal ;
  1183. imin:=jmin+1 ;
  1184. jmin:=imin ;
  1185. xfinal:=xsq(rxm(imin)) ;
  1186. yfinal:=ysq(rxm(imin)) ;
  1187. lpoly(prof,ik):=xfinal-xdep ;
  1188. ppoly(prof,ik):=(yfinal-ydep)/lpoly(prof,ik) ;
  1189. deg1:=0;
  1190. for ii:=1:parm(0) do
  1191. deg1:=deg1+deg(trav1(rxm(imin)),parm(ii));
  1192. if deg1 neq 0 then
  1193. << if lisp !*trdesir
  1194. then write "Si : ",trav1(rxm(imin))," non nul";
  1195. if (not membre({ trav1(rxm(imin)),nonnul },condprof(prof))) then
  1196. condprof(prof):=cons({ trav1(rxm(imin)),nonnul},
  1197. condprof(prof));>>;
  1198. % recherche du point final de l'arete ik ;
  1199. while imin < nbmin do
  1200. <<imin:=imin+1 ;
  1201. rxmin:=rxm(imin) ;
  1202. long:=xsq(rxmin)-xdep ;
  1203. pente:=(ysq(rxmin)-ydep)/long ;
  1204. if num(pente-ppoly(prof,ik)) <= 0 then
  1205. <<lpoly(prof,ik):=long ;
  1206. ppoly(prof,ik):=pente ;
  1207. xfinal:=xsq(rxmin);
  1208. yfinal:=ysq(rxmin) ;
  1209. jmin:=imin ;
  1210. >> ;
  1211. >> ;
  1212. >> ;
  1213. nbarete(prof):=ik ;
  1214. clear trav1;
  1215. return ik ;
  1216. end ;
  1217. procedure nouveauxaj(prof,n,x) ;
  1218. %------------------------------ ;
  1219. % construction des coefficients !&aa(j) de l'operateur envoye a
  1220. % FROBENIUS.
  1221. begin
  1222. scalar gr,t00,coeffs ;
  1223. for i:=0:n do !&aa(i):=cl(prof-1,i) ;
  1224. gr:=1/gri(prof-1);
  1225. % changement de x en xt**gr ;
  1226. % calcul des derivees en xt ;
  1227. !&hp(xt):=1/df(xt**gr,xt);
  1228. % calcul de l'operateur ;
  1229. t00:=num( for j:=0:n sum sub(x=xt**gr,!&aa(j))*!&d(xt,j)) ;
  1230. % calcul des nouveaux !&aa(j) ;
  1231. for j:=0:n do
  1232. <<coeffs:= if j=0 then coeff(t00,!&fg(xt))
  1233. else if j=1 then coeff(t00,df(!&fg(xt),xt))
  1234. else coeff(t00,df(!&fg(xt),xt,j));
  1235. if length coeffs=1 then !&aa(j):=0
  1236. else !&aa(j):=second coeffs;
  1237. t00:=first coeffs
  1238. >> ;
  1239. end ;
  1240. procedure decomplu(prof,n,x,na) ;
  1241. %------------------------------- ;
  1242. % decomposition de l'operateur lu ;
  1243. % selon les coefficients clu(prof,i) des derivees , i=0..n ;
  1244. % calcul de l'equation caracteristique ,equ(prof) : coefficient du terme
  1245. % constant de clu(prof,0) ;
  1246. begin
  1247. scalar gr,t00,tq,tj1,tj1c,coeffs ;
  1248. gr:=1/gri(prof) ;
  1249. t00:=num(lu(prof)) ; tq:=den(lu(prof)) ;
  1250. for j:=0:n do
  1251. << coeffs:= if j=0 then coeff(t00,!&ff(x))
  1252. else if j=1 then coeff(t00,df(!&ff(x),x))
  1253. else coeff(t00,df(!&ff(x),x,j)) ;
  1254. if length coeffs=1 then << clu(prof,j):=0 ; t00:=first coeffs >>
  1255. else << tj1:=sub(x=!&t**gr,second coeffs) ;
  1256. tj1c:=coeff(tj1,!&t) ;
  1257. while first tj1c =0 do tj1c:= rest tj1c;
  1258. t00:=first coeffs ;
  1259. if j=0 then <<clu(prof,j):=second coeffs/tq ;
  1260. equ(prof):=num(first tj1c)/
  1261. !&u**(deg(num(first tj1c),!&u)
  1262. -lpoly(prof,na))
  1263. >>
  1264. else clu(prof,j):=second coeffs/tq ;
  1265. >> ;
  1266. >> ;
  1267. end ;
  1268. procedure racinesequ(prof,na) ;
  1269. %----------------------------- ;
  1270. % calcul des racines de equ(prof) ;
  1271. begin
  1272. scalar nrac ;
  1273. integer nk,q1,gq,g1,dequ ;
  1274. dequ:=deg(equ(prof),!&u) ;
  1275. g1:=den(gri(prof-1)) ;q1:=den(ppoly(prof,na)) ;
  1276. gq:=gcd(g1,q1) ;
  1277. while gq > 1 do << g1:=g1/gq ;q1:=q1/gq ;
  1278. gq:=gcd(g1,q1) >> ;
  1279. let !&u**q1=!&t ;
  1280. nrac:=racine (equ(prof),!&t) ;
  1281. for ik:=1:nrac do
  1282. for j:=1:q1 do
  1283. << multi(prof,(ik-1)*q1+j):=ordremult(ik) ;
  1284. ru(prof,(ik-1)*q1+j):=rac(ik)**(1/q1)*e**(2*(j-1)*i*pi/q1);
  1285. nk:=nk+ordremult(ik) ;
  1286. >> ;
  1287. nbracine(prof):= nrac*q1 ;
  1288. clear !&u**q1 ;
  1289. if (dequ-nk) neq 0 then
  1290. write "IL Y A ",ik," SOLUTIONS RELATIVES A L'ARETE "
  1291. ,na," QUI NE PEUVENT PAS ETRE ATTEINTES : ",
  1292. "equation a resoudre de degre >=3 " ;
  1293. end ;
  1294. % +++++++++++++++++++++++++++++++++++++++++
  1295. % + +
  1296. % + ALGORITHME DE FROBENIUS +
  1297. % + +
  1298. % +++++++++++++++++++++++++++++++++++++++++
  1299. %;
  1300. operator !&g ;
  1301. % definition de !&w ;
  1302. % ------------------ ;
  1303. procedure !&w(ii,x,lambd,k);
  1304. if fixp k then for j:=0:k sum (df(!&g(j),lambd,ii)*x**j);
  1305. procedure frobenius ( n,x,k ) ;
  1306. %============================ ;
  1307. % Soit l'operateur differentielle : l d'ordre : n
  1308. %
  1309. % l(y)=a(n)*y(n)+a(n-1)*y(n-1)+.....a(0)*y(0)
  1310. % avec les a(i) = series d'ordre m en x
  1311. %
  1312. % On recherche une solution au voisinage d'un point singulier regulier
  1313. % de l'equation differentielle l(y)=0 sous la forme :
  1314. % y = x**lambda*(g(0)+g(1)*x+.....g(k)*x**k)
  1315. % on va determiner:
  1316. % - l'equation indicielle
  1317. % - les equations lineaires recurentes qui permettent de trouver
  1318. % les g(i) par identification des coefficients de x dans
  1319. % l'equation differentielle l(y)=0 ;
  1320. %
  1321. % Elle NE PEUT PAS ETRE APPELEE SEULE car un certain nombre de tableaux
  1322. % doivent etre declares et initialises.
  1323. %
  1324. % n : ordre de l'operateur
  1325. % x : variable
  1326. % k : nombre de termes du developpement asymptotique
  1327. %
  1328. % Cette procedure retourne le nombre de solutions calculees.
  1329. begin
  1330. integer nb,nbrac,nbsolution ;
  1331. scalar ss,sy, essai;
  1332. equaind(n,x,k); % calcul de f(0) : equation indicielle;
  1333. if lisp !*trdesir then write "Equation indicielle : ",!&f(0) ;
  1334. nb:=racine (!&f(0),lambd); % calcul des racines de f(0);
  1335. % verification sur le calcul des racines;
  1336. if nb=0 then
  1337. <<
  1338. write "le calcul des racines est impossible dans ce cas. ",
  1339. "Utilisez la version ALGEBRIQUE. ";
  1340. nbsolution:=0; %cette valeur sert de test dans DELIRE;
  1341. return nbsolution ;
  1342. >> ;
  1343. %etude en fonction du nombre de racines et de leur classification;
  1344. nbrac:=for i:=1:nb sum ordremult(i);
  1345. % CLASSEMENT des RACINES de l'EQUATION INDICIELLE
  1346. % cas particulier:
  1347. % ---------------- 1ou 2 racines ;
  1348. if nbrac=1 then
  1349. <<
  1350. %cas d'une racine simple;
  1351. nbsolution:=1;
  1352. frobeniussimple(x,k,rac(1),1);
  1353. solparm(1):={{{!&solution(1),rac(1)},condl} };
  1354. >>;
  1355. if nbrac=2 then << classement2r(x,k);
  1356. nbsolution:=2;
  1357. >> ;
  1358. if nbrac=3 then
  1359. << classement3r(x,k) ;
  1360. nbsolution:=3;
  1361. >>;
  1362. % nettoyage des variables ;
  1363. if nbrac>3
  1364. then write "ce cas n'est pas traite. Utilisez la version ALGEBRIQUE"
  1365. else for i:=0:k do clear !&g(i);
  1366. %fin cas ou il existe 1 ou plusieurs racines;
  1367. return nbsolution;
  1368. end ;
  1369. procedure classement2r(x,k);
  1370. %--------------------------;
  1371. % calcul des racines lorsque l'equation indicielle a 2 racines;
  1372. begin
  1373. scalar ss,essai ;
  1374. if ordremult(1)=2 then rac(2):=rac(1);
  1375. omega:=rac(1)-rac(2);
  1376. if fixp(omega) then
  1377. << nbsolution:=2;
  1378. %if rac(2) > rac(1) then << ss:=rac(1); rac(1):=rac(2) ;
  1379. % rac(2):=ss ;
  1380. %modification de 10-3-93
  1381. if coeffn(rac(2),i,0) > coeffn(rac(1),i,0) then <<
  1382. ss:=rac(1); rac(1):=rac(2);
  1383. rac(2):=ss;
  1384. >> ;
  1385. frobeniusgeneral(x,k,nbsolution);
  1386. for i:=1:nbsolution do
  1387. solparm(i):={{{!&solution(i),rac(i)},condl}};
  1388. >>
  1389. else
  1390. if parm(0)=0 then
  1391. << nbsolution:=2;
  1392. frobeniussimple(x,k,rac(1),1);
  1393. %pour la 2ieme solution les G(I) sont deja calcules;
  1394. !&solution(2):=
  1395. (for i:=0:k sum(sub(lambd=rac(2),!&g(i))*x**i));
  1396. for i:=1:nbsolution do solparm(i):={{{!&solution(i),rac(i)},condl}};
  1397. >>
  1398. else
  1399. <<
  1400. %cas omega non_entier
  1401. nbsolution:=2;
  1402. classement2rne(x,k);
  1403. >>
  1404. end;
  1405. procedure classement2rne(x,k);
  1406. %----------------------------;
  1407. % calcul des racines lorsque l'equation indicielle a 2 racines et omega
  1408. % non-entiers
  1409. begin
  1410. scalar ss,essai ;
  1411. nbsolution:=2;
  1412. frobeniussimple(x,k,rac(1),1);
  1413. essai:= for i:=1:k join if !&g(i)=0 then { i } else { } ;
  1414. if length(essai) > 0 then essai:= ", sauf :" . essai;
  1415. essai:=append({ omega, nonent }, essai);
  1416. essai:=cons(essai, condl);
  1417. !&solution(2):=
  1418. (for i:=0:k sum(sub(lambd=rac(2),!&g(i))*x**i));
  1419. for i:=1:nbsolution do solparm(i):={{{!&solution(i),rac(i)},essai}};
  1420. %cas omega >0
  1421. for i:=0:k do clear !&g(i);
  1422. nbsolution:=2;
  1423. % for i:=1:nbsolution do solparm(i):={};
  1424. frobeniusgeneral(x,k,nbsolution);
  1425. essai:=cons({ omega, entpos},condl);
  1426. for i:=1:nbsolution do
  1427. solparm(i):=append(solparm(i),{{{!&solution(i),rac(i)},essai}});
  1428. %cas omega <0
  1429. for i:=0:k do clear !&g(i);
  1430. nbsolution:=2; ss:=rac(1);rac(1):=rac(2);rac(2):=ss;
  1431. frobeniusgeneral(x,k,nbsolution);
  1432. essai:=cons({ omega, entneg},condl);
  1433. for i:=1:nbsolution do
  1434. solparm(i):=append(solparm(i),{{{!&solution(i),rac(i)},essai}});
  1435. %cas omega =0
  1436. for i:=0:k do clear !&g(i);
  1437. nbsolution:=2; rac(2):=rac(1);
  1438. frobeniusgeneral(x,k,nbsolution);
  1439. if (not membre({ omega, entnul},condl)) then
  1440. essai:=cons({ omega, entnul},condl)
  1441. else essai:=condl;
  1442. for i:=1:nbsolution do
  1443. solparm(i):=append(solparm(i),{{{!&solution(i),rac(i)},essai}});
  1444. end;
  1445. procedure classement3r(x,k) ;
  1446. %-------------------------- ;
  1447. % calcul des solutions lorsque l'equation indicielle a 3 racines ;
  1448. % cette procedure est appelee par FROBENIUS ;
  1449. begin
  1450. scalar ss,sy,nbsolution ;
  1451. if ordremult(1)=3 then
  1452. <<
  1453. % cas des racines triples;
  1454. rac(2):=rac(3):=rac(1)
  1455. >>;
  1456. if (ordremult(1)=1) and (ordremult(2)=2)
  1457. then << ss:=rac(1); sy:=ordremult(1);
  1458. rac(1):=rac(2); ordremult(1):=ordremult(2);
  1459. rac(3):=ss; ordremult(3):=sy;
  1460. >>
  1461. else
  1462. if ordremult(1)=2 then
  1463. <<
  1464. %decalage de l'indice 2 puis de 1 ;
  1465. rac(3):=rac(2); ordremult(3):=ordremult(2);
  1466. rac(2):=rac(1); ordremult(2):=ordremult(1);
  1467. >>;
  1468. %classement des racines ;
  1469. if ordremult(1)=3 then
  1470. <<
  1471. nbsolution:=3;
  1472. frobeniusgeneral(x,k,nbsolution)
  1473. >>
  1474. else
  1475. << % analyse des autres cas;
  1476. %ordremult(1)=1;
  1477. if fixp(rac(1)-rac(2)) and fixp(rac(2)-rac(3)) then
  1478. << %ordonner les racines;
  1479. %if rac(1)<rac(3) then << ss:=rac(1) ;
  1480. % rac(1):=rac(3); rac(3):=ss ;
  1481. %%modification 10-3-93
  1482. !*x1:=coeffn(rac(1),i,0);
  1483. !*x2:=coeffn(rac(2),i,0);
  1484. !*x3:=coeffn(rac(3),i,0);
  1485. if !*x1<!*x2 then << ss:=rac(1);
  1486. rac(1):=rac(2); rac(2):=ss;
  1487. ss:=!*x1;
  1488. !*x1:=!*x2; !*x2:=ss;
  1489. >> ;
  1490. if !*x1<!*x3 then << ss:=rac(1);
  1491. rac(1):=rac(3); rac(3):=ss;
  1492. !*x3:=!*x1;
  1493. >> ;
  1494. if !*x2<!*x3 then << ss:=rac(2);
  1495. rac(2):=rac(3); rac(3):=ss;
  1496. >> ;
  1497. nbsolution:=3;
  1498. frobeniusgeneral(x,k,nbsolution);
  1499. >>;
  1500. if rac(1)=rac(2) and not fixp(rac(2)-rac(3)) then
  1501. <<
  1502. nbsolution:=2;
  1503. frobeniusgeneral(x,k,nbsolution);
  1504. for i:=0:k do clear !&g(i);
  1505. nbsolution:=3;
  1506. frobeniussimple(x,k,rac(3),3);
  1507. >>;
  1508. if not fixp(rac(1)-rac(2)) and fixp(rac(2)-rac(3)) then <<
  1509. frobeniussimple(x,k,rac(1),3);
  1510. % arranger les racines avant l'appel;
  1511. rac(1):=rac(2); rac(2):=rac(3);
  1512. nbsolution:=2;
  1513. for i:=0:k do clear !&g(i);
  1514. frobeniusgeneral(x,k,nbsolution);
  1515. nbsolution:=3;
  1516. >>;
  1517. %cas des racines toutes distinctes n'est pas traite;
  1518. % if not fixp(rac(1)-rac(2)) and not fixp(rac(2)-rac(3)) then
  1519. if (not fixp(rac(1)-rac(2))) and (not fixp(rac(2)-rac(3))) then
  1520. << %ajout 5-5-88 ;
  1521. class3rne(x,k) ;
  1522. nbsolution:=3 ;
  1523. >> ;
  1524. % write "ce cas n'est pas traite. Utilisez la version ALGEBRIQUE";
  1525. >>;
  1526. for i:=1:nbsolution do
  1527. solparm(i):={{{!&solution(i),rac(i)},condl}};
  1528. end;
  1529. procedure class3rne(x,k) ;
  1530. %-----------------------
  1531. begin
  1532. scalar nbsolution ;
  1533. if fixp(rac(1)-rac(3)) then
  1534. <<
  1535. frobeniussimple(x,k,rac(2),3);
  1536. % arranger les racines avant l'appel;
  1537. rac(2):=rac(3);
  1538. nbsolution:=2;
  1539. for i:=0:k do clear !&g(i);
  1540. frobeniusgeneral(x,k,nbsolution);
  1541. nbsolution:=3;
  1542. >>
  1543. else
  1544. << nbsolution:=3;
  1545. frobeniussimple(x,k,rac(1),1);
  1546. %pour la 2ieme solution les G(I) sont deja calcules;
  1547. !&solution(2):=
  1548. (for i:=0:k sum(sub(lambd=rac(2),!&g(i))*x**i));
  1549. !&solution(3):=
  1550. (for i:=0:k sum(sub(lambd=rac(3),!&g(i))*x**i));
  1551. >>;
  1552. %fin ajout;
  1553. end;
  1554. procedure equaind (n,x,k) ;
  1555. %-------------------------- ;
  1556. % calcul de l'equation indicielle ;
  1557. % cette procedure declare un tableau f et le remplit.
  1558. % f(0) est l'equation indicielle ;
  1559. % n : ordre de l'operateur
  1560. % x : variable
  1561. % k : nombre de termes demandes pour la solution ;
  1562. begin
  1563. scalar l,denoml,ff ;
  1564. integer m,di,minai,lff ;
  1565. % Recherche de M=degre maximum des A(i);
  1566. m:=deg(!&aa(0),x);
  1567. for i:=1:n do if deg(!&aa(i),x)>m then m:=deg(!&aa(i),x);
  1568. array !&y(n),degrai(n),!&f(k+m+n+1);
  1569. % forme generale de la solution;
  1570. !&y(0):=x**lambd*(for i:=0:k sum !&g(i)*x**i);
  1571. % determination des derivees successives de !&y;
  1572. for ii:=1:n do
  1573. !&y(ii):=df(!&y(ii-1),x);
  1574. % substitution des derivees dans l;
  1575. l:=!&aa(0)*!&y(0)$
  1576. for ii:=1:n do l:=l+!&aa(ii)*!&y(ii)$
  1577. if den(l) neq 1 then << denoml:=den(l);
  1578. l:=num(l);
  1579. >>
  1580. else denoml:=1;
  1581. for ii:=0:n do
  1582. << if denoml neq 1 then !&aa(ii):=!&aa(ii)*denoml;
  1583. degrai(ii):= if den(!&aa(ii)) eq 1 or fixp den(!&aa(ii))
  1584. then length coeff(!&aa(ii),x) -1
  1585. >>;
  1586. % recherche du minimum entre degree(!&aa(i)) et i ;
  1587. minai:=0$
  1588. maxai:=0$
  1589. for ii:=0:n do
  1590. << di:=degrai(ii)-ii;
  1591. if (di<0) and (di<minai) then minai:=di;
  1592. if (di>maxai) then maxai:=di;
  1593. >>;
  1594. % on divise l par x**(lambd+minai);
  1595. l:=l/x**(lambd+minai)$
  1596. maxai:=maxai-minai;
  1597. % calcul des differentes valeurs de : !&f(i);
  1598. ff:=coeff(l,x)$
  1599. % verification si l n'est pas divisible par : x**i;
  1600. while first ff = 0 do ff:= rest ff;
  1601. lff:=length ff -1;
  1602. for i:=0:lff do
  1603. !&f(i):=part(ff,i+1);
  1604. !&degrec:=maxai;
  1605. !&f(0):=!&f(0)/!&g(0);
  1606. clear !&y,degrai ;
  1607. end ;
  1608. procedure frobeniussimple (x,k,rac,nbsol) ;
  1609. %---------------------------------------- ;
  1610. % Cette procedure est particuliere a la recherche des
  1611. % solutions formelles d'une equation differentielle dont les solution
  1612. % sont simples , c.a.d. ne comportant pas de log
  1613. % x : variable de l'equation traitee ;
  1614. % k : nombre de termes demande pour la solution
  1615. % rac : racine de l'equation indicielle
  1616. % nbsol : no de la solution calculee ;
  1617. % en fait on calcule !&solution(nbsol) ;
  1618. begin
  1619. scalar fcoeff; array ff(k);
  1620. for i:=1:k do ff(i):=!&f(i);
  1621. !&g(0):=1; %choix arbitraire;
  1622. for ii:=1:k do
  1623. <<
  1624. if den ff(ii) neq 1 then ff(ii):=num(ff(ii));
  1625. if ff(ii) eq 0 then !&g(ii):=0
  1626. else
  1627. <<
  1628. fcoeff:=coeff(ff(ii),!&g(ii));
  1629. !&g(ii):=-first fcoeff / second fcoeff;
  1630. >>;
  1631. >>;
  1632. !&solution(nbsol):= (for ii:=0:k sum(sub(lambd=rac,!&g(ii))*x**ii));
  1633. clear ff;
  1634. end ;
  1635. procedure frobeniusgeneral(x,k,nbsolution) ;
  1636. %----------------------------------------- ;
  1637. % x : variable de l'equation traitee ;
  1638. % k : nombre de termes demande pour la solution
  1639. % nbsolution : no de la solution calculee ;
  1640. begin
  1641. scalar omega,fcoeff ; array ff(k);
  1642. % determination des : G(i) , ce sont des fonctions de lambda ;
  1643. % choix de g(0);
  1644. for i:=1:k do ff(i):=!&f(i);
  1645. if nbsolution = 2 then
  1646. <<
  1647. if rac(1)=rac(2) then !&g(0):=1
  1648. else
  1649. <<
  1650. % on suppose que les racines sont ordonnees de facon croissante
  1651. % c.a.d. rac(1)>rac(2);
  1652. omega:=rac(1)-rac(2);
  1653. !&g(0):=sub(lambd=lambd+omega,!&f(0));
  1654. >>;
  1655. >>;
  1656. if nbsolution = 3 then
  1657. <<
  1658. omega:=rac(1)-rac(3);
  1659. %? if omega<0 then omega :=-omega;
  1660. % probleme pour la determination de G(0) - A revoir et verifier;
  1661. !&g(0):=for i:=1:omega product( sub(lambd=lambd+i,!&f(0)) );
  1662. >>;
  1663. for i:=1:k do
  1664. <<
  1665. %rappel K fixe (nombre de terme demande);
  1666. ff(i):=num(ff(i));
  1667. if ff(i) eq 0 then !&g(i):=0
  1668. else
  1669. <<
  1670. fcoeff:=coeff(ff(i),!&g(i));
  1671. !&g(i):=-first(fcoeff)/second(fcoeff);
  1672. >>;
  1673. >>;
  1674. if lisp !*trdesir then
  1675. << write "Solution en l'indeterminee lambda : ";
  1676. factor x;
  1677. write !&w(0,x,lambd,k);
  1678. remfac x>>;
  1679. %determination des solutions;
  1680. if rac(1)=rac(2) then
  1681. <<
  1682. !&solution(1):=sub(lambd=rac(1),!&w(0,x,lambd,k));
  1683. !&solution(2):=sub(lambd=rac(1),!&w(0,x,lambd,k))
  1684. *log(x)
  1685. + sub(lambd=rac(1),!&w(1,x,lambd,k));
  1686. >>
  1687. else
  1688. <<
  1689. !&solution(1):=sub(lambd=rac(1),!&w(0,x,lambd,k));
  1690. if parm(0)=0 then
  1691. !&solution(2):=sub(lambd=rac(2),!&w(0,x,lambd,k))
  1692. *log(x) +
  1693. sub(lambd=rac(2),!&w(1,x,lambd,k))
  1694. else
  1695. !&solution(2):=!&w(0,x,lambd,k)
  1696. *log(x) + !&w(1,x,lambd,k);
  1697. >>;
  1698. if nbsolution = 3 then
  1699. !&solution(3):=sub(lambd=rac(3),!&w(0,x,lambd,k))
  1700. *(log x)**2
  1701. + 2*sub(lambd=rac(3),!&w(1,x,lambd,k))
  1702. *log(x)
  1703. + sub(lambd=rac(3),!&w(2,x,lambd,k) ) ;
  1704. clear ff;
  1705. end ;
  1706. % +++++++++++++++++++++++++++++++++++++++++++++++
  1707. % + +
  1708. % + PROCEDURES UTILITAIRES +
  1709. % + +
  1710. % +++++++++++++++++++++++++++++++++++++++++++++++
  1711. %;
  1712. procedure racine(f,x) ;
  1713. %-------------------- ;
  1714. % procedure qui calcule les racines quelconques ( et leur ordre de
  1715. % multiplicite ) d'une equation algebrique ;
  1716. %
  1717. % f : on cherche les racines de l'equation algebrique f(x)=0
  1718. % x : variable
  1719. %
  1720. % rac : tableau a une dimension des racines distinctes (de 1 a nbrac)
  1721. % ordremult : tableau correspondand de leur ordre de multiplicite
  1722. % cette procedure retourne le nombre de racines distinctes ;
  1723. begin
  1724. integer nbrac ;
  1725. scalar sol, multsol ;
  1726. nbrac:=0 ;
  1727. sol:=solve(f,x);
  1728. multsol:=multiplicities!* ;
  1729. for each elt in sol do
  1730. if lhs(elt) = x then
  1731. << nbrac:=nbrac+1 ;
  1732. ordremult(nbrac):=first(multsol);
  1733. multsol:=rest(multsol) ;
  1734. rac(nbrac):=rhs(elt) ;
  1735. >>
  1736. else multsol:=rest(multsol) ;
  1737. return nbrac ;
  1738. end ;
  1739. procedure membre(elt,list);
  1740. %------------------------;
  1741. begin
  1742. scalar bool;
  1743. for each w in list do if w=elt then bool:= T;
  1744. return bool;
  1745. end;
  1746. symbolic ;
  1747. terpri() ; terpri() ;
  1748. princ " DESIR : solutions formelles d'equations differentielles" ;
  1749. terpri() ;
  1750. princ " lineaires homogenes au voisinage de zero, point " ;
  1751. terpri() ;
  1752. princ " singulier regulier ou irregulier, ou point regulier" ;
  1753. terpri() ; terpri() ;
  1754. princ " Version 3.3 - Novembre 1993 " ; terpri() ;
  1755. princ " Appel par desir(); " ; terpri() ;
  1756. terpri() ;
  1757. algebraic ;
  1758. on gcd ;
  1759. endmodule;
  1760. end;