1 % (c) 2014-2015 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(solver_handling,[clauses_on_level/4,
6 add_clauses_to_level/4,
7 in_solver_on_level/3,
8 solve/2, solve_negated/2,
9 initial_state/1]).
10
11 :- use_module(probsrc(module_information)).
12 :- module_info(group,symbolic_model_checker).
13 :- module_info(description,'Internal data structures for solver / prover').
14
15 :- use_module(library(avl)).
16 :- use_module(library(ordsets)).
17 :- use_module(library(lists)).
18
19 :- use_module(extension('counter/counter'),[inc_counter/1]).
20
21 :- use_module(smt_solvers_interface(smt_solvers_interface), [smt_solve_predicate/4]).
22
23 :- use_module(probsrc(atelierb_provers_interface),[prove_predicate/3]).
24 :- use_module(probsrc(preferences), [get_preference/2,
25 temporary_set_preference/3,
26 reset_temporary_preference/2]).
27 :- use_module(probsrc(solver_interface), [solve_predicate/5]).
28 :- use_module(probsrc(translate), [print_bexpr/1]).
29 :- use_module(probsrc(bsyntaxtree), [disjunct_predicates/2,
30 conjunction_to_list/2,
31 conjunct_predicates/2]).
32
33 :- use_module(symbolic_model_checker(predicate_handling)).
34
35 initial_state(Pred) :-
36 get_initial_state_predicate(Init),
37 conjunct_predicates([Init,Pred],IandPred),
38 solve(IandPred,Result),
39 Result = solution(_).
40
41 add_clauses_to_level(Level,FramesIn,Clauses,FramesOut) :-
42 maplist(list_to_ord_set,Clauses,OrdClauses),
43 clauses_on_level(Level,FramesIn,F_To,ClausesTo),
44 list_to_ord_set(OrdClauses,SetToAdd),
45 ord_union(ClausesTo,SetToAdd,NewClauses),
46 exclude(is_subsumed(NewClauses),NewClauses,FilteredNewClauses),
47 avl_store(Level,FramesIn,frame(F_To,FilteredNewClauses),FramesOut).
48
49 is_subsumed(AllClauses,C) :-
50 member(C2,AllClauses),
51 C \= C2,
52 % C is subsumed by C2 if C = C2 + additional disjuncts
53 ord_subtract(C2,C,[]).
54
55 clauses_on_level(Level,Frames,F_K,Clauses) :-
56 avl_fetch(Level,Frames,frame(F_K,Clauses)).
57
58 in_solver_on_level(Level,Frames,InSolver) :-
59 clauses_on_level(Level,Frames,F_K,Clauses),
60 maplist(disjunct_predicates,Clauses,Conjuncts),
61 append(F_K,Conjuncts,InSolver).
62
63 % the version below retuns clauses as negated conjunctions
64 % for some reason this seems to aid the solver?
65 % in_solver_on_level(Level,Frames,InSolver) :-
66 % clauses_on_level(Level,Frames,F_K,Clauses),
67 % (Clauses = [] -> InSolver = F_K ;
68 % maplist(maplist(bsyntaxtree:create_negation),Clauses,T),
69 % maplist(bsyntaxtree:conjunct_predicates,T,T2),
70 % maplist(bsyntaxtree:create_negation,T2,Conjuncts),
71 % append(F_K,Conjuncts,InSolver)).
72
73 % if our constraint solver fails, we try the atelierb provers
74 try_further_solvers(no_solution_found(_)).
75 try_further_solvers(time_out).
76
77 throw_if_solvers_too_weak(X,Pred) :-
78 X \= contradiction_found(_), X \= solution(_), !,
79 format('Solvers too weak for predicate:~n',[]),
80 print_bexpr(Pred),nl,
81 %translate:nested_print_bexpr(Pred),nl,
82 throw(solver_and_provers_too_weak).
83 throw_if_solvers_too_weak(_,_).
84
85 print_result(Solver,FullResult) :-
86 functor(FullResult,SRForPrint,_),
87 format('solve/2: result of ~w: ~w~n',[Solver,SRForPrint]).
88
89 solve_negated(P,R) :-
90 create_negation_and_cleanup(P,NP),
91 solve(NP,R).
92 solve(Predicate,Result) :-
93 inc_counter(ic3solvercalls),
94 % debug output for all solver calls
95 % translate:translate_bexpression(Predicate,PPPredicate),
96 % format('Checking: ~w~n',[PPPredicate]),
97 % calls through the solver interface
98 % uses smt support and smt fallback
99 Options = [],
100 get_timeout_factor(Options,TimeoutFactor),
101 solve_prob(Predicate,Options,TimeoutFactor,SolverResult),
102 print_result(prob,SolverResult),
103 solve2(Predicate,SolverResult,Result).
104
105 % other options to try if prob alone did not find a suitable result
106 % corresponding timeout factors for portfolio / prob only
107 options_to_try(['KODKOD']).
108 options_to_try(['SMT_SUPPORTED_INTERPRETER']).
109
110 get_timeout_factor([],Factor) :-
111 get_preference(symbolic_mc_try_other_solvers,false)
112 -> Factor = 1 ; Factor = 0.25.
113 get_timeout_factor(['KODKOD'],0.25).
114 get_timeout_factor(['SMT_SUPPORTED_INTERPRETER'],0.35). % last 0,15 reserved for ml/pp
115
116 solve2(Predicate,SolverResult,Result) :-
117 try_further_solvers(SolverResult),
118 get_preference(symbolic_mc_try_other_solvers,true),
119 options_to_try(Options), % backtracks into different options
120 inc_counter(ic3solvercalls),
121 get_timeout_factor(Options,TimeoutFactor),
122 solve_prob(Predicate,Options,TimeoutFactor,NewResult),
123 print_result(prob,NewResult),
124 \+ (try_further_solvers(NewResult)), !,
125 Result = NewResult.
126 solve2(Predicate,SolverResult,Result) :-
127 solve3(Predicate,SolverResult,Result).
128
129 solve3(Predicate,SolverResult,Result) :-
130 try_further_solvers(SolverResult),
131 get_preference(symbolic_mc_try_other_solvers,true),
132 smt_solve_predicate(z3,Predicate,_,contradiction_found), !,
133 print_result('smt_solve_predicate',contradiction_found),
134 Result = contradiction_found(Predicate).
135 solve3(Predicate,SolverResult,Result) :-
136 solve4(Predicate,SolverResult,Result).
137
138 solve4(Predicate,SolverResult,Result) :-
139 try_further_solvers(SolverResult),
140 get_preference(symbolic_mc_try_other_solvers,true), !,
141 solve_provers(Predicate,Result),
142 print_result('pp/ml',Result),
143 throw_if_solvers_too_weak(Result,Predicate).
144 solve4(Predicate,Result,Result) :-
145 throw_if_solvers_too_weak(Result,Predicate).
146
147 solve_prob(Predicate,Options,TimeoutFactor,ResultOut) :-
148 temporary_set_preference(disprover_mode,true,Changed),
149 % temporary_set_preference(smt_supported_interpreter,true),
150 solve_predicate(Predicate,_State,TimeoutFactor,Options,Result), !,
151 reset_temporary_preference(disprover_mode,Changed),
152 % reset_temporary_preference(smt_supported_interpreter),
153 (Result = contradiction_found -> ResultOut = contradiction_found(Predicate) ; % TODO: extract core
154 otherwise -> ResultOut = Result).
155
156 solve_provers(Predicate,Result) :-
157 conjunction_to_list(Predicate,Hyps),
158 % no hypotheses. might want to consider refactoring the predicate in order to find them
159 length(Hyps,L),write(len_of_hyps(L)),nl,
160 % (L=1 -> write(Predicate),nl ; true),
161 prove_predicate(Hyps,b(falsity,pred,[]),TResult), !,
162 (TResult = proved
163 -> Result = contradiction_found(Predicate) % TODO: extract core, etc.
164 ; Result = no_solution_found(atbprover_unproved)).
165 solve_provers(_,no_solution_found). % in case prove_predicate fails