The symmetry method is a powerful method to solve differential equations by finding invariant transformations (point symmetries) of the ODE. For first order ODEs, an integrating factor can be constructed from the symmetry and the ODE can then be solved. For first order ODEs, there is no closed form algorithm to find a symmetry in general, but there are algorithms for finding symmetries of a certain form. In Cheb-Terrab and Kolokolnikov [1], a very general algorithm is presented that searches for linear symmetries of the form
$[\xi = F(x),\eta=P(x)y+Q(x)]$.
In Cheb-Terrab and Roche [2], an algorithm is presented for finding several simpler symmetries of the form
(1) $[\xi=F(x)*G(y), \eta=0]$, $[\xi=0, \eta=F(x)*G(y)]$
(2) $[\xi=F(x)+G(y), \eta=0]$, $[\xi=0, \eta=F(x)+G(y)]$
(3) $[\xi=F(x), \eta=G(x)]$, $[\xi=F(y), \eta=G(y)]$
(4) $[\xi=F(x), \eta=G(y)]$, $[\xi=F(y), \eta=G(x)]$
(5) $[\xi=ax+by+c, \eta=fx+gy+h]$
We see that the linear symmetries presented in [1] are a generalization of the search for symmetries of the form (3) presented in [2].
These methods have been implemented in the function ode1solve and can be found in the file ode1_lie.mac. Additionally, several other methods have been implemented that search for symmetries of specific ODEs. These algorithms are very fast but also limited in applicability. The implemented methods are symmetry searches for ODEs of the type: linear, inverse-linear, separable, exact, Riccati, Bernoulli and Abel. These symmetries can also be found using the search for more general symmetries mentioned above, but these dedicated methods are usually much faster.
As a performance test, the database of Kamke's first order ODEs was used [3]. In the database are 367 ODEs of first order and first degree. A number of these ODEs (Cheb-Terrab and Kolokolnikov mention 20 of the first order - first degree) are unsolvable because they are too general (these are ODEs 47, 48, 50, 55, 56, 74, 79, 82, 202, 219, 234, 235, 237, 250, 253, 269, 331). 178 of the ODEs are of type separable, linear, inverse linear and Bernoulli and therefore considered straightforward to solve. They were not considered in the evaluation of the symmetry method in [2]. These equations (as well as all homogeneous and Ricatti and Abel odes with constant invariants) all have linear symmetries. Of the 246 ODEs of first order and first degree that are left, 133 were solved by the Cheb-Terrab and Roche method. With the method of Cheb-Terrab and Kolokolnikov, another 20 ODEs of first order and first degree with linear symmetries can be found.
Our implementation currently finds (nontrivial) symmetries for 298 of the 347 solvable ODEs of first order and first degree, which amounts to a success rate of 85%. Every nontrivial symmetry of a first order ODE directly leads to an integrating factor, and therefore to a solution of the ODE. Most ODEs for which no symmetries could be found are currently outside the scope of the method. They are Riccati or (nonconstant invariant) Abel ODEs with special function solutions like Bessel functions.
Function: ode1solve(ode,y,x,[options])
Returns: a list with the analytical solutions of the ODE, or false when no solutions are found.
ode1solve is an Ordinary Differential Equation (ODE) solver for first order ODEs using symmetries. If point symmetries can be found for the input ODE(s), ode1solve will use these symmetries to solve construct and integrating factor and solve the ODE. The input is a first order ode of the form F('diff(y,x),y,x)=0. ode1solve will first try to solve the ode explicitly for 'diff(y,x) and then solve each of the branches. The default is to return the explicit analytical solution(s) as a list. The list may contain more than one solution.
In [ ]:
kill(all);batch("~/mathematics/maxima_files/kamke1_1.mac");batch("~/mathematics/maxima_files/ode1_lie.mac");DEBUGFLAG:1;
In [3]:
ode1solve('diff(y,x)+x^2+5,y,x);
Out[3]:
Optional arguments are:
In [4]:
DEBUGFLAG:1;
ode:'diff(y,x)+p(x)*y=q(x)*y^4;
ode1solve(ode,y,x,'returnExplicit=false,'useMethod="bernoulli");
Out[4]:
Out[4]:
Out[4]:
The default of ode1solve is to use all these methods sequentially, in this order, to find a solution of the ode $y'=\Phi(x,y)$. The method abel is not called because all Abel ODEs with constant invariants have linear symmetries and can be solved by the method "symmetry6". Abel ODEs with non-constant invariants cannot be solved in general, althought there are a couple of specific cases where ode1solve is able to find a symmetry. All the available methods can be called individually. When for instance 'useMethod="symmetry1" is chosen, ode1solve searches for symmetries of type $[\xi=F(x)*G(y), \eta=0]$. If the ODE instead has the inverse symmetries $[\xi=0, \eta=F(x)*G(y)]$, then these inverse symmetries can be found by looking for symmetries of the inverse ode $y' =\frac{1}{\Phi(y,x)}$. The inverse of an ODE can be found by using the change of variables $x\rightarrow y^{*}(x^{*})$ and $y(x)\rightarrow x^{*}$ and then renaming $y^{*}$ as $y$ and $x^{*}$ as $x$, see e.g. [2].
The method of undetermined coefficients is called "symmetry5", an alias is "muc". This method tries to find a symmetry of an ODE using the method of undetermined coefficients. When no keywords are given by the user, we search for polynomial symmetries of the form
$ax+by+cxy+dx^2+...$,
where the default polynomial order is 2. This is determined by the global keyword SYM5DEGREE and can be changed by the user. It turns out that a polynomial degree of 5 or more is computationally too expensive for even the most patient user.
Symmetry5b is another implementation of the method of undetermined coefficients where we search for rational symmetries of the form $\frac{P}{Q}$, with $P$ and $Q$ polynomials in the undetermined variables (usually the dependent variable $y$ and independent variable $x$ in $\frac{dy}{dx}=\Psi(x,y)$).
Symmetry5b looks for first for symmetries of the form $[0,F/G]$ where $F$ is a polynomial $F(x,y)$ and $G=P$ is the polynomial expression in the denominator of the ODE $\frac{dy}{dx}=\frac{Q}{P}$. The degree of the polynomial $F$ is fixed at 5.
When these symmetries can not be found, symmetry5b looks for symmetries of the form $[0,F/G]$ and $[F/G,0]$, where $F$ and $G$ are both undetermined polynomials. The degree of the polynomials are set to SYM5DEGREE-1.
if SYM5RAT is true, symmetry5b additionally searches for polynomials of the form
$[(ax+by+c)/(dx+ey+f),(gx+hy+i)/(jx+ky+l)]$.
The default for SYM5RAT is false because this method is very expensive and does not uniquely solve any ODE in the kamke database.
The user can also define her own predefined shapes for the symmetries. This method requires two keywords: xi and eta. xi and eta define the shape of the symmetry, e.g.
$xi=a*x+b*y+c$
or
$xi=a*sin(x)$
A separate tutorial on using the method of undetermined coefficients is symmetry5.ipynb
</dl>
System variable: (bool) FIX_INTEGRATION_CONSTANT</br> default: true</br> When FIX_INTEGRATION_CONSTANT=true, the integration constant will be fixed at maxima's system variable integration_constant (which is usually %c). When FIX_INTEGRATION_CONSTANT=false, then every call to ode1SolveWithIntegrationFactor (this is called from ode1solve as well) will result in a new integration constant %c1, %c2, etc. where the initial value for the counter is taken from maxima's system variable integration_constant_counter.
System variable: (integer) DEBUGFLAG={0,1,2,3,4,5}</br> default: 1 </br> When DEBUGFLAG=0, no information except the solution or errors are printed. More intermediate information is given for increasing values of DEBUGFLAG
System variable: (string) method</br> default: false </br>
method returns the last successful method used to solve an ODE. if the last call to the solver failed, method is false.
System variable: (string) reason
default: "none"
If known, reason returns information on why the solver was not able to find a solution, for instance if the ODE was found to be an Abel ODE with non-constant invariants.
Option variable: (bool) returnSymmetries
default: false
When true, returnSymmetries returns the symmetries found as a list.
Option variable: (bool) returnIntegratingFactor
default: false
When true, returnIntegratingFactor returns the integrating factors found as a list.
Option variable: (bool) returnExplicit
default: true
When true, returnExplicit tries to return an explicit solution in the dependent variable.
Option variable: (bool) tryInverse
default: false
When true, for every symmetry method that ode1solve tries (trying to find a symmetry $X=[\xi,\eta]$), after it has failed it will then try to find the inverse symmetry $X=[\eta,\xi]$.
Option variable: (bool) SYM5RAT
default: false
When SYM5RAT=true, ode1solve will try to find rational-polynomial symmetries of the ODE. This is usually time consuming.
Option variable: (bool) CHECKSYM
default: true
When true, checks if the symmetry and integrating factor is valid.
function: ode1sym(ode,y,x)</br> an alias for ode1solve that will only return the symmetries
In [5]:
ode1sym('diff(y,x)=f(x)*g(y),y,x);
Out[5]:
function: ode1intfac(ode,y,x)</br> an alias for ode1solve that will only return the integrating factors
In [6]:
ode1intfac('diff(y,x)=f(x)*g(y),y,x);
Out[6]:
function: (list) isBernoulli(ode,y,x)</br> returns a list $[b(x),n,a(x)]$ of the ODE $y'+a(x)y=b(x)y^n$ if the input ode is a Bernoulli ODE, or false otherwise.
In [7]:
isBernoulli('diff(y,x)-x*y^2-3*x*y,y,x);
Out[7]:
function: (list) isRiccati(ode,y,x)</br> returns the coefficients of the Riccati ODE $y' = A(x)+B(x)y+C(x)y^2$.
In [8]:
isRiccati('diff(y,x)=x+y^2,y,x);
Out[8]:
function: (list) isChini(ode,y,x)</br> returns the coefficients [A,n,B,C] if the input ODE is a Chini ODE $y' = C(x) +B(x)y +A(x)y^n$, and false otherwise
In [9]:
isChini('diff(y,x)=x*y^4+x^2*y+5,y,x);
Out[9]:
function: (list) isAbel(ode,y,x)</br> returns a list of the coefficients of the abel ODE, either in first kind form or second kind form if the input ODE is an Abel ODE, or false otherwise. Abel's ODE of the first kind is $y' = a_0(x)+a_1(x)y+a_2(x)y^2 +a_3(x)y^3$. Abel's ODE of the second kind is $y' = \frac{a_0(x)+a_1(x)y+a_2(x)y^2 +a_3(x)y^3}{a(x)y+b(x)}$.
In [10]:
isAbel('diff(y,x)=5+x*y+x^2*y^2+x^3*y^3,y,x);
Out[10]:
In [11]:
isAbel('diff(y,x)=(5+x*y+x^2*y^2+x^3*y^3)/(x+y),y,x);
Out[11]:
function: (bool) isAbelFirst(ode,y,x)</br> returns true if the input ode is an Abel ODE of the first kind $y' = a_0(x)+a_1(x)y+a_2(x)y^2 +a_3(x)y^3$.
function: (bool) isAbelSecond(ode,y,x)</br> returns true if the input ode is an Abel ODE of the second kind $y' = \frac{a_0(x)+a_1(x)y+a_2(x)y^2 +a_3(x)y^3}{a(x)y+b(x)}$.
function: ode1AbelSecond2First(ode,y,x)</br> converts an Abel ODE of the second kind to an Abel ODE of the first kind
function: ode1AbelFirst2Second(ode,y,x)</br> converts an Abel ODE of the first kind to an Abel ODE of the second kind
function: ode1AbelRNF(ode,y,x)</br> converts an Abel ODE to its rational normal form, either $w'+aw3+bw=0$ or $w'+aw^3+bw+1=0$
function: ode1AbelSymmetries(ode,y,x)</br> Computes the symmetries of an Abel ODE.
function: (bool) isIntegratingFactor(mu,ode,y,x)</br> returns true if the input expression mu is an integrating factor of the ode.
function: ode1_CanonicalForm(ode,y,x)</br> Write the input ODE into a 'canonical' form, meaning that we try to write the input ODE as an explicit ode $y'=\omega(x,y)$ and we try to simplify the right hand side.
function: ode1PfaffianForm(ode,y,x)</br> writes the input ODE $\frac{dy}{dx}=\frac{P(y,x)}{Q(y,x)}$ in Pfaffian form $P(y,x)dx-Q(y,x)dy=0$ and returns $[P,Q]$.
In [12]:
ode1PfaffianForm('diff(y,x)=f(x)/g(y),y,x);
Out[12]:
function: checkSymmetries(X,ode,y,x)</br> substitutes the input symmetry into the linearized symmetry condition of the ode and returns the result. If the result is 0, then X is a symmetry of the ODE.
In [13]:
X:ode1sym('diff(y,x)=f(x)*g(y),y,x);
checkSymmetries(X,'diff(y,x)=f(x)*g(y),y,x);
Out[13]:
Out[13]:
function: reverseODE1(ode,y,x)</br> returns the reverse ODE of the input ode, that is we interchange variables: $x^{*}=y$ and $y^{*}=x$ and return an ode $\frac{dy^{*}}{dx^{*}}=\omega(x^{*},y^{*})$.
In [14]:
reverseODE1('diff(y,x)=x*y,y,x);
Out[14]:
function: rootsexpand(expr)</br> splits an expression containing square roots and factorizes the square roots such that $sqrt((p_1*p_2*...p_n)/(q_1*q_2*..q_m))= sqrt(p_1)*sqrt(p_2)*...sqrt(p_n)/(sqrt(q_1)*sqrt(q_2)*..sqrt(q_m))$. This is the inverse of rootscontract.
In [15]:
rootsexpand(sqrt(x^2*y*a^3));
Out[15]:
function: determiningEquations(ode,y,x)</br> returns the determining equations of the first order ODE $y' = \phi(x,y)$, which is given by: $\eta_x + \eta_y - \xi_x*\phi - \xi_y*\phi^2 - \xi*\phi_x - \eta*\phi_y$
In [16]:
determiningEquations('diff(y,x)=f(x)*g(y),y,x);
Out[16]:
function: canoni(X,y,x)</br> compute canonical coordinates from the input symmetry $X$.
In [17]:
canoni([1,0],y,x);
Out[17]:
function: ode1FromSym(X,y,x)</br> Generate the most general ODE under the group $X$. The result will contain unknown functions $\%F(x,y)$ in the independent and dependent variable.
In [18]:
ode1FromSym([0,y],y,x);
Out[18]:
function: (expr) differentialInvariants(X,y,x)</br> Compute differential invariants from the symmetry
In [19]:
differentialInvariants([1,0],y,x);
Out[19]:
function: (expr) riccati_RNF(ode,y,x)</br> try to put the input Riccati ODE into it's Rational Normal Form.
In [20]:
riccati_RNF('diff(y,x)=x*y^2+5*x+5,y,x);
Out[20]:
[1] E.S. Cheb-Terrab and T. Kolokolnikov, First-order ordinary differential equations, symmetries and linear transformations, Euro. J. of Applied Mathematics 14 (2003)
[2] E.S. Cheb-Terrab and A.D. Roche, Symmetries and first order ODE patterns, Computer Physics Communications 113 (1998)
[3] E. Kamke, Differentialgleichungen, L$\ddot o$sungsmethoden und L$\ddot o$sungen, Leipzig (1959)
[4] E.S. Cheb-Terrab, L.G.S. Duarte and L.A.C.P. da Mota, Computer algebra solving of first order ODEs using symmetry methods, Computer Physics Communications 101 (1997)
[5] F. Schwarz, Symmetry analysis of Abel's equation, Studies in applied mathematics 100 (1998)
[6] F. Schwarz, Algorithmic solution of Abel's equation, Computing 61 (1998)