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
|
open Graph
(*
Analysis with ChaoticIteration of the following program :
X:=0;
while X<40 do
X:=X+1
done
The analyses uses the interval abstract domain, with widening, and
the widening delay given as a parameter in the commande line (0 if
no parameter is given).
Executing this program should print:
W = WTO, delay=40:
1 -> [-∞; +∞]
2 -> [0; +∞]
3 -> [0; 39]
4 -> [40; +∞]
W = {3}, delay=39:
1 -> [-∞; +∞]
2 -> [0; +∞]
3 -> [0; +∞]
4 -> [40; +∞]
W = WTO, delay=41:
1 -> [-∞; +∞]
2 -> [0; 40]
3 -> [0; 39]
4 -> [40; 40]
*)
(* Trivial language, only one variable *)
module Operator = struct
type expr =
| Var
| Int of int
| Sum of expr * expr
type test =
| Le
| Ge
type t =
| Affect of expr
| Test of test * int
let compare = compare
let default = Affect Var
end
open Operator
(* Basic interval domain *)
module Interval = struct
type num =
| MinusInfinity
| Int of int
| PlusInfinity
let print_num = function
| MinusInfinity -> print_string "-∞"
| Int n -> print_int n
| PlusInfinity -> print_string "+∞"
let ( <% ) n1 n2 = match n1, n2 with
| MinusInfinity, MinusInfinity
| PlusInfinity, PlusInfinity -> failwith "<%"
| MinusInfinity, _ -> true
| _, PlusInfinity -> true
| Int a, Int b -> a < b
| _, _ -> false
let ( >=% ) n1 n2 =
not (n1 <% n2)
let ( <=% ) n1 n2 =
n1 <% n2 || n1 = n2
let ( >% ) n1 n2 =
n1 >=% n2 && n1 <> n2
let min_ n1 n2 =
if n1 <=% n2 then n1 else n2
let max_ n1 n2 =
if n1 >=% n2 then n1 else n2
type t =
| Bottom
| Bounded of num * num
let top =
Bounded (MinusInfinity, PlusInfinity)
let equal = ( = )
let print = function
| Bottom -> print_string "⊥"
| Bounded (a, b) ->
(* Printf is for the weak *)
print_string "[";
print_num a;
print_string "; ";
print_num b;
print_string "]"
let join i1 i2 = match i1, i2 with
| Bottom, _ -> i2
| _, Bottom -> i1
| Bounded (a, b), Bounded (c, d) -> Bounded (min_ a c, max_ b d)
let singleton n =
Bounded (Int n, Int n)
let ( +% ) x y = match x, y with
| MinusInfinity, PlusInfinity
| PlusInfinity, MinusInfinity -> failwith "+%"
| MinusInfinity, _
| _, MinusInfinity -> MinusInfinity
| PlusInfinity, _
| _, PlusInfinity -> PlusInfinity
| Int a, Int b -> Int (a + b)
let rec abstr_expr interval = function
| Var -> interval
| Int n -> singleton n
| Sum (e1, e2) ->
match abstr_expr interval e1, abstr_expr interval e2 with
| Bottom, _ -> Bottom
| _, Bottom -> Bottom
| Bounded (a, b), Bounded (c, d) -> Bounded (a +% c, b +% d)
let abstr_test interval test c = match interval with
| Bottom -> Bottom
| Bounded (a, b) ->
match test with
| Le -> if a >% c then Bottom else Bounded (a, min_ b c)
| Ge -> if b <% c then Bottom else Bounded (max_ a c, b)
let analyze (_, op, _) interval = match op with
| Affect e -> abstr_expr interval e
| Test (test, n) -> abstr_test interval test (Int n)
let widening i1 i2 = match i1, i2 with
| Bottom, _ -> i2
| Bounded _, Bottom -> failwith "widening"
| Bounded (a, b), Bounded (c, d) ->
Bounded (
(if a <=% c then a else MinusInfinity),
(if b >=% d then b else PlusInfinity)
)
end
module Int = struct
type t = int
let compare = compare
let hash = Hashtbl.hash
let equal = ( = )
end
module Data = struct
include Interval
type edge = int * Operator.t * int
end
module G = Persistent.Digraph.ConcreteLabeled (Int) (Operator)
module Wto = WeakTopological.Make (G)
module Chaotic = ChaoticIteration.Make (G) (Data)
let edges = [
1, 2, Affect (Int 0);
2, 3, Test (Le, 39);
3, 2, Affect (Sum (Var, Int 1));
2, 4, Test (Ge, 40);
]
let g =
List.fold_left
(fun acc (v, w, op) -> G.add_edge_e acc (G.E.create v op w))
G.empty edges
let strategy = Wto.recursive_scc g 1
let print_vertex_data vertex interval =
print_int vertex;
print_string " -> ";
Interval.print interval;
print_newline ()
let init v =
if v = 1 then Interval.top else Interval.Bottom
let widening_delay1 = 40
let widening_set1 = ChaoticIteration.FromWto
let widening_delay2 = 39
let widening_set2 = ChaoticIteration.Predicate (( = ) 3)
let widening_delay3 = 41
let widening_set3 = ChaoticIteration.FromWto
let result1 = Chaotic.recurse g strategy init widening_set1 widening_delay1
let result2 = Chaotic.recurse g strategy init widening_set2 widening_delay2
let result3 = Chaotic.recurse g strategy init widening_set3 widening_delay3
let () =
print_endline "W = WTO, delay=40:";
Chaotic.M.iter print_vertex_data result1;
print_newline ();
print_endline "W = {3}, delay=39:";
Chaotic.M.iter print_vertex_data result2;
print_newline ();
print_endline "W = WTO, delay=41:";
Chaotic.M.iter print_vertex_data result3;
print_newline ();
|