desir.red 64 KB

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