symbolic mathematics engine in OCaml with differentiation, integration, simplification, and numerical methods
1open Expr
2open Simplify
3open Diff
4open Substitute
5
6let rec integrate var = function
7 | Const c -> Some (Mul (Const c, Var var))
8 | SymConst _ as s -> Some (Mul (s, Var var))
9 | Var v when v = var -> Some (Div (Pow (Var var, Const 2.0), Const 2.0))
10 | Var v -> Some (Mul (Var v, Var var))
11 | Add (e1, e2) ->
12 (match (integrate var e1, integrate var e2) with
13 | Some i1, Some i2 -> Some (simplify (Add (i1, i2)))
14 | _ -> None)
15 | Sub (e1, e2) ->
16 (match (integrate var e1, integrate var e2) with
17 | Some i1, Some i2 -> Some (simplify (Sub (i1, i2)))
18 | _ -> None)
19 | Mul (Const c, e) | Mul (e, Const c) ->
20 (match integrate var e with
21 | Some i -> Some (simplify (Mul (Const c, i)))
22 | None -> None)
23 | Mul (SymConst s, e) | Mul (e, SymConst s) ->
24 (match integrate var e with
25 | Some i -> Some (simplify (Mul (SymConst s, i)))
26 | None -> None)
27 | Pow (Var v, Const n) when v = var && n <> -1.0 ->
28 let exp = n +. 1.0 in
29 Some (simplify (Div (Pow (Var var, Const exp), Const exp)))
30 | Div (Const 1.0, Var v) when v = var ->
31 Some (Ln (Abs (Var var)))
32 | Div (e, Var v) when v = var ->
33 (match e with
34 | Const c -> Some (simplify (Mul (Const c, Ln (Abs (Var var)))))
35 | _ -> None)
36 | Sin (Var v) when v = var ->
37 Some (Neg (Cos (Var var)))
38 | Cos (Var v) when v = var ->
39 Some (Sin (Var var))
40 | Tan (Var v) when v = var ->
41 Some (Neg (Ln (Abs (Cos (Var var)))))
42 | Div (Const 1.0, Pow (Cos (Var v), Const 2.0)) when v = var ->
43 Some (Tan (Var var))
44 | Sinh (Var v) when v = var ->
45 Some (Cosh (Var var))
46 | Cosh (Var v) when v = var ->
47 Some (Sinh (Var var))
48 | Tanh (Var v) when v = var ->
49 Some (Ln (Cosh (Var var)))
50 | Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0)))) when v = var ->
51 Some (Asin (Var var))
52 | Neg (Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0))))) when v = var ->
53 Some (Acos (Var var))
54 | Div (Const 1.0, Add (Const 1.0, Pow (Var v, Const 2.0))) when v = var ->
55 Some (Atan (Var var))
56 | Exp (Var v) when v = var ->
57 Some (Exp (Var var))
58 | Pow (Const a, Var v) when v = var ->
59 Some (simplify (Div (Pow (Const a, Var var), Ln (Const a))))
60 | Pow (SymConst E, Var v) when v = var ->
61 Some (Exp (Var var))
62 | e ->
63 match try_u_substitution var e with
64 | Some result -> Some result
65 | None -> try_by_parts var e
66
67and try_u_substitution var expr =
68 let rec find_inner = function
69 | Sin u | Cos u | Tan u | Sinh u | Cosh u | Tanh u
70 | Asin u | Acos u | Atan u | Exp u | Ln u | Sqrt u | Abs u -> Some u
71 | Pow (u, _) -> Some u
72 | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) ->
73 (match find_inner e1 with
74 | Some _ as r -> r
75 | None -> find_inner e2)
76 | _ -> None
77 in
78 match find_inner expr with
79 | Some u when u <> Var var ->
80 let u_prime = diff var u in
81 let expr_simplified = simplify expr in
82 let test_expr = simplify (Div (expr_simplified, u_prime)) in
83 let substituted = substitute var (Var "u_temp") test_expr in
84 (match substituted with
85 | e when not (contains_var var e) ->
86 (match integrate "u_temp" e with
87 | Some integrated ->
88 let result = substitute "u_temp" u integrated in
89 Some (simplify result)
90 | None -> None)
91 | _ -> None)
92 | _ -> None
93
94and try_by_parts var = function
95 | Mul (e1, e2) ->
96 let priority = function
97 | Ln _ -> 5
98 | Asin _ | Acos _ | Atan _ -> 4
99 | Var _ | Pow (Var _, _) -> 3
100 | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ -> 2
101 | Exp _ -> 1
102 | _ -> 0
103 in
104 let (u, dv) =
105 if priority e1 >= priority e2 then (e1, e2) else (e2, e1)
106 in
107 (match integrate var dv with
108 | Some v ->
109 let du = diff var u in
110 (match integrate var (simplify (Mul (v, du))) with
111 | Some second_integral ->
112 Some (simplify (Sub (Mul (u, v), second_integral)))
113 | None -> None)
114 | None -> None)
115 | _ -> None
116
117and contains_var var = function
118 | Const _ | SymConst _ -> false
119 | Var v -> v = var
120 | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) | Pow (e1, e2) ->
121 contains_var var e1 || contains_var var e2
122 | Neg e | Sin e | Cos e | Tan e | Sinh e | Cosh e | Tanh e
123 | Asin e | Acos e | Atan e | Exp e | Ln e | Sqrt e | Abs e ->
124 contains_var var e
125 | Atan2 (e1, e2) | Log (e1, e2) ->
126 contains_var var e1 || contains_var var e2
127
128let integrate_definite var lower upper expr =
129 match integrate var expr with
130 | None -> None
131 | Some antideriv ->
132 let upper_val = Eval.eval [(var, upper)] antideriv in
133 let lower_val = Eval.eval [(var, lower)] antideriv in
134 Some (upper_val -. lower_val)