1
|
(* Rebuilding Cex *)
|
2
|
(* In order to properly rebuild the Cex, one needsthe unsliced model. Otherwise
|
3
|
some input or state variables are removed.
|
4
|
|
5
|
*)
|
6
|
|
7
|
|
8
|
open Lustre_types
|
9
|
open Machine_code_types
|
10
|
(* open Machine_code_common *)
|
11
|
open Zustre_common
|
12
|
|
13
|
open Zustre_data
|
14
|
|
15
|
let get_conjuncts e =
|
16
|
assert (Z3.Boolean.is_bool e);
|
17
|
if Z3.Boolean.is_and e then
|
18
|
Z3.Expr.get_args e
|
19
|
else
|
20
|
[e]
|
21
|
|
22
|
let build_cex machine machines decl_err =
|
23
|
(* Recovering associated top machine (to build full traces) and property *)
|
24
|
(* TODO: for example extract top node and ok prop. We may have multiple
|
25
|
MAIN/ERR loaded at the same time. Each of them should be assocaited with a
|
26
|
CEX/Inv/Timeout.*)
|
27
|
|
28
|
let node_id = machine.mname.node_id in
|
29
|
|
30
|
let cex = match Z3.Fixedpoint.get_answer !fp with Some e -> e | None -> raise Not_found in
|
31
|
(* Original code used the function Z3.Fixedpoint.get_ground_sat_answer !fp *)
|
32
|
|
33
|
let stats = Z3.Fixedpoint.get_statistics !fp in
|
34
|
|
35
|
let conjuncts = List.rev (get_conjuncts cex) in
|
36
|
|
37
|
Format.eprintf "cex: %s@.%i conjuncts: @[<v 0>%a@]@."
|
38
|
(Z3.Expr.to_string cex)
|
39
|
(List.length conjuncts)
|
40
|
(Utils.fprintf_list ~sep:"@ " (fun fmt e -> Format.fprintf fmt "%s" (Z3.Expr.to_string e))) conjuncts;
|
41
|
|
42
|
(* Checking size *)
|
43
|
let inputs = machine.mstep.step_inputs in
|
44
|
let nb_inputs = List.length inputs in
|
45
|
let outputs = machine.mstep.step_outputs in
|
46
|
let nb_outputs = List.length inputs in
|
47
|
let nb_mems = List.length (full_memory_vars machines machine) in
|
48
|
|
49
|
let main, funs =
|
50
|
List.fold_left (fun (main, funs) conj ->
|
51
|
(* Filtering out non MAIN decls *)
|
52
|
let func_decl = Z3.Expr.get_func_decl conj in
|
53
|
let node_name = Z3.Symbol.get_string (Z3.FuncDecl.get_name func_decl) in
|
54
|
(* Focusing only on MAIN_nodeid predicates *)
|
55
|
if node_name = "MAIN_" ^ node_id then
|
56
|
(* Extracting info *)
|
57
|
(* Recall that MAIN args are in@mems@out *)
|
58
|
let args = Z3.Expr.get_args conj in
|
59
|
if List.length args = 1 + nb_inputs + nb_mems + nb_outputs then
|
60
|
(* Should be done with get_int but that function vanished from the opam Z3 API *)
|
61
|
let id = Big_int.int_of_big_int (Z3.Arithmetic.Integer.get_big_int (List.hd args)) in
|
62
|
let input_values = Utils.List.extract args 1 (1 + nb_inputs) in
|
63
|
let output_values = Utils.List.extract args (1+nb_inputs+nb_mems) (1 + nb_inputs + nb_mems + nb_outputs) in
|
64
|
(id, (input_values, output_values))::main, funs
|
65
|
else
|
66
|
assert false
|
67
|
else
|
68
|
let reg = Str.regexp_string "[a-z]*_step" in
|
69
|
if Str.string_match reg node_name 0 then (
|
70
|
let actual_name = Str.matched_group 0 node_name in
|
71
|
Format.eprintf "Name %s@." actual_name;
|
72
|
main, funs
|
73
|
)
|
74
|
else (
|
75
|
Format.eprintf "pas matché %s@." node_name;
|
76
|
main, funs
|
77
|
)
|
78
|
) ((* main*) [],(* other functions *) []) conjuncts
|
79
|
in
|
80
|
let main = List.sort (fun (id1, _) (id2, _) -> compare id1 id2) main in
|
81
|
List.iter (
|
82
|
fun (id, expr) ->
|
83
|
Format.eprintf "Id %i: %a@."
|
84
|
(id)
|
85
|
(Utils.fprintf_list ~sep:", "
|
86
|
(fun fmt e -> Format.fprintf fmt "%s" (Z3.Expr.to_string e)))
|
87
|
(fst expr)
|
88
|
) main;
|
89
|
(* let ground_val = List.map (fun e -> Z3.Expr.to_string e) (Z3.Expr.get_args conj) in *)
|
90
|
|
91
|
(* We recover the Zustre XML format, projecting each cex on each input/output
|
92
|
signal *)
|
93
|
let in_signals, out_signals =
|
94
|
List.fold_right (
|
95
|
fun (id, (sigs_in, sigs_out)) (res_sigs_in, res_sigs_out) ->
|
96
|
let add l1 l2 = List.map2 (fun e1 e2 -> fst e2, ((id, e1)::(snd e2))) l1 l2 in
|
97
|
let sigs_in_id = add sigs_in res_sigs_in in
|
98
|
let sigs_out_id = add sigs_out res_sigs_out in
|
99
|
sigs_in_id, sigs_out_id
|
100
|
) main (List.map (fun v -> v, []) inputs, List.map (fun v -> v, []) outputs)
|
101
|
in
|
102
|
|
103
|
(* let _ = List.mapi (fun k conj -> *)
|
104
|
(* (\* k-iterate *\) *)
|
105
|
(* let ground_val = List.map (fun e -> Z3.Expr.to_string e) (Z3.Expr.get_args conj) in *)
|
106
|
(* let func_decl = Z3.Expr.get_func_decl conj in *)
|
107
|
(* if !debug then Format.eprintf "FuncDecl %s@." (Z3.FuncDecl.to_string func_decl); *)
|
108
|
(* let node_name = Z3.Symbol.get_string (Z3.FuncDecl.get_name func_decl) in *)
|
109
|
|
110
|
|
111
|
(* if !debug then Format.eprintf "Node %s, args %a@." node_name (Utils.fprintf_list ~sep:", " (Format.pp_print_string)) ground_val; *)
|
112
|
|
113
|
(* () *)
|
114
|
(* (\* ground_pair = [] *)
|
115
|
(* try: *)
|
116
|
(* ground_vars = pred_dict[node_name] *)
|
117
|
(* ground_pair = zip(ground_vars,ground_val) *)
|
118
|
(* if "_reset" in node_name: *)
|
119
|
(* # this condition is to remove the node nodename_reset added by lustrec *)
|
120
|
(* continue *)
|
121
|
(* # node = node_name.split("_reset")[0] *)
|
122
|
(* # cex_dict.update({node:{k:ground_pair}}) *)
|
123
|
(* elif "_step" in node_name: *)
|
124
|
(* node = node_name.split("_step")[0] *)
|
125
|
(* try: *)
|
126
|
(* # case in which we already have the node in dict *)
|
127
|
(* d = cex_dict[node] *)
|
128
|
(* max_key = max(k for k, v in d.iteritems() if v != 0) #get the maximum key value and add 1 *)
|
129
|
(* d.update({(max_key+1):ground_pair}) *)
|
130
|
(* except Exception as e: *)
|
131
|
(* self._log.warning("Adding a new node cex " + str(e)) *)
|
132
|
(* cex_dict.update({node:{k:ground_pair}}) *)
|
133
|
(* else: *)
|
134
|
(* node = node_name *)
|
135
|
(* try: *)
|
136
|
(* d = cex_dict[node] *)
|
137
|
(* max_key = max(k for k, v in d.iteritems() if v != 0) #get the maximum key value and add 1 *)
|
138
|
(* d.update({(max_key+1):ground_pair}) *)
|
139
|
(* except Exception as e: *)
|
140
|
(* if node not in ["MAIN", "ERR"]: *)
|
141
|
(* self._log.warning("Adding a new node cex " + str(e)) *)
|
142
|
(* cex_dict.update({node:{k:ground_pair}}) *)
|
143
|
(* except Exception as e: *)
|
144
|
(* self._log.warning("Problem with getting a node name: " + str(e)) *)
|
145
|
(* *\) *)
|
146
|
(* ) conjuncts in *)
|
147
|
(* let rules_expr = Z3.Fixedpoint.get_rules !fp in *)
|
148
|
(* if !debug then *)
|
149
|
(* Format.eprintf "@[<v 2>Registered rules:@ %a@ @]@." *)
|
150
|
(* (Utils.fprintf_list ~sep:"@ " *)
|
151
|
(* (fun fmt e -> Format.pp_print_string fmt (Z3.Expr.to_string e)) ) *)
|
152
|
(* rules_expr; *)
|
153
|
(* if !debug then *)
|
154
|
(* Format.eprintf "FP help: %s@." (Z3.Fixedpoint.get_help !fp); *)
|
155
|
|
156
|
let stats_entries = Z3.Statistics.get_entries stats in
|
157
|
(* List.iter (fun e -> Format.eprintf "%s@.@?" *)
|
158
|
(* (Z3.Statistics.Entry.to_string e) *)
|
159
|
|
160
|
(* ) stats_entries; *)
|
161
|
let json : Yojson.json =
|
162
|
`Assoc [
|
163
|
"Results",
|
164
|
`Assoc [
|
165
|
"Property",
|
166
|
`Assoc [
|
167
|
"name", `String node_id;
|
168
|
"date", `String (Utils.get_date ());
|
169
|
"query", `Assoc ["unit", `String "sec";
|
170
|
"value", `Float (
|
171
|
let time_opt = Z3.Statistics.get stats "time.spacer.solve" in
|
172
|
match time_opt with None -> -1.
|
173
|
| Some f -> Z3.Statistics.Entry.get_float f)
|
174
|
];
|
175
|
"answer", `String "CEX";
|
176
|
"counterexample",
|
177
|
`Assoc [
|
178
|
node_id, `Assoc
|
179
|
(
|
180
|
List.map (fun (vardecl, values) ->
|
181
|
vardecl.var_id,
|
182
|
`Assoc [
|
183
|
"type", (let _ = Format.fprintf Format.str_formatter "%a" Printers.pp_var_type vardecl in
|
184
|
let s = Format.flush_str_formatter () in
|
185
|
`String s);
|
186
|
"values", `Assoc (List.map (fun (id, v) ->
|
187
|
string_of_int id, `String (Z3.Expr.to_string v))
|
188
|
values)
|
189
|
]
|
190
|
) in_signals
|
191
|
)
|
192
|
]
|
193
|
]
|
194
|
]
|
195
|
]
|
196
|
in
|
197
|
Format.eprintf "JSON: %s@."
|
198
|
(Yojson.to_string json);
|
199
|
()
|
200
|
(* Results *)
|
201
|
(* Property *)
|
202
|
(* Date *)
|
203
|
(* Query time *)
|
204
|
(* Answer CEX *)
|
205
|
(* Counterexample *)
|
206
|
(* Node name="nodeid" *)
|
207
|
(* Stream name="opt.x" type="unk" *)
|
208
|
(* Value instant="0">xxx</Value> *)
|
209
|
(* () *)
|
210
|
(* ordered_by_signal = self.reorder(cex_dict) *)
|
211
|
(* return self.mk_cex_xml(ordered_by_signal) *)
|
212
|
|
213
|
(* Local Variables: *)
|
214
|
(* compile-command:"make -C ../.. lustrev" *)
|
215
|
(* End: *)
|
216
|
|
217
|
|