2

I'm trying to come up with a pattern or just implement a function DifferentialEquationQ so I can have another function assume different behaviour when it's input is a differential equation

MyFunction[x_?DifferentialEquationQ]:=...

My first attempt is to go

DifferentialEquationQ[x_]:=StringContainsQ[#, "=="] && StringContainsQ[#, "Derivative"] &[ToString[InputForm[x]]]

I really don't like this solution because I know there's certainly a better way plus maybe I can learn something new by posting. Also, I would ideally like to parameterize DifferentialEquationQ with an independent and dependant variable. So DifferentialEquationQ[y,t][ode_] would match any ode of $y(t)$.

Thanks

user2757771
  • 829
  • 4
  • 9

1 Answers1

3

A quick and dirty attempt. Let me know if there is a bug somewhere. All bugs are fixed in the order they are recieved.


Mathematica graphics

code

The function getPatterns thanks to Carl Woll, see Using Cases and when to make input a list or not

getPatterns[expr_, pat_] := 
  Last@Reap[expr /. a : pat :> Sow[a], _, Sequence @@ #2 &];

The parser

(* Basic Parsing function *)
(*version alpha 1.01 Released . on April 27, 2020 at 9:38 PM*)
checkIfValidODE[odeInput_, y_[arg_], x_] := 
 Module[{ode, lhs, rhs, order, tmp, tmp0, tmp00, maxOrder, n, z, 
   independentVariables, xx, yy},

  If[Not[SameQ[arg, x]],
   Return[
    Row[{"Argument of dependent variable ", y, 
      " is not what is expected."}], Module]
   ];

  If[Not[SameQ[Head[odeInput], Equal]],
   Return[Row[{"Expected equation as input but found ", odeInput}], 
    Module]
   ];

  tmp = getPatterns[odeInput, Derivative[n_][yy_][xx_]];
  If[Length@tmp == 0,
   Return[Row[{"No derivative found in ", odeInput}], Module]
   ];

  tmp0 = Cases[tmp, Derivative[n_][yy_][xx_] :> xx];
  tmp00 = getPatterns[tmp0, Derivative[n_][yy_][xx_]];

  If [Length@tmp00 > 0,
   Return[Row[{"Nested derivatives not allowed"}], Module]
   ];

  order = Cases[tmp, Derivative[n_][y][x] :> n];
  If[order === {},
   Return[Row[{"No ", y'[x], " found in the ODE ", odeInput}], Module]
   ];

  tmp = getPatterns[odeInput, y[xx_]];
  independentVariables = Union@Cases[tmp, y[xx_] :> xx];
  If [Length@independentVariables > 1,
   Return[Row[{"Unexpected argument for ", y , " found ", y[x]}], 
    Module]
   ];

  If[Length@independentVariables == 
     1 && (First@independentVariables) =!=  x,
   Return[
    Row[{"Unexpected argument for", y , " found", independentVariables}], Module]
   ];

  Print["Input is valid ODE of order ", order]

  ]

Test code

checkIfValidODE[y'[y'[x]] == x^3, y[x], x]
checkIfValidODE[y''[x] == z, y[x], x]
checkIfValidODE[y''[x], y[x], x]
checkIfValidODE[y''[x] == 0, y[x], x]
checkIfValidODE[y''[x] == 0, y[z], x]
checkIfValidODE[y''[x] == 0, y[x], z]
checkIfValidODE[y[x] == 0, y[x], x]
checkIfValidODE[y''[x] == 0, y[x], y]
checkIfValidODE[y''[x] == Tan[y[x]], y[x], x]
checkIfValidODE[y''[x] == Tan[y[z]], y[x], x]
checkIfValidODE[1/y''[x] == Tan[y[x]], y[x], x]
checkIfValidODE[1/y''[x] == x^3, y[x], x]
checkIfValidODE[y[x] == x^3, y[x], x]
Nasser
  • 143,286
  • 11
  • 154
  • 359