package phylogenetics
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Algorithms and datastructures for phylogenetics
Install
dune-project
Dependency
Authors
Maintainers
Sources
phylogenetics-0.3.0.tbz
sha256=de867d7cc017a8e434dab43ef16f0f6495973892cd7b6a8446b18e79393704a8
sha512=0209538caf94be47eabcaa25399c54849bd4fa0fc79e0579acee27f46ef3b72aa50e17bdb48fed8e86674d4caee6c1c4c423833a2757db12e2a6cc28234510de
doc/src/phylogenetics/fitch.ml.html
Source file fitch.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 117open Core let default_cost x y = if x = y then 0. else 1. let rec forward ?(cost = default_cost) ~n ~category (t : (_,'l,_) Tree.t) = match t with | Leaf l -> let costs = match category l with | Some cat -> if cat < 0 || cat >= n then invalid_arg "category returned integer not in [0;n[" ; Array.init n ~f:(fun i -> if i = cat then 0. else Float.infinity) | None -> Array.create ~len:n 0. in costs, Tree.leaf l | Node node -> let children_costs, children = List1.map node.branches ~f:(fun (Branch b) -> let cost, child = forward ~cost ~n ~category b.tip in cost, Tree.branch b.data child ) |> List1.unzip in let costs, choices = Array.init n ~f:(fun i -> let costs_for_root_i = List1.map children_costs ~f:(fun costs -> let cost j = costs.(j) +. cost i j in let rec loop j best_cost best_choice = if j = n then (best_cost, best_choice) else let candidate_cost = cost j in if Float.(candidate_cost < best_cost) then loop (j + 1) candidate_cost j else loop (j + 1) best_cost best_choice in loop 1 (cost 0) 0 ) in let costs, choices = List1.unzip costs_for_root_i in let total_cost = List1.fold costs ~init:0. ~f:( +. ) in total_cost, choices ) |> Array.unzip in costs, Tree.node (node.data, choices) children let rec backward_aux t i = match t with | Tree.Leaf l -> Tree.leaf (l, i) | Node n -> Tree.node (fst n.data, i) ( List1.map2_exn n.branches (snd n.data).(i) ~f:(fun (Branch b) choice -> Tree.branch b.data (backward_aux b.tip choice) ) ) let array_min_elt_index xs ~compare = match xs with | [| |] -> None | _ -> let n = Array.length xs in let rec loop acc i = if i >= n then Some acc else let acc' = match compare xs.(acc) xs.(i) with | -1 | 0 -> acc | 1 -> i | _ -> assert false in loop acc' (i + 1) in loop 0 1 let backward costs t = match array_min_elt_index costs ~compare:Float.compare with | None -> assert false | Some root -> backward_aux t root let fitch ?cost ~n ~category t = let costs, routing = forward ?cost ~n ~category t in backward costs routing let%expect_test "fitch" = let node x y = Tree.node () List1.(cons (Tree.branch () x) [ Tree.branch () y ]) in let leaf x = Tree.leaf x in let t = node (node (leaf 0) (leaf 1)) (leaf 0) in let p (_, i) = Int.to_string i in fitch ~category:Option.return ~n:2 t |> Tree.to_printbox ~leaf:p ~node:p |> PrintBox_text.output stdout ; [%expect {| 0 ├─0 │ ├─0 │ └─1 └─0 |}] let%expect_test "fitch_2" = let node x y = Tree.node () List1.(cons (Tree.branch () x) [ Tree.branch () y ]) in let leaf x = Tree.leaf x in let p (_, i) = Int.to_string i in let t = node (node (leaf 0) (leaf 1)) (node (leaf 1) (leaf 2)) in fitch ~n:3 ~category:Option.return t |> Tree.to_printbox ~leaf:p ~node:p |> PrintBox_text.output stdout ; [%expect {| 1 ├─1 │ ├─0 │ └─1 └─1 ├─1 └─2 |}]
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>