19
$\begingroup$

V 13.1 introduced the option IncludeSingularSolutions

When trying it, so far I have found over 250 ode's which hangs when using this option. First and second order. At the bottom I've put a link to plain .m file that contains list of ode's that hang and also link to a more complete notebook that shows more examples.

I do not mean DSolve just takes longer time now to finish, but I mean really hangs. I've waited for more than one hr on some and DSolve was still running.

Without this option, DSolve would otherwise finish almost instantly.

My question is: Is there an option to set a timelimit on finding the Singular solution, so that if it can't find it within this time, to simply ignore this option? Similar to

 "IntegrateOptions" /. SystemOptions[]

Mathematica graphics

Where one can set a timelimit on some options so not to cause the whole command to hang or take more time than wanted.

And why it seem to always hang when the solution of the ode has ProductLog in it. But I have found cases where it also hang when the solution has no ProductLog but these are much less common.

This is unfortunate, since now it means one has to try this option not knowing in advanced if the long time being taken and the reason for the timeout and failure of DSolve is because it could not find the singular solution and not because it could not find the general solution (which it can find). This option should be able to quickly decide if there is singular solution or not and not hang trying to find it.

Here is an example

ode=y'[x]==(1+x+y[x])^(1/2);
sol=AbsoluteTiming[TimeConstrained[DSolve[ode,y[x],x,IncludeSingularSolutions->False],60]];
Print["time used ",sol[[1]],"\nsolution =",sol[[2]]];
sol=AbsoluteTiming[TimeConstrained[DSolve[ode,y[x],x,IncludeSingularSolutions->True],60]];
Print["time used ",sol[[1]],"\nsolution =",sol[[2]]];

Mathematica graphics

Here is another

ode=-(a*(-y[x]+x*y'[x])^r)+y''[x]==0;
sol=AbsoluteTiming[TimeConstrained[DSolve[ode,y[x],x,IncludeSingularSolutions->False],60]];
Print["time used ",sol[[1]],"\nsolution =",sol[[2]]];
sol=AbsoluteTiming[TimeConstrained[DSolve[ode,y[x],x,IncludeSingularSolutions->True],60]];
Print["time used ",sol[[1]],"\nsolution =",sol[[2]]];

Mathematica graphics

Here is another

ode = (y[x] + 3*x - 1)^2*y'[x] - (2*y[x] - 1)*(4*y[x] + 6*x - 3) == 
   0;
sol = AbsoluteTiming[
   TimeConstrained[
    DSolve[ode, y[x], x, IncludeSingularSolutions -> False], 60]];
Print["time used ", sol[[1]], "\nsolution =", sol[[2]]];
sol = AbsoluteTiming[
   TimeConstrained[
    DSolve[ode, y[x], x, IncludeSingularSolutions -> True], 60]];
Print["time used ", sol[[1]], "\nsolution =", sol[[2]]];

Mathematica graphics

Links

m file that contains list of odes

notebook showing more examples

Current DSolve test report

$\endgroup$
2
  • 1
    $\begingroup$ Moreover, DSolve[y'[x] == Sqrt[1 + x + y[x]], y, x] produces a wrong solution {{y -> Function[{x}, -x + 2 ProductLog[-E^(-(3/2) - x/2 - C[1]/2)] + ProductLog[-E^(-(3/2) - x/2 - C[1]/2)]^2]}} in view of y'[x] == Sqrt[1 + x + y[x]] /. %;% /. {C[1] -> 1, x -> 1} which results in {False}. $\endgroup$
    – user64494
    Jul 10, 2022 at 12:00
  • $\begingroup$ If you replace ProductLog[z] by ProductLog[k, z] in the solution to y'[x] == Sqrt[1 + x + y[x]], as hinted at by the warning from Solve, one finds domains over which the altered solution is valid for k a nonzero integer. For k == 0, the solution seems to satisfy the ode only at x - C[1] - 1 == 0 (in the complex plane), which is not much of a solution. $\endgroup$
    – Michael E2
    Jul 10, 2022 at 15:18

3 Answers 3

10
$\begingroup$

Overloading the internal function with the Villegas-Gayley trick:

DSolve`DSolveSingularSolutions[];
Internal`InheritedBlock[{DSolve`DSolveSingularSolutions},
 (*****)
 DSolve`DSolveSingularSolutions // Unprotect;
 DownValues@DSolve`DSolveSingularSolutions = Join[
   {HoldPattern[
      call : DSolve`DSolveSingularSolutions[___] /; ! TrueQ[$in]] :> 
     Block[{$in = True},
      TimeConstrained[call,
       If[NumericQ@$singularSolutionsTimeConstraint,
        $singularSolutionsTimeConstraint,
        Infinity],
       {}]
      ]},
   DownValues@DSolve`DSolveSingularSolutions];
 DSolve`DSolveSingularSolutions // Protect;
 (*****)
 PrintTemporary@Dynamic@{Clock@Infinity};
 ode = y'[x] == (1 + x + y[x])^(1/2);
 sol = AbsoluteTiming[
   Block[{$singularSolutionsTimeConstraint = 2}, 
    DSolve[ode, y[x], x, IncludeSingularSolutions -> True]]
   ];
 Print["time used ", sol[[1]], "\nsolution =", sol[[2]]]
 ]
Solve::ifun: Inverse functions are being used by Solve, so some solutions may not be found; use Reduce for complete solution information.

time used 2.069711

solution = {
 {y[x] -> -x + 2*ProductLog[-E^(-3/2 - x/2 - C[1]/2)] + 
    ProductLog[-E^(-3/2 - x/2 - C[1]/2)]^2}}  
$\endgroup$
3
  • $\begingroup$ Note (in response to a comment I just saw): I believe the fail-expression in TimeConstrained, which I specified as {} which is what DSolve`DSolveSingularSolutions returns when it fails, may be replaced by {{y[x] -> "Failed"}}$Failed is not good because FreeQ[result, $Failed] is used in higher-level functions to test the result of internal ones. However, {{y[x] -> Failure["TimeConstraint", <||>]}} seems to work. $\endgroup$
    – Michael E2
    Jul 10, 2022 at 14:27
  • $\begingroup$ -1. Sorry, -x + 2 ProductLog[-E^(-(3/2) - x/2 - C[1]/2)] + ProductLog[-E^(-(3/2) - x/2 - C[1]/2)]^2] is not any solution of ` y'[x] == (1 + x + y[x])^(1/2)` (see my comment to the question). The verification is very useful. $\endgroup$
    – user64494
    Jul 10, 2022 at 16:58
  • 1
    $\begingroup$ @user64494 That's what I said.. Don't be so thoughtless, and try to stay on topic. The problem is to time-constrain solving for the singular solution, not to fix the ordinary general solution of DSolve. Your downvote is unethical. $\endgroup$
    – Michael E2
    Jul 10, 2022 at 17:10
9
$\begingroup$

Evaluate this:

$ModifyDSolve=True;
Unprotect[DSolve];
DSolve[eqns_,u_Symbol,opts___?OptionQ]:=Block[{$ModifyDSolve},TimeConstrained[
   DSolve[eqns,u,opts],
   600,
   DSolve[eqns,u,Flatten@{IncludeSingularSolutions->False,opts}]
]]/;And[$ModifyDSolve,IncludeSingularSolutions/.Flatten[{opts,Options@DSolve}]];
Protect[DSolve]

That should make DSolve start over with IncludeSingularSolutions->False after trying with IncludeSingularSolutions->True for 10 minutes. I learned this Block trick from tech support at Wolfram Research about 25 years ago!

$\endgroup$
2
  • $\begingroup$ Thanks. But I am already doing this using a simple If statement. Like this res=AbsoluteTiming[TimeConstrained[DSolve[{ode,y[x],x,IncludeSingularSolutions->True],3*60]]; If[res[[2]] === $Aborted, res = AbsoluteTiming[TimeConstrained[ DSolve[{ode,y[x],xIncludeSingularSolutions -> False], 3*60]] ] But both these methods means one have to now always try DSovle 2 times. Wasting lots of time even though the first time the general solution (most likely) was found already, which means having to find it again.... $\endgroup$
    – Nasser
    Jul 10, 2022 at 13:28
  • 2
    $\begingroup$ .... A better solution would have been that Mathematica returns the general solution (assuming it can) and $Failed in the slot where the singular solution would be. Something like {{the solution here},{$Failed}} so one does not have to try again. They can read the general solution, and check if the last slot was $Failed or not, then they know if the singular solution was found or not. Then there is no need to try again. Now my test takes almost 50% more time than it needs to be due to this. almost 2 days. $\endgroup$
    – Nasser
    Jul 10, 2022 at 13:31
9
$\begingroup$

Thanks for reporting about this issue. The slow evaluation arises because DSolve uses several different methods to generate all possible singular solutions, and some of them can be time expensive. We are already working to fix this issue.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.