package forester
A tool for tending mathematical forests
Install
Dune Dependency
Authors
Maintainers
Sources
4.3.1.tar.gz
md5=d1623b2919d2984bfcd841b5e772abd1
sha512=5924c8822d7e5a7bc49eb2b451cfd06cb372415559bc5ff232a59395b0aa28eb9819e351426ab25510f7d96ffb85ec652fa1878478b046c61e51ff471c285710
doc/src/forester.core/Query.ml.html
Source file Query.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 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
module Rel = struct type t = string let pp = Format.pp_print_string let show x = x let make_builtin name = "org.forester.rel." ^ name let links = make_builtin "links" let transclusion = make_builtin "transclusion" let = make_builtin "authors" let contributors = make_builtin "contributors" let taxa = make_builtin "taxa" let = make_builtin "tags" end type rel = Rel.t type mode = | Edges | Paths [@@deriving show, repr] type polarity = | Incoming | Outgoing [@@deriving show, repr] open Base type dbix = int [@@deriving show] type name = Symbol.t [@@deriving show] type lnvar = | F of name | B of dbix [@@deriving show] type 'var addr_expr = | Addr of addr | Var of 'var [@@deriving show] type 'a binder = {body : 'a} [@@deriving show] type 'var expr = | Rel of mode * polarity * Rel.t * 'var addr_expr | Isect of 'var expr list | Union of 'var expr list | Complement of 'var expr | Union_fam of 'var expr * 'var expr binder | Isect_fam of 'var expr * 'var expr binder [@@deriving show] let rec open_expr k a = function | Rel (mode, pol, rel, a') -> Rel (mode, pol, rel, open_addr_expr k a a') | Isect qs -> Isect (List.map (open_expr k a) qs) | Union qs -> Union (List.map (open_expr k a) qs) | Complement q -> Complement (open_expr k a q) | Isect_fam (q, scope) -> Isect_fam (open_expr k a q, open_scope k a scope) | Union_fam (q, scope) -> Union_fam (open_expr k a q, open_scope k a scope) and open_scope k a scope = {body = open_expr (k + 1) a scope.body} and open_addr_expr k a = function | Addr addr -> Addr addr | Var x -> open_lnvar k a x and open_lnvar k a = function | F x -> Var (F x) | B i when i = k -> a | B x -> Var (B x) let rec close_expr k x = function | Rel (mode, pol, rel, a) -> Rel (mode, pol, rel, close_addr_expr k x a) | Isect qs -> Isect (List.map (close_expr k x) qs) | Union qs -> Union (List.map (close_expr k x) qs) | Complement q -> Complement (close_expr k x q) | Union_fam (q, scope) -> Union_fam (close_expr k x q, close_scope k x scope) | Isect_fam (q, scope) -> Isect_fam (close_expr k x q, close_scope k x scope) and close_scope k x scope = {body = close_expr (k + 1) x scope.body} and close_addr_expr k x = function | Addr addr -> Addr addr | Var var -> Var (close_addr_var k x var) and close_addr_var k x = function | F name when x = name -> B k | F name -> F name | B i when i < k -> B i | B i -> B (i + 1) let bind x qx : lnvar expr binder = {body = close_expr 0 x qx} let unbind scope = let name = Symbol.fresh [] in let var = Var (F name) in name, open_expr 0 var scope.body let isect_fam q x qx = Isect_fam (q, bind x qx) let union_fam q x qx = Union_fam (q, bind x qx) let rel mode pol rel a = Rel (mode, pol, rel, a) let isect_fam_rel q mode pol r = let name = Symbol.fresh [] in isect_fam q name @@ rel mode pol r (Var (F name)) let union_fam_rel q mode pol r : lnvar expr = let name = Symbol.fresh [] in union_fam q name @@ rel mode pol r (Var (F name)) exception Distill of name let rec distill_expr : lnvar expr -> dbix expr = function | Rel (mode, pol, rel, a) -> Rel (mode, pol, rel, distill_addr_expr a) | Isect qs -> Isect (List.map distill_expr qs) | Union qs -> Union (List.map distill_expr qs) | Complement q -> Complement (distill_expr q) | Union_fam (q, scope) -> Union_fam (distill_expr q, distill_scope scope) | Isect_fam (q, scope)-> Isect_fam (distill_expr q, distill_scope scope) and distill_scope scope = {body = distill_expr scope.body} and distill_addr_expr = function | Addr addr -> Addr addr | Var var -> Var (distill_lnvar var) and distill_lnvar = function | F name -> raise @@ Distill name | B ix -> ix (** A heuristic for computing an intersection of queries. *) let rec query_cost q = match q with | Rel _ -> 1 | Isect qs -> List.fold_left (fun i q -> min (query_cost q) i) 1000 qs | Union qs -> List.fold_left (fun i q -> max (query_cost q) i) 0 qs | Union_fam (q, scope) -> query_cost q * query_cost scope.body | Isect_fam (q, scope) -> query_cost q * query_cost scope.body | Complement _ -> 900 let sort_by_ascending_cost qs = qs |> List.sort @@ fun q0 q1 -> compare (query_cost q0) (query_cost q1) let sort_by_descending_cost qs = qs |> List.sort @@ fun q0 q1 -> compare (query_cost q1) (query_cost q0) let rec isect qs = match sort_by_ascending_cost qs with | Isect qs :: qs' -> isect @@ qs @ qs' | qs -> Isect qs let rec union qs = match sort_by_descending_cost qs with | Union qs :: qs' -> union @@ qs @ qs' | qs -> Union qs let rec complement = function | Union qs -> isect @@ List.map complement qs | Complement q -> q | q -> Complement q let tree_under x = rel Paths Outgoing Rel.transclusion x let has_taxon taxon = rel Edges Incoming Rel.taxa (Addr (User_addr taxon)) let hereditary_contributors addr = let q_non_ref_under = isect [ tree_under addr; complement @@ has_taxon "reference" ] in let q_immediate_contributors = rel Edges Outgoing Rel.contributors addr in let q_all_contributors = union [ q_immediate_contributors; union_fam_rel q_non_ref_under Edges Outgoing Rel.contributors ] in let = rel Edges Outgoing Rel.authors addr in isect [q_all_contributors; complement q_authors] let references addr = isect [ union_fam_rel (tree_under addr) Edges Outgoing Rel.links; has_taxon "reference" ] let context addr = rel Edges Incoming Rel.transclusion addr let backlinks addr = rel Edges Incoming Rel.links addr let addr = isect [ rel Edges Outgoing Rel.links addr; complement @@ has_taxon "reference" ] let contributions addr = union [ rel Edges Incoming Rel.authors addr; rel Edges Incoming Rel.contributors addr ]
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>