Mathematica Stack Exchange is a question and answer site for users of Mathematica. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

When solving transcendental equations, Solve frequently warns us that inverse functions are being used so that some solutions may not be found.

enter image description here

We also see that Reduce might provide a more complete solution and, indeed, simply changing Solve to Reduce provides a complete, quantified result.

enter image description here

Somtimes, however, this same message is produced by DSolve.

enter image description here

My guess is that DSolve calls Solve which in turn generates the message. Is it possible, though, to access Reduce through DSolve? For this particular equation, it would be easy enough to separate variables, Integrate and then apply Reduce. I'm wondering about a more general solution, though.

share|improve this question
up vote 14 down vote accepted

You could swap Reduce for Solve like this:

Internal`InheritedBlock[{Solve}, Unprotect[Solve];Solve = Reduce; Solve[t^2 + t + 1 == 0, t]]

t == -(-1)^(1/3) || t == (-1)^(2/3)

which is indeed Reduce's output. Solve's output would have looked like this:

Solve[t^2 + t + 1 == 0, t]

{{t -> -(-1)^(1/3)}, {t -> (-1)^(2/3)}}

Unfortunately, this trick doesn't work for DSolve:

Internal`InheritedBlock[{Solve}, Unprotect[Solve];Solve = Reduce; 
                                 DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]

DSolve[Derivative[1][u][t] == u[t]/(4 + u[t]^2), u[t], t]

It clearly has an effect as it now returns unevaluated, whereas previously you got a solution. So it seems Solve is indeed used internally. My guess is that the results as returned from Reduce are not in the form DSolve expects and wants, so it certainly isn't the last step. I assume that internal error checking then halts execution and spits out the unresolved call.

Given that DSolve doesn't seem to have options that determine the way the output is treated I don't think that what you want is possible.

share|improve this answer
Very interesting comments - thanks! I'm pretty sure you're right about the difficulties. Ultimately, I'm trying to produce DSolve output that is as palatable as possible for my DE students. – Mark McClure Sep 16 '12 at 14:24
I think you're right; the dependence on Solve seems to be hard-coded. See, for instance, the definition of DSolve`DSolveSolve. – Oleksandr R. Sep 16 '12 at 14:30
It can be salvaged, somewhat. The difficulty lies in how the results of Solve and Reduce differ, and likely DSolve relies on that distinction. The DE $u^\prime(t)=-5u(t)$ illustrates it nicely. So, replace Solve = Reduce with Solve[a___]:= {ToRules@Reduce[a]} which works fine for my example. However, it still emits a lot of messages with Mark's DE, but that seems due to a number of conditions being imposed on the solutions. It may be workable, if not easily readable. – rcollyer Sep 16 '12 at 14:45

It's interesting to see what DSolve is using Solve for. This code prints Solve expressions which occur during the evaluation:

(Note - @belisarius reminds me that TracePrint[DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t], Solve[__], TraceInternal -> True]; would also work for this purpose)

  Solve[x___] := Block[{$guard = True},
         Print["Solve called : ", HoldForm[Solve[x]]];
         Solve[x]] /; ! TrueQ[$guard];
  DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]];

enter image description here

The first of these is just rearranging the original differential equation to get an expression for u'[t] and causes no problems. The second is an attempt to rearrange the solution, and it's here that the warning is produced. Evaluating Reduce[4 Log[u[t]] + u[t]^2/2 == t + C[1], u[t]] gives the result and message that rcollyer obtained.

The more general solution that Reduce provides can also be obtained like this:

SetOptions[Solve, MaxExtraConditions -> All];
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]

enter image description here

share|improve this answer
Most excellent! – Mark McClure Sep 16 '12 at 21:53
Nice spelunking. I didn't even think to try that. +1 – rcollyer Sep 17 '12 at 3:20
By running Trace[] with TraceInternal->True you could also see that that call to Solve[] came in turn from System`Private`OldSolve[4 Log[u[t]] + u[t]^2/2 == t + C[1], {u[t]}, {}, InverseFunctions -> Automatic, MakeRules -> False, Method -> 3, Mode -> Generic, Sort -> True, VerifySolutions -> Automatic, WorkingPrecision -> \[Infinity]] – Dr. belisarius Sep 17 '12 at 5:05
@belisarius, interesting observation. Of course Trace would have been a far simpler way to extract the calls to Solve. (My excuse is that I originally had extra code in there, comparing the output of Solve and Reduce). – Simon Woods Sep 17 '12 at 18:17

As a piggy back onto Sjoerd's solution, here's a solution that will give you Solve like answers with the conditions still attached:

Block[{Solve, conds},
 Solve[e_, v_] :=
  With[{res = Reduce[e, v]},

   (* capture the conditiions via a side-effect *)
   conds = res /. Equal[var_?(MemberQ[Flatten[{v}], #] &), __] :> Sequence[];

          var_?(MemberQ[Flatten[{v}], #] &) == rhs_ :> Rule[var, rhs], 
    DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t][[1]], 
    List @@ LogicalExpand[conds]

{{u[t] -> -2*
  some obscene condition},

But, it also produces this message:

enter image description here

which could be removed with Quiet, but I left it in as I don't think it is as bad as the Solve one. Also, I used Block instead of Internal`InheritedBlock as we are completely replacing the behavior of Solve with something else.

share|improve this answer
Thanks. I tried a few variations of this without real success. As I said in a response to Sjoerd, it's really an attempt to make things simpler for my students so I'd really need a fairly simple solution. – Mark McClure Sep 16 '12 at 16:38

One can access Reduce through Solve via the Solve option Method -> Reduce. To get this through DSolve, we can use SetOptions.

opts = Options[Solve];
SetOptions[Solve, Method -> Reduce];
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t] // FullSimplify
SetOptions[Solve, opts];

(* long messy answer that looks quite like rcollyer's and Simon Wood's,
   together with the same warning message. *)

It's still not suitable for undergraduates, of course.

The usual by-hand solution has the form t = f(u), so an alternative is to solve the differential equation obtained by transforming the original into terms of the inverse function t[u]:

DSolve[{u'[t] == u[t]/(4 + u[t]^2)} /. {u[t] -> u, u'[t] -> 1/t'[u]}, t[u], u]
  {{t[u] -> u^2/2 + C[1] + 4 Log[u]}}

You can get back the OP's DSolve output with

Solve[First[%] /. {Rule -> Equal, t[u] -> t}, u] /. u -> u[t]
share|improve this answer
Seems so simple - thanks! – Mark McClure Oct 28 '14 at 13:11

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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