This detects the general Riccati ode \(y'=f_0(x) + f_1(x) y(x)+ f_2(x) y^2\)
The input to the proc is the ode and the dependent function \(y(x)\). The parsing function will return \(f_0,f_1,f_2\) if successful match is found, or FAIL if ode does not match the expected pattern.
\(f_0,f_2\) can not be zero (i.e. missing), but \(f_1\) could be missing.
In the case \(f_1=0\), either \(f_0\) or \(f_2\) or both must be functions of \(x\). Also in the case of \(f_1=0\), if it is reduced Riccati, then it return FAIL.
In the case \(f_1\) is present and also depends on \(x\), then now \(f_0,f_2\) are both allowed not to be functions of \(x\). But if \(f_1\) present and also does not depend on \(x\), then now at least one of \(f_0,f_2\) must be function of \(x\).
general_riccati_parse:=proc(ode::`=`,func::function(name),$) local RHS; local y:=op(0,func); local x:=op(1,func); local stat; local la,f0,f1,f2; stat:= reduced_riccati_parse(ode,func); if stat<>FAIL then #this is reduced riccati, hence not general RETURN(FAIL); fi; #now check if general riccati try RHS:=timelimit(30,[solve(ode,diff(y(x),x))]); if nops(RHS)<>1 then RETURN(FAIL); fi; RHS:=expand(RHS[1]); RHS:=collect(RHS,[y(x),y(x)^2]);#must collect to insure the right form catch: RETURN(FAIL); end try; if patmatch(RHS,f0::anything+f1::anything*y(x)+f2::anything*y(x)^2,'la') then assign(la); if f0=0 or f2=0 then RETURN(FAIL); fi; if has(f0,y(x)) or has(f1,y(x)) or has(f2,y(x)) then RETURN(FAIL); fi; if has(f1,x) then RETURN(f0,f1,f2); else if not has(f0,x) and not has(f2,x) then RETURN(FAIL); else RETURN(f0,f1,f2); fi; fi; else #check for f1 missing if patmatch(RHS,f0::anything+f2::anything*y(x)^2,'la') then assign(la); if has(f0,y(x)) or has(f2,y(x)) then RETURN(FAIL); fi; if not has(f0,x) and not has(f2,x) then RETURN(FAIL); fi; RETURN(f0,0,f2); else RETURN(FAIL); fi; fi; end proc:
Example usage
ode:=diff(y(x),x)=f0(x)+f1*y(x)+f2*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); f0(x), f1, f2 [_Riccati] ode:=diff(y(x),x)=f0+f1(x)*y(x)+f2*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); f0, f1(x), f2 [_Riccati] ode:=diff(y(x),x)=f0(x)+f1(x)*y(x)+f2*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); f0(x), f1(x), f2 [_Riccati] ode:=diff(y(x),x)=f0(x)+f1(x)*y(x)+f2(x)*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); f0(x), f1(x), f2(x) [_Riccati] ode:=diff(y(x),x)=f0(x)+f2(x)*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); f0(x), 0, f2(x) [_Riccati] ode:=diff(y(x),x)=x+f2(x)*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); x, 0, f2(x) [_Riccati] ode:=diff(y(x),x)=x+f2*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); FAIL [[_Riccati, _special]] ode:=diff(y(x),x)=1/x+y(x)+y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); 1 -, 1, 1 x [_rational, _Riccati] ode:=diff(y(x),x)=1/x+y(x)+x*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); 1 -, 1, x x [_rational, _Riccati] ode:=diff(y(x),x)=x*y(x)+c*y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); FAIL [_Bernoulli] ode:=diff(y(x),x)=x-1+y(x)^2: general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); -1 + x, 0, 1 [_Riccati] ode:=diff(y(x),x)=(3+9*x+8*y(x))^(2): #this ode needs the collect general_riccati_parse(ode,y(x)); DETools:-odeadvisor(ode); 81*x^2 + 54*x + 9, 144*x + 48, 64 [[_homogeneous, class C], _Riccati]