| 1 | % (c) 2021-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 | :- module(set_rewriter, [rewrite_set_to_list_of_asts/3, | |
| 5 | rewrite_set_to_list_of_asts/4, | |
| 6 | avl_list_to_list_of_asts/4, | |
| 7 | rewrite_finite_card/3]). | |
| 8 | ||
| 9 | :- use_module(library(avl), [avl_to_list/2]). | |
| 10 | ||
| 11 | :- use_module(probsrc(b_global_sets), [enumerated_set/1, | |
| 12 | all_elements_of_type/2]). | |
| 13 | :- use_module(probsrc(preferences), [get_preference/2]). | |
| 14 | :- use_module(probsrc(bsyntaxtree), [get_integer/2, | |
| 15 | conjunct_predicates/2, | |
| 16 | disjunct_predicates/2, | |
| 17 | get_texpr_type/2, | |
| 18 | get_texpr_expr/2, | |
| 19 | safe_create_texpr/4]). | |
| 20 | ||
| 21 | :- use_module(probsrc(performance_messages), [perfmessage/3]). | |
| 22 | ||
| 23 | rewrite_set_to_list_of_asts(b(E,Type,Info), ScopeIds, L) :- | |
| 24 | rewrite_set_aux(E, Type, Info, ScopeIds, [], L). | |
| 25 | ||
| 26 | rewrite_set_to_list_of_asts(b(E,Type,Info), ScopeIds, Options, L) :- | |
| 27 | rewrite_set_aux(E, Type, Info, ScopeIds, Options, L). | |
| 28 | ||
| 29 | rewrite_set_aux(identifier(EnumSet), set(global(EnumSet)), Info, ScopeIds, _, SetAsts) :- | |
| 30 | enumerated_set(EnumSet), | |
| 31 | \+ memberchk(EnumSet, ScopeIds), | |
| 32 | \+ memberchk(introduced_by(_), Info), | |
| 33 | all_elements_of_type(EnumSet, SetValues), | |
| 34 | !, | |
| 35 | findall(b(value(Val),global(EnumSet),[]), member(Val, SetValues), SetAsts). | |
| 36 | rewrite_set_aux(boolean_set, _, _, _, _, L) :- | |
| 37 | !, | |
| 38 | L = [b(boolean_true,boolean,[]), b(boolean_false,boolean,[])]. | |
| 39 | rewrite_set_aux(interval(From,To), _, Info, _, Options, L) :- | |
| 40 | !, | |
| 41 | get_integer_constant(From, FI), | |
| 42 | get_integer_constant(To, TI), | |
| 43 | check_limit(FI, TI, Info, Options), | |
| 44 | !, | |
| 45 | constant_interval_as_list(FI, TI, L). | |
| 46 | rewrite_set_aux(set_extension(L), _, _, _, _, R) :- | |
| 47 | !, | |
| 48 | R = L. | |
| 49 | rewrite_set_aux(value(Value), Type, _, _, Options, L) :- nonvar(Value), | |
| 50 | !, | |
| 51 | rewrite_value(Value, Type, Options, L). | |
| 52 | rewrite_set_aux(cartesian_product(A,B), set(Type), _, ScopeIds, Options, L) :- !, | |
| 53 | rewrite_set_to_list_of_asts(A, ScopeIds, Options, AL), | |
| 54 | rewrite_set_to_list_of_asts(B, ScopeIds, Options, BL), | |
| 55 | findall(b(couple(VA,VB),Type,[]), (member(VA,AL),member(VB,BL)), L). | |
| 56 | %rewrite_set_aux(E, Type, _, L) :- write(impossible(E)), nl, fail. | |
| 57 | ||
| 58 | rewrite_value(global_set(EnumSet), _, _, L) :- | |
| 59 | enumerated_set(EnumSet), | |
| 60 | all_elements_of_type(EnumSet, SetValues), | |
| 61 | !, | |
| 62 | findall(b(value(Val),global(EnumSet),[]), member(Val, SetValues), L). | |
| 63 | rewrite_value(avl_set(AvlSet), Type, _, L) :- | |
| 64 | !, | |
| 65 | ( Type = set(InType) | |
| 66 | ; Type = seq(SeqType), | |
| 67 | InType = couple(integer,SeqType) | |
| 68 | ), | |
| 69 | avl_to_list(AvlSet, AvlList), | |
| 70 | avl_list_to_list_of_asts(InType, AvlList, [], L). | |
| 71 | rewrite_value(closure(P,T,B), _Type, Options, L) :- | |
| 72 | custom_explicit_sets:is_interval_closure(P,T,B,FI,TI), integer(FI),integer(TI), | |
| 73 | check_limit(FI, TI, B, Options), | |
| 74 | !, | |
| 75 | constant_interval_as_list(FI, TI, L). | |
| 76 | ||
| 77 | ||
| 78 | check_limit(FI, TI, Info, Options) :- | |
| 79 | Card is TI - FI, | |
| 80 | ( ( memberchk(instantiate_sets_limit(SetLimit), Options) -> true | |
| 81 | ; memberchk(instantiate_quantifier_limit(SetLimit), Options) | |
| 82 | ) | |
| 83 | -> ( Card =< SetLimit | |
| 84 | -> true | |
| 85 | ; perfmessage(quantifier,not_expanding_interval_in_quantifier(FI,TI,limit(SetLimit)),Info), | |
| 86 | fail | |
| 87 | ) | |
| 88 | ; true | |
| 89 | ). | |
| 90 | ||
| 91 | ||
| 92 | avl_list_to_list_of_asts(_, [], Acc, Acc). | |
| 93 | avl_list_to_list_of_asts(InType, [Val-_|T], Acc, L) :- | |
| 94 | ? | avl_list_to_list_of_asts(InType, T, [b(value(Val),InType,[])|Acc], L). |
| 95 | ||
| 96 | get_integer_constant(Ast, IntConst) :- | |
| 97 | get_integer(Ast, IntConst). | |
| 98 | get_integer_constant(b(min_int,integer,_), MinInt) :- | |
| 99 | get_preference(minint, MinInt). | |
| 100 | get_integer_constant(b(max_int,integer,_), MaxInt) :- | |
| 101 | get_preference(maxint, MaxInt). | |
| 102 | ||
| 103 | %% constant_interval_as_list(+Lower, +Upper, -List). | |
| 104 | constant_interval_as_list(FI,TI,[]) :- | |
| 105 | FI > TI. | |
| 106 | constant_interval_as_list(FI,FI,[BI]) :- | |
| 107 | !, %safe_create_texpr(integer(FI), integer, [], BI). | |
| 108 | BI = b(value(int(FI)),integer,[]). | |
| 109 | constant_interval_as_list(FI,TI,[BI|BIs]) :- | |
| 110 | %safe_create_texpr(integer(FI), integer, [], BI), | |
| 111 | BI = b(value(int(FI)),integer,[]), | |
| 112 | NFI is FI + 1, | |
| 113 | constant_interval_as_list(NFI,TI,BIs). | |
| 114 | ||
| 115 | %% rewrite_finite_card(+GL, -Res, -RuleDescr). | |
| 116 | % Rewrite some cardinality constraints on finite sets to prevent the translation to SMT-LIB using quantifiers. | |
| 117 | % TODO: card({a1,..,ak}) > j where j < k --> at least j equalities (watch out for exponential blowup) | |
| 118 | % TODO: card({a1,..,ak}) = k - 1 (watch out for exponential blowup) | |
| 119 | rewrite_finite_card(less(Card,Integer), Res, card_to_at_least_one_eq) :- | |
| 120 | % card({a1,..,ak}) < k --> at least one eq (has n*log(n) disjuncts) | |
| 121 | rewrite_finite_card_k_less_k(Card, Integer, Res). | |
| 122 | rewrite_finite_card(greater(Integer,Card), Res, card_to_at_least_one_eq) :- | |
| 123 | % k > card({a1,..,ak}) --> at least one eq (has n*log(n) disjuncts) | |
| 124 | rewrite_finite_card_k_less_k(Card, Integer, Res). | |
| 125 | rewrite_finite_card(less_equal(Card,Integer), Res, card_to_at_least_one_eq) :- | |
| 126 | % card({a1,..,ak}) <= k - 1 --> at least one eq (has n*log(n) disjuncts) | |
| 127 | rewrite_finite_card_k_leq_k_minus_1(Card, Integer, Res). | |
| 128 | rewrite_finite_card(greater_equal(Integer,Card), Res, card_to_at_least_one_eq) :- | |
| 129 | % k - 1 >= card({a1,..,ak}) --> at least one eq (has n*log(n) disjuncts) | |
| 130 | rewrite_finite_card_k_leq_k_minus_1(Card, Integer, Res). | |
| 131 | rewrite_finite_card(less_equal(Card,Integer), Res, card_to_truth_leq_k) :- | |
| 132 | % card({a1,..,ak}) <= k --> truth | |
| 133 | rewrite_finite_card_k_leq_k(Card, Integer, Res). | |
| 134 | rewrite_finite_card(greater_equal(Integer,Card), Res, card_to_truth_leq_k) :- | |
| 135 | % k >= card({a1,..,ak}) --> truth | |
| 136 | rewrite_finite_card_k_leq_k(Card, Integer, Res). | |
| 137 | rewrite_finite_card(less(Card,Integer), Res, card_to_truth_leq_k1) :- | |
| 138 | % card({a1,..,ak}) < k + 1 --> truth | |
| 139 | rewrite_finite_card_k_leq_k_plus_1(Card, Integer, Res). | |
| 140 | rewrite_finite_card(greater(Integer,Card), Res, card_to_truth_leq_k1) :- | |
| 141 | % k + 1 > card({a1,..,ak}) --> truth | |
| 142 | rewrite_finite_card_k_leq_k_plus_1(Card, Integer, Res). | |
| 143 | rewrite_finite_card(greater_equal(Card,Integer), Res, card_to_all_different_greater_eq) :- | |
| 144 | % card({a1,..,ak}) >= k --> all_different | |
| 145 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 146 | rewrite_finite_card(less_equal(Integer,Card), Res, card_to_all_different_greater_eq) :- | |
| 147 | % k <= card({a1,..,ak}) --> all_different | |
| 148 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 149 | rewrite_finite_card(greater(Card,Integer), Res, card_to_falsity) :- | |
| 150 | % card({a1,..,ak}) > n --> falsity if n>=k | |
| 151 | rewrite_finite_card_greater_less_k(Card, Integer, Res). | |
| 152 | rewrite_finite_card(less(Integer,Card), Res, card_to_falsity) :- | |
| 153 | % n < card({a1,..,ak}) --> falsity if n>=k | |
| 154 | rewrite_finite_card_greater_less_k(Card, Integer, Res). | |
| 155 | rewrite_finite_card(greater_equal(Card,Integer), Res, card_to_falsity) :- | |
| 156 | % card({a1,..,ak}) >= n --> falsity if n>k | |
| 157 | rewrite_finite_card_greatereq_lesseq_n(Card, Integer, Res). | |
| 158 | rewrite_finite_card(less_equal(Integer,Card), Res, card_to_falsity) :- | |
| 159 | % n <= card({a1,..,ak}) --> falsity if n>k | |
| 160 | rewrite_finite_card_greatereq_lesseq_n(Card, Integer, Res). | |
| 161 | rewrite_finite_card(greater(Card,Integer), Res, card_to_all_different_greater) :- | |
| 162 | % card({a1,..,ak}) > k - 1 --> all different | |
| 163 | rewrite_finite_card_greater_less_k1(Card, Integer, Res). | |
| 164 | rewrite_finite_card(less(Integer,Card), Res, card_to_all_different_greater) :- | |
| 165 | % k - 1 < card({a1,..,ak}) --> all different | |
| 166 | rewrite_finite_card_greater_less_k1(Card, Integer, Res). | |
| 167 | rewrite_finite_card(greater_equal(Card,Integer1), Res, card_to_truth) :- | |
| 168 | % card({a1,..,ak}) >= 1 --> truth | |
| 169 | rewrite_finite_card_geq_leq_1(Card, Integer1, Res). | |
| 170 | rewrite_finite_card(less_equal(Integer1,Card), Res, card_to_truth) :- | |
| 171 | % 1 <= card({a1,..,ak}) --> truth | |
| 172 | rewrite_finite_card_geq_leq_1(Card, Integer1, Res). | |
| 173 | rewrite_finite_card(equal(Card,Integer), Res, card_to_single_equality) :- | |
| 174 | % card({a1,a2}) = 1 --> a1=a2 | |
| 175 | rewrite_finite_card_2_eq_1(Card, Integer, Res). | |
| 176 | rewrite_finite_card(equal(Integer,Card), Res, card_to_single_equality) :- | |
| 177 | % 1 = card({a1,a2}) --> a1=a2 | |
| 178 | rewrite_finite_card_2_eq_1(Card, Integer, Res). | |
| 179 | rewrite_finite_card(not_equal(Card,Integer), Res, card_to_single_non_equality) :- | |
| 180 | % card({a1,a2}) /= 1 --> a1/=a2 | |
| 181 | rewrite_finite_card_2_neq_1(Card, Integer, Res). | |
| 182 | rewrite_finite_card(not_equal(Integer,Card), Res, card_to_single_non_equality) :- | |
| 183 | % 1 /= card({a1,a2}) --> a1/=a2 | |
| 184 | rewrite_finite_card_2_neq_1(Card, Integer, Res). | |
| 185 | rewrite_finite_card(equal(Card,Integer), Res, card_to_falsity_nonempty_eq_zero) :- | |
| 186 | % card({a1,..,ak}) = 0 --> falsity | |
| 187 | rewrite_finite_card_eq_0(Card, Integer, Res). | |
| 188 | rewrite_finite_card(equal(Integer,Card), Res, card_to_falsity_nonempty_eq_zero) :- | |
| 189 | % card({a1,..,ak}) = 0 --> falsity | |
| 190 | rewrite_finite_card_eq_0(Card, Integer, Res). | |
| 191 | rewrite_finite_card(equal(Card,Integer), Res, card_to_all_different_eq_k) :- | |
| 192 | % card({a1,..,ak}) = k --> all different | |
| 193 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 194 | rewrite_finite_card(equal(Integer,Card), Res, card_to_all_different_eq_k) :- | |
| 195 | % k = card({a1,..,ak}) --> all different | |
| 196 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 197 | rewrite_finite_card(greater_equal(Card,Integer), Res, card_to_all_different_geq_k) :- | |
| 198 | % card({a1,..,ak}) >= k --> all different | |
| 199 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 200 | rewrite_finite_card(less_equal(Integer,Card), Res, card_to_all_different_geq_k) :- | |
| 201 | % k >= card({a1,..,ak}) --> all different | |
| 202 | rewrite_finite_card_k_eq_k(Card, Integer, Res). | |
| 203 | ||
| 204 | rewrite_finite_card_k_less_k(Card, Integer, Res) :- | |
| 205 | Card = b(card(SetExtension),integer,_), | |
| 206 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 207 | SetExtension = b(set_extension(L),_,_), | |
| 208 | length(L, Len), | |
| 209 | ICard =:= Len, | |
| 210 | !, | |
| 211 | create_at_least_one_eq(L, AtLeastOneEqAst), | |
| 212 | get_texpr_expr(AtLeastOneEqAst, Res). | |
| 213 | ||
| 214 | rewrite_finite_card_k_leq_k_minus_1(Card, Integer, Res) :- | |
| 215 | Card = b(card(SetExtension),integer,_), | |
| 216 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 217 | SetExtension = b(set_extension(L),_,_), | |
| 218 | length(L, Len), | |
| 219 | ICard =:= Len - 1, | |
| 220 | !, | |
| 221 | create_at_least_one_eq(L, AtLeastOneEqAst), | |
| 222 | get_texpr_expr(AtLeastOneEqAst, Res). | |
| 223 | ||
| 224 | rewrite_finite_card_k_leq_k(Card, Integer, Res) :- | |
| 225 | Card = b(card(SetExtension),integer,_), | |
| 226 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 227 | SetExtension = b(set_extension(L),_,_), | |
| 228 | length(L, Len), | |
| 229 | ICard >= Len, | |
| 230 | !, | |
| 231 | get_texpr_type(SetExtension, SetType), | |
| 232 | % don't create simple truth to keep variables in scope, could be the only occurrence | |
| 233 | Res = not_equal(SetExtension,b(empty_set,SetType,[])). | |
| 234 | ||
| 235 | rewrite_finite_card_k_leq_k_plus_1(Card, Integer, Res) :- | |
| 236 | Card = b(card(SetExtension),integer,_), | |
| 237 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 238 | SetExtension = b(set_extension(L),_,_), | |
| 239 | length(L, Len), | |
| 240 | ICard1 is ICard + 1, | |
| 241 | ICard1 >= Len, | |
| 242 | !, | |
| 243 | get_texpr_type(SetExtension, SetType), | |
| 244 | % don't create simple truth to keep variables in scope, could be the only occurrence | |
| 245 | Res = not_equal(SetExtension,b(empty_set,SetType,[])). | |
| 246 | ||
| 247 | rewrite_finite_card_geq_leq_k(Card, Integer, Res) :- | |
| 248 | Card = b(card(SetExtension),integer,_), | |
| 249 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 250 | SetExtension = b(set_extension(L),_,_), | |
| 251 | length(L, Len), | |
| 252 | ICard > Len, | |
| 253 | !, | |
| 254 | Res = falsity. | |
| 255 | ||
| 256 | rewrite_finite_card_greatereq_lesseq_n(Card, Integer, Res) :- | |
| 257 | Card = b(card(SetExtension),integer,_), | |
| 258 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 259 | SetExtension = b(set_extension(L),_,_), | |
| 260 | length(L, Len), | |
| 261 | ICard > Len, | |
| 262 | !, | |
| 263 | Res = falsity. | |
| 264 | ||
| 265 | rewrite_finite_card_greater_less_k(Card, Integer, Res) :- | |
| 266 | Card = b(card(SetExtension),integer,_), | |
| 267 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 268 | SetExtension = b(set_extension(L),_,_), | |
| 269 | length(L, Len), | |
| 270 | ICard >= Len, | |
| 271 | !, | |
| 272 | Res = falsity. | |
| 273 | ||
| 274 | rewrite_finite_card_greater_less_k1(Card, Integer, Res) :- | |
| 275 | Card = b(card(SetExtension),integer,_), | |
| 276 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 277 | SetExtension = b(set_extension(L),_,_), | |
| 278 | length(L, Len), | |
| 279 | ICard =:= Len - 1, | |
| 280 | !, | |
| 281 | create_all_different(L, AllDiffAst), | |
| 282 | get_texpr_expr(AllDiffAst, Res). | |
| 283 | ||
| 284 | rewrite_finite_card_geq_leq_1(Card, Integer1, Res) :- | |
| 285 | Card = b(card(SetExtension),integer,_), | |
| 286 | (Integer1 = b(integer(1),integer,_); Integer1 = b(value(int(1)),integer,_)), | |
| 287 | SetExtension = b(set_extension(L),_,_), | |
| 288 | L \== [], | |
| 289 | !, | |
| 290 | get_texpr_type(SetExtension, SetType), | |
| 291 | % don't create simple truth to keep variables in scope, could be the only occurrence | |
| 292 | Res = not_equal(SetExtension,b(empty_set,SetType,[])). | |
| 293 | ||
| 294 | rewrite_finite_card_2_eq_1(Card, Integer, Res) :- | |
| 295 | Card = b(card(SetExtension),integer,_), | |
| 296 | (Integer = b(integer(1),integer,_); Integer = b(value(int(1)),integer,_)), | |
| 297 | SetExtension = b(set_extension([A1,A2]),_,_), | |
| 298 | !, | |
| 299 | Res = equal(A1,A2). | |
| 300 | ||
| 301 | rewrite_finite_card_2_neq_1(Card, Integer, Res) :- | |
| 302 | Card = b(card(SetExtension),integer,_), | |
| 303 | (Integer = b(integer(1),integer,_); Integer = b(value(int(1)),integer,_)), | |
| 304 | SetExtension = b(set_extension([A1,A2]),_,_), | |
| 305 | !, | |
| 306 | Res = not_equal(A1,A2). | |
| 307 | ||
| 308 | rewrite_finite_card_eq_0(Card, Integer, Res) :- | |
| 309 | Card = b(card(SetExtension),integer,_), | |
| 310 | (Integer = b(integer(0),integer,_); Integer = b(value(int(0)),integer,_)), | |
| 311 | SetExtension = b(set_extension(L),_,_), | |
| 312 | L \== [], | |
| 313 | !, | |
| 314 | Res = falsity. | |
| 315 | ||
| 316 | rewrite_finite_card_k_eq_k(Card, Integer, Res) :- | |
| 317 | Card = b(card(SetExtension),integer,_), | |
| 318 | (Integer = b(integer(ICard),integer,_); Integer = b(value(int(ICard)),integer,_)), | |
| 319 | SetExtension = b(set_extension(L),_,_), | |
| 320 | length(L, Len), | |
| 321 | ICard == Len, | |
| 322 | !, | |
| 323 | create_all_different(L, AllDiffAst), | |
| 324 | get_texpr_expr(AllDiffAst, Res). | |
| 325 | ||
| 326 | % {x1,..,xk} -> x1 = x2 or ... or xk-1 = xk | |
| 327 | create_at_least_one_eq(L, AtLeastOneEq) :- | |
| 328 | create_at_least_one_eq(L, [], Eqs), | |
| 329 | disjunct_predicates(Eqs, AtLeastOneEq). | |
| 330 | ||
| 331 | create_at_least_one_eq([], Acc, Acc). | |
| 332 | create_at_least_one_eq([A|T], Acc, List) :- | |
| 333 | create_all_same_fixed(A, T, Acc, NAcc), | |
| 334 | create_at_least_one_eq(T, NAcc, List). | |
| 335 | ||
| 336 | create_all_different(Asts, AllDiffAst) :- | |
| 337 | create_all_different(Asts, [], InEqs), | |
| 338 | conjunct_predicates(InEqs, AllDiffAst). | |
| 339 | ||
| 340 | create_all_different([], Acc, Acc). | |
| 341 | create_all_different([A|T], Acc, InEqs) :- | |
| 342 | create_all_different_fixed(A, T, Acc, NAcc), | |
| 343 | create_all_different(T, NAcc, InEqs). | |
| 344 | ||
| 345 | create_all_different_fixed(_, [], Acc, Acc). | |
| 346 | create_all_different_fixed(A, [B|T], Acc, InEqs) :- | |
| 347 | safe_create_texpr(not_equal(A,B), pred, [], InEq), | |
| 348 | NAcc = [InEq|Acc], | |
| 349 | create_all_different_fixed(A, T, NAcc, InEqs). | |
| 350 | ||
| 351 | create_all_same_fixed(_, [], Acc, Acc). | |
| 352 | create_all_same_fixed(A, [B|T], Acc, InEqs) :- | |
| 353 | safe_create_texpr(equal(A,B), pred, [], InEq), | |
| 354 | NAcc = [InEq|Acc], | |
| 355 | create_all_same_fixed(A, T, NAcc, InEqs). |