package lp
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Page
Library
Module
Module type
Parameter
Class
Class type
Source
Source file term.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
type t = | Const of float | Linear of float * Var.t | Quad of float * Var.t * Var.t let c x = Const x let var ?(integer = false) ?(lb = Float.zero) ?(ub = Float.infinity) name = Linear (Float.one, Var.make ~integer ~lb ~ub name) let of_var v = Linear (Float.one, v) let binary name = Linear (Float.one, Var.make ~integer:true ~lb:Float.zero ~ub:Float.one name) let range ?(integer = false) ?(lb = Float.zero) ?(ub = Float.infinity) name num = Array.init num (fun i -> Linear ( Float.one , Var.make ~integer ~lb ~ub (String.concat "_" [name; string_of_int i]) )) let format_float f = let s = Printf.sprintf "%+.18e" f in String.concat " " [String.sub s 0 1; String.sub s 1 (String.length s - 1)] let format_float_short f = let s = Printf.sprintf "%+.2f" f in String.concat " " [String.sub s 0 1; String.sub s 1 (String.length s - 1)] let to_string ?(short = false) t = let fmt = if short then format_float_short else format_float in match t with | Const c -> fmt c | Linear (c, v) -> fmt c ^ " " ^ Var.to_string v | Quad (c, v0, v1) when v0 = v1 -> fmt c ^ " " ^ Var.to_string v0 ^ " ^ 2" | Quad (c, v0, v1) -> fmt c ^ " " ^ Var.to_string v0 ^ " * " ^ Var.to_string v1 let mul x y = match (x, y) with | Const c0, Const c1 -> Const (c0 *. c1) | Const c0, Linear (c1, v) -> Linear (c0 *. c1, v) | Linear (c0, v), Const c1 -> Linear (c0 *. c1, v) | Linear (c0, v0), Linear (c1, v1) -> Quad (c0 *. c1, v0, v1) | Quad (c0, v0, v1), Const c1 -> Quad (c0 *. c1, v0, v1) | Const c0, Quad (c1, v0, v1) -> Quad (c0 *. c1, v0, v1) | _ -> failwith "Unsupported operation (trying to create Cubic or Quartic ?)" let div x y = match (x, y) with | Const c0, Const c1 -> Const (c0 /. c1) | Linear (c0, v), Const c1 -> Linear (c0 /. c1, v) | Linear (c0, v0), Linear (c1, v1) when v0 = v1 -> Const (c0 /. c1) | Quad (c0, v0, v1), Const c1 -> Quad (c0 /. c1, v0, v1) | Quad (c, v0, v1), Linear (cr, vr) when v0 = vr || v1 = vr -> if v0 = vr then Linear (c /. cr, v1) else Linear (c /. cr, v0) | Const c0, Quad (c1, v0, v1) -> Quad (c0 *. c1, v0, v1) | _ -> failwith "Unsupported operation (trying to invert variables ?)" let zero = Const Float.zero let one = Const Float.one let neg = function | Const c -> Const (Float.neg c) | Linear (c, v) -> Linear (Float.neg c, v) | Quad (c, v0, v1) -> Quad (Float.neg c, v0, v1) let sort = function | Quad (c, v0, v1) -> if v0 > v1 then Quad (c, v1, v0) else Quad (c, v0, v1) | t -> t let degree = function Quad _ -> 2 | Linear _ -> 1 | Const _ -> 0 let near_zero ?(eps = 10. *. epsilon_float) = function | Const c -> Float.abs c < eps | Linear (c, _) -> Float.abs c < eps | Quad (c, _, _) -> Float.abs c < eps let common_var tl tr = let stl = sort tl in let str = sort tr in match (stl, str) with | Linear (_, vl), Linear (_, vr) -> vl = vr | Quad (_, vl0, vl1), Quad (_, vr0, vr1) -> vl0 = vr0 && vl1 = vr1 | _ -> false let collision tl tr = let stl = sort tl in let str = sort tr in match (stl, str) with | Linear (_, vl), Linear (_, vr) -> Var.collision vl vr | Quad (_, vl0, vl1), Quad (_, vr0, vr1) -> Var.collision vl0 vr0 || Var.collision vl1 vr1 | _ -> false let compare tl tr = match (tl, tr) with | Const cl, Const cr -> Float.compare cl cr | Linear (cl, vl), Linear (cr, vr) -> let n = Var.compare_name vl vr in if n <> 0 then n else Float.compare cl cr | Quad (cl, vl0, vl1), Quad (cr, vr0, vr1) -> let n0 = Var.compare_name vl0 vr0 in if n0 <> 0 then n0 else let n1 = Var.compare_name vl1 vr1 in if n1 <> 0 then n1 else Float.compare cl cr | Linear _, Const _ -> 1 | Const _, Linear _ -> -1 | Quad _, Const _ -> 1 | Const _, Quad _ -> -1 | Quad _, Linear _ -> 1 | Linear _, Quad _ -> -1 let with_bound name lb ub = function | Linear (c, v) when v.name = name -> Linear (c, Var.with_bound lb ub v) | Quad (c, v0, v1) when v0.name = name && v1.name = name -> let newv = Var.with_bound lb ub v0 in Quad (c, newv, newv) | Quad (c, v0, v1) when v0.name = name -> Quad (c, Var.with_bound lb ub v0, v1) | Quad (c, v0, v1) when v1.name = name -> Quad (c, v0, Var.with_bound lb ub v1) | org -> org let to_binary name = function | Linear (c, v) when v.name = name -> Linear (c, Var.to_binary v) | Quad (c, v0, v1) when v0.name = name && v1.name = name -> let newv = Var.to_binary v0 in Quad (c, newv, newv) | Quad (c, v0, v1) when v0.name = name -> Quad (c, Var.to_binary v0, v1) | Quad (c, v0, v1) when v1.name = name -> Quad (c, v0, Var.to_binary v1) | org -> org let to_integer name = function | Linear (c, v) when v.name = name -> Linear (c, Var.to_integer v) | Quad (c, v0, v1) when v0.name = name && v1.name = name -> let newv = Var.to_integer v0 in Quad (c, newv, newv) | Quad (c, v0, v1) when v0.name = name -> Quad (c, Var.to_integer v0, v1) | Quad (c, v0, v1) when v1.name = name -> Quad (c, v0, Var.to_integer v1) | org -> org let double_quad = function | Quad (c, v0, v1) -> Quad (c *. 2.0, v0, v1) | org -> org let half_quad = function | Quad (c, v0, v1) -> Quad (c /. 2.0, v0, v1) | org -> org