From 0b84629592f0f423db061e986b5110206717e4d9 Mon Sep 17 00:00:00 2001 From: Guyslain <guyslain.naves@lis-lab.fr> Date: Mon, 15 Jan 2024 13:57:43 +0100 Subject: [PATCH] add sampler for compatible orders of a pqtree --- lib/pqtrees/pqTree.ml | 57 ++++++++++++++++++++++++++++++++++++++++++ lib/pqtrees/pqTree.mli | 16 ++++++++++-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/lib/pqtrees/pqTree.ml b/lib/pqtrees/pqTree.ml index cec2e6c..c6b8926 100644 --- a/lib/pqtrees/pqTree.ml +++ b/lib/pqtrees/pqTree.ml @@ -126,6 +126,7 @@ sig type elt include FeatCore.EnumSig.ENUM val enumeration : elt t enum + val compatible_orders : 'elt t -> 'elt list IFSeq.seq end module MakeEnumerate = @@ -189,6 +190,54 @@ module MakeEnumerate = include PQTEnum let enumeration = PQTEnum.map to_pqtree enum_skeleton + + + let extensions list = + let rec go previous = function + | [] -> [] + | this::next -> (this, List.rev_append previous next) :: go (this::previous) next + in + go [] list + + + let rec enum_permutations = + let open PQTIFSeq in + function + | [] -> singleton [] + | elements -> + exists + (extensions elements) + (fun (head,tail) -> map (List.cons head) (enum_permutations tail)) + + + let rec big_product = + let open PQTIFSeq in + function + | [] -> singleton [] + | head::tail -> + product head (big_product tail) + |> map (fun (sample_head, samples_tail) -> sample_head :: samples_tail) + + let apply_permutation (sigma : int list) (elements : 'a list) : 'a list = + List.map (List.nth elements) sigma + + let rec compatible_orders pqtree = + let open PQTIFSeq in + match pqtree with + | Leaf x -> singleton [x] + | P children -> + let permutations = enum_permutations (List.mapi (fun i _ -> i) children) in + let orders = big_product (List.map compatible_orders children) in + product permutations orders + |> map (fun (permutation, orders) -> apply_permutation permutation orders |> List.concat) + | Q children -> + let left_to_right_seq = + children + |> List.map compatible_orders + |> big_product + |> map List.concat + in + sum (left_to_right_seq) (left_to_right_seq |> map List.rev) end @@ -201,6 +250,14 @@ let sample size = | _ -> invalid_arg (Format.sprintf "PqTree.sample %d" size) +let sample_compatible_order pqtree = + let sequence = Enum.compatible_orders pqtree in + match Seq.uncons (Enum.PQTIFSeq.sample 1 sequence Seq.empty) with + | Some (sample,_) -> sample + | None -> assert false + + + let rec shrink_a_child children = MoreList.extend children |> List.to_seq diff --git a/lib/pqtrees/pqTree.mli b/lib/pqtrees/pqTree.mli index 875b7ed..57eea92 100644 --- a/lib/pqtrees/pqTree.mli +++ b/lib/pqtrees/pqTree.mli @@ -61,7 +61,8 @@ val count_permutations : 'elt t -> Big_int_Z.big_int (** A random permutation among those encoded by a given PQ-tree. @param tree a PQ-tree - @return a random permutation, as a list of elements, chosen uniformly randomly among all permutations encoded by [tree] + @return a random permutation, as a list of elements, chosen + uniformly randomly among all permutations encoded by [tree] *) val sample_permutation : 'elt t -> 'elt list @@ -71,7 +72,7 @@ val sample_permutation : 'elt t -> 'elt list consecutively in any permutation in the set {%$\mathcal{P}$%}. The interval is sampled by first sampling a uniformly chosen permutation, then sampling in this permutation a random - subsequence of elemnts. This sampling is not uniform in general. + subsequence of elements. This sampling is not uniform in general. @param tree a PQ-tree @return a random interval for the set of permutations encoded by [tree] @@ -161,6 +162,9 @@ sig (** An enumeration of all PQ-trees over some type of elements *) val enumeration : elt t enum + + (** A sequence of all compatible orders of a PQ-tree. *) + val compatible_orders : 'elt t -> 'elt list IFSeq.seq end (** A functor to build a function to enumerate over PQ-trees. *) @@ -183,6 +187,14 @@ module Enum : EnumerateSig with type elt = int val sample : int -> int t +(** Sample a uniformly random compatible order from a PQ-tree. + + @param pqtree the pqtree from which a compatible order must be sampled. + @return A uniformly random compatible order of [pqtree]. +*) +val sample_compatible_order : 'elt t -> 'elt list + + (** A type for modules providing functions to define a canonical representation of equivalent PQ-trees, where two PQ-trees are equivalent when they encode the same set of permutations. -- GitLab