package orgeat

  1. Overview
  2. Docs
Ocaml Random Generation of Arbitrary Types

Install

Dune Dependency

Authors

Maintainers

Sources

0.0.1.tar.gz
md5=591bfdcd7f0705efeb32b72015d96086
sha512=deb30610151e53b8dc9bd2eaebc88573be8a5c5192bfbc2d4fa2a02462fd2b6c7247974a46bd1ece5e0bf06589a4194db2ffab37d40d26ada23758a0c41d3e02

doc/src/orgeat/combi.ml.html

Source file combi.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
open Misc

module Make (K : Scalar.S) = struct
  module Boltzmann = Sampler.Boltzmann (K)

  (**
   Tree representation of the definition of a combinatorial class

Note: the functions in Map should be bijections whenever possible.
   Not doing so is not a problem in itself, but we can predict what will happen:
   - without injectivity, some elements will have a greater probability of occurence;
   - without surjectivity, the sampling will not be exhaustive.
   Please keep this notion in mind when manually creating [class_tree]s.
 *)

  type sequence_kind = {min : int; max : int option}

  let unbounded_seq = {min = 0; max = None}

  let bounded_seq min max = {min; max}

  type _ class_tree =
    (* Leaves of the tree *)
    | One : unit class_tree
    (* Skew *)
    | Scalar : K.t -> unit class_tree
    | Z : unit class_tree
    | Empty : 'a class_tree
    (* Arbitrary sampler, size one *)
    | Sampler : 'a Sampler.t -> 'a class_tree
    (* Reference to a class, used for recursion. *)
    | Class : 'a combi_class -> 'a class_tree
    | Union : 'a class_tree list -> 'a class_tree
    (* Product type, builds couples *)
    | Product : 'a class_tree * 'b class_tree -> ('a * 'b) class_tree
    (* Sequence constructor, for lists (not sets) *)
    | Sequence : sequence_kind * 'a class_tree -> 'a list class_tree
    (* Mapping, for types. *)
    | Map : 'a class_tree * ('a -> 'b) -> 'b class_tree

  and 'a solved_tree = T : (K.t * 'a stub) -> 'a solved_tree

  and 'a stub =
    | S_One : unit stub
    | S_Z : unit stub
    | S_Sampler : 'a Sampler.t -> 'a stub
    | S_Empty : 'a stub
    | S_Class : 'a combi_class -> 'a stub
    | S_Union : 'a solved_tree list -> 'a stub
    | S_Product : 'a solved_tree * 'b solved_tree -> ('a * 'b) stub
    | S_Sequence : sequence_kind * 'a solved_tree -> 'a list stub
    | S_Map : 'a solved_tree * ('a -> 'b) -> 'b stub

  (** Reference to a [class_tree] with a name.
    Allows for mutual recursion. *)
  and 'a combi_class = {
    name : Literal.Class.t;
    mutable class_tree : 'a class_tree option;
    mutable solved_tree : 'a solved_tree option;
  }

  let get_name cc = cc.name

  let get_class cc = cc.class_tree

  let get_solved cc = cc.solved_tree

  let new_class name : 'a combi_class =
    {name; class_tree = None; solved_tree = None}

  let new_class_of_str name = new_class (Literal.Class.of_string name)

  let reset_class cc = cc.class_tree <- None

  let update_class cc t = cc.class_tree <- Some t

  let reset_solved cc = cc.solved_tree <- None

  let update_solved cc t = cc.solved_tree <- Some t

  (** [tupn] generates a [t class_tree] where [t] is a tuple of size [n] 
    Useful before a Map to build records. *)
  let tup2 a b = Product (a, b)

  let tup3 a b c = Map (Product (tup2 a b, c), fun ((a, b), c) -> (a, b, c))

  let tup4 a b c d =
    Map (Product (tup3 a b c, d), fun ((a, b, c), d) -> (a, b, c, d))

  let tup5 a b c d e =
    Map (Product (tup4 a b c d, e), fun ((a, b, c, d), e) -> (a, b, c, d, e))

  (* etc... *)

  (** [mul_scalar k t] multiplies the given tree [t] with a weight [k].
   Used to skew the distribution without changing the generated objects.
 *)
  let mul_scalar k t =
    if K.(equal k zero) then Empty else Map (Product (Scalar k, t), snd)

  let ( + ) a b =
    match (a, b) with
    | (Union la, Union lb) -> Union (la @ lb)
    | (Union la, _) -> Union (la @ [b])
    | (_, Union lb) -> Union (a :: lb)
    | _ -> Union [a; b]

  let ( * ) = tup2

  let z a = Map (Z * a, snd)

  let seq a = Sequence (unbounded_seq, a)

  let seq_bounded ~min ?max a = Sequence (bounded_seq min max, a)

  let option a = Map (One, fun _ -> None) + Map (a, fun x -> Some x)

  let stub_node_to_string : type a. a stub -> string = function
    | S_One -> "1"
    | S_Z -> "Z"
    | S_Empty -> "∅"
    | S_Sampler _ -> "Sampler"
    | S_Class c -> "Class " ^ Literal.Class.to_string c.name
    | S_Union _ -> "Union"
    | S_Product (_, _) -> "Product"
    | S_Sequence _ -> "List of"
    | S_Map _ -> "Map"

  let solved_node_to_string : type a. a solved_tree -> string = function
    | T (z, stub) ->
        Format.asprintf "(w:%s) %s" (K.to_string z) (stub_node_to_string stub)

  let rec solved_to_strings : type a. a solved_tree -> string list =
   fun a ->
    let (T (_, stub)) = a in
    match stub with
    | S_One | S_Z | S_Empty | S_Class _ | S_Sampler _ ->
        pp_tree (solved_node_to_string a) []
    | S_Union l ->
        pp_tree (solved_node_to_string a) (List.map solved_to_strings l)
    | S_Product (l, r) ->
        pp_tree
          (solved_node_to_string a)
          [solved_to_strings l; solved_to_strings r]
    | S_Sequence (_skind, s) ->
        pp_tree (solved_node_to_string a) [solved_to_strings s]
    | S_Map (s, _) -> solved_to_strings s

  let pp_solved_tree fmt a = pp_string_list fmt (solved_to_strings a)
end
OCaml

Innovation. Community. Security.