1 | % (c) 2014-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
2 | % Heinrich Heine Universitaet Duesseldorf | |
3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
4 | ||
5 | :- module(disprover_test_runner, [test_repl/0, run_disprover_on_all_pos/1, load_po_file/1, | |
6 | set_disprover_timeout/1, reset_disprover_timeout/0, | |
7 | set_disprover_options/1, | |
8 | print_disprover_stats/0]). | |
9 | ||
10 | :- use_module(prob_startup, [startup_prob/0]). | |
11 | %:- use_module(pathes,[set_search_pathes/0]). % imported first to set_compile_time_search_pathes, now loaded by prob_startup | |
12 | ||
13 | portray_message(informational, _). | |
14 | ||
15 | :- use_module(module_information). | |
16 | :- module_info(group,cbc). | |
17 | :- module_info(description,'Rodin Prover / Disprover'). | |
18 | ||
19 | ||
20 | :- use_module(eclipse_interface). | |
21 | :- use_module(prob2_interface). | |
22 | :- use_module(disprover). | |
23 | :- use_module(error_manager). | |
24 | :- use_module(tools). | |
25 | :- use_module(solver_interface). | |
26 | :- use_module(debug). | |
27 | :- use_module(preferences). | |
28 | ||
29 | :- use_module(library(system)). | |
30 | :- use_module(library(lists)). | |
31 | ||
32 | ||
33 | ||
34 | %:- use_module(eventhandling, [announce_event/1]). | |
35 | ||
36 | test_repl :- | |
37 | startup_prob, | |
38 | init_eclipse_preferences, | |
39 | disprover_load_at_repl_startup, | |
40 | disprover_help, | |
41 | disprover_repl_loop. | |
42 | ||
43 | ||
44 | disprover_repl_loop :- print('DISPROVER ==> '),safe_read(T), | |
45 | (quit_command(T) -> get_total_number_of_errors(X), format('~nTotal number of errors: ~w~n~n',[X]) | |
46 | ; test_eval(T) -> disprover_repl_loop | |
47 | ; print('Command failed !!'),nl, disprover_repl_loop). | |
48 | ||
49 | safe_read(T) :- on_exception(E,read(T), | |
50 | ( format('Exception while reading user input: ~w ~n',[E]), T=help)). | |
51 | ||
52 | disprover_help :- | |
53 | print('Available commands: run, run(PO), timeout(T), stats, list, q, x, FILE, v, vv, write(S,FILE), '),nl, | |
54 | print(' trace_info, observe, debug, kodkod,core, cse, chr_off,smt_off, ...'),nl. | |
55 | ||
56 | :- meta_predicate wall(0). | |
57 | wall(Call) :- | |
58 | statistics(walltime,[Start,_]), | |
59 | call(Call), | |
60 | statistics(walltime,[Stop,_]), WT is Stop-Start, | |
61 | format('Walltime: ~w ms~n',[WT]). | |
62 | ||
63 | quit_command(q). | |
64 | quit_command(quit). | |
65 | quit_command(halt). | |
66 | ||
67 | test_eval(run) :- !,wall(run). | |
68 | test_eval(run(PO)) :- !,disprover_timeout(TO), wall(run_on_po(PO,TO)). | |
69 | test_eval(timeout(T)) :- !, set_disprover_timeout(T). | |
70 | test_eval(time_out(T)) :- !, set_disprover_timeout(T). | |
71 | test_eval(stats) :- !,print_disprover_stats. | |
72 | test_eval(x) :- !,halt. | |
73 | test_eval(list) :- !,list(_). | |
74 | test_eval(lup) :- !,list(unknown). | |
75 | test_eval(lf) :- !,list(false). | |
76 | test_eval(help) :- !,disprover_help. | |
77 | test_eval(h) :- !,disprover_help. | |
78 | test_eval(v) :- !,tcltk_turn_debugging_on(19). | |
79 | test_eval(vv) :- !,tcltk_turn_debugging_on(4). | |
80 | test_eval(load(FILE)) :- !,load_po_file(FILE). | |
81 | test_eval(wp) :- !, write_pos(true,_). | |
82 | test_eval(write(Status)) :- !, write_pos(Status,_). | |
83 | test_eval(wc) :- !, write_pos(true,contradiction_in_hypotheses). | |
84 | test_eval(wp(FILE)) :- !, tell(FILE), write_pos(true,_), told. | |
85 | test_eval(write(Status,FILE)) :- !, tell(FILE), write_pos(Status,_), told. | |
86 | test_eval(cse) :- !,enable_cse. | |
87 | test_eval(chr_off) :- !,disable_chr. | |
88 | test_eval(smt_off) :- !,disable_smt. | |
89 | test_eval(core) :- !,add_opts([disprover_option(unsat_core),unsat_core_algorithm/linear]). | |
90 | test_eval(corem) :- !,add_opts([disprover_option(unsat_core),disprover_option(unsat_core_as_machine),unsat_core_algorithm/linear]). | |
91 | test_eval(coredc) :- !,add_opts([disprover_option(unsat_core)]). | |
92 | test_eval(observe) :- !,add_opts([disprover_option(observe_state)]). | |
93 | test_eval(pob) :- !,add_opts([disprover_option(show_po_as_machine)]). | |
94 | test_eval(kodkod) :- !,enable_kodkod. | |
95 | test_eval(abort) :- !, print('TRY FIND ABORT true'),nl,set_preference(find_abort_values,true). | |
96 | test_eval(abortfull) :- !, print('TRY FIND ABORT full'),nl,set_preference(find_abort_values,full). | |
97 | test_eval(nocounter) :- print('ENUMERATE_INFINITE_TYPES=FALSE'),nl,!, set_preference(allow_enumeration_of_infinite_types,false). | |
98 | test_eval(trace_info) :- !, print('TRACE_INFO true'),nl,set_preference(provide_trace_information,true). | |
99 | test_eval(trace) :- !, print('Tracing upon error'),nl,set_preference(trace_upon_error,true). | |
100 | test_eval(debug) :- !, | |
101 | on_exception(error(existence_error(_,_),_),debug, print('CAN ONLY BE USED WHEN RUNNING PROB FROM SOURCE')). | |
102 | test_eval(eval(Atom)) :- !, | |
103 | eval_strings:eval_string(Atom,Result), | |
104 | format('Evaluation result: ~w~n',[Result]). | |
105 | test_eval(dir) :- | |
106 | loaded_po_file(File),!, | |
107 | directory_listing_for_file(File). | |
108 | test_eval(PO) :- disprover_po(PO,_,_,_,_,_),!, | |
109 | test_eval(run(PO)). | |
110 | test_eval(Filename) :- format('Trying to consult file: ~w~n',[Filename]), | |
111 | load_po_file(Filename), print_disprover_stats,!. | |
112 | test_eval(Cmd) :- format('Could not executed command: ~w~n',[Cmd]). | |
113 | ||
114 | ||
115 | :- use_module(library(file_systems)). | |
116 | % list the directory in which a file is in and allow use to load a po file in that directory | |
117 | directory_listing_for_file(File) :- | |
118 | get_parent_directory(File,Dir), | |
119 | findall(FF,(file_member_of_directory(Dir,F,FF),get_filename_extension(F,'pl')),List), | |
120 | sort(List,SList), | |
121 | prdir(SList), | |
122 | write('==Nr==>'), read(Nr), | |
123 | ((number(Nr),nth1(Nr,SList,NewFile)) -> load_po_file(NewFile) ; print('No file loaded'),nl). | |
124 | prdir(List) :- nth1(N,List,File), format(' ~w -> ~w~n',[N,File]), fail. | |
125 | prdir(_). | |
126 | ||
127 | print_disprover_stats :- | |
128 | disprover_timeout(TO), | |
129 | project_name(N), format('Project ~w~n',[N]), | |
130 | generated(_,D), | |
131 | machine_name(M), format('Machine ~w (exported ~w)~n',[M,D]), | |
132 | print_nr_pos('',_,_), | |
133 | print_nr_pos('proven (within Rodin)',true,_), | |
134 | format('ProB Disprover Analysis with timeout ~w ms~n',[TO]), | |
135 | print_nr_pos('proven (by ProB)',_,true), | |
136 | (disprover_result(_,_,contradiction_in_hypotheses) | |
137 | -> print_nr_pos('those with contradiction in hypotheses',_,true,contradiction_in_hypotheses) ; true), | |
138 | print_nr_pos('disproven (by ProB)',_,false), | |
139 | print_nr_pos('unproven (by ProB)',_,unknown), | |
140 | (raw_result_exists(failure) -> print_nr_pos('failure (of ProB)',_,failure) ; true). | |
141 | ||
142 | raw_result_exists(RawResult) :- disprover_po_with_info(_,_,_,RawResult). | |
143 | print_nr_pos(Msg,RodinStatus,ProBStatus) :- print_nr_pos(Msg,RodinStatus,ProBStatus,_). | |
144 | print_nr_pos(Msg,RodinStatus,ProBStatus,RawResult) :- | |
145 | findall(Name,disprover_po_with_info(Name,RodinStatus,ProBStatus,RawResult),L), | |
146 | length(L,Len), | |
147 | (Len<12 | |
148 | -> format('Number of ~w POs: ~w (~w)~n',[Msg,Len,L]) | |
149 | ; (L = [First|_],last(L,Last)) | |
150 | -> format('Number of ~w POs: ~w (~w -- ~w)~n',[Msg,Len,First,Last]) | |
151 | ; format('Number of ~w POs: ~w~n',[Msg,Len]) | |
152 | ). | |
153 | ||
154 | disprover_po_with_info(Name,RodinStatus,ProBStatus,RawResult) :- | |
155 | disprover_po(Name,_Context,_Goal,_All,_Sel,RodinStatus), | |
156 | (disprover_result(Name,ProBStatus,RawResult) -> true ; ProBStatus='not_run', RawResult='not_run'). | |
157 | ||
158 | :- dynamic disprover_timeout/1. | |
159 | disprover_timeout(300). | |
160 | set_disprover_timeout(N) :- retractall(disprover_timeout(_)), assert(disprover_timeout(N)). | |
161 | reset_disprover_timeout :- retractall(disprover_timeout(_)), assert(disprover_timeout(300)). | |
162 | ||
163 | run :- run_disprover_on_all_pos(_). | |
164 | ||
165 | :- use_module(tools_lists,[count_occurences/2]). | |
166 | ||
167 | run_disprover_on_all_pos(_) :- retractall(disprover_result(_,_,_)), disprover_timeout(TO),run_on_po(_,TO), fail. | |
168 | run_disprover_on_all_pos(Summary) :- findall(R,disprover_result(_,R,_),L), | |
169 | count_occurences(L,Occs), | |
170 | format('~nDisprover Run Summary: ~w~n',[Occs]), | |
171 | add_info(true,Occs,O1), add_info(false,O1,O2), add_info(unknown,O2,O3), | |
172 | add_info(failure,O3,Summary). | |
173 | ||
174 | add_info(Info,List,Result) :- member(Info-_,List) -> List=Result ; Result = [Info-0|List]. | |
175 | ||
176 | ||
177 | run_on_po(PO_Name,TimeOut) :- | |
178 | disprover_po(PO_Name,Context,Goal,AllHypotheses,SelectedHypotheses,Status), | |
179 | formatsilent('Testing ~w (~w)~n',[PO_Name,Status]), | |
180 | load_event_b_project([],[Context],[],_), | |
181 | start_animation, | |
182 | debug_println(5,loaded_context), | |
183 | (my_disprove(Goal,AllHypotheses,SelectedHypotheses,TimeOut,OutResult) | |
184 | -> translate_result_for_po(OutResult,ProverResult), | |
185 | formatsilent('Disprover Result ~w (PO is ~w)~n',[OutResult,ProverResult]), | |
186 | functor(OutResult,RawOutFunctor,_), | |
187 | assert(disprover_result(PO_Name,ProverResult,RawOutFunctor)), | |
188 | check_soundness(ProverResult,Status,PO_Name) | |
189 | ; add_error(disprover,'Disprover failed: ',(PO_Name:Status)), | |
190 | assert(disprover_result(PO_Name,'failure',unknown)) | |
191 | ). | |
192 | run_on_po(PO_Name,_TimeOut) :- nonvar(PO_Name), | |
193 | \+ disprover_po(PO_Name,_,_,_,_,_), | |
194 | format('PO ~w does not exist !~n',[PO_Name]), | |
195 | findall(PO,disprover_po(PO,_,_,_,_,_),L), | |
196 | format('Available POs: ~w~n',[L]), | |
197 | fail. | |
198 | ||
199 | translate_result_for_po(solution(_),R) :- !, R=false. | |
200 | translate_result_for_po(contradiction_found,R) :- !,R=true. | |
201 | translate_result_for_po(contradiction_in_hypotheses,R) :- !,R=true. | |
202 | translate_result_for_po(_,unknown). | |
203 | ||
204 | check_soundness(unknown,_,_) :- !. | |
205 | check_soundness(Status,unknown,PO_Name) :- !, | |
206 | format('ProB Disprover result ~w improves upon unknown Rodin prover status for ~w!~n',[Status,PO_Name]). | |
207 | check_soundness(X,X,_) :- !. | |
208 | check_soundness(Disprover,Prover,PO_Name) :- | |
209 | add_error(disprover_unsound,'Disprover result incompatible with Rodin proof status:',Disprover:Prover:PO_Name). | |
210 | ||
211 | ||
212 | :- dynamic extra_opts/1. | |
213 | extra_opts([]). | |
214 | add_opts(Extra) :- | |
215 | retract(extra_opts(Old)), | |
216 | append(Extra,Old,New), sort(New,SNew), | |
217 | assert(extra_opts(SNew)). | |
218 | enable_cse :- XO = [use_common_subexpression_elimination/true, | |
219 | use_common_subexpression_also_for_predicates/true], | |
220 | add_opts(XO). | |
221 | enable_kodkod :- XO = [try_kodkod_on_load/true, kodkod_for_components/true], add_opts(XO). | |
222 | disable_chr :- add_opts([use_chr_solver/false]). | |
223 | disable_smt :- add_opts([use_smt_mode/false]). | |
224 | set_disprover_options(L) :- | |
225 | retractall(extra_opts(_)), | |
226 | assert(extra_opts(L)). | |
227 | ||
228 | my_disprove(Goal,AllHypotheses,SelectedHypotheses,Timeout,OutResult) :- | |
229 | Opts = [use_smt_mode/true,use_clpfd_solver/true,use_chr_solver/true], | |
230 | % interesting extra opts : disprover_option(unsat_core),unsat_core_algorithm/linear | |
231 | extra_opts(X), merge_opts(X,Opts,AllOpts), | |
232 | % Note: disprover_mode is always set to true | |
233 | disprove_with_opts(Goal,AllHypotheses,SelectedHypotheses,Timeout,AllOpts,OutResult). | |
234 | ||
235 | merge_opts([],Opts,Opts). | |
236 | merge_opts([Opt/Val|T],Other,[Opt/Val|ResT]) :- | |
237 | delete(Other,Opt/_,Other2), | |
238 | merge_opts(T,Other2,ResT). | |
239 | ||
240 | :- use_module(translate). | |
241 | ||
242 | list(DPRes) :- disprover_po(Name,Context,Goal,_All,_Sel,Status), | |
243 | get_disprover_result(Name,DPRes,RawResult), | |
244 | format('~w (~w : ~w [~w]) : ',[Name,Status,DPRes,RawResult]), | |
245 | load_event_b_project([],[Context],[],_), | |
246 | start_animation, | |
247 | type_check_in_machine_context([Goal],[TypedGoal]), | |
248 | translate:print_bexpr(TypedGoal),nl,fail. | |
249 | list(_). | |
250 | ||
251 | :- dynamic project_name/1. | |
252 | :- dynamic machine_name/1. | |
253 | :- dynamic generated/2. | |
254 | :- dynamic disprover_po/6. | |
255 | :- dynamic disprover_result/3. | |
256 | project_name(unknown). | |
257 | machine_name(unknown). | |
258 | generated(unknown,unknown). | |
259 | disprover_po(unknown,unknown,unknown,unknown,unknown,unknown). | |
260 | disprover_result(unknown,unknown,unknown). | |
261 | ||
262 | reset_po_facts :- retractall(loaded_po_file(_)), | |
263 | retractall(project_name(_)), | |
264 | retractall(machine_name(_)), retractall(generated(_,_)), | |
265 | retractall(disprover_po(_,_,_,_,_,_)), retractall(disprover_result(_,_,_)). | |
266 | ||
267 | % write POs which have a certain status; can be used to generate .pl files with only proven or not-proven POs | |
268 | write_pos(Status,RawResult) :- | |
269 | format('% Proof Obligations with status = ~w~n',[Status]), | |
270 | write_facts(project_name(_)), write_facts(machine_name(_)), | |
271 | write_facts(generated(_,_)), | |
272 | disprover_result(Name,Status,RawResult), | |
273 | write_facts(disprover_po(Name,_Context,_Goal,_All,_Sel,_RodinStatus)), | |
274 | fail. | |
275 | write_pos(_,_) :- nl. | |
276 | ||
277 | write_facts(Fact) :- Fact, | |
278 | write_term(Fact,[quoted(true),numbervars(true)]), write('.'),nl,fail. | |
279 | write_facts(_). | |
280 | ||
281 | get_disprover_result(PO_Name,Result,RawResult) :- | |
282 | (disprover_result(PO_Name,R,Raw) -> Result=R,RawResult=Raw | |
283 | ; Result = 'not_yet_run', RawResult='not_yet_run'). | |
284 | ||
285 | :- dynamic loaded_po_file/1. | |
286 | load_po_file(File) :- reset_po_facts, | |
287 | % consult_without_redefine_warning | |
288 | prolog_flag(redefine_warnings, Old, off), | |
289 | (% load in dynamic mode: so that we can retract later | |
290 | my_po_consult(File) | |
291 | -> OK=true ; OK=false), | |
292 | prolog_flag(redefine_warnings, _, Old), | |
293 | (OK=true -> assert(loaded_po_file(File)) ; | |
294 | add_error_and_fail(disprover_test_runner,'Consulting of File failed: ',File)). | |
295 | ||
296 | my_po_consult(File) :- on_exception(error(existence_error(_,_),_), | |
297 | load_files(File,[compilation_mode(assert_all)]), | |
298 | add_error_fail(my_consult,'File does not exist: ',File)). | |
299 | ||
300 | ||
301 | disprover_load_at_repl_startup :- prolog_flag(argv,ArgV),ArgV = [FILE|T], | |
302 | (T=[] -> load_po_file(FILE) | |
303 | ; format('*** Please provide only one command-line argument: ~w~n',[ArgV]),fail). | |
304 | disprover_load_at_repl_startup :- | |
305 | print('Loading default file'),nl, | |
306 | load_po_file('../prob_examples/examples/ProofObligations/ABZ14_Mery/M3_mch.pl'). | |
307 | disprover_load_at_repl_startup. | |
308 | ||
309 | % :- load_po_file('../../prob_examples/examples/ProofObligations/ABZ14_Mery/M2_mch.pl'). | |
310 | % :- load_po_file('../../prob_examples/examples/ProofObligations/ABZ14_Mery/M3_mch.pl'). | |
311 | % :- load_po_file('../../prob_examples/examples/ProofObligations/ABZ14_Mery/M4_mch.pl'). | |
312 | % :- load_po_file('../../prob_examples/public_examples/EventBPrologPackages/Disprover/ProofTests/DefSetCst_ctx.pl'). | |
313 | % '/Users/leuschel/git_root/prob_examples/public_examples/SMT/QF_IDL/queens_bench/toroidal_bench/toroidal_queen_2_QF_IDL_ctx.pl'. | |
314 | ||
315 | %:- test_repl. | |
316 |