Picard iterations
Consider the initial value problem
The inverse of the derivative operator \( \texttt{D} \) is not an operator in general mathematical sense because it assigns to every function infinite many outputs that are usually called the «antiderivative». In order to single out one output, we consider the differential operator on a special set of functions that have a prescribed value at one point x = x0, so f(x0) = y0. We denote \( \texttt{D} \) on such set of functions (which is not a linear space) as L. If we rewrite our initial value problem in the operator form \( L[y] = f , \) then apply its inverse L-1 to both sides, we reduce the given problem to the fixed point problem
If we integrate (that is, apply the inverse operator L-1 to the unbounded derivative operator restricted on the set of functions with a specified initial condition) both sides of the differential equation \( y' = f(x,y) \) with respect to x from x0 to x, we get the following integral equation
Now we deal with the fixed point problem that is more computationally friendly because we can approximate an integral with any accuracy we want. The Picard iterative process consists of constructing a sequence of functions { φn } that will get closer and closer to the desired solution. This is how the process works:
- The slope function is bounded: \( M = \max_{(x,y) \in R} \, |f(x,y)| . \)
- The slope function is Lipschitz continuous: \( |f(x,y) - f(x,z) | \le L\,|y-z| . \) for all (x,y) from R.
First, we verify that all members of the sequence exist. This follows from the inequality:
To show that the sequence converges, we represent the limit function as infinite series
We go step by step, and consider the first term
Next we prove that the limit function is a solution of the given initial value problem. Allowing n to approach infinity on both sides of
More details for the existence and uniqueness of the initial value problem can be found in the following textbooks
- Birkhoff, G. and Rota, G.-C., Ordinary Differential equations, 4rd Ed., John Wiley and Sons, New York, NY, 1989, Chapter 1, p. 23. https://doi.org/10.1137/1005043
- Boyce, W.E. and DiPrima, R.C., Elementary Differential equations and Boundary Value Problems, 11th edition, Wiley, New York; section 2.8.
- Dobrushkin, V.A., Applied Differential Equations. The Primary Course, CRC Press, Boca Raton, FL, 2015. Section 1.6.
- Edwards, C.H. and Penney, D.E., Differential Equations and Boundary Value Problems: Computing and Modeling, 5th edition, 2014, Prentice Hall, Upper Saddle River, NJ, Appendix A.1.
- Goode, S.W. and Annin, S.W., Differential Equations and Linear Algebra, 4th edition, Prentice Hall, Upper Saddle River, NJ, 2016, Appendix 4.
- Hille, E., Lectures on Ordinary Differential Equations, Addison-Wesley Pub. Co., Reading, MA, 1969, pp. 32-41.
- Nagle, R.K., Saff, E.K., and Snider, A.D., Fundamentals of Differential Equations and Boundary Value Problems, 8th edition, Addison-Wesley, Boston, MA, 2019, Chapter 13, Sections 1 and 2.
- Wouk, A., On the Cauchy-Picard Method, The American Mathematical Monthly, Vol. 70, No. 2. (Feb., 1963), pp. 158-162.
Although this approach is most often connected with the names of Charles Emile Picard, Giuseppe Peano, Ernst Lindelöf, Rudolph Lipschitz, and Augustin Cauchy, it was first published by the French mathematician Joseph Liouville in 1838 for solving second order homogeneous linear equations. About fifty years later, Picard developed a much more generalized form, which placed the concept on a more rigorous mathematical foundation, and used this approach to solve boundary value problems described by second order ordinary differential equations.
Note that Picard's iteration procedure, if it could be performed, provides an explicit solution to the initial value problem. This method is not for practical applications mostly for two reasons: finding the next iterate may be impossible, and, when it works, Picard's iteration contains repetitions. Therefore, it could be used sometimes for approximations only. Moreover, the interval of existence (-h, h) for the considered initial value problem is in most cases far away from the validity interval. There are known some improvements in this direction (for instance, S.M. Lozinsky theorem), but we are far away from complete determination of the validity interval based on Picard's iteration procedure. Also, there are a number of counterexamples in which Picard iteration is guaranteed not to converge, even if the starting function is arbitrarily close to the real solution.
Here are some versions of Picard's iteration procedure for Mathematica:
Print[{n, y[n][t]}]]
iterate[initial_, flow_, psi_, n_, t_] :=
initial +
Expand@Apply[Subtract,
Assuming[{Subscript[t, n + 1] > 0},
Integrate[flow[Subscript[t, n + 1], psi], Subscript[t, n + 1]]] /. {{Subscript[t, n + 1] -> Subscript[t, n]}, {Subscript[t, n + 1] -> 0}}]
picardSeries[initialVector_, flow_, n_, var_] :=
Module[{time},
Fold[
iterate[
initialVector, flow, #1, #2, time ] &,
initialVector, Reverse[Range[n] - 1]] /. {Subscript[time, 0] -> var} ]
iterate
, and it keeps track of the iteration order n so that it can assign a separate integration variable name at each step. As additional tricks to speed things up, I avoid the automatic simplifications for definite integrals by doing the integral as an indefinite one first, then using Subtract
to apply the integration limits.
Instead of a generic simplification, I add Expand
to the result in order to help the subsequent integration step recognize how to split up the integral over the current result. The last argument in iterate
is the name that I intend to use as the base variable name for the integration, but it will get a subscript n attached to it.
Then iterate is called by picardSeries, using increasing subscripts starting with the outermost integration. This is implemented using Fold with a Reverse range of indices. The first input is the initial condition, followed by the function defining the flow (specifically, defined below as flow[t_, f_]). After the order n, I also specify the name of the independent variable var
as the last argument.
Here is the example applied to the IVP: \( y' = y^2 + x^2 , \ y(0) =1 . \)
picardSeries[1, flow, 5, x]
h = Function[{t}, 1 + Integrate[#^2 + x^2, {x, 0, t}]][x] & ;
NestList[h, 1, 3]
h = Function[{t}, 1 + Integrate[#^2 + x^2, {x, 0, t}]][x] & ;
y[0][x_] = 1
y[n_][x_] := y[n][x] = h[y[n - 1][x]]
FoldList[h, 1, Range[2]]
Example: Consider the initial value problem for the linear equation
Expanding the explicit solution into Maclaurin series, we obtain
y0:=x->1:
f:=(x,y)->x^2 + y^2: y1:=x->1+int(f(t,y0(t)),t=0..x):
y2:=x->1+int(f(t,y1(t)),t=0..x):
y3:=x->1+int(f(t,y2(t)),t=0..x):
y0(x),y1(x),y2(x),y3(x);
de:=diff(y(x),x)=f(x,y(x)): ic:=y(0)=1:
dsolve({de,ic},y(x));
dsolve({de,ic},y(x),series);
seriesDSolve[ode_, y_, iter : {x_, x0_, n_}, ics_: {}] :=
Module[{dorder, coeff},
dorder = Max[0, Cases[ode, Derivative[m_][y][x] :> m, Infinity]];
(coeff = Fold[
Flatten[{#1,
Solve[#2 == 0 /. #1,
Union@Cases[#2 /. #1, Derivative[m_][y][x0] /; m >= dorder,
Infinity]]}] &,
ics,
Table[
SeriesCoefficient[ode /. Equal -> Subtract, {x, x0, k}],
{k, 0, Max[n - dorder, 0]}]
];
Series[y[x], iter] /. coeff) /; dorder > 0 ]
( 75092 x^11)/51975 + (1238759 x^12)/831600 + (9884 x^13)/6435 + ( 17121817 x^14)/10810800 + (115860952 x^15)/70945875 + SeriesData[ x, 0, {}, 0, 16, 1]
y[n][x_] = 1 + Integrate[y[n - 1][t]^2 + t^2, {t, 0, x}];
Print[{n, y[n][t]}]]
{2,1+t+t^2+(2 t^3)/3+t^4/6+(2 t^5)/15+t^7/63}
{3,1+t+t^2+(4 t^3)/3+(5 t^4)/6+(8 t^5)/15+(29 t^6)/90+(47 t^7)/315+
(41 t^8)/630+(299 t^9)/11340+(4 t^10)/525+(184 t^11)/51975+t^12/2268+(4 t^13)/12285+t^15/59535}
Module[{time},
FoldList[
iterate[
initialVector, flow, #1, #2, time
] &,
initialVector,
Reverse[Range[n] - 1]] /. {Subscript[time, _] -> var} ]
picardList[1, flow, 4, x] // TableForm
iterate[initial_, flow_, psi_, n_, t_] :=
initial +
Expand@Apply[Subtract,
Assuming[{Subscript[t, n + 1] > 0},
Integrate[flow[Subscript[t, n + 1], psi],
Subscript[t, n + 1]]] /. {{Subscript[t, n + 1] ->
Subscript[t, n]}, {Subscript[t, n + 1] -> 0}}]
picardSeries[initialVector_, flow_, n_, var_] :=
Module[{time},
Fold[iterate[initialVector, flow, #1, #2, time] &, initialVector,
Reverse[Range[n] - 1]] /. {Subscript[time, 0] -> var}]
picardSeries[1, flow, 5, x]
BesselJ[-(1/4), x^2/2] Gamma[3/4] - x^2 BesselJ[3/4, x^2/2] Gamma[3/ 4])/
(x (BesselJ[1/4, x^2/2] Gamma[1/4] - 2 BesselJ[-(1/4), x^2/2] Gamma[3/4]))}}
x^2 BesselJ[-(5/4), x^2/2] Gamma[3/4] +
BesselJ[-(1/4), x^2/2] Gamma[3/4] -
x^2 BesselJ[3/4, x^2/2] Gamma[3/ 4])/
(x (BesselJ[1/4, x^2/2] Gamma[1/4] - 2 BesselJ[-(1/4), x^2/2] Gamma[3/4]))
phi4[x_] =
1 + x + x^2 + (4 x^3)/3 + (7 x^4)/6 + (6 x^5)/5 + (107 x^6)/90 +
( 362 x^7)/315 + (2683 x^8)/2520 + (2689 x^9)/2835 + (92179 x^10)/ 113400 +
(6673 x^11)/9900 + (201503 x^12)/374220 + (612853 x^13)/ 1474200 +
(3774677 x^14)/12162150 + (127144841 x^15)/567567000
Plot[{y[x], phi4[x]}, {x, 0, 1}, PlotStyle -> Thick]
y[n][x_] = 1 + Integrate[-y[n - 1][t]^2 + t^2, {t, 0, x}];
Print[{n, y[n][t]}]]
( Sqrt[37] x^5)/240 + x^6/240 + (Sqrt[37] x^7)/10080 + x^8/13440 +
( Sqrt[37] x^9)/725760 + x^10/1209600 +
( Sqrt[37] x^11)/79833600 + x^12/159667200 +
( Sqrt[37] x^13)/12454041600 + x^14/29059430400 +
( Sqrt[37] x^15)/2615348736000 + SeriesData[x, 0, {}, 0, 16, 1]
(a*b)/c+13*d
ur code
another line
(a*b)/c+13*d
ur code
another line