# Evading the fewer dependent variables than equations error

I'm writing a code that tries to solve differential equations generated from some existing code. The equations so generated are often seemingly overdetermined but actually solvable: e.g.

{f'[x] == 0, f''[x] == 0 }


However, plugging this into DSolve spits the DSolve::overdet: There are fewer dependent variables than equations, so the system is overdetermined error.

These equations can of course be preprocessed by hand before feeding into DSolve. But I wonder if there is a way to automatically solve this kind of equations?

• It's like we need a "DReduce[]"... Commented Apr 18, 2022 at 16:50
• As far as ad hoc approaches go, the most straightforward to modify the given system is DSolve[First@{f'[x] == 0, f''[x] == 0 }, f x] or simply DSolve[f'[x] == 0, f, x]. Commented Apr 19, 2022 at 14:59

DSolve[{f'[x] == 0, g'[x] == 0, f'[y] == g[y]}, {f, g}, x]

(*   {{f -> Function[{x}, C[1]], g -> Function[{x}, 0]}}   *)


Or

fsol = f /. Flatten@DSolve[{f''[x] == 0}, f, x]

(*  Function[{x}, C[1] + x C[2]]    *)

sol = Flatten@Solve[fsol'[x] == 0]

(*   {C[2] -> 0}   *)

f[x_] = fsol[x] /. sol

(*   C[1]   *)


Here's a start (a truck fire shutdown the highway and we were stuck in the mountains; so I had some extra time and got the below to work with systems as well). Assumptions about input:

• The systems essentially can be reduced to one equation for each dependent variable.
• The equations are ODEs.

In this case, we may deduce the order of the desired ODE and use Solve to find it. I guess I have supposed it is obvious, at least in the examples below, that the output of dReduce may be plugged into DSolve.

dReduce // ClearAll;
iDReduce // ClearAll;

dReduce::incon =
"The system of differential equations is inconsistent.";
dReduce::noivar =
"No independent variables were specified; specify one.";
dReduce::nopde =
"There is more than one independent variable : PDEs are not implemented.";
dReduce::nodvar =
"No dependent variables were specified; specify one.";

dReduce[sys1_, y1_, x1_] := Module[
{sys, y, x, dorder, redorder, res, tests = 0},
sys = Flatten@{sys1};
x = Flatten@{x1};
y = Flatten@{y1 /. v_[Sequence @@ x] :> v};
(* check inputs *)
Switch[Length@x,
0, Message[dReduce::noivar],
1, tests++,
_, Message[dReduce::nopde, x]];
Switch[Length@y,
0, Message[dReduce::nodvar],
_, tests++];
(* call the solver *)
(dorder =
Flatten@InternalProcessEquationsDifferentialOrder[sys, x, y];
redorder = Length@y + Total@dorder - Length@sys;
iDReduce[sys, y, First@x, dorder, redorder]) /; tests == 2
];
iDReduce[sys_, y_, x_, dorder_, redorder_] :=
Module[{orders, res, a},
With[{vars = Array[a, Length@y]},
orders = SolveValues[ (* possible target orders *)
Join[{Total@vars == redorder},
Thread[0 <= Array[a, Length@y] <= dorder]],
vars, Integers]
];
orders = SortBy[orders, -Min[#] &]; (* heuristic: avoid zero-order *)
res = Do[ (* try each order - first to succeed wins *)
res = Solve[
sys,
Table[Derivative[n][#1][x], {n, #2, #3, -1}] &,
{y, dorder, orders[[k]]}
]
];
If[MatchQ[res, {{__Rule} ..}],
Return[{res, orders[[k]]}, Do]],
{k, Length@orders}];
With[{dvars = MapThread[Derivative[#1][#2][x] &, {Last@res, y}]},
Times @@ (Thread[dvars - #] & /@
(dvars /. First@res)) == 0] //
Simplify
] /; MatchQ[res, {{{___Rule} ...}, _}]
];


Examples.

OP's:

dReduce[{f'[x] == 0, f''[x] == 0}, f, x]
(*  f'[x] == 0  *)


OP's with a twist:

dReduce[{f'[x] + f''[x] == f''[x], f''[x] == 0}, f, x]
(*  {f'[x] == 0}  *)


With another twist:

dReduce[{f'''[x] + f''[x] == f''[x], f''[x] == 0}, f, x]
(*  {f''[x] == 0}  *)


Nesting D[] is an easy way to create redundant equations:

dReduce[NestList[D[#, t] &, y'[t] + y[t]^3 == 0, 3], y, t]
(*  {y[t]^3 + y'[t] == 0}  *)


Nonlinear:

dReduce[NestList[D[#, t] &, y''[t]^2 + t^2 y[t] == 0, 2], y, t]
(*  {t^2 y[t] + y''[t]^2 == 0}  *)


System:

dReduce[
NestList[D[#, t] &, {y'[t] == x[t], x''[t] == -y[t]}, 2],
{x,y}, t]
(*  {y[t] + x''[t] == 0, x[t] == y'[t]}  *)

• TBD: Decide how to handle ConditionalExpression solutions returned by Solve. DSolve doesn't like conditions, so could simply use res = Normal@Solve[...] in iDReduce and hope for the best. Commented Apr 19, 2022 at 15:07