1 % (c) 2009-2024 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(maxsolver, [
6 maxsolver/3,
7 maxsolver_by_longest_prefix/3,
8 maxsolver_by_longest_segment/3,
9 maxsolver_exact_with_marker/3,
10 longest_satisfiable_prefix/4
11 ]).
12
13 :- use_module(probsrc(module_information)).
14 :- module_info(group,dot).
15 :- module_info(description,'Finds a maximally satisfiable subset for predicates; used by bvisual_any_maxsolver.').
16
17 :- use_module(library(lists)).
18 :- use_module(library(timeout)).
19
20 :- use_module(probsrc(preferences),[get_preference/2]).
21 minimal_timeout(Val) :- get_preference(formula_tree_minimal_timeout,Val). % Default 1000
22 maximal_timeout(Val) :- get_preference(formula_tree_maximal_timeout,Val). % Default 30000
23
24
25 :- meta_predicate maxsolver(1,-,-).
26 :- meta_predicate maxsolver(-,1,-,-).
27 maxsolver(Eval, Set, Solver):-
28 maxsolver(automatic, Eval, Set, Solver).
29
30
31 :- meta_predicate maxsolver_by_longest_prefix(1,-,-).
32
33 maxsolver(automatic, Eval, Set, Solver):-
34 length(Set, L),
35 x_method_by_length(Method, MaxLength),
36 L =< MaxLength,!,
37 call(Method, Eval, Set, Solver).
38
39 maxsolver(automatic, Eval, Set, Solver):-
40 maxsolver_by_longest_prefix(Eval, Set, Solver).
41
42
43 x_method_by_length(maxsolver_exact_with_marker, 10).
44 x_method_by_length(maxsolver_by_longest_segment, 18).
45
46
47
48 :- meta_predicate x_append_and_eval(1,-,-).
49 x_append_and_eval(Eval, Prefix, Set):-
50 append(Prefix, Set, NewSet),
51 call(Eval, NewSet).
52
53 :- meta_predicate x_prepend_and_eval(1,-,-).
54 x_prepend_and_eval(Eval, Suffix, Set):-
55 append(Set, Suffix, NewSet),
56 call(Eval, NewSet).
57
58 x_half_length(List, Smaller):-
59 length(List, Length),
60 Half is Length // 2,
61 length(Smaller, Half).
62
63
64 :- meta_predicate longest_satisfiable_prefix(1,-,-,-).
65 :- meta_predicate x_longest_satisfiable_prefix(1,-,-,-).
66
67 longest_satisfiable_prefix(Eval, Set, Prefix, R) :-
68 call(Eval, Set),!, Prefix=Set,
69 R=[].
70 longest_satisfiable_prefix(Eval, Set, Prefix, Complement) :-
71 x_longest_satisfiable_prefix(Eval, Set, Prefix, Complement).
72
73 x_longest_satisfiable_prefix(_, [C], [], [C]):-!.
74 x_longest_satisfiable_prefix(Eval, Set, Prefix, Complement):-
75 x_half_length(Set, Half),
76 append(Half, Tail, Set),
77 ( call(Eval, Half) ->
78 append(Half, NewPrefix, Prefix),
79 x_longest_satisfiable_prefix(x_append_and_eval(Eval, Half),
80 Tail, NewPrefix, Complement)
81 ;
82 x_longest_satisfiable_prefix(Eval, Half, Prefix, Suffix),
83 append(Suffix, Tail, Complement)
84 ).
85
86
87
88 :- meta_predicate satisfiable_segment(1,-,-,-,-).
89 satisfiable_segment(_, [], [], [], []) :- !.
90 satisfiable_segment(Eval, Set, Segment, Prefix, Suffix):-
91 append(Prefix, Subset, Set),
92 Subset\=[],
93 longest_satisfiable_prefix(Eval, Subset, Segment, Suffix),
94 ( Suffix = [],! ; true ).
95
96
97
98 :- meta_predicate longest_satisfiable_segment(1,-,-,-,-).
99 longest_satisfiable_segment(Eval, Set, Segment, Prefix, Suffix):-
100 findall(
101 x(Segment0, Prefix0, Suffix0),
102 satisfiable_segment(Eval, Set, Segment0, Prefix0, Suffix0),
103 Segments),
104 max_member(
105 x_shorter_or_same_length_list,
106 x(Segment, Prefix, Suffix),
107 Segments).
108
109
110 x_shorter_or_same_length_list(x(L1,_,_), x(L2,_,_)):-
111 shorter_list(L1, L2).
112
113 x_shorter_or_same_length_list(x(L1,_,S1), x(L2,_,S2)):-
114 same_length(L1, L2),
115 ( shorter_list(S1, S2); same_length(S1, S2) ).
116
117
118 :- meta_predicate maxsolver_by_longest_segment(1,-,-).
119 :- meta_predicate x_maxsolver_by_longest_segment(1,-,-,-,-).
120 maxsolver_by_longest_segment(Eval, Set, Solver) :-
121 longest_satisfiable_segment(Eval, Set, Segment, Prefix, Suffix),
122 x_maxsolver_by_longest_segment(Eval, Segment, Prefix, Suffix, Solver).
123
124
125 x_maxsolver_by_longest_segment(_, [], _, _, []):-!.
126
127 x_maxsolver_by_longest_segment(Eval, Segment, Prefix, Suffix, Solver):-
128 append(Prefix0, [_], Prefix),
129 Prefix0 \= [],!,
130 maxsolver_by_longest_segment(
131 x_prepend_and_eval(Eval, Segment), Prefix0, PrefixSolver),
132 append(PrefixSolver, Segment, NewSegment),
133 x_maxsolver_by_longest_segment(Eval, NewSegment, [], Suffix, Solver).
134
135 x_maxsolver_by_longest_segment(_, Segment, _, [], Segment):-!.
136
137 x_maxsolver_by_longest_segment(_, Segment, _, [_], Segment):-!.
138
139 x_maxsolver_by_longest_segment(Eval, Segment, _, [_|Suffix], Solver):-
140 append(Segment, SuffixSolver, Solver),
141 maxsolver_by_longest_segment(
142 x_append_and_eval(Eval, Segment), Suffix, SuffixSolver).
143
144
145
146 maxsolver_by_longest_prefix(_, Set, Solver) :- !, Set=1,Solver=1.
147 maxsolver_by_longest_prefix(Eval, Set, Solver):-
148 longest_satisfiable_prefix(Eval, Set, Prefix, Tail),!,
149 ( Tail = [_|NewSet] ->
150 append(Prefix, SubSolver, Solver),
151 maxsolver_by_longest_prefix(
152 x_append_and_eval(Eval, Prefix), NewSet, SubSolver)
153 ;
154 Solver = Prefix
155 ).
156
157 %x_print_debug_msg(Markers, L, U):-
158 % print(bounds(L,U)),nl, length(Markers, Length), print(markers(Length)), nl, flush_output.
159
160 :- meta_predicate maxsolver_exact_with_marker(1,-,-).
161 :- meta_predicate x_precalc(1,-,-,-,-).
162 :- meta_predicate x_false_subset_til_true(1,-,-,-,-).
163 :- meta_predicate x_existis_satisfiable_subset_of_length(1,-,-,-,-).
164 :- meta_predicate x_satisfiable_subset_of_length(1,-,-,-,-).
165 :- meta_predicate x_maxsolver_exact_with_marker(1,-,-,-,-,-).
166 :- meta_predicate x_false_subset(1,-,-,-).
167
168
169 maxsolver_exact_with_marker(Eval, Set, Solver):-
170 call(Eval, Set),!, Solver=Set.
171 maxsolver_exact_with_marker(Eval, Set, Solver):-
172 length(Set, Length),
173 (Length == 0
174 -> PrecalcBound is 1
175 ; PrecalcBound is max(msb(Length) - 1, 1)),
176 x_precalc(Eval, Set, 1, PrecalcBound, Markers),
177 x_maxsolver_exact_with_marker(Eval, Set, Markers, 0, Length, Solver).
178
179
180 x_precalc(_, _, L, U, []):-
181 L > U,!.
182
183 x_precalc(Eval, Set, L, U, Markers):-
184 findall(Subset, x_false_subset(Eval, Set, L, Subset), Subsets),
185 append(Subsets, NewMarkers, Markers),
186 LL is L+1,
187 x_precalc(Eval, Set, LL, U, NewMarkers).
188
189
190 x_false_subset(Eval, Set, L, Subset):-
191 length(Subset, L),
192 subseq0(Set, Subset),
193 \+call(Eval, Subset).
194
195 x_maxsolver_exact_with_marker(Eval, Set, Markers, L, U, Solver):-
196 L is U-1,!,
197 % x_print_debug_msg(Markers, L, U),
198 x_satisfiable_subset_of_length(Eval, Set, Markers, L, Solver).
199
200 x_maxsolver_exact_with_marker(Eval, Set, Markers, L, U, Solver):-
201 % x_print_debug_msg(Markers, L, U),
202 Half is (L+U) // 2,
203 Goal = x_existis_satisfiable_subset_of_length(Eval, Set, Markers, Half, FalseSets),
204 minimal_timeout(MinTimeout),
205 maximal_timeout(MaxTimeout),
206 Time is max(integer(1/(U-L)*MaxTimeout), MinTimeout),
207 ( time_out(Goal, Time, Res) ->
208 ( Res = time_out ->
209 LL is L+1,
210 Solver = timeout(Solver0),
211 x_maxsolver_exact_with_marker(Eval, Set, Markers, L, LL, Solver0)
212 ;
213 append(FalseSets, Markers, NewMarkers),
214 x_maxsolver_exact_with_marker(Eval, Set, NewMarkers, Half, U, Solver)
215 )
216 ;
217 x_maxsolver_exact_with_marker(Eval, Set, Markers, L, Half, Solver)
218 ).
219
220
221 x_satisfiable_subset_of_length(Eval, Set, Markers, L, Subset):-
222 length(Subset, L),
223 subseq0(Set, Subset),
224 \+x_marked_as_false(Markers, Subset),
225 call(Eval, Subset).
226
227 :- public x_existis_satisfiable_subset_of_length/5.
228 x_existis_satisfiable_subset_of_length(Eval, Set, Markers, Length, FalseSets):-
229 findall(Subset,
230 x_false_subset_til_true(Eval, Set, Markers, Length, Subset),
231 Sets),!,
232 append(FalseSets, [xxx], Sets).
233
234 x_false_subset_til_true(Eval, Set, Markers, Length, Subset):-
235 length(Subset0,Length),
236 subseq0(Set,Subset0),
237 \+x_marked_as_false(Markers, Subset0),
238 ( call(Eval, Subset0) ->
239 !, Subset = xxx
240 ;
241 Subset = Subset0
242 ).
243
244 x_marked_as_false(Markers, Set):-
245 member(FalseSet, Markers),
246 subseq0(Set, FalseSet).