| 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). |