desir.red 58 KB

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