package apronext

  1. Overview
  2. Docs

Source file domain.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
(*****************************************************************************)
(** This file is an extension for the Abstract1 module from the apron Library.
    It is not meant to be used as it is but through the instanciated modules
    Abox, Apol and Aoct *)
(*****************************************************************************)

open Apron

(** Abstract domain signature used by the following functor *)
module type ADomain = sig
  (** Abstract element type *)
  type t

  (** Apron manager *)
  val man: t Manager.t
end

(** functor that allows hiding the use of the manager, It also adds
   few utilities to the Abstract1 module *)
module Make(D:ADomain) = struct
  (** This functor implements all the constraint/generator based
     operations over abstract elements. These are generic and stand
     for Boxes, Octagons and Polyhedra.  *)

  (** Conventions :
  - functions ending with _s allow to use/return string instead of variables
  - functions ending with _f allow to use/return float instead of apron scalar
  - functions ending with _fs mix the two
   *)

  module A = Abstract1
  module G = Generatorext
  module T = Tconsext
  module L = Linconsext
  module E = Environmentext

  open A
  type t = D.t A.t

  let man = D.man

  (** Set-theoritic operations *)

  let bottom = bottom man

  let top = top man

  let join = join man

  let meet = meet man

  let widening = widening man

  (** predicates *)

  let is_bottom = is_bottom man

  let is_top = is_top man

  let is_leq = is_leq man

  let is_eq = is_eq man

  (** constraint satisfaction and filter *)

  let sat_lincons = sat_lincons man

  let sat_tcons = sat_tcons man

  let filter_lincons abs l =
    let ear = L.array_make abs.env 1 in
    L.array_set ear 0 l;
    meet_lincons_array man abs ear

  let filter_tcons abs l =
    let ear = T.array_make abs.env 1 in
    T.array_set ear 0 l;
    meet_tcons_array man abs ear

  (** of and to constraints/generator *)

  let to_lincons_array = to_lincons_array man

  let to_tcons_array = to_tcons_array man

  let to_generator_array = to_generator_array man

  let to_lincons_list e = to_lincons_array e |> L.array_to_list

  let to_tcons_list e = to_tcons_array e |> T.array_to_list

  let to_generator_list e = to_generator_array e |> G.array_to_list

  let of_generator_list (e : E.t) (g : Generator1.t list) =
    let open Generator1 in
    let _,lray = List.partition (fun g -> get_typ g = VERTEX) g in
    let ofvertice v =
      E.fold (fun acc var ->
          let c = Texprext.cst e (get_coeff v var) in
          assign_texpr man acc var c None
        ) (top e) e
    in
    let closed = join_array man (Array.of_list (List.map ofvertice g)) in
    Generatorext.array_of_list lray |> add_ray_array man closed

  let of_generator_array (e : E.t) g =
    of_generator_list e (G.array_to_list g)

  let of_lincons_array = of_lincons_array man

  let of_tcons_array = of_tcons_array man

  let of_lincons_list env l = of_lincons_array env (L.array_of_list l)

  let of_tcons_list env l = of_tcons_array env (T.array_of_list l)

  let of_box = of_box man

  (** Environment and variable related operations *)

  let get_environment a = env a

  let change_environment a e = change_environment man a e false

  (*FIXME : What is the purpose of None?*)
  let assign_texpr abs var texpr = assign_texpr man abs var texpr None

  (*FIXME : What is the purpose of None?*)
  let assign_linexpr abs var linexpr = assign_linexpr man abs var linexpr None

  let assign_f abs var f =
    let texpr = Texprext.cst_f f |> Texprext.of_expr abs.env in
    assign_texpr abs var texpr

  let assign_fs abs var f = assign_f abs (Var.of_string var) f

  (* utilities*)
  let add_var abs typ v =
    let e = env abs in
    let ints,reals =
      if typ = Environment.INT then [|v|],[||]
      else [||],[|v|]
    in
    let env = Environment.add e ints reals in
    A.change_environment man abs env false

  let add_var_s abs typ v = add_var abs typ (Var.of_string v)

  let bound_variable abs v = bound_variable man abs v

  let bound_variable_f abs v =
    let open Intervalext in
    bound_variable abs v |> to_float

  let bound_variable_s abs v = bound_variable abs (Var.of_string v)

  let bound_variable_fs abs v = bound_variable_f abs (Var.of_string v)

  let is_bounded_variable abs v = Intervalext.is_bounded (bound_variable abs v)

  let is_bounded_s abs v = is_bounded_variable abs (Var.of_string v)

  let is_bounded abs =
    let env = env abs in
    try
      E.iter (fun v -> if is_bounded_variable abs v |> not then raise Exit) env;
      true
    with Exit -> false

  (** Cross-domain conversion *)
  let to_box abs =
    let env = env abs in
    let abs' = A.change_environment man abs env false in
    to_tcons_array abs' |> A.of_tcons_array (Box.manager_alloc ()) env

  let to_oct abs =
    let env = env abs in
    to_lincons_array abs |> A.of_lincons_array (Oct.manager_alloc ()) env

  let to_poly abs =
    let env = env abs in
    let abs' = A.change_environment man abs env false in
    to_tcons_array abs' |> A.of_tcons_array (Polka.manager_alloc_strict ()) env

  (** Printing *)
  let print fmt a =
    (* print fmt a *)
    let constraints = to_lincons_list a in
    Format.fprintf fmt "{%a}"
      (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ";")
         Linconsext.print) constraints

  (** Projection on 2 dimensions *)
  let proj2D abs v1 v2 =
    let env = env abs in
    let new_env = Environmentext.empty in
    let new_env =
      if Array.exists ((=) v1) (Environmentext.get_ints env) then
        Environmentext.add_int v1 new_env
      else Environmentext.add_real v1 new_env
    in
    let new_env =
      if Array.exists ((=) v2) (Environmentext.get_ints env) then
        Environmentext.add_int v2 new_env
      else Environmentext.add_real v2 new_env
    in
    change_environment abs new_env

  (** Projection on 3 dimensions *)
  let proj3D abs v1 v2 v3 =
    let env = env abs in
    let new_env = Environmentext.empty in
    let new_env =
      if Array.exists ((=) v1) (Environmentext.get_ints env) then
        Environmentext.add_int v1 new_env
      else Environmentext.add_real v1 new_env
    in
    let new_env =
      if Array.exists ((=) v2) (Environmentext.get_ints env) then
        Environmentext.add_int v2 new_env
      else Environmentext.add_real v2 new_env
    in
    let new_env =
      if Array.exists ((=) v3) (Environmentext.get_ints env) then
        Environmentext.add_int v3 new_env
      else Environmentext.add_real v3 new_env
    in change_environment abs new_env

  (** Projection on 2 dimensions with string as variables *)
  let proj2D_s abs v1 v2 =
    proj2D abs (Apron.Var.of_string v1) (Apron.Var.of_string v2)

  (** Projection on 3 dimensions with string as variables *)
  let proj3D_s abs v1 v2 v3 =
    proj3D abs (Apron.Var.of_string v1) (Apron.Var.of_string v2) (Apron.Var.of_string v3)

  (** returns the vertices of an abstract element projected on 2 dimensions *)
  let to_vertices2D abs v1 v2 =
    let gen' = to_generator_array abs in
    let get_coord l = Apron.Linexpr1.(get_coeff l v1, get_coeff l v2) in
    Array.init
      (Generatorext.array_length gen')
	    (fun i -> get_coord
	                (Generatorext.(get_linexpr1 (array_get gen' i))))

    |> Array.to_list
    |> List.rev_map (fun(a,b)-> (Coeffext.to_float a, Coeffext.to_float b))

  (** returns the vertices of an abstract element projected on 2 dimensions *)
  let to_vertices2D_s abs v1 v2 =
    to_vertices2D abs (Apron.Var.of_string v1) (Apron.Var.of_string v2)

end
OCaml

Innovation. Community. Security.