Accessing Reduce from DSolve

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)

Internal`InheritedBlock[{Solve},
  Unprotect[Solve];
  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


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.


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},
 Unprotect[Solve];
 Solve[e_, v_] :=
  With[{res = Reduce[e, v]},

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

   {
    Cases[res, 
          var_?(MemberQ[Flatten[{v}], #] &) == rhs_ :> Rule[var, rhs], 
          Infinity
   ]
  }
 ];
 Transpose[{
    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.