134 lines
4.8 KiB
OCaml
134 lines
4.8 KiB
OCaml
open Expr
|
|
open Simplify
|
|
open Diff
|
|
open Substitute
|
|
|
|
let rec integrate var = function
|
|
| Const c -> Some (Mul (Const c, Var var))
|
|
| SymConst _ as s -> Some (Mul (s, Var var))
|
|
| Var v when v = var -> Some (Div (Pow (Var var, Const 2.0), Const 2.0))
|
|
| Var v -> Some (Mul (Var v, Var var))
|
|
| Add (e1, e2) ->
|
|
(match (integrate var e1, integrate var e2) with
|
|
| Some i1, Some i2 -> Some (simplify (Add (i1, i2)))
|
|
| _ -> None)
|
|
| Sub (e1, e2) ->
|
|
(match (integrate var e1, integrate var e2) with
|
|
| Some i1, Some i2 -> Some (simplify (Sub (i1, i2)))
|
|
| _ -> None)
|
|
| Mul (Const c, e) | Mul (e, Const c) ->
|
|
(match integrate var e with
|
|
| Some i -> Some (simplify (Mul (Const c, i)))
|
|
| None -> None)
|
|
| Mul (SymConst s, e) | Mul (e, SymConst s) ->
|
|
(match integrate var e with
|
|
| Some i -> Some (simplify (Mul (SymConst s, i)))
|
|
| None -> None)
|
|
| Pow (Var v, Const n) when v = var && n <> -1.0 ->
|
|
let exp = n +. 1.0 in
|
|
Some (simplify (Div (Pow (Var var, Const exp), Const exp)))
|
|
| Div (Const 1.0, Var v) when v = var ->
|
|
Some (Ln (Abs (Var var)))
|
|
| Div (e, Var v) when v = var ->
|
|
(match e with
|
|
| Const c -> Some (simplify (Mul (Const c, Ln (Abs (Var var)))))
|
|
| _ -> None)
|
|
| Sin (Var v) when v = var ->
|
|
Some (Neg (Cos (Var var)))
|
|
| Cos (Var v) when v = var ->
|
|
Some (Sin (Var var))
|
|
| Tan (Var v) when v = var ->
|
|
Some (Neg (Ln (Abs (Cos (Var var)))))
|
|
| Div (Const 1.0, Pow (Cos (Var v), Const 2.0)) when v = var ->
|
|
Some (Tan (Var var))
|
|
| Sinh (Var v) when v = var ->
|
|
Some (Cosh (Var var))
|
|
| Cosh (Var v) when v = var ->
|
|
Some (Sinh (Var var))
|
|
| Tanh (Var v) when v = var ->
|
|
Some (Ln (Cosh (Var var)))
|
|
| Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0)))) when v = var ->
|
|
Some (Asin (Var var))
|
|
| Neg (Div (Const 1.0, Sqrt (Sub (Const 1.0, Pow (Var v, Const 2.0))))) when v = var ->
|
|
Some (Acos (Var var))
|
|
| Div (Const 1.0, Add (Const 1.0, Pow (Var v, Const 2.0))) when v = var ->
|
|
Some (Atan (Var var))
|
|
| Exp (Var v) when v = var ->
|
|
Some (Exp (Var var))
|
|
| Pow (Const a, Var v) when v = var ->
|
|
Some (simplify (Div (Pow (Const a, Var var), Ln (Const a))))
|
|
| Pow (SymConst E, Var v) when v = var ->
|
|
Some (Exp (Var var))
|
|
| e ->
|
|
match try_u_substitution var e with
|
|
| Some result -> Some result
|
|
| None -> try_by_parts var e
|
|
|
|
and try_u_substitution var expr =
|
|
let rec find_inner = function
|
|
| Sin u | Cos u | Tan u | Sinh u | Cosh u | Tanh u
|
|
| Asin u | Acos u | Atan u | Exp u | Ln u | Sqrt u | Abs u -> Some u
|
|
| Pow (u, _) -> Some u
|
|
| Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) ->
|
|
(match find_inner e1 with
|
|
| Some _ as r -> r
|
|
| None -> find_inner e2)
|
|
| _ -> None
|
|
in
|
|
match find_inner expr with
|
|
| Some u when u <> Var var ->
|
|
let u_prime = diff var u in
|
|
let expr_simplified = simplify expr in
|
|
let test_expr = simplify (Div (expr_simplified, u_prime)) in
|
|
let substituted = substitute var (Var "u_temp") test_expr in
|
|
(match substituted with
|
|
| e when not (contains_var var e) ->
|
|
(match integrate "u_temp" e with
|
|
| Some integrated ->
|
|
let result = substitute "u_temp" u integrated in
|
|
Some (simplify result)
|
|
| None -> None)
|
|
| _ -> None)
|
|
| _ -> None
|
|
|
|
and try_by_parts var = function
|
|
| Mul (e1, e2) ->
|
|
let priority = function
|
|
| Ln _ -> 5
|
|
| Asin _ | Acos _ | Atan _ -> 4
|
|
| Var _ | Pow (Var _, _) -> 3
|
|
| Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ -> 2
|
|
| Exp _ -> 1
|
|
| _ -> 0
|
|
in
|
|
let (u, dv) =
|
|
if priority e1 >= priority e2 then (e1, e2) else (e2, e1)
|
|
in
|
|
(match integrate var dv with
|
|
| Some v ->
|
|
let du = diff var u in
|
|
(match integrate var (simplify (Mul (v, du))) with
|
|
| Some second_integral ->
|
|
Some (simplify (Sub (Mul (u, v), second_integral)))
|
|
| None -> None)
|
|
| None -> None)
|
|
| _ -> None
|
|
|
|
and contains_var var = function
|
|
| Const _ | SymConst _ -> false
|
|
| Var v -> v = var
|
|
| Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) | Pow (e1, e2) ->
|
|
contains_var var e1 || contains_var var e2
|
|
| Neg e | Sin e | Cos e | Tan e | Sinh e | Cosh e | Tanh e
|
|
| Asin e | Acos e | Atan e | Exp e | Ln e | Sqrt e | Abs e ->
|
|
contains_var var e
|
|
| Atan2 (e1, e2) | Log (e1, e2) ->
|
|
contains_var var e1 || contains_var var e2
|
|
|
|
let integrate_definite var lower upper expr =
|
|
match integrate var expr with
|
|
| None -> None
|
|
| Some antideriv ->
|
|
let upper_val = Eval.eval [(var, upper)] antideriv in
|
|
let lower_val = Eval.eval [(var, lower)] antideriv in
|
|
Some (upper_val -. lower_val)
|