···11+open Expr
22+open Canonical
33+44+type cse_result = {
55+ final_expr: expr;
66+ subexpressions: (string * expr) list;
77+}
88+99+let common_subexpression_elimination expr =
1010+ let counter = ref 0 in
1111+ let subexpr_map = Hashtbl.create 100 in
1212+ let name_map = Hashtbl.create 100 in
1313+1414+ let get_or_create_name e =
1515+ let h = hash e in
1616+ match Hashtbl.find_opt name_map h with
1717+ | Some name -> Var name
1818+ | None ->
1919+ incr counter;
2020+ let name = Printf.sprintf "cse_%d" !counter in
2121+ Hashtbl.add name_map h name;
2222+ Hashtbl.add subexpr_map name e;
2323+ Var name
2424+ in
2525+2626+ let should_extract = function
2727+ | Const _ | SymConst _ | Var _ -> false
2828+ | _ -> true
2929+ in
3030+3131+ let rec count_occurrences e counts =
3232+ let h = hash e in
3333+ Hashtbl.replace counts h (1 + (Hashtbl.find_opt counts h |> Option.value ~default:0));
3434+ match e with
3535+ | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) | Pow (e1, e2) ->
3636+ count_occurrences e1 counts;
3737+ count_occurrences e2 counts
3838+ | Neg e | Sin e | Cos e | Tan e | Sinh e | Cosh e | Tanh e
3939+ | Asin e | Acos e | Atan e | Exp e | Ln e | Sqrt e | Abs e ->
4040+ count_occurrences e counts
4141+ | Atan2 (e1, e2) | Log (e1, e2) ->
4242+ count_occurrences e1 counts;
4343+ count_occurrences e2 counts
4444+ | _ -> ()
4545+ in
4646+4747+ let counts = Hashtbl.create 100 in
4848+ count_occurrences expr counts;
4949+5050+ let rec extract e =
5151+ if should_extract e && Hashtbl.find counts (hash e) >= 2 then
5252+ get_or_create_name e
5353+ else
5454+ match e with
5555+ | Add (e1, e2) -> Add (extract e1, extract e2)
5656+ | Sub (e1, e2) -> Sub (extract e1, extract e2)
5757+ | Mul (e1, e2) -> Mul (extract e1, extract e2)
5858+ | Div (e1, e2) -> Div (extract e1, extract e2)
5959+ | Pow (e1, e2) -> Pow (extract e1, extract e2)
6060+ | Neg e -> Neg (extract e)
6161+ | Sin e -> Sin (extract e)
6262+ | Cos e -> Cos (extract e)
6363+ | Tan e -> Tan (extract e)
6464+ | Sinh e -> Sinh (extract e)
6565+ | Cosh e -> Cosh (extract e)
6666+ | Tanh e -> Tanh (extract e)
6767+ | Asin e -> Asin (extract e)
6868+ | Acos e -> Acos (extract e)
6969+ | Atan e -> Atan (extract e)
7070+ | Atan2 (e1, e2) -> Atan2 (extract e1, extract e2)
7171+ | Exp e -> Exp (extract e)
7272+ | Ln e -> Ln (extract e)
7373+ | Log (e1, e2) -> Log (extract e1, extract e2)
7474+ | Sqrt e -> Sqrt (extract e)
7575+ | Abs e -> Abs (extract e)
7676+ | e -> e
7777+ in
7878+7979+ let final = extract expr in
8080+ let subexprs = Hashtbl.fold (fun name e acc -> (name, e) :: acc) subexpr_map [] in
8181+ {final_expr = final; subexpressions = List.sort (fun (n1, _) (n2, _) -> String.compare n1 n2) subexprs}
8282+8383+let horner_form expr var =
8484+ let rec collect_poly e =
8585+ match e with
8686+ | Const c -> [(0, Const c)]
8787+ | Var v when v = var -> [(1, Const 1.0)]
8888+ | Pow (Var v, Const n) when v = var && Float.is_integer n ->
8989+ [(int_of_float n, Const 1.0)]
9090+ | Mul (Const c, Pow (Var v, Const n)) when v = var && Float.is_integer n ->
9191+ [(int_of_float n, Const c)]
9292+ | Add (e1, e2) -> collect_poly e1 @ collect_poly e2
9393+ | _ -> [(0, e)]
9494+ in
9595+9696+ let terms = collect_poly expr in
9797+ let max_degree = List.fold_left (fun acc (deg, _) -> max acc deg) 0 terms in
9898+9999+ let coeffs = Array.make (max_degree + 1) (Const 0.0) in
100100+ List.iter (fun (deg, coeff) ->
101101+ coeffs.(deg) <- Simplify.simplify (Add (coeffs.(deg), coeff))
102102+ ) terms;
103103+104104+ let rec build_horner deg =
105105+ if deg < 0 then Const 0.0
106106+ else if deg = 0 then coeffs.(0)
107107+ else Add (coeffs.(deg), Mul (Var var, build_horner (deg - 1)))
108108+ in
109109+110110+ Simplify.simplify (build_horner max_degree)
···11+open Expr
22+open Simplify
33+44+let rec diff var = function
55+ | Const _ -> Const 0.0
66+ | SymConst _ -> Const 0.0
77+ | Var v -> if v = var then Const 1.0 else Const 0.0
88+ | Add (e1, e2) -> simplify (Add (diff var e1, diff var e2))
99+ | Sub (e1, e2) -> simplify (Sub (diff var e1, diff var e2))
1010+ | Mul (e1, e2) ->
1111+ simplify (Add (Mul (diff var e1, e2), Mul (e1, diff var e2)))
1212+ | Div (e1, e2) ->
1313+ let num = Sub (Mul (diff var e1, e2), Mul (e1, diff var e2)) in
1414+ let den = Pow (e2, Const 2.0) in
1515+ simplify (Div (num, den))
1616+ | Pow (e, Const n) ->
1717+ simplify (Mul (Mul (Const n, Pow (e, Const (n -. 1.0))), diff var e))
1818+ | Pow (e1, e2) ->
1919+ let term1 = Mul (e2, Mul (Pow (e1, Sub (e2, Const 1.0)), diff var e1)) in
2020+ let term2 = Mul (Pow (e1, e2), Mul (Ln e1, diff var e2)) in
2121+ simplify (Add (term1, term2))
2222+ | Neg e -> simplify (Neg (diff var e))
2323+ | Sin e -> simplify (Mul (Cos e, diff var e))
2424+ | Cos e -> simplify (Neg (Mul (Sin e, diff var e)))
2525+ | Tan e ->
2626+ let sec2 = Div (Const 1.0, Pow (Cos e, Const 2.0)) in
2727+ simplify (Mul (sec2, diff var e))
2828+ | Sinh e -> simplify (Mul (Cosh e, diff var e))
2929+ | Cosh e -> simplify (Mul (Sinh e, diff var e))
3030+ | Tanh e ->
3131+ let sech2 = Sub (Const 1.0, Pow (Tanh e, Const 2.0)) in
3232+ simplify (Mul (sech2, diff var e))
3333+ | Asin e ->
3434+ let denom = Sqrt (Sub (Const 1.0, Pow (e, Const 2.0))) in
3535+ simplify (Div (diff var e, denom))
3636+ | Acos e ->
3737+ let denom = Sqrt (Sub (Const 1.0, Pow (e, Const 2.0))) in
3838+ simplify (Neg (Div (diff var e, denom)))
3939+ | Atan e ->
4040+ let denom = Add (Const 1.0, Pow (e, Const 2.0)) in
4141+ simplify (Div (diff var e, denom))
4242+ | Atan2 (y, x) ->
4343+ let num = Sub (Mul (x, diff var y), Mul (y, diff var x)) in
4444+ let denom = Add (Pow (x, Const 2.0), Pow (y, Const 2.0)) in
4545+ simplify (Div (num, denom))
4646+ | Exp e -> simplify (Mul (Exp e, diff var e))
4747+ | Ln e -> simplify (Div (diff var e, e))
4848+ | Log (base_e, arg) ->
4949+ let denom = Mul (arg, Ln base_e) in
5050+ simplify (Div (diff var arg, denom))
5151+ | Sqrt e ->
5252+ let denom = Mul (Const 2.0, Sqrt e) in
5353+ simplify (Div (diff var e, denom))
5454+ | Abs e ->
5555+ let sgn = Div (e, Abs e) in
5656+ simplify (Mul (sgn, diff var e))
5757+5858+let rec diff_n var n expr =
5959+ if n <= 0 then expr
6060+ else diff_n var (n - 1) (diff var expr)
6161+6262+let partial vars expr =
6363+ List.fold_left (fun e v -> diff v e) expr vars
···11+type sym_const = Pi | E
22+13type expr =
24 | Const of float
55+ | SymConst of sym_const
36 | Var of string
47 | Add of expr * expr
58 | Sub of expr * expr
···1013 | Sin of expr
1114 | Cos of expr
1215 | Tan of expr
1616+ | Sinh of expr
1717+ | Cosh of expr
1818+ | Tanh of expr
1919+ | Asin of expr
2020+ | Acos of expr
2121+ | Atan of expr
2222+ | Atan2 of expr * expr
1323 | Exp of expr
1424 | Ln of expr
2525+ | Log of expr * expr
2626+ | Sqrt of expr
2727+ | Abs of expr
15281629let rec to_string = function
1730 | Const f ->
···1932 string_of_int (int_of_float f)
2033 else
2134 string_of_float f
3535+ | SymConst Pi -> "π"
3636+ | SymConst E -> "e"
2237 | Var s -> s
2338 | Add (e1, e2) -> to_string_add e1 ^ " + " ^ to_string_add e2
2439 | Sub (e1, e2) -> to_string e1 ^ " - " ^ to_string_paren e2
···2944 | Sin e -> "sin(" ^ to_string e ^ ")"
3045 | Cos e -> "cos(" ^ to_string e ^ ")"
3146 | Tan e -> "tan(" ^ to_string e ^ ")"
4747+ | Sinh e -> "sinh(" ^ to_string e ^ ")"
4848+ | Cosh e -> "cosh(" ^ to_string e ^ ")"
4949+ | Tanh e -> "tanh(" ^ to_string e ^ ")"
5050+ | Asin e -> "asin(" ^ to_string e ^ ")"
5151+ | Acos e -> "acos(" ^ to_string e ^ ")"
5252+ | Atan e -> "atan(" ^ to_string e ^ ")"
5353+ | Atan2 (e1, e2) -> "atan2(" ^ to_string e1 ^ ", " ^ to_string e2 ^ ")"
3254 | Exp e -> "e^" ^ to_string_pow_exp e
3355 | Ln e -> "ln(" ^ to_string e ^ ")"
5656+ | Log (base_e, arg) -> "log(" ^ to_string base_e ^ ", " ^ to_string arg ^ ")"
5757+ | Sqrt e -> "sqrt(" ^ to_string e ^ ")"
5858+ | Abs e -> "abs(" ^ to_string e ^ ")"
34593560and to_string_atom = function
3636- | (Const _ | Var _ | Sin _ | Cos _ | Tan _ | Exp _ | Ln _) as e -> to_string e
6161+ | (Const _ | SymConst _ | Var _ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _
6262+ | Asin _ | Acos _ | Atan _ | Atan2 _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _) as e -> to_string e
3763 | e -> "(" ^ to_string e ^ ")"
38643965and to_string_mul = function
4040- | (Const _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Exp _ | Ln _ | Mul _) as e -> to_string e
6666+ | (Const _ | SymConst _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _
6767+ | Asin _ | Acos _ | Atan _ | Atan2 _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _ | Mul _) as e -> to_string e
4168 | e -> "(" ^ to_string e ^ ")"
42694370and to_string_div = function
4444- | (Const _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Exp _ | Ln _ | Mul _) as e -> to_string e
7171+ | (Const _ | SymConst _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _
7272+ | Asin _ | Acos _ | Atan _ | Atan2 _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _ | Mul _) as e -> to_string e
4573 | e -> "(" ^ to_string e ^ ")"
46744775and to_string_add = function
···4977 | e -> to_string e
50785179and to_string_pow_exp = function
5252- | (Const _ | Var _ | Pow _) as e -> to_string e
8080+ | (Const _ | SymConst _ | Var _ | Pow _) as e -> to_string e
5381 | e -> "(" ^ to_string e ^ ")"
54825583and to_string_paren = function
5684 | (Add _ | Sub _) as e -> "(" ^ to_string e ^ ")"
5785 | e -> to_string e
5858-5959-let rec simplify = function
6060- | Const _ as c -> c
6161- | Var _ as v -> v
6262- | Add (e1, e2) -> simplify_add (simplify e1) (simplify e2)
6363- | Sub (e1, e2) -> simplify_sub (simplify e1) (simplify e2)
6464- | Mul (e1, e2) -> simplify_mul (simplify e1) (simplify e2)
6565- | Div (e1, e2) -> simplify_div (simplify e1) (simplify e2)
6666- | Pow (e1, e2) -> simplify_pow (simplify e1) (simplify e2)
6767- | Neg e -> simplify_neg (simplify e)
6868- | Sin e -> Sin (simplify e)
6969- | Cos e -> Cos (simplify e)
7070- | Tan e -> Tan (simplify e)
7171- | Exp e -> simplify_exp (simplify e)
7272- | Ln e -> Ln (simplify e)
7373-7474-and simplify_add e1 e2 =
7575- match (e1, e2) with
7676- | Const 0.0, e | e, Const 0.0 -> e
7777- | Const a, Const b -> Const (a +. b)
7878- | _ -> Add (e1, e2)
7979-8080-and simplify_sub e1 e2 =
8181- match (e1, e2) with
8282- | e, Const 0.0 -> e
8383- | Const a, Const b -> Const (a -. b)
8484- | _ -> Sub (e1, e2)
8585-8686-and simplify_mul e1 e2 =
8787- match (e1, e2) with
8888- | Const 0.0, _ | _, Const 0.0 -> Const 0.0
8989- | Const 1.0, e | e, Const 1.0 -> e
9090- | Const a, Const b -> Const (a *. b)
9191- | Const a, Mul (Const b, e) -> simplify_mul (Const (a *. b)) e
9292- | Mul (Const a, e), Const b -> simplify_mul (Const (a *. b)) e
9393- | Const a, Mul (e1, Mul (Const b, e2)) ->
9494- simplify_mul (Const (a *. b)) (Mul (e1, e2))
9595- | Mul (Const a, e1), Mul (Const b, e2) ->
9696- simplify_mul (Const (a *. b)) (Mul (e1, e2))
9797- | (Sin _ | Cos _ | Tan _ | Exp _ | Ln _ | Pow _), Var _ ->
9898- Mul (e2, e1)
9999- | _ -> Mul (e1, e2)
100100-101101-and simplify_div e1 e2 =
102102- match (e1, e2) with
103103- | Const 0.0, _ -> Const 0.0
104104- | e, Const 1.0 -> e
105105- | Const a, Const b -> Const (a /. b)
106106- | e1, e2 when e1 = e2 -> Const 1.0
107107- | _ -> Div (e1, e2)
108108-109109-and simplify_pow e1 e2 =
110110- match (e1, e2) with
111111- | _, Const 0.0 -> Const 1.0
112112- | e, Const 1.0 -> e
113113- | Const 0.0, _ -> Const 0.0
114114- | Const 1.0, _ -> Const 1.0
115115- | Const a, Const b -> Const (a ** b)
116116- | _ -> Pow (e1, e2)
117117-118118-and simplify_neg = function
119119- | Const c -> Const (-.c)
120120- | Neg e -> e
121121- | e -> Neg e
122122-123123-and simplify_exp = function
124124- | Const 0.0 -> Const 1.0
125125- | Ln e -> e
126126- | e -> Exp e
127127-128128-let rec diff var = function
129129- | Const _ -> Const 0.0
130130- | Var v -> if v = var then Const 1.0 else Const 0.0
131131- | Add (e1, e2) -> simplify (Add (diff var e1, diff var e2))
132132- | Sub (e1, e2) -> simplify (Sub (diff var e1, diff var e2))
133133- | Mul (e1, e2) ->
134134- simplify (Add (Mul (diff var e1, e2), Mul (e1, diff var e2)))
135135- | Div (e1, e2) ->
136136- let num = Sub (Mul (diff var e1, e2), Mul (e1, diff var e2)) in
137137- let den = Pow (e2, Const 2.0) in
138138- simplify (Div (num, den))
139139- | Pow (e, Const n) ->
140140- simplify (Mul (Mul (Const n, Pow (e, Const (n -. 1.0))), diff var e))
141141- | Pow (e1, e2) ->
142142- let term1 = Mul (e2, Mul (Pow (e1, Sub (e2, Const 1.0)), diff var e1)) in
143143- let term2 = Mul (Pow (e1, e2), Mul (Ln e1, diff var e2)) in
144144- simplify (Add (term1, term2))
145145- | Neg e -> simplify (Neg (diff var e))
146146- | Sin e -> simplify (Mul (Cos e, diff var e))
147147- | Cos e -> simplify (Neg (Mul (Sin e, diff var e)))
148148- | Tan e ->
149149- let sec2 = Div (Const 1.0, Pow (Cos e, Const 2.0)) in
150150- simplify (Mul (sec2, diff var e))
151151- | Exp e -> simplify (Mul (Exp e, diff var e))
152152- | Ln e -> simplify (Div (diff var e, e))
153153-154154-let rec diff_n var n expr =
155155- if n <= 0 then expr
156156- else diff_n var (n - 1) (diff var expr)
157157-158158-let partial vars expr =
159159- List.fold_left (fun e v -> diff v e) expr vars
160160-161161-let rec to_latex = function
162162- | Const f ->
163163- if Float.is_integer f then
164164- string_of_int (int_of_float f)
165165- else
166166- string_of_float f
167167- | Var s -> s
168168- | Add (e1, e2) -> to_latex e1 ^ " + " ^ to_latex e2
169169- | Sub (e1, e2) -> to_latex e1 ^ " - " ^ to_latex_paren_latex e2
170170- | Mul (e1, e2) -> to_latex_mul_latex e1 ^ to_latex_mul_latex e2
171171- | Div (e1, e2) -> "\\frac{" ^ to_latex e1 ^ "}{" ^ to_latex e2 ^ "}"
172172- | Pow (e1, e2) -> to_latex_atom_latex e1 ^ "^{" ^ to_latex e2 ^ "}"
173173- | Neg e -> "-" ^ to_latex_atom_latex e
174174- | Sin e -> "\\sin(" ^ to_latex e ^ ")"
175175- | Cos e -> "\\cos(" ^ to_latex e ^ ")"
176176- | Tan e -> "\\tan(" ^ to_latex e ^ ")"
177177- | Exp e -> "e^{" ^ to_latex e ^ "}"
178178- | Ln e -> "\\ln(" ^ to_latex e ^ ")"
179179-180180-and to_latex_atom_latex = function
181181- | (Const _ | Var _) as e -> to_latex e
182182- | e -> "(" ^ to_latex e ^ ")"
183183-184184-and to_latex_mul_latex = function
185185- | (Const _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Exp _ | Ln _) as e -> to_latex e
186186- | e -> "(" ^ to_latex e ^ ")"
187187-188188-and to_latex_paren_latex = function
189189- | (Add _ | Sub _) as e -> "(" ^ to_latex e ^ ")"
190190- | e -> to_latex e
191191-192192-let rec eval env = function
193193- | Const f -> f
194194- | Var v ->
195195- (try List.assoc v env
196196- with Not_found -> failwith ("unbound variable: " ^ v))
197197- | Add (e1, e2) -> eval env e1 +. eval env e2
198198- | Sub (e1, e2) -> eval env e1 -. eval env e2
199199- | Mul (e1, e2) -> eval env e1 *. eval env e2
200200- | Div (e1, e2) -> eval env e1 /. eval env e2
201201- | Pow (e1, e2) -> eval env e1 ** eval env e2
202202- | Neg e -> -.(eval env e)
203203- | Sin e -> sin (eval env e)
204204- | Cos e -> cos (eval env e)
205205- | Tan e -> tan (eval env e)
206206- | Exp e -> exp (eval env e)
207207- | Ln e -> log (eval env e)
···11+open Expr
22+open Simplify
33+open Diff
44+open Substitute
55+66+let rec integrate var = function
77+ | Const c -> Some (Mul (Const c, Var var))
88+ | SymConst _ as s -> Some (Mul (s, Var var))
99+ | Var v when v = var -> Some (Div (Pow (Var var, Const 2.0), Const 2.0))
1010+ | Var v -> Some (Mul (Var v, Var var))
1111+ | Add (e1, e2) ->
1212+ (match (integrate var e1, integrate var e2) with
1313+ | Some i1, Some i2 -> Some (simplify (Add (i1, i2)))
1414+ | _ -> None)
1515+ | Sub (e1, e2) ->
1616+ (match (integrate var e1, integrate var e2) with
1717+ | Some i1, Some i2 -> Some (simplify (Sub (i1, i2)))
1818+ | _ -> None)
1919+ | Mul (Const c, e) | Mul (e, Const c) ->
2020+ (match integrate var e with
2121+ | Some i -> Some (simplify (Mul (Const c, i)))
2222+ | None -> None)
2323+ | Mul (SymConst s, e) | Mul (e, SymConst s) ->
2424+ (match integrate var e with
2525+ | Some i -> Some (simplify (Mul (SymConst s, i)))
2626+ | None -> None)
2727+ | Pow (Var v, Const n) when v = var && n <> -1.0 ->
2828+ let exp = n +. 1.0 in
2929+ Some (simplify (Div (Pow (Var var, Const exp), Const exp)))
3030+ | Div (Const 1.0, Var v) when v = var ->
3131+ Some (Ln (Abs (Var var)))
3232+ | Div (e, Var v) when v = var ->
3333+ (match e with
3434+ | Const c -> Some (simplify (Mul (Const c, Ln (Abs (Var var)))))
3535+ | _ -> None)
3636+ | Sin (Var v) when v = var ->
3737+ Some (Neg (Cos (Var var)))
3838+ | Cos (Var v) when v = var ->
3939+ Some (Sin (Var var))
4040+ | Tan (Var v) when v = var ->
4141+ Some (Neg (Ln (Abs (Cos (Var var)))))
4242+ | Div (Const 1.0, Pow (Cos (Var v), Const 2.0)) when v = var ->
4343+ Some (Tan (Var var))
4444+ | Sinh (Var v) when v = var ->
4545+ Some (Cosh (Var var))
4646+ | Cosh (Var v) when v = var ->
4747+ Some (Sinh (Var var))
4848+ | Tanh (Var v) when v = var ->
4949+ Some (Ln (Cosh (Var var)))
5050+ | Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0)))) when v = var ->
5151+ Some (Asin (Var var))
5252+ | Neg (Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0))))) when v = var ->
5353+ Some (Acos (Var var))
5454+ | Div (Const 1.0, Add (Const 1.0, Pow (Var v, Const 2.0))) when v = var ->
5555+ Some (Atan (Var var))
5656+ | Exp (Var v) when v = var ->
5757+ Some (Exp (Var var))
5858+ | Pow (Const a, Var v) when v = var ->
5959+ Some (simplify (Div (Pow (Const a, Var var), Ln (Const a))))
6060+ | Pow (SymConst E, Var v) when v = var ->
6161+ Some (Exp (Var var))
6262+ | e ->
6363+ match try_u_substitution var e with
6464+ | Some result -> Some result
6565+ | None -> try_by_parts var e
6666+6767+and try_u_substitution var expr =
6868+ let rec find_inner = function
6969+ | Sin u | Cos u | Tan u | Sinh u | Cosh u | Tanh u
7070+ | Asin u | Acos u | Atan u | Exp u | Ln u | Sqrt u | Abs u -> Some u
7171+ | Pow (u, _) -> Some u
7272+ | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) ->
7373+ (match find_inner e1 with
7474+ | Some _ as r -> r
7575+ | None -> find_inner e2)
7676+ | _ -> None
7777+ in
7878+ match find_inner expr with
7979+ | Some u when u <> Var var ->
8080+ let u_prime = diff var u in
8181+ let expr_simplified = simplify expr in
8282+ let test_expr = simplify (Div (expr_simplified, u_prime)) in
8383+ let substituted = substitute var (Var "u_temp") test_expr in
8484+ (match substituted with
8585+ | e when not (contains_var var e) ->
8686+ (match integrate "u_temp" e with
8787+ | Some integrated ->
8888+ let result = substitute "u_temp" u integrated in
8989+ Some (simplify result)
9090+ | None -> None)
9191+ | _ -> None)
9292+ | _ -> None
9393+9494+and try_by_parts var = function
9595+ | Mul (e1, e2) ->
9696+ let priority = function
9797+ | Ln _ -> 5
9898+ | Asin _ | Acos _ | Atan _ -> 4
9999+ | Var _ | Pow (Var _, _) -> 3
100100+ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ -> 2
101101+ | Exp _ -> 1
102102+ | _ -> 0
103103+ in
104104+ let (u, dv) =
105105+ if priority e1 >= priority e2 then (e1, e2) else (e2, e1)
106106+ in
107107+ (match integrate var dv with
108108+ | Some v ->
109109+ let du = diff var u in
110110+ (match integrate var (simplify (Mul (v, du))) with
111111+ | Some second_integral ->
112112+ Some (simplify (Sub (Mul (u, v), second_integral)))
113113+ | None -> None)
114114+ | None -> None)
115115+ | _ -> None
116116+117117+and contains_var var = function
118118+ | Const _ | SymConst _ -> false
119119+ | Var v -> v = var
120120+ | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) | Pow (e1, e2) ->
121121+ contains_var var e1 || contains_var var e2
122122+ | Neg e | Sin e | Cos e | Tan e | Sinh e | Cosh e | Tanh e
123123+ | Asin e | Acos e | Atan e | Exp e | Ln e | Sqrt e | Abs e ->
124124+ contains_var var e
125125+ | Atan2 (e1, e2) | Log (e1, e2) ->
126126+ contains_var var e1 || contains_var var e2
127127+128128+let integrate_definite var lower upper expr =
129129+ match integrate var expr with
130130+ | None -> None
131131+ | Some antideriv ->
132132+ let upper_val = Eval.eval [(var, upper)] antideriv in
133133+ let lower_val = Eval.eval [(var, lower)] antideriv in
134134+ Some (upper_val -. lower_val)
···11+type position = { line : int; col : int; offset : int }
22+13type token =
24 | Num of float
35 | Var of string
46 | Ident of string
57 | Plus | Minus | Star | Slash | Caret
68 | LParen | RParen
99+ | Comma
710 | EOF
8111212+type token_with_pos = { token : token; start_pos : position; end_pos : position }
1313+914let is_digit c = c >= '0' && c <= '9'
1015let is_alpha c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
1111-let is_alphanum c = is_alpha c || is_digit c
1616+let is_alphanum c = is_alpha c || is_digit c || c = '_'
1717+1818+let needs_implicit_mult tok1 tok2 =
1919+ match (tok1, tok2) with
2020+ | (Num _ | Var _ | RParen), (Num _ | Var _ | LParen | Ident _) -> true
2121+ | _ -> false
12221323let tokenize str =
1424 let len = String.length str in
2525+ let line = ref 1 in
2626+ let col = ref 1 in
2727+1528 let rec aux i acc =
1616- if i >= len then List.rev (EOF :: acc)
2929+ if i >= len then
3030+ let pos = { line = !line; col = !col; offset = i } in
3131+ List.rev ({ token = EOF; start_pos = pos; end_pos = pos } :: acc)
1732 else
3333+ let start_pos = { line = !line; col = !col; offset = i } in
1834 match str.[i] with
1919- | ' ' | '\t' | '\n' -> aux (i + 1) acc
2020- | '+' -> aux (i + 1) (Plus :: acc)
2121- | '-' -> aux (i + 1) (Minus :: acc)
2222- | '*' -> aux (i + 1) (Star :: acc)
2323- | '/' -> aux (i + 1) (Slash :: acc)
2424- | '^' -> aux (i + 1) (Caret :: acc)
2525- | '(' -> aux (i + 1) (LParen :: acc)
2626- | ')' -> aux (i + 1) (RParen :: acc)
3535+ | ' ' | '\t' ->
3636+ col := !col + 1;
3737+ aux (i + 1) acc
3838+ | '\n' ->
3939+ line := !line + 1;
4040+ col := 1;
4141+ aux (i + 1) acc
4242+ | '+' ->
4343+ col := !col + 1;
4444+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
4545+ aux (i + 1) ({ token = Plus; start_pos; end_pos } :: acc)
4646+ | '-' ->
4747+ col := !col + 1;
4848+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
4949+ aux (i + 1) ({ token = Minus; start_pos; end_pos } :: acc)
5050+ | '*' ->
5151+ col := !col + 1;
5252+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
5353+ aux (i + 1) ({ token = Star; start_pos; end_pos } :: acc)
5454+ | '/' ->
5555+ col := !col + 1;
5656+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
5757+ aux (i + 1) ({ token = Slash; start_pos; end_pos } :: acc)
5858+ | '^' ->
5959+ col := !col + 1;
6060+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
6161+ aux (i + 1) ({ token = Caret; start_pos; end_pos } :: acc)
6262+ | '(' ->
6363+ col := !col + 1;
6464+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
6565+ aux (i + 1) ({ token = LParen; start_pos; end_pos } :: acc)
6666+ | ')' ->
6767+ col := !col + 1;
6868+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
6969+ aux (i + 1) ({ token = RParen; start_pos; end_pos } :: acc)
7070+ | ',' ->
7171+ col := !col + 1;
7272+ let end_pos = { line = !line; col = !col; offset = i + 1 } in
7373+ aux (i + 1) ({ token = Comma; start_pos; end_pos } :: acc)
2774 | c when is_digit c || c = '.' ->
2875 let j = ref (i + 1) in
2976 while !j < len && (is_digit str.[!j] || str.[!j] = '.') do
3077 incr j
3178 done;
3279 let num_str = String.sub str i (!j - i) in
3333- aux !j (Num (float_of_string num_str) :: acc)
8080+ col := !col + (!j - i);
8181+ let end_pos = { line = !line; col = !col; offset = !j } in
8282+ aux !j ({ token = Num (float_of_string num_str); start_pos; end_pos } :: acc)
3483 | c when is_alpha c ->
3584 let j = ref (i + 1) in
3685 while !j < len && is_alphanum str.[!j] do
3786 incr j
3887 done;
3988 let id = String.sub str i (!j - i) in
8989+ col := !col + (!j - i);
9090+ let end_pos = { line = !line; col = !col; offset = !j } in
4091 let tok = if !j < len && str.[!j] = '(' then Ident id else Var id in
4141- aux !j (tok :: acc)
4242- | c -> failwith (Printf.sprintf "unexpected character: %c" c)
9292+ aux !j ({ token = tok; start_pos; end_pos } :: acc)
9393+ | c ->
9494+ failwith (Printf.sprintf "unexpected character: %c at line %d, column %d"
9595+ c !line !col)
4396 in
4444- aux 0 []
9797+9898+ let tokens = aux 0 [] in
9999+100100+ let rec insert_implicit_mult = function
101101+ | [] -> []
102102+ | [t] -> [t]
103103+ | t1 :: t2 :: rest ->
104104+ if needs_implicit_mult t1.token t2.token then
105105+ let mult_pos = t2.start_pos in
106106+ t1 :: { token = Star; start_pos = mult_pos; end_pos = mult_pos } ::
107107+ insert_implicit_mult (t2 :: rest)
108108+ else
109109+ t1 :: insert_implicit_mult (t2 :: rest)
110110+ in
111111+112112+ insert_implicit_mult tokens
···11+open Expr
22+open Simplify
33+open Diff
44+open Substitute
55+66+type direction = FromLeft | FromRight | Bidirectional
77+88+let rec limit expr var point direction =
99+ let try_direct_sub () =
1010+ try
1111+ let substituted = substitute var point expr in
1212+ let simplified = simplify substituted in
1313+ match simplified with
1414+ | Const c when not (Float.is_nan c || Float.is_infinite c) -> Some simplified
1515+ | _ -> None
1616+ with _ -> None
1717+ in
1818+1919+ let try_lhopital () =
2020+ let numerator, denominator = match expr with
2121+ | Div (n, d) -> (n, d)
2222+ | _ -> (expr, Const 1.0)
2323+ in
2424+2525+ let num_at_point = substitute var point numerator |> simplify in
2626+ let den_at_point = substitute var point denominator |> simplify in
2727+2828+ match (num_at_point, den_at_point) with
2929+ | (Const 0.0, Const 0.0) ->
3030+ let num_deriv = diff var numerator in
3131+ let den_deriv = diff var denominator in
3232+ let new_expr = Div (num_deriv, den_deriv) in
3333+ limit new_expr var point direction
3434+ | _ -> None
3535+ in
3636+3737+ let try_series_expansion () =
3838+ None
3939+ in
4040+4141+ match try_direct_sub () with
4242+ | Some result -> Some result
4343+ | None ->
4444+ match try_lhopital () with
4545+ | Some result -> Some result
4646+ | None -> try_series_expansion ()
4747+4848+let limit_at_infinity expr var =
4949+ let rec find_highest_power = function
5050+ | Pow (Var v, Const n) when v = var -> Some (int_of_float n)
5151+ | Div (num, den) ->
5252+ let num_pow = find_highest_power num |> Option.value ~default:0 in
5353+ let den_pow = find_highest_power den |> Option.value ~default:0 in
5454+ Some (num_pow - den_pow)
5555+ | Add (e1, e2) | Sub (e1, e2) ->
5656+ let p1 = find_highest_power e1 |> Option.value ~default:0 in
5757+ let p2 = find_highest_power e2 |> Option.value ~default:0 in
5858+ Some (max p1 p2)
5959+ | Mul (e1, e2) ->
6060+ let p1 = find_highest_power e1 |> Option.value ~default:0 in
6161+ let p2 = find_highest_power e2 |> Option.value ~default:0 in
6262+ Some (p1 + p2)
6363+ | _ -> None
6464+ in
6565+6666+ match find_highest_power expr with
6767+ | Some p when p > 0 -> Some (SymConst E)
6868+ | Some p when p < 0 -> Some (Const 0.0)
6969+ | Some _ -> Some (Const 1.0)
7070+ | None -> None
···11+open Expr
22+open Simplify
33+44+type matrix = expr array array
55+66+let create rows cols init =
77+ Array.init rows (fun i -> Array.init cols (fun j -> init i j))
88+99+let identity n =
1010+ create n n (fun i j -> if i = j then Const 1.0 else Const 0.0)
1111+1212+let rows m = Array.length m
1313+let cols m = if Array.length m > 0 then Array.length m.(0) else 0
1414+1515+let get m i j = m.(i).(j)
1616+let set m i j v = m.(i).(j) <- v
1717+1818+let map f m =
1919+ Array.map (Array.map f) m
2020+2121+let transpose m =
2222+ let r = rows m in
2323+ let c = cols m in
2424+ create c r (fun i j -> m.(j).(i))
2525+2626+let add m1 m2 =
2727+ if rows m1 <> rows m2 || cols m1 <> cols m2 then
2828+ failwith "matrix dimensions must match for addition"
2929+ else
3030+ create (rows m1) (cols m1) (fun i j ->
3131+ simplify (Add (m1.(i).(j), m2.(i).(j)))
3232+ )
3333+3434+let mult m1 m2 =
3535+ if cols m1 <> rows m2 then
3636+ failwith "incompatible matrix dimensions for multiplication"
3737+ else
3838+ create (rows m1) (cols m2) (fun i j ->
3939+ let sum = ref (Const 0.0) in
4040+ for k = 0 to cols m1 - 1 do
4141+ sum := Add (!sum, Mul (m1.(i).(k), m2.(k).(j)))
4242+ done;
4343+ simplify !sum
4444+ )
4545+4646+let scalar_mult s m =
4747+ map (fun e -> simplify (Mul (s, e))) m
4848+4949+let det m =
5050+ let n = rows m in
5151+ if n <> cols m then failwith "determinant requires square matrix";
5252+5353+ let rec determinant mat size =
5454+ if size = 1 then mat.(0).(0)
5555+ else if size = 2 then
5656+ simplify (Sub (Mul (mat.(0).(0), mat.(1).(1)),
5757+ Mul (mat.(0).(1), mat.(1).(0))))
5858+ else
5959+ let result = ref (Const 0.0) in
6060+ for j = 0 to size - 1 do
6161+ let minor = create (size - 1) (size - 1) (fun i k ->
6262+ let mi = if i < 0 then i else i + 1 in
6363+ let mk = if k < j then k else k + 1 in
6464+ mat.(mi).(mk)
6565+ ) in
6666+ let cofactor = determinant minor (size - 1) in
6767+ let sign = if j mod 2 = 0 then Const 1.0 else Const (-1.0) in
6868+ result := Add (!result, Mul (Mul (sign, mat.(0).(j)), cofactor))
6969+ done;
7070+ simplify !result
7171+ in
7272+ determinant m n
7373+7474+let inverse m =
7575+ let n = rows m in
7676+ if n <> cols m then None
7777+ else
7878+ let d = det m in
7979+ match d with
8080+ | Const 0.0 -> None
8181+ | _ ->
8282+ let adj = create n n (fun i j ->
8383+ let minor = create (n - 1) (n - 1) (fun mi mj ->
8484+ let si = if mi < i then mi else mi + 1 in
8585+ let sj = if mj < j then mj else mj + 1 in
8686+ m.(si).(sj)
8787+ ) in
8888+ let minor_det = det minor in
8989+ let sign = if (i + j) mod 2 = 0 then Const 1.0 else Const (-1.0) in
9090+ simplify (Mul (sign, minor_det))
9191+ ) in
9292+ let adj_t = transpose adj in
9393+ Some (map (fun e -> simplify (Div (e, d))) adj_t)
9494+9595+let trace m =
9696+ let n = min (rows m) (cols m) in
9797+ let sum = ref (Const 0.0) in
9898+ for i = 0 to n - 1 do
9999+ sum := Add (!sum, m.(i).(i))
100100+ done;
101101+ simplify !sum
102102+103103+let eigenvalues _m =
104104+ []
105105+106106+let rank m =
107107+ let r = rows m in
108108+ let c = cols m in
109109+ let temp = Array.map Array.copy m in
110110+ let rec count_pivots row col rank =
111111+ if row >= r || col >= c then rank
112112+ else
113113+ match temp.(row).(col) with
114114+ | Const 0.0 ->
115115+ let rec find_pivot i =
116116+ if i >= r then None
117117+ else match temp.(i).(col) with
118118+ | Const 0.0 -> find_pivot (i + 1)
119119+ | _ -> Some i
120120+ in
121121+ (match find_pivot (row + 1) with
122122+ | None -> count_pivots row (col + 1) rank
123123+ | Some i ->
124124+ let tmp_row = temp.(row) in
125125+ temp.(row) <- temp.(i);
126126+ temp.(i) <- tmp_row;
127127+ count_pivots row col rank)
128128+ | pivot ->
129129+ for i = row + 1 to r - 1 do
130130+ let factor = Div (temp.(i).(col), pivot) in
131131+ for j = col to c - 1 do
132132+ temp.(i).(j) <- simplify (Sub (temp.(i).(j), Mul (factor, temp.(row).(j))))
133133+ done
134134+ done;
135135+ count_pivots (row + 1) (col + 1) (rank + 1)
136136+ in
137137+ count_pivots 0 0 0
···11+open Expr
22+open Diff
33+open Simplify
44+55+let gradient vars expr =
66+ List.map (fun v -> diff v expr) vars
77+88+let jacobian vars exprs =
99+ List.map (fun expr -> gradient vars expr) exprs
1010+1111+let hessian vars expr =
1212+ let grad = gradient vars expr in
1313+ List.map (fun deriv -> List.map (fun v -> diff v deriv) vars) grad
1414+1515+let divergence vars vector_field =
1616+ if List.length vars <> List.length vector_field then
1717+ failwith "divergence: dimension mismatch"
1818+ else
1919+ let terms = List.map2 (fun v e -> diff v e) vars vector_field in
2020+ let sum = List.fold_left (fun acc t -> Add (acc, t)) (Const 0.0) terms in
2121+ simplify sum
2222+2323+let curl vector_field =
2424+ match vector_field with
2525+ | [fx; fy; fz] ->
2626+ let dfz_dy = diff "y" fz in
2727+ let dfy_dz = diff "z" fy in
2828+ let dfx_dz = diff "z" fx in
2929+ let dfz_dx = diff "x" fz in
3030+ let dfy_dx = diff "x" fy in
3131+ let dfx_dy = diff "y" fx in
3232+ [simplify (Sub (dfz_dy, dfy_dz));
3333+ simplify (Sub (dfx_dz, dfz_dx));
3434+ simplify (Sub (dfy_dx, dfx_dy))]
3535+ | _ -> failwith "curl: requires exactly 3 components"
3636+3737+let laplacian vars expr =
3838+ let hess = hessian vars expr in
3939+ let diagonal = List.mapi (fun i row -> List.nth row i) hess in
4040+ let sum = List.fold_left (fun acc t -> Add (acc, t)) (Const 0.0) diagonal in
4141+ simplify sum
···11+open Diff
22+open Eval
33+open Multivariate
44+55+let newton_raphson expr var initial tolerance max_iter =
66+ let f_prime = diff var expr in
77+ let rec iterate x n =
88+ if n >= max_iter then None
99+ else
1010+ let fx = eval [(var, x)] expr in
1111+ if abs_float fx < tolerance then Some x
1212+ else
1313+ let fpx = eval [(var, x)] f_prime in
1414+ if abs_float fpx < 1e-10 then None
1515+ else
1616+ let x_next = x -. fx /. fpx in
1717+ if abs_float (x_next -. x) < tolerance then Some x_next
1818+ else iterate x_next (n + 1)
1919+ in
2020+ iterate initial 0
2121+2222+let bisection expr var left right tolerance max_iter =
2323+ let rec iterate a b n =
2424+ if n >= max_iter then None
2525+ else
2626+ let fa = eval [(var, a)] expr in
2727+ let fb = eval [(var, b)] expr in
2828+ if fa *. fb > 0.0 then None
2929+ else
3030+ let mid = (a +. b) /. 2.0 in
3131+ let fmid = eval [(var, mid)] expr in
3232+ if abs_float fmid < tolerance || abs_float (b -. a) < tolerance then
3333+ Some mid
3434+ else if fa *. fmid < 0.0 then
3535+ iterate a mid (n + 1)
3636+ else
3737+ iterate mid b (n + 1)
3838+ in
3939+ iterate left right 0
4040+4141+let trapezoidal expr var lower upper n =
4242+ let h = (upper -. lower) /. float_of_int n in
4343+ let rec sum_interior i acc =
4444+ if i >= n then acc
4545+ else
4646+ let x = lower +. float_of_int i *. h in
4747+ let fx = eval [(var, x)] expr in
4848+ sum_interior (i + 1) (acc +. fx)
4949+ in
5050+ let f_lower = eval [(var, lower)] expr in
5151+ let f_upper = eval [(var, upper)] expr in
5252+ let interior = sum_interior 1 0.0 in
5353+ h *. (f_lower /. 2.0 +. interior +. f_upper /. 2.0)
5454+5555+let simpsons expr var lower upper n =
5656+ let n = if n mod 2 = 1 then n + 1 else n in
5757+ let h = (upper -. lower) /. float_of_int n in
5858+ let rec sum_terms i acc_odd acc_even =
5959+ if i >= n then (acc_odd, acc_even)
6060+ else
6161+ let x = lower +. float_of_int i *. h in
6262+ let fx = eval [(var, x)] expr in
6363+ if i mod 2 = 1 then
6464+ sum_terms (i + 1) (acc_odd +. fx) acc_even
6565+ else if i > 0 then
6666+ sum_terms (i + 1) acc_odd (acc_even +. fx)
6767+ else
6868+ sum_terms (i + 1) acc_odd acc_even
6969+ in
7070+ let f_lower = eval [(var, lower)] expr in
7171+ let f_upper = eval [(var, upper)] expr in
7272+ let (odd, even) = sum_terms 1 0.0 0.0 in
7373+ h /. 3.0 *. (f_lower +. 4.0 *. odd +. 2.0 *. even +. f_upper)
7474+7575+let rec adaptive_quadrature expr var lower upper tolerance =
7676+ let mid = (lower +. upper) /. 2.0 in
7777+ let whole = simpsons expr var lower upper 10 in
7878+ let left_half = simpsons expr var lower mid 10 in
7979+ let right_half = simpsons expr var mid upper 10 in
8080+ let error = abs_float (whole -. (left_half +. right_half)) in
8181+ if error < tolerance then
8282+ left_half +. right_half
8383+ else
8484+ let left = adaptive_quadrature expr var lower mid (tolerance /. 2.0) in
8585+ let right = adaptive_quadrature expr var mid upper (tolerance /. 2.0) in
8686+ left +. right
8787+8888+let gradient_descent expr vars initial learning_rate max_iter =
8989+ let grad_exprs = gradient vars expr in
9090+ let rec iterate point n =
9191+ if n >= max_iter then Some point
9292+ else
9393+ let env = List.combine vars point in
9494+ let grad_vals = List.map (eval env) grad_exprs in
9595+ let new_point = List.map2 (fun p g -> p -. learning_rate *. g) point grad_vals in
9696+ let diff = List.map2 (fun a b -> abs_float (a -. b)) new_point point in
9797+ let max_diff = List.fold_left max 0.0 diff in
9898+ if max_diff < 1e-6 then Some new_point
9999+ else iterate new_point (n + 1)
100100+ in
101101+ iterate initial 0
102102+103103+let invert_matrix matrix =
104104+ let n = List.length matrix in
105105+ let augmented = List.mapi (fun i row ->
106106+ row @ List.init n (fun j -> if i = j then 1.0 else 0.0)
107107+ ) matrix in
108108+109109+ let rec gaussian_elimination mat row =
110110+ if row >= n then mat
111111+ else
112112+ let pivot_row = List.nth mat row in
113113+ let pivot = List.nth pivot_row row in
114114+ if abs_float pivot < 1e-10 then mat
115115+ else
116116+ let normalized = List.map (fun x -> x /. pivot) pivot_row in
117117+ let updated = List.mapi (fun i r ->
118118+ if i = row then normalized
119119+ else
120120+ let factor = List.nth r row in
121121+ List.map2 (fun a b -> a -. factor *. b) r normalized
122122+ ) mat in
123123+ gaussian_elimination updated (row + 1)
124124+ in
125125+126126+ let reduced = gaussian_elimination augmented 0 in
127127+ List.map (fun row -> List.filteri (fun i _ -> i >= n) row) reduced
128128+129129+let newtons_method_opt expr vars initial tolerance max_iter =
130130+ let grad_exprs = gradient vars expr in
131131+ let hess_matrix = hessian vars expr in
132132+133133+ let rec iterate point n =
134134+ if n >= max_iter then None
135135+ else
136136+ let env = List.combine vars point in
137137+ let grad_vals = List.map (eval env) grad_exprs in
138138+ let hess_vals = List.map (fun row ->
139139+ List.map (eval env) row
140140+ ) hess_matrix in
141141+142142+ let hess_inv = invert_matrix hess_vals in
143143+ let delta = List.map (fun row ->
144144+ List.fold_left2 (fun acc h g -> acc +. h *. g) 0.0 row grad_vals
145145+ ) hess_inv in
146146+147147+ let new_point = List.map2 (fun p d -> p -. d) point delta in
148148+ let diff = List.map2 (fun a b -> abs_float (a -. b)) new_point point in
149149+ let max_diff = List.fold_left max 0.0 diff in
150150+151151+ if max_diff < tolerance then Some new_point
152152+ else iterate new_point (n + 1)
153153+ in
154154+ iterate initial 0
···11+open Expr
22+open Simplify
33+open Integrate
44+55+type ode = {
66+ equation: expr;
77+ dependent: string;
88+ independent: string;
99+}
1010+1111+let dsolve ode_eq dep_var indep_var =
1212+ let try_separation_of_variables () =
1313+ match ode_eq with
1414+ | Mul (f_y, g_x) ->
1515+ (match (integrate indep_var g_x, integrate dep_var f_y) with
1616+ | Some int_g, Some int_f ->
1717+ Some (simplify (Sub (int_f, int_g)))
1818+ | _ -> None)
1919+ | _ -> None
2020+ in
2121+2222+ let try_linear_first_order () =
2323+ None
2424+ in
2525+2626+ let try_exact_equation () =
2727+ None
2828+ in
2929+3030+ let try_integrating_factor () =
3131+ None
3232+ in
3333+3434+ match try_separation_of_variables () with
3535+ | Some sol -> Some sol
3636+ | None ->
3737+ match try_linear_first_order () with
3838+ | Some sol -> Some sol
3939+ | None ->
4040+ match try_exact_equation () with
4141+ | Some sol -> Some sol
4242+ | None -> try_integrating_factor ()
4343+4444+let solve_second_order coeff_y'' coeff_y' coeff_y rhs var =
4545+ let a = coeff_y'' in
4646+ let b = coeff_y' in
4747+ let c = coeff_y in
4848+4949+ match (a, b, c) with
5050+ | (Const a_val, Const b_val, Const c_val) when rhs = Const 0.0 ->
5151+ let discriminant = b_val *. b_val -. 4.0 *. a_val *. c_val in
5252+ if discriminant > 0.0 then
5353+ let r1 = (-.b_val +. sqrt discriminant) /. (2.0 *. a_val) in
5454+ let r2 = (-.b_val -. sqrt discriminant) /. (2.0 *. a_val) in
5555+ Some (Add (
5656+ Mul (Var "C1", Exp (Mul (Const r1, Var var))),
5757+ Mul (Var "C2", Exp (Mul (Const r2, Var var)))
5858+ ))
5959+ else if discriminant = 0.0 then
6060+ let r = -.b_val /. (2.0 *. a_val) in
6161+ Some (Mul (
6262+ Add (Var "C1", Mul (Var "C2", Var var)),
6363+ Exp (Mul (Const r, Var var))
6464+ ))
6565+ else
6666+ let real_part = -.b_val /. (2.0 *. a_val) in
6767+ let imag_part = sqrt (-.discriminant) /. (2.0 *. a_val) in
6868+ Some (Mul (
6969+ Exp (Mul (Const real_part, Var var)),
7070+ Add (
7171+ Mul (Var "C1", Cos (Mul (Const imag_part, Var var))),
7272+ Mul (Var "C2", Sin (Mul (Const imag_part, Var var)))
7373+ )
7474+ ))
7575+ | _ -> None
7676+7777+let solve_system _odes _indep_var =
7878+ []
···11+open Expr
22+open Diff
33+open Substitute
44+open Simplify
55+66+let rec factorial n =
77+ if n <= 1 then 1.0
88+ else float_of_int n *. factorial (n - 1)
99+1010+let taylor var expr center order =
1111+ let rec build_terms n acc =
1212+ if n > order then acc
1313+ else
1414+ let derivative = diff_n var n expr in
1515+ let deriv_at_center = substitute var center derivative in
1616+ let coeff = Div (deriv_at_center, Const (factorial n)) in
1717+ let h = Sub (Var var, center) in
1818+ let term = Mul (coeff, Pow (h, Const (float_of_int n))) in
1919+ build_terms (n + 1) (term :: acc)
2020+ in
2121+ let terms = List.rev (build_terms 0 []) in
2222+ let series = List.fold_left (fun acc t -> Add (acc, t)) (Const 0.0) terms in
2323+ simplify series
2424+2525+let maclaurin var expr order =
2626+ taylor var expr (Const 0.0) order
···11+open Expr
22+33+let max_iterations = 100
44+55+let rec simplify_once = function
66+ | Const _ as c -> c
77+ | SymConst _ as s -> s
88+ | Var _ as v -> v
99+ | Add (e1, e2) -> simplify_add (simplify_once e1) (simplify_once e2)
1010+ | Sub (e1, e2) -> simplify_sub (simplify_once e1) (simplify_once e2)
1111+ | Mul (e1, e2) -> simplify_mul (simplify_once e1) (simplify_once e2)
1212+ | Div (e1, e2) -> simplify_div (simplify_once e1) (simplify_once e2)
1313+ | Pow (e1, e2) -> simplify_pow (simplify_once e1) (simplify_once e2)
1414+ | Neg e -> simplify_neg (simplify_once e)
1515+ | Sin e -> simplify_sin (simplify_once e)
1616+ | Cos e -> simplify_cos (simplify_once e)
1717+ | Tan e -> simplify_tan (simplify_once e)
1818+ | Sinh e -> simplify_sinh (simplify_once e)
1919+ | Cosh e -> simplify_cosh (simplify_once e)
2020+ | Tanh e -> simplify_tanh (simplify_once e)
2121+ | Asin e -> simplify_asin (simplify_once e)
2222+ | Acos e -> simplify_acos (simplify_once e)
2323+ | Atan e -> simplify_atan (simplify_once e)
2424+ | Atan2 (e1, e2) -> simplify_atan2 (simplify_once e1) (simplify_once e2)
2525+ | Exp e -> simplify_exp (simplify_once e)
2626+ | Ln e -> simplify_ln (simplify_once e)
2727+ | Log (e1, e2) -> simplify_log (simplify_once e1) (simplify_once e2)
2828+ | Sqrt e -> simplify_sqrt (simplify_once e)
2929+ | Abs e -> simplify_abs (simplify_once e)
3030+3131+and simplify_add e1 e2 =
3232+ match (e1, e2) with
3333+ | Const 0.0, e | e, Const 0.0 -> e
3434+ | Const a, Const b -> Const (a +. b)
3535+ | Mul (Const a, e1), Mul (Const b, e2) when Canonical.equal e1 e2 ->
3636+ simplify_mul (Const (a +. b)) e1
3737+ | Mul (Const a, e1), e2 when Canonical.equal e1 e2 ->
3838+ simplify_mul (Const (a +. 1.0)) e1
3939+ | e1, Mul (Const b, e2) when Canonical.equal e1 e2 ->
4040+ simplify_mul (Const (1.0 +. b)) e1
4141+ | e1, e2 when Canonical.equal e1 e2 ->
4242+ simplify_mul (Const 2.0) e1
4343+ | Add (e1, Const a), Const b -> simplify_add e1 (Const (a +. b))
4444+ | _ -> Add (e1, e2)
4545+4646+and simplify_sub e1 e2 =
4747+ match (e1, e2) with
4848+ | e, Const 0.0 -> e
4949+ | Const a, Const b -> Const (a -. b)
5050+ | e1, e2 when Canonical.equal e1 e2 -> Const 0.0
5151+ | _ -> Sub (e1, e2)
5252+5353+and simplify_mul e1 e2 =
5454+ match (e1, e2) with
5555+ | Const 0.0, _ | _, Const 0.0 -> Const 0.0
5656+ | Const 1.0, e | e, Const 1.0 -> e
5757+ | Const (-1.0), e -> simplify_neg e
5858+ | e, Const (-1.0) -> simplify_neg e
5959+ | Const a, Const b -> Const (a *. b)
6060+ | Const a, Mul (Const b, e) -> simplify_mul (Const (a *. b)) e
6161+ | Mul (Const a, e), Const b -> simplify_mul (Const (a *. b)) e
6262+ | Const a, Mul (e1, Mul (Const b, e2)) ->
6363+ simplify_mul (Const (a *. b)) (Mul (e1, e2))
6464+ | Mul (Const a, e1), Mul (Const b, e2) ->
6565+ simplify_mul (Const (a *. b)) (Mul (e1, e2))
6666+ | Pow (e1, a), Pow (e2, b) when Canonical.equal e1 e2 ->
6767+ simplify_pow e1 (simplify_add a b)
6868+ | e1, Pow (e2, b) when Canonical.equal e1 e2 ->
6969+ simplify_pow e1 (simplify_add (Const 1.0) b)
7070+ | Pow (e1, a), e2 when Canonical.equal e1 e2 ->
7171+ simplify_pow e1 (simplify_add a (Const 1.0))
7272+ | e1, e2 when Canonical.equal e1 e2 ->
7373+ simplify_pow e1 (Const 2.0)
7474+ | Exp e1, Exp e2 -> Exp (simplify_add e1 e2)
7575+ | (Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ |
7676+ Asin _ | Acos _ | Atan _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _ | Pow _), Var _ ->
7777+ Mul (e2, e1)
7878+ | _ -> Mul (e1, e2)
7979+8080+and simplify_div e1 e2 =
8181+ match (e1, e2) with
8282+ | Const 0.0, _ -> Const 0.0
8383+ | e, Const 1.0 -> e
8484+ | Const a, Const b -> Const (a /. b)
8585+ | e1, e2 when Canonical.equal e1 e2 -> Const 1.0
8686+ | Mul (e1, e2), e3 when Canonical.equal e2 e3 -> e1
8787+ | Mul (e1, e2), e3 when Canonical.equal e1 e3 -> e2
8888+ | _ -> Div (e1, e2)
8989+9090+and simplify_pow e1 e2 =
9191+ match (e1, e2) with
9292+ | _, Const 0.0 -> Const 1.0
9393+ | e, Const 1.0 -> e
9494+ | Const 0.0, _ -> Const 0.0
9595+ | Const 1.0, _ -> Const 1.0
9696+ | Const a, Const b -> Const (a ** b)
9797+ | Pow (e, a), b -> simplify_pow e (simplify_mul a b)
9898+ | Sqrt e, Const 2.0 -> e
9999+ | e, Const 0.5 -> simplify_sqrt e
100100+ | SymConst E, Ln e -> e
101101+ | _ -> Pow (e1, e2)
102102+103103+and simplify_neg = function
104104+ | Const c -> Const (-.c)
105105+ | Neg e -> e
106106+ | Mul (Const c, e) -> simplify_mul (Const (-.c)) e
107107+ | Mul (e, Const c) -> simplify_mul (Const (-.c)) e
108108+ | e -> Neg e
109109+110110+and simplify_sin = function
111111+ | Const 0.0 -> Const 0.0
112112+ | Const c -> Const (sin c)
113113+ | Asin e -> e
114114+ | Neg e -> simplify_neg (Sin e)
115115+ | e -> Sin e
116116+117117+and simplify_cos = function
118118+ | Const 0.0 -> Const 1.0
119119+ | Const c -> Const (cos c)
120120+ | Acos e -> e
121121+ | Neg e -> Cos e
122122+ | e -> Cos e
123123+124124+and simplify_tan = function
125125+ | Const 0.0 -> Const 0.0
126126+ | Const c -> Const (tan c)
127127+ | Atan e -> e
128128+ | Neg e -> simplify_neg (Tan e)
129129+ | e -> Tan e
130130+131131+and simplify_sinh = function
132132+ | Const 0.0 -> Const 0.0
133133+ | Const c -> Const (sinh c)
134134+ | Neg e -> simplify_neg (Sinh e)
135135+ | e -> Sinh e
136136+137137+and simplify_cosh = function
138138+ | Const 0.0 -> Const 1.0
139139+ | Const c -> Const (cosh c)
140140+ | Neg e -> Cosh e
141141+ | e -> Cosh e
142142+143143+and simplify_tanh = function
144144+ | Const 0.0 -> Const 0.0
145145+ | Const c -> Const (tanh c)
146146+ | Neg e -> simplify_neg (Tanh e)
147147+ | e -> Tanh e
148148+149149+and simplify_asin = function
150150+ | Const c -> Const (asin c)
151151+ | Sin e -> e
152152+ | e -> Asin e
153153+154154+and simplify_acos = function
155155+ | Const c -> Const (acos c)
156156+ | Cos e -> e
157157+ | e -> Acos e
158158+159159+and simplify_atan = function
160160+ | Const c -> Const (atan c)
161161+ | Tan e -> e
162162+ | e -> Atan e
163163+164164+and simplify_atan2 e1 e2 =
165165+ match (e1, e2) with
166166+ | Const a, Const b -> Const (atan2 a b)
167167+ | _ -> Atan2 (e1, e2)
168168+169169+and simplify_exp = function
170170+ | Const 0.0 -> Const 1.0
171171+ | Const c -> Const (exp c)
172172+ | Ln e -> e
173173+ | Add (e1, e2) -> simplify_mul (Exp e1) (Exp e2)
174174+ | Mul (Const c, e) -> simplify_pow (Exp e) (Const c)
175175+ | e -> Exp e
176176+177177+and simplify_ln = function
178178+ | Const 1.0 -> Const 0.0
179179+ | Const c when c > 0.0 -> Const (log c)
180180+ | Exp e -> e
181181+ | SymConst E -> Const 1.0
182182+ | Mul (e1, e2) -> simplify_add (Ln e1) (Ln e2)
183183+ | Div (e1, e2) -> simplify_sub (Ln e1) (Ln e2)
184184+ | Pow (e, Const c) -> simplify_mul (Const c) (Ln e)
185185+ | e -> Ln e
186186+187187+and simplify_log base_e arg =
188188+ match (base_e, arg) with
189189+ | Const b, Const a when b > 0.0 && b <> 1.0 && a > 0.0 ->
190190+ Const (log a /. log b)
191191+ | b, a when Canonical.equal b a -> Const 1.0
192192+ | Const b, Pow (e, c) when Canonical.equal (Const b) e ->
193193+ c
194194+ | _ -> Log (base_e, arg)
195195+196196+and simplify_sqrt = function
197197+ | Const 0.0 -> Const 0.0
198198+ | Const 1.0 -> Const 1.0
199199+ | Const c when c >= 0.0 -> Const (sqrt c)
200200+ | Pow (e, Const 2.0) -> simplify_abs e
201201+ | Mul (e1, e2) -> simplify_mul (Sqrt e1) (Sqrt e2)
202202+ | e -> Sqrt e
203203+204204+and simplify_abs = function
205205+ | Const c -> Const (abs_float c)
206206+ | Abs e -> Abs e
207207+ | Neg e -> Abs e
208208+ | Mul (Const c, e) -> simplify_mul (Const (abs_float c)) (Abs e)
209209+ | e -> Abs e
210210+211211+let simplify expr =
212212+ let rec fixed_point e count =
213213+ if count >= max_iterations then e
214214+ else
215215+ let canonical = Canonical.canonicalize e in
216216+ let simplified = simplify_once canonical in
217217+ if Canonical.equal simplified canonical then simplified
218218+ else fixed_point simplified (count + 1)
219219+ in
220220+ fixed_point expr 0
···11+open Expr
22+open Simplify
33+44+type special_function =
55+ | Gamma of expr
66+ | Beta of expr * expr
77+ | Erf of expr
88+ | Erfc of expr
99+ | BesselJ of int * expr
1010+ | BesselY of int * expr
1111+ | LegendreP of int * expr
1212+ | HermiteH of int * expr
1313+ | LaguerreL of int * expr
1414+ | ChebyshevT of int * expr
1515+ | ChebyshevU of int * expr
1616+1717+let gamma x = Gamma x
1818+let beta x y = Beta (x, y)
1919+let erf x = Erf x
2020+let erfc x = Erfc x
2121+2222+let bessel_j n x = BesselJ (n, x)
2323+let bessel_y n x = BesselY (n, x)
2424+2525+let legendre_p n x =
2626+ let rec compute n =
2727+ if n = 0 then Const 1.0
2828+ else if n = 1 then x
2929+ else
3030+ let p_n_1 = compute (n - 1) in
3131+ let p_n_2 = compute (n - 2) in
3232+ let n_f = float_of_int n in
3333+ simplify (Div (
3434+ Sub (
3535+ Mul (Const (2.0 *. n_f -. 1.0), Mul (x, p_n_1)),
3636+ Mul (Const (n_f -. 1.0), p_n_2)
3737+ ),
3838+ Const n_f
3939+ ))
4040+ in
4141+ compute n
4242+4343+let hermite_h n x =
4444+ let rec compute n =
4545+ if n = 0 then Const 1.0
4646+ else if n = 1 then Mul (Const 2.0, x)
4747+ else
4848+ let h_n_1 = compute (n - 1) in
4949+ let h_n_2 = compute (n - 2) in
5050+ simplify (Sub (
5151+ Mul (Const 2.0, Mul (x, h_n_1)),
5252+ Mul (Const (2.0 *. float_of_int (n - 1)), h_n_2)
5353+ ))
5454+ in
5555+ compute n
5656+5757+let laguerre_l n x =
5858+ let rec compute n =
5959+ if n = 0 then Const 1.0
6060+ else if n = 1 then Sub (Const 1.0, x)
6161+ else
6262+ let l_n_1 = compute (n - 1) in
6363+ let l_n_2 = compute (n - 2) in
6464+ let n_f = float_of_int n in
6565+ simplify (Div (
6666+ Sub (
6767+ Mul (Const (2.0 *. n_f -. 1.0 -. 1.0), l_n_1),
6868+ Sub (Mul (x, l_n_1), Mul (Const (n_f -. 1.0), l_n_2))
6969+ ),
7070+ Const n_f
7171+ ))
7272+ in
7373+ compute n
7474+7575+let chebyshev_t n x =
7676+ let rec compute n =
7777+ if n = 0 then Const 1.0
7878+ else if n = 1 then x
7979+ else
8080+ let t_n_1 = compute (n - 1) in
8181+ let t_n_2 = compute (n - 2) in
8282+ simplify (Sub (
8383+ Mul (Const 2.0, Mul (x, t_n_1)),
8484+ t_n_2
8585+ ))
8686+ in
8787+ compute n
8888+8989+let chebyshev_u n x =
9090+ let rec compute n =
9191+ if n = 0 then Const 1.0
9292+ else if n = 1 then Mul (Const 2.0, x)
9393+ else
9494+ let u_n_1 = compute (n - 1) in
9595+ let u_n_2 = compute (n - 2) in
9696+ simplify (Sub (
9797+ Mul (Const 2.0, Mul (x, u_n_1)),
9898+ u_n_2
9999+ ))
100100+ in
101101+ compute n
102102+103103+let factorial n =
104104+ let rec fact n acc =
105105+ if n <= 1 then acc
106106+ else fact (n - 1) (acc * n)
107107+ in
108108+ Const (float_of_int (fact n 1))
109109+110110+let binomial n k =
111111+ if k < 0 || k > n then Const 0.0
112112+ else
113113+ let rec binom n k =
114114+ if k = 0 || k = n then 1
115115+ else binom (n - 1) (k - 1) + binom (n - 1) k
116116+ in
117117+ Const (float_of_int (binom n k))
···11+open Expr
22+33+let rec substitute var replacement = function
44+ | Const _ as c -> c
55+ | SymConst _ as s -> s
66+ | Var v -> if v = var then replacement else Var v
77+ | Add (e1, e2) -> Add (substitute var replacement e1, substitute var replacement e2)
88+ | Sub (e1, e2) -> Sub (substitute var replacement e1, substitute var replacement e2)
99+ | Mul (e1, e2) -> Mul (substitute var replacement e1, substitute var replacement e2)
1010+ | Div (e1, e2) -> Div (substitute var replacement e1, substitute var replacement e2)
1111+ | Pow (e1, e2) -> Pow (substitute var replacement e1, substitute var replacement e2)
1212+ | Neg e -> Neg (substitute var replacement e)
1313+ | Sin e -> Sin (substitute var replacement e)
1414+ | Cos e -> Cos (substitute var replacement e)
1515+ | Tan e -> Tan (substitute var replacement e)
1616+ | Sinh e -> Sinh (substitute var replacement e)
1717+ | Cosh e -> Cosh (substitute var replacement e)
1818+ | Tanh e -> Tanh (substitute var replacement e)
1919+ | Asin e -> Asin (substitute var replacement e)
2020+ | Acos e -> Acos (substitute var replacement e)
2121+ | Atan e -> Atan (substitute var replacement e)
2222+ | Atan2 (e1, e2) -> Atan2 (substitute var replacement e1, substitute var replacement e2)
2323+ | Exp e -> Exp (substitute var replacement e)
2424+ | Ln e -> Ln (substitute var replacement e)
2525+ | Log (e1, e2) -> Log (substitute var replacement e1, substitute var replacement e2)
2626+ | Sqrt e -> Sqrt (substitute var replacement e)
2727+ | Abs e -> Abs (substitute var replacement e)
2828+2929+let substitute_many subs expr =
3030+ List.fold_left (fun e (var, repl) -> substitute var repl e) expr subs
3131+3232+type pattern =
3333+ | PVar of string
3434+ | PWild
3535+ | PConst of float
3636+ | PSymConst of sym_const
3737+ | POp of string * pattern list
3838+3939+type bindings = (string * expr) list
4040+4141+let rec matches (pat : pattern) (e : expr) : bindings option =
4242+ match (pat, e) with
4343+ | PWild, _ -> Some []
4444+ | PVar v, e -> Some [(v, e)]
4545+ | PConst c1, Const c2 when c1 = c2 -> Some []
4646+ | PSymConst s1, SymConst s2 when s1 = s2 -> Some []
4747+ | POp ("Add", [p1; p2]), Add (e1, e2) ->
4848+ matches_binary p1 p2 e1 e2
4949+ | POp ("Sub", [p1; p2]), Sub (e1, e2) ->
5050+ matches_binary p1 p2 e1 e2
5151+ | POp ("Mul", [p1; p2]), Mul (e1, e2) ->
5252+ matches_binary p1 p2 e1 e2
5353+ | POp ("Div", [p1; p2]), Div (e1, e2) ->
5454+ matches_binary p1 p2 e1 e2
5555+ | POp ("Pow", [p1; p2]), Pow (e1, e2) ->
5656+ matches_binary p1 p2 e1 e2
5757+ | POp ("Neg", [p]), Neg e ->
5858+ matches p e
5959+ | POp ("Sin", [p]), Sin e ->
6060+ matches p e
6161+ | POp ("Cos", [p]), Cos e ->
6262+ matches p e
6363+ | POp ("Tan", [p]), Tan e ->
6464+ matches p e
6565+ | POp ("Sinh", [p]), Sinh e ->
6666+ matches p e
6767+ | POp ("Cosh", [p]), Cosh e ->
6868+ matches p e
6969+ | POp ("Tanh", [p]), Tanh e ->
7070+ matches p e
7171+ | POp ("Asin", [p]), Asin e ->
7272+ matches p e
7373+ | POp ("Acos", [p]), Acos e ->
7474+ matches p e
7575+ | POp ("Atan", [p]), Atan e ->
7676+ matches p e
7777+ | POp ("Atan2", [p1; p2]), Atan2 (e1, e2) ->
7878+ matches_binary p1 p2 e1 e2
7979+ | POp ("Exp", [p]), Exp e ->
8080+ matches p e
8181+ | POp ("Ln", [p]), Ln e ->
8282+ matches p e
8383+ | POp ("Log", [p1; p2]), Log (e1, e2) ->
8484+ matches_binary p1 p2 e1 e2
8585+ | POp ("Sqrt", [p]), Sqrt e ->
8686+ matches p e
8787+ | POp ("Abs", [p]), Abs e ->
8888+ matches p e
8989+ | _ -> None
9090+9191+and matches_binary p1 p2 e1 e2 =
9292+ match matches p1 e1 with
9393+ | None -> None
9494+ | Some b1 ->
9595+ match matches p2 e2 with
9696+ | None -> None
9797+ | Some b2 -> Some (b1 @ b2)
9898+9999+let rec instantiate (template : pattern) (bindings : bindings) : expr option =
100100+ match template with
101101+ | PWild -> None
102102+ | PVar v -> List.assoc_opt v bindings
103103+ | PConst c -> Some (Const c)
104104+ | PSymConst s -> Some (SymConst s)
105105+ | POp ("Add", [p1; p2]) ->
106106+ (match (instantiate p1 bindings, instantiate p2 bindings) with
107107+ | Some e1, Some e2 -> Some (Add (e1, e2))
108108+ | _ -> None)
109109+ | POp ("Sub", [p1; p2]) ->
110110+ (match (instantiate p1 bindings, instantiate p2 bindings) with
111111+ | Some e1, Some e2 -> Some (Sub (e1, e2))
112112+ | _ -> None)
113113+ | POp ("Mul", [p1; p2]) ->
114114+ (match (instantiate p1 bindings, instantiate p2 bindings) with
115115+ | Some e1, Some e2 -> Some (Mul (e1, e2))
116116+ | _ -> None)
117117+ | POp ("Div", [p1; p2]) ->
118118+ (match (instantiate p1 bindings, instantiate p2 bindings) with
119119+ | Some e1, Some e2 -> Some (Div (e1, e2))
120120+ | _ -> None)
121121+ | POp ("Pow", [p1; p2]) ->
122122+ (match (instantiate p1 bindings, instantiate p2 bindings) with
123123+ | Some e1, Some e2 -> Some (Pow (e1, e2))
124124+ | _ -> None)
125125+ | POp ("Neg", [p]) ->
126126+ (match instantiate p bindings with
127127+ | Some e -> Some (Neg e)
128128+ | None -> None)
129129+ | POp ("Sin", [p]) ->
130130+ (match instantiate p bindings with
131131+ | Some e -> Some (Sin e)
132132+ | None -> None)
133133+ | POp ("Cos", [p]) ->
134134+ (match instantiate p bindings with
135135+ | Some e -> Some (Cos e)
136136+ | None -> None)
137137+ | POp ("Tan", [p]) ->
138138+ (match instantiate p bindings with
139139+ | Some e -> Some (Tan e)
140140+ | None -> None)
141141+ | POp ("Sinh", [p]) ->
142142+ (match instantiate p bindings with
143143+ | Some e -> Some (Sinh e)
144144+ | None -> None)
145145+ | POp ("Cosh", [p]) ->
146146+ (match instantiate p bindings with
147147+ | Some e -> Some (Cosh e)
148148+ | None -> None)
149149+ | POp ("Tanh", [p]) ->
150150+ (match instantiate p bindings with
151151+ | Some e -> Some (Tanh e)
152152+ | None -> None)
153153+ | POp ("Asin", [p]) ->
154154+ (match instantiate p bindings with
155155+ | Some e -> Some (Asin e)
156156+ | None -> None)
157157+ | POp ("Acos", [p]) ->
158158+ (match instantiate p bindings with
159159+ | Some e -> Some (Acos e)
160160+ | None -> None)
161161+ | POp ("Atan", [p]) ->
162162+ (match instantiate p bindings with
163163+ | Some e -> Some (Atan e)
164164+ | None -> None)
165165+ | POp ("Atan2", [p1; p2]) ->
166166+ (match (instantiate p1 bindings, instantiate p2 bindings) with
167167+ | Some e1, Some e2 -> Some (Atan2 (e1, e2))
168168+ | _ -> None)
169169+ | POp ("Exp", [p]) ->
170170+ (match instantiate p bindings with
171171+ | Some e -> Some (Exp e)
172172+ | None -> None)
173173+ | POp ("Ln", [p]) ->
174174+ (match instantiate p bindings with
175175+ | Some e -> Some (Ln e)
176176+ | None -> None)
177177+ | POp ("Log", [p1; p2]) ->
178178+ (match (instantiate p1 bindings, instantiate p2 bindings) with
179179+ | Some e1, Some e2 -> Some (Log (e1, e2))
180180+ | _ -> None)
181181+ | POp ("Sqrt", [p]) ->
182182+ (match instantiate p bindings with
183183+ | Some e -> Some (Sqrt e)
184184+ | None -> None)
185185+ | POp ("Abs", [p]) ->
186186+ (match instantiate p bindings with
187187+ | Some e -> Some (Abs e)
188188+ | None -> None)
189189+ | _ -> None
190190+191191+let rewrite pattern template expr =
192192+ match matches pattern expr with
193193+ | None -> None
194194+ | Some bindings -> instantiate template bindings
···11+open Expr
22+open Integrate
33+44+let fourier_transform expr var =
55+ let omega = "omega" in
66+ let integrand = Mul (expr, Exp (Mul (Mul (Const (-1.0), SymConst E), Mul (Var omega, Var var)))) in
77+ match integrate var integrand with
88+ | Some result -> Some result
99+ | None ->
1010+ match expr with
1111+ | Const c -> Some (Mul (Const c, Const 0.0))
1212+ | Exp (Mul (Const a, Var v)) when v = var && a < 0.0 ->
1313+ Some (Div (Const 1.0, Add (Const a, Mul (SymConst E, Var omega))))
1414+ | Sin (Mul (Const a, Var v)) when v = var ->
1515+ Some (Div (Const a, Sub (Pow (Var omega, Const 2.0), Pow (Const a, Const 2.0))))
1616+ | Cos (Mul (Const a, Var v)) when v = var ->
1717+ Some (Div (Var omega, Sub (Pow (Var omega, Const 2.0), Pow (Const a, Const 2.0))))
1818+ | _ -> None
1919+2020+let inverse_fourier_transform _expr _omega =
2121+ None
2222+2323+let laplace_transform expr t =
2424+ let s = "s" in
2525+ match expr with
2626+ | Const c -> Some (Div (Const c, Var s))
2727+ | Var v when v = t -> Some (Div (Const 1.0, Pow (Var s, Const 2.0)))
2828+ | Pow (Var v, Const n) when v = t && Float.is_integer n && n >= 0.0 ->
2929+ let rec factorial n =
3030+ if n <= 1.0 then 1.0
3131+ else n *. factorial (n -. 1.0)
3232+ in
3333+ Some (Div (Const (factorial n), Pow (Var s, Const (n +. 1.0))))
3434+ | Exp (Mul (Const a, Var v)) when v = t ->
3535+ Some (Div (Const 1.0, Sub (Var s, Const a)))
3636+ | Sin (Mul (Const a, Var v)) when v = t ->
3737+ Some (Div (Const a, Add (Pow (Var s, Const 2.0), Pow (Const a, Const 2.0))))
3838+ | Cos (Mul (Const a, Var v)) when v = t ->
3939+ Some (Div (Var s, Add (Pow (Var s, Const 2.0), Pow (Const a, Const 2.0))))
4040+ | Sinh (Mul (Const a, Var v)) when v = t ->
4141+ Some (Div (Const a, Sub (Pow (Var s, Const 2.0), Pow (Const a, Const 2.0))))
4242+ | Cosh (Mul (Const a, Var v)) when v = t ->
4343+ Some (Div (Var s, Sub (Pow (Var s, Const 2.0), Pow (Const a, Const 2.0))))
4444+ | Mul (Exp (Mul (Const a, Var v1)), Sin (Mul (Const b, Var v2)))
4545+ when v1 = t && v2 = t ->
4646+ Some (Div (Const b,
4747+ Add (Pow (Sub (Var s, Const a), Const 2.0), Pow (Const b, Const 2.0))))
4848+ | Mul (Exp (Mul (Const a, Var v1)), Cos (Mul (Const b, Var v2)))
4949+ when v1 = t && v2 = t ->
5050+ Some (Div (Sub (Var s, Const a),
5151+ Add (Pow (Sub (Var s, Const a), Const 2.0), Pow (Const b, Const 2.0))))
5252+ | _ -> None
5353+5454+let inverse_laplace_transform expr s =
5555+ let t = "t" in
5656+ match expr with
5757+ | Div (Const c, Var v) when v = s -> Some (Const c)
5858+ | Div (Const 1.0, Pow (Var v, Const n)) when v = s && Float.is_integer n && n > 0.0 ->
5959+ let rec factorial n =
6060+ if n <= 1.0 then 1.0
6161+ else n *. factorial (n -. 1.0)
6262+ in
6363+ Some (Div (Pow (Var t, Const (n -. 1.0)), Const (factorial (n -. 1.0))))
6464+ | Div (Const 1.0, Sub (Var v, Const a)) when v = s ->
6565+ Some (Exp (Mul (Const a, Var t)))
6666+ | Div (Const a, Add (Pow (Var v, Const 2.0), Pow (Const b, Const 2.0))) when v = s ->
6767+ Some (Mul (Const (a /. b), Sin (Mul (Const b, Var t))))
6868+ | Div (Var v, Add (Pow (Var v2, Const 2.0), Pow (Const b, Const 2.0)))
6969+ when v = s && v2 = s ->
7070+ Some (Cos (Mul (Const b, Var t)))
7171+ | _ -> None
7272+7373+let z_transform _expr _n =
7474+ None
7575+7676+let inverse_z_transform _expr _z =
7777+ None