symbolic mathematics engine in OCaml with differentiation, integration, simplification, and numerical methods
1open Expr
2
3let rec compare_expr e1 e2 =
4 match (e1, e2) with
5 | Const a, Const b -> Float.compare a b
6 | Const _, _ -> -1
7 | _, Const _ -> 1
8 | SymConst a, SymConst b -> Stdlib.compare a b
9 | SymConst _, _ -> -1
10 | _, SymConst _ -> 1
11 | Var a, Var b -> String.compare a b
12 | Var _, _ -> -1
13 | _, Var _ -> 1
14 | Neg a, Neg b -> compare_expr a b
15 | Neg _, _ -> -1
16 | _, Neg _ -> 1
17 | Add (a1, a2), Add (b1, b2) ->
18 let c = compare_expr a1 b1 in
19 if c <> 0 then c else compare_expr a2 b2
20 | Add _, _ -> -1
21 | _, Add _ -> 1
22 | Sub (a1, a2), Sub (b1, b2) ->
23 let c = compare_expr a1 b1 in
24 if c <> 0 then c else compare_expr a2 b2
25 | Sub _, _ -> -1
26 | _, Sub _ -> 1
27 | Mul (a1, a2), Mul (b1, b2) ->
28 let c = compare_expr a1 b1 in
29 if c <> 0 then c else compare_expr a2 b2
30 | Mul _, _ -> -1
31 | _, Mul _ -> 1
32 | Div (a1, a2), Div (b1, b2) ->
33 let c = compare_expr a1 b1 in
34 if c <> 0 then c else compare_expr a2 b2
35 | Div _, _ -> -1
36 | _, Div _ -> 1
37 | Pow (a1, a2), Pow (b1, b2) ->
38 let c = compare_expr a1 b1 in
39 if c <> 0 then c else compare_expr a2 b2
40 | Pow _, _ -> -1
41 | _, Pow _ -> 1
42 | Sin a, Sin b -> compare_expr a b
43 | Sin _, _ -> -1
44 | _, Sin _ -> 1
45 | Cos a, Cos b -> compare_expr a b
46 | Cos _, _ -> -1
47 | _, Cos _ -> 1
48 | Tan a, Tan b -> compare_expr a b
49 | Tan _, _ -> -1
50 | _, Tan _ -> 1
51 | Sinh a, Sinh b -> compare_expr a b
52 | Sinh _, _ -> -1
53 | _, Sinh _ -> 1
54 | Cosh a, Cosh b -> compare_expr a b
55 | Cosh _, _ -> -1
56 | _, Cosh _ -> 1
57 | Tanh a, Tanh b -> compare_expr a b
58 | Tanh _, _ -> -1
59 | _, Tanh _ -> 1
60 | Asin a, Asin b -> compare_expr a b
61 | Asin _, _ -> -1
62 | _, Asin _ -> 1
63 | Acos a, Acos b -> compare_expr a b
64 | Acos _, _ -> -1
65 | _, Acos _ -> 1
66 | Atan a, Atan b -> compare_expr a b
67 | Atan _, _ -> -1
68 | _, Atan _ -> 1
69 | Atan2 (a1, a2), Atan2 (b1, b2) ->
70 let c = compare_expr a1 b1 in
71 if c <> 0 then c else compare_expr a2 b2
72 | Atan2 _, _ -> -1
73 | _, Atan2 _ -> 1
74 | Exp a, Exp b -> compare_expr a b
75 | Exp _, _ -> -1
76 | _, Exp _ -> 1
77 | Ln a, Ln b -> compare_expr a b
78 | Ln _, _ -> -1
79 | _, Ln _ -> 1
80 | Log (a1, a2), Log (b1, b2) ->
81 let c = compare_expr a1 b1 in
82 if c <> 0 then c else compare_expr a2 b2
83 | Log _, _ -> -1
84 | _, Log _ -> 1
85 | Sqrt a, Sqrt b -> compare_expr a b
86 | Sqrt _, _ -> -1
87 | _, Sqrt _ -> 1
88 | Abs a, Abs b -> compare_expr a b
89
90let rec canonicalize = function
91 | Const _ as c -> c
92 | SymConst _ as s -> s
93 | Var _ as v -> v
94 | Neg (Neg e) -> canonicalize e
95 | Neg e -> Neg (canonicalize e)
96 | Sub (e1, e2) -> canonicalize (Add (e1, Neg e2))
97 | Div (e1, e2) -> canonicalize (Mul (e1, Pow (e2, Const (-.1.0))))
98 | Add (e1, e2) ->
99 let c1 = canonicalize e1 in
100 let c2 = canonicalize e2 in
101 if compare_expr c1 c2 <= 0 then Add (c1, c2) else Add (c2, c1)
102 | Mul (e1, e2) ->
103 let c1 = canonicalize e1 in
104 let c2 = canonicalize e2 in
105 if compare_expr c1 c2 <= 0 then Mul (c1, c2) else Mul (c2, c1)
106 | Pow (e1, e2) -> Pow (canonicalize e1, canonicalize e2)
107 | Sin e -> Sin (canonicalize e)
108 | Cos e -> Cos (canonicalize e)
109 | Tan e -> Tan (canonicalize e)
110 | Sinh e -> Sinh (canonicalize e)
111 | Cosh e -> Cosh (canonicalize e)
112 | Tanh e -> Tanh (canonicalize e)
113 | Asin e -> Asin (canonicalize e)
114 | Acos e -> Acos (canonicalize e)
115 | Atan e -> Atan (canonicalize e)
116 | Atan2 (e1, e2) -> Atan2 (canonicalize e1, canonicalize e2)
117 | Exp e -> Exp (canonicalize e)
118 | Ln e -> Ln (canonicalize e)
119 | Log (e1, e2) -> Log (canonicalize e1, canonicalize e2)
120 | Sqrt e -> Sqrt (canonicalize e)
121 | Abs e -> Abs (canonicalize e)
122
123let equal e1 e2 =
124 let c1 = canonicalize e1 in
125 let c2 = canonicalize e2 in
126 compare_expr c1 c2 = 0
127
128let compare e1 e2 =
129 let c1 = canonicalize e1 in
130 let c2 = canonicalize e2 in
131 compare_expr c1 c2
132
133let rec hash = function
134 | Const f -> Hashtbl.hash ("Const", f)
135 | SymConst s -> Hashtbl.hash ("SymConst", s)
136 | Var v -> Hashtbl.hash ("Var", v)
137 | Add (e1, e2) -> Hashtbl.hash ("Add", hash e1, hash e2)
138 | Sub (e1, e2) -> Hashtbl.hash ("Sub", hash e1, hash e2)
139 | Mul (e1, e2) -> Hashtbl.hash ("Mul", hash e1, hash e2)
140 | Div (e1, e2) -> Hashtbl.hash ("Div", hash e1, hash e2)
141 | Pow (e1, e2) -> Hashtbl.hash ("Pow", hash e1, hash e2)
142 | Neg e -> Hashtbl.hash ("Neg", hash e)
143 | Sin e -> Hashtbl.hash ("Sin", hash e)
144 | Cos e -> Hashtbl.hash ("Cos", hash e)
145 | Tan e -> Hashtbl.hash ("Tan", hash e)
146 | Sinh e -> Hashtbl.hash ("Sinh", hash e)
147 | Cosh e -> Hashtbl.hash ("Cosh", hash e)
148 | Tanh e -> Hashtbl.hash ("Tanh", hash e)
149 | Asin e -> Hashtbl.hash ("Asin", hash e)
150 | Acos e -> Hashtbl.hash ("Acos", hash e)
151 | Atan e -> Hashtbl.hash ("Atan", hash e)
152 | Atan2 (e1, e2) -> Hashtbl.hash ("Atan2", hash e1, hash e2)
153 | Exp e -> Hashtbl.hash ("Exp", hash e)
154 | Ln e -> Hashtbl.hash ("Ln", hash e)
155 | Log (e1, e2) -> Hashtbl.hash ("Log", hash e1, hash e2)
156 | Sqrt e -> Hashtbl.hash ("Sqrt", hash e)
157 | Abs e -> Hashtbl.hash ("Abs", hash e)