symbolic mathematics engine in OCaml with differentiation, integration, simplification, and numerical methods
17

Configure Feed

Select the types of activity you want to include in your feed.

leibniz / lib / format.ml
5.2 kB 109 lines
1open Expr 2 3let rec to_latex ?(implicit_mult=true) = function 4 | Const f -> 5 if Float.is_integer f then 6 string_of_int (int_of_float f) 7 else 8 string_of_float f 9 | SymConst Pi -> "\\pi" 10 | SymConst E -> "e" 11 | Var s -> s 12 | Add (e1, e2) -> to_latex ~implicit_mult e1 ^ " + " ^ to_latex ~implicit_mult e2 13 | Sub (e1, e2) -> to_latex ~implicit_mult e1 ^ " - " ^ to_latex_paren ~implicit_mult e2 14 | Mul (e1, e2) -> 15 let sep = if implicit_mult && should_implicit e1 e2 then "\\," else "\\cdot" in 16 to_latex_mul ~implicit_mult e1 ^ sep ^ to_latex_mul ~implicit_mult e2 17 | Div (e1, e2) -> "\\frac{" ^ to_latex ~implicit_mult e1 ^ "}{" ^ to_latex ~implicit_mult e2 ^ "}" 18 | Pow (e1, e2) -> to_latex_atom ~implicit_mult e1 ^ "^{" ^ to_latex ~implicit_mult e2 ^ "}" 19 | Neg e -> "-" ^ to_latex_atom ~implicit_mult e 20 | Sin e -> "\\sin\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 21 | Cos e -> "\\cos\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 22 | Tan e -> "\\tan\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 23 | Sinh e -> "\\sinh\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 24 | Cosh e -> "\\cosh\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 25 | Tanh e -> "\\tanh\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 26 | Asin e -> "\\arcsin\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 27 | Acos e -> "\\arccos\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 28 | Atan e -> "\\arctan\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 29 | Atan2 (e1, e2) -> "\\text{atan2}\\left(" ^ to_latex ~implicit_mult e1 ^ ", " ^ to_latex ~implicit_mult e2 ^ "\\right)" 30 | Exp e -> "e^{" ^ to_latex ~implicit_mult e ^ "}" 31 | Ln e -> "\\ln\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 32 | Log (base_e, arg) -> "\\log_{" ^ to_latex ~implicit_mult base_e ^ "}\\left(" ^ to_latex ~implicit_mult arg ^ "\\right)" 33 | Sqrt e -> "\\sqrt{" ^ to_latex ~implicit_mult e ^ "}" 34 | Abs e -> "\\left|" ^ to_latex ~implicit_mult e ^ "\\right|" 35 36and should_implicit e1 e2 = 37 match (e1, e2) with 38 | (Const _ | SymConst _), (Var _ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ | 39 Asin _ | Acos _ | Atan _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _ | Pow _) -> true 40 | _ -> false 41 42and to_latex_atom ?(implicit_mult=true) = function 43 | (Const _ | SymConst _ | Var _) as e -> to_latex ~implicit_mult e 44 | e -> "\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 45 46and to_latex_mul ?(implicit_mult=true) = function 47 | (Const _ | SymConst _ | Var _ | Pow _ | Sin _ | Cos _ | Tan _ | Sinh _ | Cosh _ | Tanh _ 48 | Asin _ | Acos _ | Atan _ | Atan2 _ | Exp _ | Ln _ | Log _ | Sqrt _ | Abs _) as e -> to_latex ~implicit_mult e 49 | e -> "\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 50 51and to_latex_paren ?(implicit_mult=true) = function 52 | (Add _ | Sub _) as e -> "\\left(" ^ to_latex ~implicit_mult e ^ "\\right)" 53 | e -> to_latex ~implicit_mult e 54 55let to_graphviz expr = 56 let counter = ref 0 in 57 let next_id () = 58 incr counter; 59 !counter 60 in 61 62 let rec build_graph e = 63 let id = next_id () in 64 match e with 65 | Const f -> 66 let label = if Float.is_integer f then string_of_int (int_of_float f) else string_of_float f in 67 (id, Printf.sprintf " n%d [label=\"%s\" shape=oval];\n" id label, "") 68 | SymConst Pi -> (id, Printf.sprintf " n%d [label=\"π\" shape=oval];\n" id, "") 69 | SymConst E -> (id, Printf.sprintf " n%d [label=\"e\" shape=oval];\n" id, "") 70 | Var v -> (id, Printf.sprintf " n%d [label=\"%s\" shape=oval];\n" id v, "") 71 | Add (e1, e2) -> build_binary id "+" e1 e2 72 | Sub (e1, e2) -> build_binary id "-" e1 e2 73 | Mul (e1, e2) -> build_binary id "*" e1 e2 74 | Div (e1, e2) -> build_binary id "/" e1 e2 75 | Pow (e1, e2) -> build_binary id "^" e1 e2 76 | Neg e -> build_unary id "-" e 77 | Sin e -> build_unary id "sin" e 78 | Cos e -> build_unary id "cos" e 79 | Tan e -> build_unary id "tan" e 80 | Sinh e -> build_unary id "sinh" e 81 | Cosh e -> build_unary id "cosh" e 82 | Tanh e -> build_unary id "tanh" e 83 | Asin e -> build_unary id "asin" e 84 | Acos e -> build_unary id "acos" e 85 | Atan e -> build_unary id "atan" e 86 | Atan2 (e1, e2) -> build_binary id "atan2" e1 e2 87 | Exp e -> build_unary id "exp" e 88 | Ln e -> build_unary id "ln" e 89 | Log (e1, e2) -> build_binary id "log" e1 e2 90 | Sqrt e -> build_unary id "sqrt" e 91 | Abs e -> build_unary id "abs" e 92 93 and build_unary id op e = 94 let (eid, enodes, eedges) = build_graph e in 95 let node = Printf.sprintf " n%d [label=\"%s\" shape=diamond];\n" id op in 96 let edge = Printf.sprintf " n%d -> n%d;\n" id eid in 97 (id, node ^ enodes, edge ^ eedges) 98 99 and build_binary id op e1 e2 = 100 let (id1, nodes1, edges1) = build_graph e1 in 101 let (id2, nodes2, edges2) = build_graph e2 in 102 let node = Printf.sprintf " n%d [label=\"%s\" shape=box];\n" id op in 103 let edge1 = Printf.sprintf " n%d -> n%d [label=\"L\"];\n" id id1 in 104 let edge2 = Printf.sprintf " n%d -> n%d [label=\"R\"];\n" id id2 in 105 (id, node ^ nodes1 ^ nodes2, edge1 ^ edge2 ^ edges1 ^ edges2) 106 in 107 108 let (_, nodes, edges) = build_graph expr in 109 "digraph expr {\n" ^ nodes ^ edges ^ "}\n"