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(kernel_equality,[equality_objects_wf/4,
6 equality_objects_wf_no_enum/4, % a version which does not enumerate boolean result
7 equality_objects_lwf/5, equality_objects/3,
8 equality_objects_with_type_wf/5,
9 empty_set_test/2, empty_set_test_wf/3,
10 empty_cartesian_product_wf/4,
11 or_eq_obj/3,
12 get_cardinality_wait_flag/4, get_cardinality_wait_flag/5,
13 get_cardinality_powset_wait_flag/5,
14 get_cardinality_relation_over_wait_flag/6,
15 %get_cardinality_partial_function_wait_flag/7,
16 check_and_remove/4,
17 membership_test_wf/4,
18 membership_test_wf_with_force/4,
19 enum_equality_result_wf/3, enum_equality_result_smt_mode_wf/3,
20 cartesian_pair_test_wf/5,
21 in_nat_range_test/4,
22
23 dif/3, integer_dif/2, bool_dif/2, eq_atomic/4,
24
25 subset_test/4, subset_strict_test/4,
26 test_interval_subset_wf/6,
27 conjoin_test/4,
28 equality_can_be_decided_by_unification/1]).
29
30 :- use_module(module_information,[module_info/2]).
31 :- module_info(group,kernel).
32 :- module_info(description,'This module provides reified equality and membership predicates.').
33
34 :- use_module(library(clpfd)).
35
36 :- use_module(kernel_objects,[equal_object/3, equal_object_wf/4,
37 not_equal_object/2, not_equal_object_wf/3,
38 cardinality_as_int_for_wf/2,
39 empty_set_wf/2, not_empty_set_wf/2,
40 exhaustive_kernel_check/2, exhaustive_kernel_check/1,
41 exhaustive_kernel_check_wf/2, exhaustive_kernel_fail_check_wf/2,
42 exhaustive_kernel_check_wfdet/2, exhaustive_kernel_fail_check_wfinit/2,
43 exhaustive_kernel_fail_check/1]).
44 :- use_module(kernel_card_arithmetic,[safe_mul/3, safe_add_card/3, safe_pow2/2, is_inf_or_overflow_card/1]).
45 :- use_module(b_interpreter_check,[conjoin/6]).
46 :- use_module(kernel_dif).
47
48 :- use_module(self_check).
49
50
51 :- use_module(probsrc(clpfd_interface),[catch_clpfd_overflow_call3/3, clpfd_in_domain/3]).
52 :- use_module(probsrc(debug),[debug_println/2]).
53
54
55 :- use_module(error_manager).
56
57 % kernel_equality
58 % :- ensure_loaded(kernel_equality).
59
60 :- use_module(custom_explicit_sets).
61 :- use_module(kernel_waitflags).
62
63 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(2),int(1)],[int(2)],pred_false))).
64 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(2),int(1)],[],pred_false))).
65 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(2),int(1)],[int(1),int(2)],pred_true))).
66 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([[int(2)],[int(1)]],[[int(1)],[int(2)]],pred_true))).
67 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([string('STRING1')],[string('STRING2')],pred_false))).
68 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([string('STRING2'),string('STRING1')],
69 [string('STRING1'),string('STRING2')],pred_true))).
70 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([(int(1),int(2)),(int(1),int(3))],[(int(1),int(3)),(int(1),int(2))],pred_true))).
71 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([(int(2),int(2)),(int(1),int(3))],[(int(2),int(3)),(int(1),int(2))],pred_false))).
72 :- assert_must_succeed((equality_objects(A,B,R), A=[int(2),int(3)],B=[int(X),int(Y)],
73 X=4,Y=2, R==pred_false)).
74 :- assert_must_succeed((equality_objects(A,B,R), A=[int(2),int(3)],B=[int(X),int(Y)],
75 X=2,Y=4, R==pred_false)).
76 :- assert_must_succeed((equality_objects(A,B,R), A=[int(2),int(3)],B=[int(X),int(Y)],
77 X=3,Y=2, R==pred_true)).
78 :- assert_must_succeed((equality_objects(A,B,R), A=[int(2),int(3)],B=[int(X),int(Y)],
79 X=2,Y=3, R==pred_true)).
80 :- assert_must_succeed((equality_objects(A,B,R), A=int(2),B=int(X),
81 R=pred_true, X==2)).
82
83
84 /* equality_objects/3 is a function which compares two objects
85 and returns either pred_true or pred_false in the third argument,
86 as soon as it can be decided whether the objects are equal */
87
88
89 equality_objects_wf(X,Y,Res,no_wf_available) :- !,
90 equality_objects(X,Y,Res).
91 equality_objects_wf(X,Y,Res,WF) :-
92 ? equality_objects_lwf(X,Y,Res,LWF,WF),
93 ? (var(Res) -> get_last_wait_flag(equality_objects_wf,WF,LWF) ; true).
94
95 equality_objects_lwf(X,Y,Res,LWF,WF) :-
96 ? equality_objects_wf_no_enum(X,Y,Res,WF),
97 ? force_equality_objects_lwf2(X,Y,Res,LWF).
98
99 :- block force_equality_objects_lwf2(?,?,-,-).
100 force_equality_objects_lwf2(X,Y,Res,LWF) :-
101 % tools_printing:print_term_summary(force_equality(X,Y,Res,LWF)),nl,
102 ( nonvar(Res) -> true
103 ; nonvar(X), X=int(_),
104 number(LWF), LWF>= 1152921504606844951, % only catch overflows if equality's priority low
105 preferences:preference(use_clpfd_solver,true)
106 -> force_equality_int_clpfd(X,Y,Res)
107 ; ( % print(forcing_equal(_X,_Y,_LWF)),nl, %%
108 % alternative would be to propagate LWF down to and_equality ?
109 %Res \== pred_false, equal_object(X,Y,force_equality_objects_lwf2), % not required anymore as and_equality can propagate pred_true down (commented out 27.2.2015)
110 % this can trigger CLPFD overflow; e.g., for x>1 & y:NATURAL & y=x+x & z={y,x}
111 Res=pred_true
112 ; %Res \== pred_true, not_equal_object(X,Y), % note required anymore (commented out 27.2.2015)
113 Res=pred_false
114 )).
115
116 % useful for e.g. x>1 & y:NATURAL & y=x+x & z={y,x}
117 force_equality_int_clpfd(_X,_Y,Res) :- %print(try_force_equality_int_clpfd(Res,_X,_Y)),nl,
118 catch_clpfd_overflow_call3(Res=pred_true,silent,Overflow=true),
119 (Overflow==true
120 -> !, debug_println(19,'Not forcing equality to true due to CLPFD overflow') % hope that enumeration will work
121 ; true).
122 force_equality_int_clpfd(_X,_Y,Res) :-
123 catch_clpfd_overflow_call3(Res=pred_false,message,
124 (debug_println(19,'Not forcing equality to false due to CLPFD overflow'),
125 delay_check_pred_false(Res))).
126
127 :- block delay_check_pred_false(-).
128 delay_check_pred_false(pred_false).
129
130 :- block equality_objects_with_expansion(-,-,?,?), equality_objects_with_expansion(?,-,-,?), equality_objects_with_expansion(-,?,-,?).
131 % will expand second argument; use if first argument is a tail of a list (representing a set)
132 equality_objects_with_expansion(X,Y,R,WF) :-
133 nonvar(Y), is_custom_explicit_set_nonvar(Y),!,
134 expand_custom_set_wf(Y,ExpSet,equality_objects_with_expansion,WF),
135 ? equality_objects_wf_no_enum(X,ExpSet,R,WF).
136 equality_objects_with_expansion(X,Y,R,WF) :-
137 equality_objects_wf_no_enum(X,Y,R,WF).
138
139
140 :- use_module(bool_pred).
141 % a version of equality_objects with type information available: allows to dispatch to boolean version
142 equality_objects_with_type_wf(boolean,X,Y,R,_) :- !, bool_pred:bool_equality(X,Y,R).
143 equality_objects_with_type_wf(_,X,Y,R,WF) :-
144 (X==Y -> R=pred_true ; equality_objects_block_wf(X,Y,R,WF)).
145
146 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(1)],[],pred_false))).
147 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(1)],[int(2)],pred_false))).
148 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects([int(1),int(2)],[int(2),int(1)],pred_true))).
149 :- assert_must_succeed((kernel_equality:equality_objects([int(1)],[],R),R==pred_false)).
150 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects(freeval(id1,case1,int(1)),freeval(id1,case1,int(1)),pred_true))).
151 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects(freeval(id1,case1,int(1)),freeval(id1,case1,int(2)),pred_false))).
152 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:equality_objects(freeval(id1,case1,int(1)),freeval(id1,case2,int(1)),pred_false))).
153
154 equality_objects(X,Y,R) :- equality_objects_wf_no_enum(X,Y,R,no_wf_available).
155
156 equality_objects_wf_no_enum(X,Y,R,WF) :-
157 (X==Y % could be expensive for long lists
158 -> R=pred_true
159 ? ; equality_objects_block_wf(X,Y,R,WF)).
160 % This is in principle more precise: but entails some performance penalty?!
161 %equality_objects(X,Y,R) :- when((?=(X,Y);nonvar(X);nonvar(Y)), (X==Y -> R=pred_true ; equality_objectsb(X,Y,R))).
162 :- block equality_objects_block_wf(-,-,-,?).
163 %equality_objectsb_wf(X,Y,R) :- % this case no longer needed, basic_type below will instantiate Y for this special case
164 % (nonvar(X) -> X=fd(XN,GS) ; nonvar(Y) -> Y=fd(XN,GS)),
165 % (var(GS) -> print(var_gs(fd(XN,GS))),nl,fail ; true),
166 % b_global_sets:is_global_set_of_cardinality_one(GS,N),!, % there exist only one object of that type
167 % XN=N, Y=X, R=pred_true.
168 %equality_objectsb(X,Y,R) :- X==Y,!,R=pred_true. % only makes sense if all three are variables; cannot happen here; we could have int(X)==int(Y), but then code further below will trigger
169 equality_objects_block_wf(X,Y,R,WF) :-
170 ? equality_objects0(X,Y,R,WF).
171
172 %:- block %equality_objects0(-,-,?,?),
173 % equality_objects0(?,-,-,?), equality_objects0(-,?,-,?).
174 equality_objects0(X,Y,R,WF) :- nonvar(R),!, % we know the result of the comparison
175 ? ( R=pred_true -> equal_object_wf(X,Y,equality_objects0,WF)
176 ; R=pred_false -> not_equal_object_wf(X,Y,WF)
177 ; add_error_fail(equality_objects0,'Illegal result: ',equality_objects0(X,Y,R,WF))
178 ).
179 % now we know that either X or Y must be nonvar
180 equality_objects0(X,Y,R,WF) :-
181 (nonvar(Y)
182 ? -> (X==[] -> eq_empty_set_wf(Y,R,WF)
183 ? ; equality_objects1(Y,X,R,WF)
184 )
185 ; equality_objects1(X,Y,R,WF)
186 ).
187
188 :- use_module(chrsrc(chr_integer_inequality),[chr_eq/3]).
189 :- use_module(clpfd_interface,[post_constraint2/2]).
190
191 equality_int(X,Y,Res) :- nonvar(X),nonvar(Y),!,
192 (X=Y -> Res=pred_true ; Res=pred_false).
193 equality_int(X,Y,Res) :-
194 % check for attached dif co-routines; diabled if CHR is used (no dif coroutine needed)
195 % !! there might still be dif coroutines set up by equality_expr and dis
196 % preferences:preference(use_chr_solver,false),
197 ? fd_frozen_dif(X,Y),!, Res=pred_false.
198 equality_int(X,Y,Res) :-
199 (preferences:preference(use_chr_solver,true) -> chr_eq(X,Y,Res) ; true),
200 % with CHR we detect e.g. r=TRUE in (X=Y <=> r=TRUE) & X:1..100 & Y > X
201 % see code for equality_fd
202 post_constraint2( ((X#=Y) #<=> R01), Posted), % from clpfd_interface
203 (Posted = true
204 -> prop_eq_01(Res,R01),
205 (var(R01) -> syntactic_equality_test(X,Y,Res) ; true) % CLPFD does not detect variable equality
206 ; eq_atomic_simple(X,Y,integer,Res)).
207
208
209 :- use_module(kernel_freetypes,[freetype_with_single_case/2, instantiate_freetype_case/3]).
210 %:- block equality_objects1(?,-,-,?). % avoid instantiating arg2 if result not known, problem for test 1488 : R:INTEGER<->INTEGER & dom(R)=D & X /: D & dom({(X,Y),B}) = DS & D=DS & Y:INTEGER
211 % equality_objects1 assumes first argument is nonvar:
212 %%equality_objects1(X,Y,R,_) :- print(equality_objects1(X,Y,R)),nl,fail. %%
213 equality_objects1(pred_true /* bool_true */,X,Res,_WF) :- !,
214 X=Res. % equivalent to bool_equality(pred_true /* bool_true */,X,Res).
215 equality_objects1(pred_false /* bool_false */,X,Res,_WF) :- !,
216 ? bool_pred:negate(X,Res). % equivalent to bool_equality(pred_false /* bool_false */,X,Res).
217 equality_objects1(int(X),IY,Res,_WF) :- !, IY=int(Y), equality_int(X,Y,Res).
218 equality_objects1(term(X),TY,Res,WF) :- !, TY=term(Y), eq_term_wf(X,Y,Res,WF).
219 equality_objects1(string(X),SY,Res,_WF) :- !, SY=string(Y), eq_atomic(X,Y,string,Res).
220 equality_objects1(fd(X,Type),FY,Res,_WF) :- !,
221 b_global_sets:get_global_type_value(FY,Type,Y),
222 ? equality_fd_objects(X,Y,Type,Res).
223 equality_objects1(freeval(Id,Case1,Value1),FY,Res,WF) :- !, FY=freeval(Id,Case2,Value2),
224 (nonvar(Id), freetype_with_single_case(Id,Case)
225 -> (Case,Case)=(Case1,Case2), % cases must match
226 equality_objects_wf_no_enum(Value1,Value2,Res,WF)
227 ; and_equality(CaseRes,ValueRes,Res),
228 eq_atomic(Case1,Case2,freeval_case,CaseRes),
229 equality_freeval_content(CaseRes,Value1,Value2,ValueRes,WF),
230 (var(Id) -> instantiate_freetype_case(Id,Case1,Case2) ; true)
231 ).
232 equality_objects1(rec(X),RY,Res,WF) :- !, RY=rec(Y), equality_fields(X,Y,Res,WF).
233 equality_objects1((X,Y),XY2,Res,WF) :- !, XY2=(X2,Y2),
234 equality_objects_wf_no_enum(X,X2,RX,WF),
235 and_equality(RY,RX,Res), % typically Res is var, hence it is better to call and_equality after X
236 (RX==pred_false -> true
237 ; equality_objects_wf_no_enum(Y,Y2,RY,WF)).
238 ?equality_objects1([],S,R,WF) :- !,eq_empty_set_wf(S,R,WF).
239 %equality_objects1(X,[],R,WF) :- !,eq_empty_set_wf(X,R,WF).
240 ?equality_objects1(X,Y,R,WF) :- equality_objects2(X,Y,R,WF).
241
242 :- block equality_freeval_content(-,?,?,?,?).
243 % if the case is different, we don't care anymore about the content; and the types could be different
244 equality_freeval_content(pred_false,_Value1,_Value2,_,_).
245 equality_freeval_content(pred_true,Value1,Value2,Res,WF) :-
246 % if we do not wait until we now that the case is the same,
247 % an internal type error might be raised
248 equality_objects_wf_no_enum(Value1,Value2,Res,WF).
249
250
251 :- use_module(error_manager,[add_warning/2]).
252
253 :- block equality_objects2(?,-,-,?). % also wait on second or third argument
254 equality_objects2(X,Y,Res,WF) :- nonvar(Res),!,% we know the result of the comparison
255 ( Res=pred_true -> %% print(forcing_equal(X,Y)),nl,%%
256 ? equal_object_wf(X,Y,equality_objects2_1,WF)
257 ; Res=pred_false -> not_equal_object_wf(X,Y,WF)
258 ; add_error_fail(equality_objects2,'Illegal result: ',equality_objects2(X,Y,Res,WF))
259 ).
260 ?equality_objects2([H|T],S,Res,WF) :- !,eq_cons(S,H,T,Res,WF). % move to equality_objects1 ?!
261 equality_objects2(avl_set(A),S,Res,WF) :-
262 (S=[H|T] -> !, eq_cons(avl_set(A),H,T,Res,WF)
263 ; S = [] -> !, (A=empty -> add_warning(equality_objects2,'Empty avl_set'), Res=pred_true
264 ; Res=pred_false)).
265 equality_objects2(ES1,ES2,Res,WF) :-
266 equality_explicit_sets_wf(ES1,ES2,ERes,WF), !,
267 Res=ERes.
268 equality_objects2(ES1,S,Res,WF) :- is_custom_explicit_set(ES1,eq_cons),!, % move to custom_explicit_sets?
269 % S = [] or ES1 = [] is already covered above
270 ? (S=[H|T] -> eq_cons(ES1,H,T,Res,WF) % maybe we can avoid expanding ES1
271 ; is_infinite_explicit_set(ES1),is_custom_explicit_set(S,eq_cons)
272 -> expand_custom_set_wf(S,ExpSet,equality_objects2,WF),
273 equality_objects0(ExpSet,ES1,Res,WF)
274 ; expand_custom_set_wf(ES1,ExpSet,equality_objects2,WF), equality_objects0(ExpSet,S,Res,WF)
275 ).
276 equality_objects2(X,Y,Res,WF) :-
277 add_internal_error('Unknown objects:',equality_objects2(X,Y,Res,WF)), % could happen with abort(.) terms ?
278 (equal_object_wf(X,Y,equality_objects2_2,WF),Res=pred_true
279 ;
280 not_equal_object_wf(X,Y,WF),Res=pred_false
281 ).
282
283 %:- use_module(b_global_sets,[b_get_fd_type_bounds/3]).
284 equality_fd_objects(X,Y,_,Res) :- number(X),number(Y),!,
285 (X=Y -> Res=pred_true ; Res= pred_false).
286 equality_fd_objects(X,Y,_,Res) :- % check for attached dif co-routines; later we should probably use CHR
287 fd_frozen_dif(X,Y),!,
288 % THIS DROPS THE PERFORMANCE OF probsli ../prob_examples/examples/B/ClearSy/alloc_large.mch -init -p TIME_OUT 5000
289 Res=pred_false.
290 % Is it really necessary to keep code below: clp(FD) will do this for us ?!
291 equality_fd_objects(X,Y,Type,Res) :-
292 nonvar(Type),b_global_sets:b_get_fd_type_bounds(Type,LowBnd,UpBnd),!,
293 (LowBnd=UpBnd
294 -> X=Y,Res=pred_true /* only one object of Type exists */
295 ; LB1 is LowBnd+1,
296 (LB1 = UpBnd
297 -> bin_eq_atomic(X,Y,Res,LowBnd,UpBnd) /* two objects exist */
298 ; eq_atomic_simple(X,Y,global(Type),Res),
299 (var(Res),(var(X);var(Y))
300 -> clpfd_in_domain(X,LowBnd,UpBnd), % just like X in LowBnd..UpBnd but can deal with UpBnd=inf
301 clpfd_in_domain(Y,LowBnd,UpBnd),
302 % still required ! even with fd_utils_clpfd ! (for v8 of Bosch CrCtl_Comb2_Final_mch.eventb)
303 equality_fd(X,Y,Res)
304 ; true
305 )
306 )
307 ).
308 equality_fd_objects(X,Y,Type,Res) :-
309 add_internal_error('Unknown type: ',equality_fd_objects(X,Y,Type,Res)),
310 eq_atomic_simple(X,Y,global(Type),Res).
311
312
313 % a reified version of equality
314 %equality_fd(X,Y,Res) :- X==Y,!, Res=pred_true. % not necessary; syntactic_equality_test below will trigger
315 equality_fd(X,Y,Res) :-
316 ((X#=Y) #<=> Reification01),
317 % (preferences:preference(use_chr_solver,true) -> chr_eq(X,Y,Res) ; true), Probably not useful as we do not keep track of info for FD variables; Sebastian: please investigate
318 prop_eq_01(Res,Reification01),
319 (var(Reification01)
320 -> syntactic_equality_test(X,Y,Res)
321 ; true).
322
323
324 % propagate pred_false/true <-> 0/1
325 :- block prop_eq_01(-,-).
326 % prop_eq_01(A,B) :- print(prop(A,B)),nl,fail.
327 ?prop_eq_01(P,B) :- var(P), !, prop_01_eq(B,P).
328 prop_eq_01(pred_true,1).
329 prop_eq_01(pred_false,0).
330 prop_01_eq(1,pred_true).
331 prop_01_eq(0,pred_false).
332
333
334 :- use_module(kernel_non_empty_attr,[get_empty_set_attr/3]).
335 %eq_empty_set(Set,PredRes) :-
336 % var(Set), var(PredRes), clpfd_card_is_gt0_for_var(Set),!, PredRes=false.
337 %eq_empty_set(Set,Res) :- eq_empty_set_attr_wf(Set,Res,no_wf_available).
338
339 eq_empty_set_attr_wf(Set,PredRes,WF) :- var(PredRes), var(Set),!,
340 get_empty_set_attr(Set,PredRes,ExistsAlready), % get attribute or create one if it does not exist
341 (ExistsAlready=is_empty_attr_exists
342 -> true % no need to compute the predicate; another call will already do it
343 ; eq_empty_set_wf(Set,PredRes,WF)).
344 eq_empty_set_attr_wf(X,R,WF) :- eq_empty_set_wf(X,R,WF).
345
346 :- use_module(kernel_waitflags,[add_error_wf/5]).
347
348 :- block eq_empty_set_wf(-,-,?).
349 % TO DO: inspect kernel_cardinality attributes
350 eq_empty_set_wf(X,R,WF) :- var(X),!,
351 ? (R=pred_true -> empty_set_wf(X,WF) ; not_empty_set_wf(X,WF)).
352 eq_empty_set_wf([],R,_) :- !,R=pred_true.
353 eq_empty_set_wf([_|_],R,_) :- !,R=pred_false.
354 eq_empty_set_wf(CS,R,WF) :- is_custom_explicit_set(CS,eq_empty_set_wf),!,
355 test_empty_explicit_set_wf(CS,R,WF).
356 eq_empty_set_wf(S,R,WF) :-
357 (S==term(undefined)
358 -> add_error_wf(eq_empty_set_wf,'Accessing uninitialised set value','',unknown,WF)
359 ; add_internal_error('Illegal Set: ',eq_empty_set_wf(S,R,_))
360 ),fail.
361
362
363 %%eq_cons(S,H,T,Res,_) :- print(eq_cons(S,H,T,Res)),nl,fail.
364 eq_cons([],_,_,Res,_) :- !, Res=pred_false.
365 eq_cons([H2|T2],H1,T1,Res,WF) :- !, % T2==[] checked? TODO: call eq_singleton_set_cons
366 check_and_remove_wf([H2|T2],H1,NewSet2,RemoveSuccesful,WF),
367 %% print(removed(H1,H2,T2,NewSet2,RemoveSuccesful)), %%
368 ? eq_cons2(RemoveSuccesful,H1,T1,H2,T2,NewSet2,Res,WF).
369 eq_cons(avl_set(A),H1,T1,Res,WF) :- !,
370 ? eq_cons_avl_set(A,H1,T1,Res,WF).
371 eq_cons(global_set(G),_H,T,Res,WF) :- %print(chk(G,H,T)),nl,
372 is_infinite_global_set(G,_),!,
373 expand_custom_set_to_list_wf(T,_ET,_Done,eq_cons,WF), % this will either succeed and we have a finite list ; or it will raise an enumeration warning exception
374 Res = pred_false.
375 eq_cons(ES,H1,T1,Res,WF) :- is_custom_explicit_set(ES,eq_cons),
376 expand_custom_set_wf(ES,ExpSet,eq_cons,WF),
377 ? eq_cons1(ExpSet,H1,T1,Res,WF).
378
379 % check if {H2} = {H1|T1}
380 eq_singleton_set_cons(H2,H1,T1,Res,WF) :- T1==[], !, equality_objects_wf_no_enum(H2,H1,Res,WF).
381 eq_singleton_set_cons(H2,H1,T1,Res,WF) :- empty_set_test_wf(T1,T1Empty,WF),
382 % TODO: we could also call equality_objects(H2,H1,H2H1Eq) if T1Empty is not known and conjoin it
383 ? eq_singleton2(H2,H1,T1Empty,Res,WF).
384
385 :- block eq_singleton2(?,?,-,-,?).
386 eq_singleton2(H2,H1,T1Empty,Res,WF) :- T1Empty==pred_true,!,
387 ? equality_objects_wf_no_enum(H2,H1,Res,WF).
388 eq_singleton2(_,_,T1Empty,Res,_) :- T1Empty==pred_false,!,
389 Res=pred_false. % if T1 is not empty, [H1|T1] is different from [H2]
390 eq_singleton2(H2,H1,T1Empty,Res,WF) :- Res==pred_true,!,T1Empty=pred_true,
391 equal_object_wf(H2,H1,eq_singleton2,WF).
392 eq_singleton2(H2,H1,T1Empty,Res,WF) :- Res==pred_false,!,
393 when(nonvar(T1Empty),eq_singleton2(H2,H1,T1Empty,Res,WF)).
394
395
396 % this treatment (second clause) is relevant for avoiding unnecessary choice points
397 % see e.g. codespeed test probsli ../prob_examples/examples/B/Alstom/vesg_Aug11/gradient_train_altitude.mch -animate 5 -p TIME_OUT 300000000 -p MAXINT 2147483647 -p MININT -2147483647 -p CLPFD TRUE (walltime/2471)
398 eq_cons_avl_set(A,H1,T1,Res,WF) :- is_one_element_avl(A,AEl),
399 !,
400 ? eq_singleton_set_cons(AEl,H1,T1,Res,WF).
401 eq_cons_avl_set(A,H1,T1,Res,WF) :-
402 (var(Res) -> kernel_tools:ground_value_check(H1,GrH1) ; true), % if Res already bound, no need to do ground check
403 ? block_eq_cons_avl_set(A,H1,T1,Res,GrH1,WF).
404 :- block block_eq_cons_avl_set(?,?,?,-,-,?).
405 block_eq_cons_avl_set(A,H1,T1,Res,_,WF) :- Res==pred_true,!,
406 kernel_objects:equal_custom_explicit_set_cons_wf(avl_set(A),H1,T1,WF).
407 block_eq_cons_avl_set(A,H1,T1,Res,_,WF) :-
408 element_can_be_added_or_removed_to_avl(H1),!, % should hopefully be true as H1 is now ground
409 (remove_element_from_explicit_set(avl_set(A),H1,RA)
410 ? -> equality_objects_with_expansion(T1,RA,Res,WF) %%% PROBLEM: T1 has to be in list form !
411 ; Res = pred_false
412 ).
413 block_eq_cons_avl_set(A,H1,T1,Res,_,WF) :-
414 % TO DO: we could call propagate_avl_element_information(X,AVL,ApproxSize,WF) if Res=pred_true and with WF or something similar higher up to detect when an element cannot be within the AVL set
415 expand_custom_set_wf(avl_set(A),ExpSet,block_eq_cons_avl_set,WF),
416 eq_cons1(ExpSet,H1,T1,Res,WF).
417
418 :- block eq_cons1(-,?,?,?,?).
419 ?eq_cons1(ExpSet,H1,T1,Res,WF) :- eq_cons(ExpSet,H1,T1,Res,WF).
420
421 :- block eq_cons2(-, ?,?,?,?, ?,-,?).
422 eq_cons2(RemoveSuccesful, H1,T1,H2,T2, _NewSet2,Res,WF) :- var(RemoveSuccesful),!,
423 % result has been instantiated before Remove finished; now force equal_object or not_equal_object
424 % note: without this the remove could be pending (see test 1112, 1105)
425 % TO DO: look whether we could force remove and continue from there ?
426 ? equality_objects2([H1|T1],[H2|T2],Res,WF).
427 eq_cons2(not_successful, _,_T1,_,_, _NewSet2,pred_false,_).
428 ?eq_cons2(successful, _, T1,_,_, NewSet2,Res,WF) :- equality_objects_wf_no_enum(T1,NewSet2,Res,WF).
429
430
431 check_and_remove(Set,ElementToRemove,ResultingSet,Res) :-
432 check_and_remove_wf(Set,ElementToRemove,ResultingSet,Res,no_wf_available).
433
434 :- block check_and_remove_wf(-,?,?,?,?).
435 check_and_remove_wf([],_,ResultingSet,Res,_) :- !, ResultingSet=[],Res=not_successful.
436 check_and_remove_wf([H|T],ElementToRemove,ResultingSet,Res,WF) :- !,
437 equality_objects_wf_no_enum(H,ElementToRemove,RH,WF),
438 %%print(equality_objects_result(H,ElementToRemove,RH)),nl,
439 ? check_and_remove2(RH,H,T,ElementToRemove,ResultingSet,Res,WF).
440 check_and_remove_wf(CS,ElementToRemove,ResultingSet,Res,WF) :-
441 expand_custom_set_to_list_wf(CS,ESet,_,check_and_remove,WF),
442 check_and_remove_wf(ESet,ElementToRemove,ResultingSet,Res,WF).
443
444 :- block check_and_remove2(-,?,?,?,?,?,?).
445 check_and_remove2(pred_true, _H,T,_ElementToRemove,T,successful,_).
446 check_and_remove2(pred_false,H,T,ElementToRemove,[H|RT],Res,WF) :-
447 ? check_and_remove_wf(T,ElementToRemove,RT,Res,WF).
448
449
450 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:and_equality(pred_false,pred_false,pred_false))).
451 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:and_equality(pred_true,pred_false,pred_false))).
452 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:and_equality(pred_true,pred_true,pred_true))).
453 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:and_equality(pred_true,pred_true,pred_false))).
454 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:and_equality(pred_true,pred_false,pred_true))).
455 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:and_equality(pred_false,pred_true,pred_true))).
456 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:and_equality(pred_false,pred_false,pred_true))).
457 :- block and_equality(-,-,-).
458 and_equality(X,Y,Res) :-
459 ( X==pred_true -> Res=Y
460 ; X==pred_false -> Res=pred_false
461 ; Y==pred_true -> Res=X
462 ; Y==pred_false -> Res=pred_false
463 ; Res==pred_true -> X=pred_true, Y=pred_true
464 ; Res==pred_false -> and_equality2(X,Y,Res) % we know that one of X,Y must be pred_false; if X==Y we could infer X=Y=pred_false
465 ; add_error_fail(and_equality,'Illegal call: ',and_equality(X,Y,Res))
466 ).
467 :- block and_equality2(-,-,?).
468 and_equality2(X,Y,Res) :-
469 ( X==pred_true -> Res=Y
470 ; X==pred_false -> Res=pred_false
471 ; Y==pred_true -> Res=X
472 ; Y==pred_false -> Res=pred_false
473 ; add_error_fail(and_equality,'Illegal call: ',and_equality2(X,Y,Res))
474 ).
475
476 /*
477 :- block bool_eq_atomic(-,?,?,-).
478 bool_eq_atomic(X,Y,OtherY,Res) :- nonvar(Res),!,
479 (Res=pred_true -> X=Y ; X=OtherY).
480 bool_eq_atomic(X,Y,_,Res) :- X==Y -> Res=pred_true ; Res=pred_false. */
481
482 % a version for base types with just two possible values
483 :- block bin_eq_atomic(-,?,-,?,?), bin_eq_atomic(?,-,-,?,?).
484 % no need to check for frozen_dif: a dif would instantly trigger instantiation to other value
485 % However, we could use when(?=(X,Y) ; nonvar(Res) as trigger ! maybe this would slowdown SATLIB tests ??
486 bin_eq_atomic(X,Y,Res,V1,V2) :- nonvar(Res),!,
487 %print(forcing_bin_eq_atomic(X,Y,Res,V1,V2)),nl,
488 (Res=pred_true -> X=Y
489 ; %print(bin_dif(X,Y)),nl,
490 (X=V1,Y=V2 ; X=V2,Y=V1)
491 ). % difference with eq_atomic: we now know the value !
492 bin_eq_atomic(X,Y,Res,_,_) :-
493 %print(triggering_bin_eq(X,Y,Res)), translate:print_frozen_info(Res),nl,
494 (X==Y -> Res=pred_true ; Res=pred_false).
495
496 eq_atomic(X,Y,_Type,Res) :- nonvar(X),nonvar(Y),!,
497 (X=Y -> Res=pred_true ; Res=pred_false).
498 eq_atomic(X,Y,_,Res) :- % check for attached dif co-routines; later we should probably use CHR
499 ? frozen_dif(X,Y),!, Res=pred_false.
500 eq_atomic(X,Y,Type,Res) :- when((?=(X,Y);nonvar(Res)),eq_atomic2(X,Y,Type,Res)).
501
502 % version of eq_atomic without frozen_dif check (if already performed)
503 % eq_atomic_simple(X,Y,_Type,Res) :- % in all calling contexts this test is already performed
504 % nonvar(X),nonvar(Y),!, (X=Y -> Res=pred_true ; Res=pred_false).
505 eq_atomic_simple(X,Y,Type,Res) :- when((?=(X,Y);nonvar(Res)),eq_atomic2(X,Y,Type,Res)).
506
507 /*
508 Comment: % for integers CLPFD reification will not ground Res if X==Y, need to do when((?=(X,Y)...
509 | ?- X in 1..10, Y in 1..10, (X#=Y #<=> Z), X=Y.
510 Y = X,
511 X in 1..10,
512 Z in 0..1 ? */
513
514 eq_atomic2(X,Y,Type,Res) :- nonvar(Res),!,
515 ? (Res=pred_true -> X=Y ; dif(Type,X,Y)).
516 eq_atomic2(X,Y,_Type,Res) :-
517 (X=Y -> Res=pred_true
518 ; Res=pred_false).
519
520 :- block eq_term_wf(-,-,?,?).
521 eq_term_wf(TX,TY,Res,_WF) :- nonvar(TX),TX = floating(FX),!,
522 TY=floating(FY), eq_atomic(FX,FY,real,Res). % TODO: use a proper equality check for reals/floats
523 eq_term_wf(TY,TX,Res,_WF) :- nonvar(TX),TX = floating(FX),!,
524 TY=floating(FY), eq_atomic(FX,FY,real,Res).
525 eq_term_wf(TX,TY,Res,_) :- eq_atomic(TX,TY,term,Res).
526
527 :- use_module(fd_utils_clpfd,[neq_fd/3]).
528 dif(boolean,A,B) :- !,
529 bool_pred:negate(A,B). % was: bool_dif(A,B).
530 % usually not covered: equality_objects_with_type calls bool_equality,
531 % equality_objects waits for either arg to be fully instantiated to pred_false or pred_true
532 dif(integer,A,B) :- !, integer_dif(A,B).
533 ?dif(global(T),A,B) :- !, neq_fd(A,B,T).
534 dif(_,A,B) :- dif(A,B).
535
536 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:integer_dif(0,1))).
537 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:integer_dif(1,1))).
538 :- use_module(clpfd_interface,[clpfd_neq/2]).
539 integer_dif(A,B) :- clpfd_neq(A,B). % clpfd_neq calls dif on overflow
540
541
542 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:bool_dif(pred_false,pred_true))).
543 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:bool_dif(pred_true,pred_false))).
544 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:bool_dif(pred_true,pred_true))).
545 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:bool_dif(pred_false,pred_false))).
546 bool_dif(A,B) :- bool_pred:negate(A,B).
547
548 /* old version:
549 :- block eq_atomic(-,?,-), eq_atomic(?,-,-).
550 eq_atomic(X,Y,Res) :- nonvar(Res),!,
551 (Res=pred_true -> X=Y ; dif(X,Y)).
552 eq_atomic(X,Y,Res) :- X==Y -> Res=pred_true
553 ; Res=pred_false.
554 */
555
556 :- use_module(kernel_records,[check_field_name_compatibility/3]).
557 :- block equality_fields(-,?,-,?), equality_fields(?,-,-,?), equality_fields(-,-,?,?).
558 % if last argument is known we should propagate the field names from one record to another; see test 1289 (Hansen12)
559 equality_fields([],[],pred_true,_).
560 equality_fields([field(Name1,V1)|T1],[field(Name2,V2)|T2],Res,WF) :-
561 % should we wait for Name1 or Name2 to become nonvar?
562 check_field_name_compatibility(Name1,Name2,equality_fields),
563 and_equality(RH,RT,Res),
564 equality_objects_wf_no_enum(V1,V2,RH,WF),
565 (RH==pred_false -> true
566 ? ; equality_fields(T1,T2,RT,WF)).
567
568
569
570 empty_set_test_wf(Set,EqRes,WF) :- eq_empty_set_attr_wf(Set,EqRes,WF).
571 empty_set_test(Set,EqRes) :- eq_empty_set_attr_wf(Set,EqRes,no_wf_available).
572 empty_cartesian_product_wf(Set1,Set2,EqRes,WF) :- % TO DO: pass WF
573 eq_empty_set_wf(Set1,EqRes1,WF),
574 (EqRes1==pred_true -> EqRes=pred_true /* avoid inspecting Set2 */
575 ; or_eq_obj(EqRes1,EqRes2,EqRes),
576 eq_empty_set_wf(Set2,EqRes2,WF)).
577
578
579 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:or_eq_obj(pred_false,pred_false,pred_false))).
580 :- assert_must_succeed(exhaustive_kernel_check([commutative],kernel_equality:or_eq_obj(pred_false,pred_true,pred_true))).
581 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:or_eq_obj(pred_true,pred_true,pred_true))).
582 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:or_eq_obj(pred_true,pred_true,pred_false))).
583 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:or_eq_obj(pred_true,pred_false,pred_false))).
584 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:or_eq_obj(pred_false,pred_true,pred_false))).
585 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:or_eq_obj(pred_false,pred_false,pred_true))).
586 :- block or_eq_obj(-,-,-).
587 % very similar to disjoin in b_interpreter_check; no waitflag to instantiate if result false
588 or_eq_obj(X,Y,XorY) :-
589 ( (X==pred_true ; Y==pred_true) -> XorY=pred_true
590 ; XorY==pred_false -> X=pred_false,Y=pred_false
591 ; X==pred_false -> XorY = Y
592 ; Y==pred_false -> XorY = X
593 ; XorY==pred_true -> or_eq_obj2(X,Y)
594 ; add_internal_error('Illegal call: ',or_eq_obj(X,Y,XorY)) ).
595 :- block or_eq_obj2(-,-).
596 or_eq_obj2(X,Y) :- ((X==pred_true; Y=pred_true) -> true
597 ; X==pred_false -> Y=pred_true
598 ; Y==pred_false -> X=pred_true
599 ; add_internal_error('Illegal call: ',or_eq_obj2(X,Y))).
600
601 % ------------------------------------------------------------------
602
603
604 % not used at the moment:
605 %get_partial_subset_priority(Set,WF,LWF) :- get_partial_set_size(Set,Size),
606 % safe_pow2(Size,Prio),
607 % get_wait_flag(Prio,psubset(Set),WF,LWF).
608 %get_partial_set_priority(Set,WF,LWF) :- get_partial_set_size(Set,Size),
609 % get_wait_flag(Size,pset(Set),WF,LWF).
610 %get_partial_set_size(X,R) :- var(X),!,R=3.
611 %get_partial_set_size([],R) :- !,R=0.
612 %get_partial_set_size([_|T],R) :- !,get_partial_set_size(T,RT), R is RT+1.
613 %get_partial_set_size(_,10).
614
615
616 get_cardinality_wait_flag(Set,Info,WF,LWF) :-
617 get_cardinality_wait_flag(Set,Info,WF,_Card,LWF).
618 get_cardinality_wait_flag(Set,Info,WF,Card,LWF) :-
619 cardinality_as_int_for_wf(Set,Card),
620 % when(nonvar(X), (print(get_card_waitflag(X,Set,WF,LWF)),nl)),
621 (var(Card)
622 -> kernel_waitflags:get_last_wait_flag(get_cardinality_wait_flag(Info),WF,LastWF)
623 ; true), % ensure that we trigger choice points waiting on LWF before infinite enumeration starts
624 get_cardinality_wait_flag2(Card,Info,WF,LastWF,LWF).
625 :- block get_cardinality_wait_flag2(-,?,?,-,?).
626 get_cardinality_wait_flag2(X,_Info,_WF,LastWF,LWF) :- var(X),!,LWF=LastWF.
627 get_cardinality_wait_flag2(X,Info,WF,_,LWF) :- get_bounded_wait_flag(X,Info,WF,LWF).
628
629 get_cardinality_powset_wait_flag(Set,Info,WF,CardSet,LWF) :-
630 cardinality_as_int_for_wf(Set,CardSet),
631 get_cardinality_powset_wait_flag2(CardSet,Info,WF,LWF).
632 :- block get_cardinality_powset_wait_flag2(-,?,?,?).
633 get_cardinality_powset_wait_flag2(X,Info,WF,LWF) :-
634 safe_pow2(X,X2),
635 %safe_mul(X2,10000,X3), % as generating subsets this way will generate repetitions
636 (is_inf_or_overflow_card(X2)
637 -> integer_pow2_priority(R), get_wait_flag(R,powset_card(Info),WF,LWF)
638 ; get_bounded_wait_flag(X2,powset_card(Info),WF,LWF) % finite prio; ensure we do not exceed infinite prios if X2 very large
639 ).
640
641
642 % CARDINALITY FOR NUMBER OF PARTIAL FUNCTIONS: (not used at the moment)
643 %get_cardinality_partial_function_wait_flag(DomSet,RanSet,Info,WF,CardDomSet,CardRanSet,LWF) :-
644 % cardinality_as_int_for_wf(DomSet,CardDomSet),
645 % cardinality_as_int_for_wf(RanSet,CardRanSet),
646 % get_cardinality_partial_function_wait_flag(CardDomSet,CardRanSet,Info,WF,LWF).
647 %:- block get_cardinality_partial_function_wait_flag(-,?,?,?,?),
648 % get_cardinality_partial_function_wait_flag(?,-,?,?,?).
649 %get_cardinality_partial_function_wait_flag(DC,RC,Info,WF,LWF) :-
650 % priority_pow1n(RC,DC,PFCARD), print(prio(PFCARD)),nl,
651 % get_bounded_wait_flag(PFCARD,powset_card(Info),WF,LWF).
652 % % Cardinality of the set of partial functions : (card(Range)+1)^card(Domain)
653 %priority_pow1n(X,Y,R) :- (X==inf ; Y==inf),!, integer_pow2_priority(R). %R=10000010. % TO DO: provide a separate module for combining priorities in a systematic way !
654 %priority_pow1n(X,Y,RR) :- X1 is X+1, safe_pown(X1,Y,R),
655 % (R==inf -> integer_pow2_priority(RR) %RR=10000010
656 % ; RR=R).
657
658 % CARDINALITY FOR NUMBER OF RELATIONS:
659 get_cardinality_relation_over_wait_flag(Dom,Ran,WF,LWF,MaxCardOfRel,MaxNrOfRels) :-
660 cardinality_as_int_for_wf(Dom,X),
661 cardinality_as_int_for_wf(Ran,Y),
662 get_cardinality_relation_over_wait_flag2(X,Y,WF,LWF,MaxCardOfRel,MaxNrOfRels).
663
664 :- block get_cardinality_relation_over_wait_flag2(-,?,?,?,?,?), get_cardinality_relation_over_wait_flag2(?,-,?,?,?,?).
665 get_cardinality_relation_over_wait_flag2(X,Y,WF,LWF,MaxCardOfRel,MaxNrOfRels1) :-
666 safe_mul(X,Y,MaxCardOfRel),
667 safe_pow2(MaxCardOfRel,MaxNrOfRels),
668 safe_add_card(MaxNrOfRels,1,MaxNrOfRels1), /* add 1 to give priority to tighter_enum */
669 get_bounded_wait_flag(MaxNrOfRels1,powset_rel_card,WF,LWF).
670
671 % ------------------------------------------------------------------
672
673 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([int(2),int(1)],int(2),pred_true,WF),WF)).
674 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([int(2),int(1)],int(1),pred_true,WF),WF)).
675 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([int(2),int(1),int(3),int(4),int(5)],int(4),pred_true,WF),WF)).
676 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([int(2),int(1)],int(3),pred_false,WF),WF)).
677 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([],int(3),pred_false,WF),WF)).
678 :- assert_must_succeed(exhaustive_kernel_fail_check_wf(kernel_equality:membership_test_wf([int(2),int(1)],int(3),pred_true,WF),WF)).
679 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([[int(2)],[int(1),int(3)],[int(4),int(1)]],[int(1),int(4)],pred_true,WF),WF)).
680 :- assert_must_succeed(exhaustive_kernel_check_wf(kernel_equality:membership_test_wf([[int(2)],[int(1),int(3)],[int(4),int(1)]],[int(4)],pred_false,WF),WF)).
681 :- assert_must_succeed(exhaustive_kernel_fail_check_wf(kernel_equality:membership_test_wf([[int(2)],[int(1),int(3)],[int(4),int(1)]],[int(4)],pred_true,WF),WF)).
682 :- assert_must_succeed((membership_test_wf([int(2),int(1)],int(2),R,_WF),R==pred_true)).
683 :- assert_must_succeed((membership_test_wf([int(2),int(1)],int(X),R,_WF),var(R),X=1,R==pred_true)).
684 :- assert_must_succeed((membership_test_wf([int(2),int(1)],int(3),R,_WF),R==pred_false)).
685 :- assert_must_succeed((membership_test_wf(global_set('Name'),fd(1,'Name'),R,_WF),R==pred_true)).
686
687 :- assert_must_succeed((kernel_equality:membership_test_wf(avl_set(node(rec([field(cardinality,int(2)),field(col,fd(2,setField1)),field(fill,fd(1,setField2)),field(shape,fd(1,setField1))]),true,0,empty,empty)),
688 rec([field(cardinality,int(2)),field(col,fd(2,setField1)),field(fill,fd(1,setField2)),field(shape,fd(1,setField1))]),R,_WF), R==pred_true)).
689 :- assert_must_succeed((
690 kernel_equality:membership_test_wf([rec([field(cardinality,int(2)),field(col,fd(2,setField1)),field(fill,fd(1,setField2)),field(shape,fd(1,setField1))])],
691 rec([field(cardinality,int(2)),field(col,fd(2,setField1)),field(fill,fd(1,setField2)),field(shape,fd(1,setField1))]),R,_WF), R==pred_true
692 )).
693 /* membership_test_wf: A function that instantiates last argument when membership test can be decided */
694
695
696 % a version which also creates a choice point in SMT mode
697 membership_test_wf_with_force(Set,X,Res,WF) :-
698 membership_test_wf(Set,X,Res,outer,WF),
699 enum_equality_result_smt_mode_wf(Res,membership_test_wf,WF).
700 :- block force_equality_result(-,-).
701 force_equality_result(pred_true,_).
702 force_equality_result(pred_false,_).
703
704 enum_equality_result_smt_mode_wf(Res,PP,WF) :- var(Res),
705 preferences:preference(use_smt_mode,true),!,
706 enum_equality_result_wf(Res,PP,WF).
707 enum_equality_result_smt_mode_wf(_,_,_).
708
709 enum_equality_result_wf(Res,PP,WF) :-
710 get_last_wait_flag(PP,WF,LWF),
711 force_equality_result(Res,LWF).
712
713 ?membership_test_wf(Set,X,Res,WF) :- membership_test_wf(Set,X,Res,outer,WF).
714
715 :- load_files(library(system), [when(compile_time), imports([environ/2])]).
716 :- if(environ(prob_data_validation_mode,true)).
717 :- block membership_test_wf(-,?,?,?,?). % avoid instantiating Set
718 :- else.
719 :- block membership_test_wf(-,?,-,?,?).
720 :- endif.
721 membership_test_wf(Set,X,Res,_OuterInner,WF) :- nonvar(Res),!,
722 (Res==pred_true
723 ? -> call_check_element_of_wf0(X,Set,WF)
724 /* (kernel_objects:unbound_variable_for_cons(Set)
725 -> kernel_objects:mark_as_non_free(X), % attach co-routine to indicate that we cannot freely chose X
726 print(instantiate_set(Set,X,Res)),nl,
727 Set=[X|_] % TO DO: normalise X first ?
728 ; when(nonvar(Set), membership_test_wf2(Set,X,Res,OuterInner,WF))
729 ) */
730 ; membership_not_el(Set,X,WF)).
731 membership_test_wf(Set,X,Res,OuterInner,WF) :-
732 ? membership_test_wf2(Set,X,Res,OuterInner,WF).
733
734 % we are not sure if WF0 is set; go via kernel_mappings:
735 call_check_element_of_wf0(X,Set,WF) :- get_wait_flag0(WF,WF0),
736 ? kernel_mappings:check_element_of_wf0(X,Set,WF,WF0,unknown).
737
738
739 :- block membership_not_el(-,?,?).
740 membership_not_el([],_,_WF) :- !.
741 membership_not_el([H|T],X,WF) :- !,
742 ? not_equal_object_wf(H,X,WF),
743 membership_not_el(T,X,WF).
744 membership_not_el(avl_set(A),X,WF) :- !,membership_custom_set_wf(avl_set(A),X,pred_false,WF).
745 membership_not_el(CS,X,WF) :- is_custom_explicit_set_nonvar(CS),!,
746 membership_custom_set_wf(CS,X,pred_false,WF).
747
748 membership_test_wf2([],_X,Res,_,_WF) :- !, Res=pred_false.
749 membership_test_wf2([H|T],X,Res,OuterInner,WF) :- !,
750 (Res==pred_false
751 -> not_equal_object_wf(H,X,WF), membership_test_wf(T,X,Res,WF)
752 ? ; T==[] -> equality_objects_wf_no_enum(H,X,Res,WF)
753 % TO DO: at the outer level we could check whether the list has the same length as the type of X
754 ; OuterInner=outer, is_definitely_maximal_set([H|T]) -> Res=pred_true
755 ; (OuterInner=outer, % avoid re-checking ground_list_with_fd over and over again
756 preferences:preference(use_clpfd_solver,true),
757 ground_list_with_fd([H|T]),
758 construct_avl_from_lists_wf([H|T],CS,WF))
759 % this slows down: probsli ../prob_examples/public_examples/EventBPrologPackages/SET_Game/SET_GAM_Sym_NoSet20_mch.eventb -mc 10000000 -expcterr goal_found -p SYMMETRY_MODE hash -p TIME_OUT 7000 -p CLPFD TRUE -df -goal "n=18" -p MAX_OPERATIONS 82 -cc 155 833
760 % TO DO: call clpfd_reify_inlist directly ? avoid translating to AVL and back to list; detect maximal list
761 -> membership_custom_set_wf(CS,X,Res,WF) %, print(conv_to_avl(X,[H|T],CS,Res)),nl
762 ; %print(eq(Res,H,X,T,WF)),nl,equality_objects_wf_dbg(H,X,HXRes,WF), % makes test 1003 : plavis-MemoryLoad_SP_55 fail
763 ? equality_objects_wf_no_enum(H,X,HXRes,WF),cons_el_of(HXRes,T,X,Res,WF)
764 % ,(var(HXRes) -> print(mem(X,[H|T],Res)), tools_printing:print_arg(X),nl ; true)
765 ).
766 membership_test_wf2(avl_set(A),X,Res,_,WF) :- !, membership_avl_set_wf(A,X,Res,WF).
767 membership_test_wf2(CS,X,Res,_,WF) :- is_custom_explicit_set(CS,membership_test_wf),!,
768 membership_custom_set_wf(CS,X,Res,WF).
769 membership_test_wf2(term(Z),_,_,_,_WF) :- Z==undefined,!,
770 add_error_fail(membership_test_wf,'Encountered uninitialised set variable', ''). % we will normally generate other error messages as well
771 membership_test_wf2(Z,X,Res,OuterInner,WF) :-
772 add_error_fail(membership_test_wf,'Not Set as first argument: ', membership_test_wf(Z,X,Res,OuterInner,WF)).
773
774 % detect certain lists containing FD values and convert them to avl sets: they have improved reification and can detect when a list is complete
775 ground_list_with_fd(V) :- var(V),!,fail.
776 ground_list_with_fd([H|T]) :- nonvar(H),ground_val(H),ground_list_with_fd(T).
777 ground_list_with_fd([]).
778
779 :- use_module(kernel_tools,[ground_value/1]).
780 ground_val(int(X)) :- number(X).
781 ground_val(pred_false).
782 ground_val(pred_true).
783 ground_val(fd(X,T)) :- number(X),ground(T).
784 ground_val((A,B)) :- nonvar(A),ground_val(A),ground_value(B).
785 ground_val(rec(Fields)) :- nonvar(Fields), Fields = [field(Name,V)|TFields], ground(Name),
786 ground_val(V),
787 ground_value(rec(TFields)).
788 % TO DO: add more checks; do we need this check ? related to is_avl_fd_index_set
789
790 :- block cons_el_of(-,?,?,-,?).
791 cons_el_of(HX_EQRES,T,X,MEMRES,WF) :- var(HX_EQRES),!, %print(cons_el_of(HX_EQRES,T,X,MEMRES)),nl,
792 (MEMRES=pred_false -> HX_EQRES=pred_false, /* otherwise element of set */
793 ? membership_not_el(T,X,WF)
794 % MEMRES must be pred_true
795 ; (T==[] -> %print(forcing_cons_el_of(T,X,MEMRES)),nl,
796 HX_EQRES=pred_true
797 ; cons_el_of_mem_obj(HX_EQRES,T,X,WF)) /* we have to wait for result of comparison with X */
798 ).
799 cons_el_of(pred_true,_,_,pred_true,_WF).
800 cons_el_of(pred_false,T,X,Res,WF) :-
801 (Res==pred_true -> non_empty_chk(T) ; true),
802 ? membership_test_wf(T,X,Res,inner,WF).
803
804 non_empty_chk(V) :- var(V),!,V=[_|_].
805 non_empty_chk(X) :- X \= []. % could be avl_set or closure
806
807 :- block cons_el_of_mem_obj(-,?,?,?).
808 cons_el_of_mem_obj(pred_true,_,_,_WF).
809 cons_el_of_mem_obj(pred_false,T,X,WF) :-
810 % Instantiation of T will be done by membership_test_wf, relevant for test 1273
811 ? membership_test_wf(T,X,pred_true,inner,WF).
812
813
814 :- assert_must_succeed((kernel_equality:cartesian_pair_test_wf((int(1),int(1)),
815 [int(1),int(2)],[int(2),int(3)],R,_WF),R==pred_false)).
816 :- assert_must_succeed((kernel_equality:cartesian_pair_test_wf((int(3),int(1)),
817 [int(1),int(2)],[int(2),int(3)],R,_WF),R==pred_false)).
818 :- assert_must_succeed((kernel_equality:cartesian_pair_test_wf((int(2),int(3)),
819 [int(1),int(2)],[int(2),int(3)],R,_WF),R==pred_true)).
820 :- assert_must_fail((kernel_equality:cartesian_pair_test_wf((int(1),int(3)),
821 [int(1),int(2)],[int(2),int(3)],pred_false,_WF))).
822
823 cartesian_pair_test_wf((X,Y),XType,YType,Res,WF) :- check_cartesian_pair1(X,XType,Y,YType,Res,WF).
824
825 :- block check_cartesian_pair1(-,?,-,?,-,?).
826 %check_cartesian_pair1(X,XType,Y,YType,Res) :- Res==pred_true,!,
827 % is_cartesian_pair_wf((X,Y),XType,YType,WF).
828 %check_cartesian_pair1(X,XType,Y,YType,Res) :- Res==pred_false,!,
829 % not_is_cartesian_pair((X,Y),XType,YType,WF).
830 check_cartesian_pair1(X,XType,Y,YType,Res,WF) :-
831 ((var(X),nonvar(Y)) -> check_cartesian_pair2(Y,YType,X,XType,Res,WF)
832 ; check_cartesian_pair2(X,XType,Y,YType,Res,WF)).
833
834 check_cartesian_pair2(X,XType,Y,YType,Res,WF) :- prop_pred_true(Res,MemResX),
835 membership_test_wf(XType,X,MemResX,WF),
836 ((var(MemResX), is_definitely_maximal_set(YType)) % TO DO: maybe actually also call membership_test_wf
837 -> Res=MemResX
838 ; check_cartesian_pair3(MemResX,Y,YType,Res,WF)).
839
840 :- block check_cartesian_pair3(-,?,?,?,?).
841 check_cartesian_pair3(pred_true,Y,YType,Res,WF) :- membership_test_wf(YType,Y,Res,WF).
842 check_cartesian_pair3(pred_false,_Y,_YType,pred_false,_WF).
843
844 :- block prop_pred_true(-,?).
845 prop_pred_true(pred_true,pred_true).
846 prop_pred_true(pred_false,_).
847
848
849
850
851
852 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:in_nat_range_test(int(9),int(10),int(12),pred_false))).
853 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:in_nat_range_test(int(11),int(10),int(12),pred_true))).
854 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:in_nat_range_test(int(22),int(22),int(22),pred_true))).
855 :- assert_must_succeed(exhaustive_kernel_check(kernel_equality:in_nat_range_test(int(22),int(22),int(21),pred_false))).
856 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:in_nat_range_test(int(9),int(10),int(12),pred_true))).
857 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:in_nat_range_test(int(22),int(22),int(22),pred_false))).
858 :- assert_must_succeed((in_nat_range_test(X,int(11),int(12),pred_false), X=int(10) )).
859 :- assert_must_succeed((kernel_equality:in_nat_range_test(X,int(11),int(12),pred_false), X=int(13) )).
860 :- assert_must_succeed((in_nat_range_test(X,int(11),int(12),pred_true), X=int(11) )).
861 :- assert_must_succeed((kernel_equality:in_nat_range_test(int(11),X,int(12),pred_true), X=int(11) )).
862 :- assert_must_succeed((in_nat_range_test(int(11),X,int(12),pred_false), X=int(12) )).
863 :- assert_must_succeed((kernel_equality:in_nat_range_test(int(11),int(10),int(12),R), R==pred_true )).
864 :- assert_must_fail((kernel_equality:in_nat_range_test(int(11),int(10),int(12),pred_false))).
865
866 in_nat_range_test(int(X),int(Y),int(Z),Res) :- in_nat_range_test1(X,Y,Z,Res).
867
868 in_nat_range_test1(X,Y,Z,Res) :- number(X),number(Y),number(Z),!,
869 % for improved performance, e.g., inside large set differences with intervals
870 ( X < Y -> Res = pred_false
871 ; X > Z -> Res = pred_false
872 ; Res = pred_true).
873 % this clause does not seem to add any power: (x:x..x <=> b=TRUE) already determines b=TRUE deterministically
874 %in_nat_range_test1(X,Y,Z,ResYZ) :- Y==Z, !, print(in_nat_eq_obj(X,Y,ResYZ)),nl,
875 % equality_objects(int(X),int(Y),ResYZ).
876 in_nat_range_test1(X,Y,Z,ResYZ) :-
877 prop_eq_01(ResYZ,R01),
878 % TO DO: check CHR + possibly X==Y or X==Z
879 clpfd_interface:try_post_constraint((X#>=Y #/\ X#=<Z) #<=> R01), % reify constraint if CLP(FD) active
880 %was : convert_eq_to_mem(RYZ,Res),
881 and_equality(RY,RZ,ResYZ),
882 geq_test(X,Y,RY),
883 geq_test(Z,X,RZ).
884
885 :- block geq_test(?,-,-),geq_test(-,?,-).
886 geq_test(X,Y,Res) :- % TO DO: use CHR ?
887 ( Res==pred_true -> kernel_objects:less_than_equal_direct(Y,X)
888 ; Res==pred_false -> kernel_objects:less_than_direct(X,Y)
889 ; X >= Y -> Res=pred_true
890 ; Res = pred_false
891 ).
892
893
894
895 /* SUBSET CHECK REIFICATION */
896
897 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([int(2)],[],pred_false,WF),WF)).
898 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([int(2),int(1)],[int(2)],pred_false,WF),WF)).
899 :- assert_must_succeed(exhaustive_kernel_fail_check_wfinit(kernel_equality:subset_test([int(2),int(1)],[int(2)],pred_true,WF),WF)).
900 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([int(2),int(1)],[int(2),int(1)],pred_true,WF),WF)).
901 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([int(2),int(1)],[int(2),int(1),int(3)],pred_true,WF),WF)).
902 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([int(2),int(1)],global_set('NATURAL1'),pred_true,WF),WF)).
903 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_test([],[int(2),int(1)],pred_true,WF),WF)).
904 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:subset_test([],[int(2),int(1)],pred_false,_WF))).
905 :- assert_must_succeed((kernel_equality:subset_test([],[int(3)],R,_WF),R==pred_true)).
906 :- assert_must_succeed((kernel_equality:subset_test([int(2),int(1)],[int(2),int(1),int(3)],R,_WF),R==pred_true)).
907 :- assert_must_succeed((kernel_equality:subset_test([int(2),int(1),int(4)],[int(2),int(1),int(3)],R,_WF),R==pred_false)).
908 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(1)],global_set('NATURAL'),R,_WF),R==pred_true)).
909 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(1)],global_set('NATURAL1'),R,_WF),R==pred_true)).
910 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(1),int(0)],global_set('NATURAL1'),R,_WF),R==pred_false)).
911 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(1),int(0)],X,R,_WF),X=global_set('NATURAL1'),R==pred_false)).
912 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(-11)],global_set('INTEGER'),R,_WF),R==pred_true)).
913 :- assert_must_succeed((kernel_equality:subset_test([int(222),int(-11)],global_set('INTEGER'),R,_WF),R==pred_true)).
914 :- assert_must_succeed((kernel_equality:subset_test(global_set('INTEGER'),global_set('NATURAL1'),R,_WF),R==pred_false)).
915 :- assert_must_succeed((kernel_equality:subset_test(global_set('NATURAL1'),global_set('NATURAL1'),R,_WF),R==pred_true)).
916
917 :- use_module(kernel_objects,[check_subset_of_wf/3, not_subset_of_wf/3,
918 check_subset_of_global_sets/2, check_not_subset_of_global_sets/2,
919 both_global_sets/4]).
920
921 :- use_module(custom_explicit_sets,[expand_custom_set_to_list/4,
922 expand_custom_set_to_list_no_dups_wf/5, expand_custom_set_to_list_wf/5,
923 is_definitely_maximal_set/1]).
924 :- block subset_test(-,-,-,?).
925 subset_test(_S1,S2,R,_WF) :- % tools_printing:print_term_summary(subset_test(_S1,S2,R,WF)), %%
926 is_definitely_maximal_set(S2),!,R=pred_true.
927 subset_test(S1,S2,R,WF) :- subset_test0(S1,S2,R,WF).
928
929 :- block subset_test0(-,?,-,?).
930 subset_test0(S1,S2,R,WF) :- % tools_printing:print_term_summary(subset_test0(S1,S2,R,WF)), %%
931 nonvar(R),!,
932 ? (R==pred_true -> check_subset_of_wf(S1,S2,WF)
933 ; R==pred_false -> not_subset_of_wf(S1,S2,WF)
934 ; add_error_fail(subset_test0,'Illegal result value: ',R)).
935 subset_test0([],_,R,_WF) :- !,R=pred_true.
936 subset_test0(S1,S2,R,WF) :- subset_test1(S1,S2,R,WF).
937
938
939 :- use_module(covsrc(coverage_tools_annotations),['$NOT_COVERED'/1]).
940
941 :- block subset_test1(-,?,-,?),subset_test1(?,-,-,?).
942 subset_test1(S1,S2,R,WF) :- nonvar(R),!,
943 ? (R==pred_true -> check_subset_of_wf(S1,S2,WF) ; not_subset_of_wf(S1,S2,WF)).
944 subset_test1([],_,R,_WF) :- !,R=pred_true, '$NOT_COVERED'('cannot be covered'). /* cannot be covered; emtpy set treated above */
945 subset_test1(Set1,Set2,R,WF) :- both_global_sets(Set1,Set2,G1,G2),!, % also deals with two intervals
946 test_subset_of_global_sets_wf(G1,G2,R,WF).
947 subset_test1(_Set1,Set2,R,_WF) :-
948 is_definitely_maximal_set(Set2),!, % TO DO: avoid re-checking it if we have already checked it above in subset_test
949 R=pred_true.
950 subset_test1(Set1,Set2,R,WF) :- Set2==[],!, eq_empty_set_attr_wf(Set1,R,WF).
951 ?subset_test1(Set1,Set2,R,WF) :- test_subset_of_explicit_set(Set1,Set2,R,WF,Code),!,
952 call(Code).
953 subset_test1(Set1,Set2,R,WF) :-
954 expand_custom_set_to_list_no_dups_wf(Set1,ESet1,_,subset_test1,WF),
955 % no_dups relevant for test 2202 on SWI Prolog, where conjoin(pred_true,X,Y) -> propagation of X & Y are separate
956 subset_test2(ESet1,Set2,R,WF).
957
958 :- block subset_test2(-,?,?,?).
959 subset_test2([],_,R,_WF) :- !, R=pred_true.
960 subset_test2(Set1,Set2,R,WF) :- R==pred_true,!,
961 ? check_subset_of_wf(Set1,Set2,WF). % may more aggressively instantiate Set2
962 % not useful to have special case for pred_false which uses membership_test_wf also
963 subset_test2([H|T],Set2,R,WF) :- %print(subset_test2([H|T],Set2,R)),nl,
964 (T==[]
965 -> membership_test_wf(Set2,H,R,WF)
966 ; membership_test_wf(Set2,H,MemRes,WF),
967 subset_test3(MemRes,T,Set2,R,WF),
968 (var(MemRes) -> propagate_true(R,MemRes) ; true) % in case overall subset holds, then MemRes must be true
969 ).
970
971 :- block subset_test3(-,?,?,?,?).
972 subset_test3(pred_false,_T,_Set2,R,_WF) :- R=pred_false.
973 ?subset_test3(pred_true,T,Set2,R,WF) :- subset_test2(T,Set2,R,WF).
974
975 :- block propagate_true(-,?).
976 propagate_true(pred_true,X) :- !, X=pred_true.
977 propagate_true(_,_).
978
979 %:- block test_subset_of_global_sets(-,?,?), not_subset_of_global_sets(?,-,?).
980 test_subset_of_global_sets_wf(interval(Low1,Up1),interval(Low2,Up2),Res,WF) :- !,
981 test_interval_subset_wf(Low1,Up1,Low2,Up2,Res,WF).
982 test_subset_of_global_sets_wf(G1,G2,R,_) :- G1==G2,!,R=pred_true.
983 test_subset_of_global_sets_wf(G1,G2,R,_) :- %print(check_subset(G1,G2)),nl,
984 when((nonvar(R);(ground(G1),ground(G2))),test_subset_of_global_sets_aux(G1,G2,R)).
985 % TO DO: provide better reified version, especially for intervals with variables !
986 % e.g., 1..x <: NATURAL1 ==> R=pred_true, ...
987
988 test_subset_of_global_sets_aux(G1,G2,R) :- R==pred_true,!, check_subset_of_global_sets(G1,G2).
989 test_subset_of_global_sets_aux(G1,G2,R) :- R==pred_false,!, check_not_subset_of_global_sets(G1,G2).
990 test_subset_of_global_sets_aux(G1,G2,R) :-
991 (check_subset_of_global_sets(G1,G2) -> R=pred_true ; R=pred_false).
992
993
994 :- use_module(b_interpreter_check,[imply/3, conjoin/6]).
995 test_interval_subset_wf(Low1,Up1,Low2,Up2,Res,WF) :-
996 % print(test_interval_subset_wf(Low1,Up1,Low2,Up2,Res)),nl,
997 check_less_than_equal_inf(Low1,Up1,NonEmpty),
998 (NonEmpty==false -> Res=pred_true % if Low1..Up1 is empty it is a subset of anything
999 ; check_less_than_equal_inf(Low2,Low1,R1),
1000 (R1 == pred_false, NonEmpty==pred_true -> Res=pred_false
1001 ; check_less_than_equal_inf(Up1,Up2,R2),
1002 conjoin_test(R1,R2,R12,WF),
1003 imply(NonEmpty,R12,Res) % if Low1..Up1 is empty the bounds must be within Low2..Up2
1004 )
1005 ).
1006
1007 :- use_module(b_interpreter_check,[check_less_than_equal/3]).
1008 % reify: X<=Y, a version of check_less_than_equal that can deal with minus_inf and inf
1009 % assumption: minus_inf, inf are either there directly; a variable will never be instantiated to inf, minus_inf
1010 % does not treat inf_overflow
1011 check_less_than_equal_inf(Low1,_,Res) :- Low1==minus_inf,!,Res=pred_true.
1012 check_less_than_equal_inf(_,Low2,Res) :- Low2==inf,!,Res=pred_true.
1013 check_less_than_equal_inf(Low1,_,Res) :- Low1==inf,!,Res=pred_false.
1014 check_less_than_equal_inf(_,Low2,Res) :- Low2==minus_inf,!,Res=pred_false.
1015 check_less_than_equal_inf(X,Y,Res) :- check_less_than_equal(X,Y,Res).
1016
1017
1018 % ---------------------------- strict subset reification
1019
1020
1021 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([int(2)],[],pred_false,WF),WF)).
1022 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([int(2),int(1)],[int(2)],pred_false,WF),WF)).
1023 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:subset_strict_test([int(2),int(1)],[int(2)],pred_true,_WF))).
1024 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([int(2),int(1)],[int(2),int(1)],pred_false,WF),WF)).
1025 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([int(2),int(1)],[int(2),int(1),int(3)],pred_true,WF),WF)).
1026 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([int(2),int(1)],global_set('NATURAL1'),pred_true,WF),WF)).
1027 :- assert_must_succeed(exhaustive_kernel_check_wfdet(kernel_equality:subset_strict_test([],[int(2),int(1)],pred_true,WF),WF)).
1028 :- assert_must_succeed(exhaustive_kernel_fail_check(kernel_equality:subset_strict_test([],[int(2),int(1)],pred_false,_WF))).
1029 :- assert_must_succeed((kernel_equality:subset_strict_test([],[int(3)],R,_WF),R==pred_true)).
1030 :- assert_must_succeed((kernel_equality:subset_strict_test([int(2),int(1)],[int(2),int(1),int(3)],R,_WF),R==pred_true)).
1031 :- assert_must_succeed((kernel_equality:subset_strict_test([int(2),int(1),int(4)],[int(2),int(1),int(3)],R,_WF),R==pred_false)).
1032 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(1)],global_set('NATURAL'),R,_WF),R==pred_true)).
1033 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(1)],global_set('NATURAL1'),R,_WF),R==pred_true)).
1034 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(1),int(0)],global_set('NATURAL1'),R,_WF),R==pred_false)).
1035 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(1),int(0)],X,R,_WF),X=global_set('NATURAL1'),R==pred_false)).
1036 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(-11)],global_set('INTEGER'),R,_WF),R==pred_true)).
1037 :- assert_must_succeed((kernel_equality:subset_strict_test([int(222),int(-11)],global_set('INTEGER'),R,_WF),R==pred_true)).
1038 :- assert_must_succeed((kernel_equality:subset_strict_test(global_set('INTEGER'),global_set('NATURAL1'),R,_WF),R==pred_false)).
1039
1040 :- assert_must_succeed((kernel_equality:subset_strict_test(global_set('NATURAL1'),global_set('NATURAL1'),R,_WF),R==pred_false)).
1041
1042 :- block subset_strict_test(-,-,-,?).
1043 subset_strict_test(_S1,S2,R,_WF) :- % tools_printing:print_term_summary(subset_test(_S1,S2,R,WF)), %%
1044 S2==[],!,R=pred_false.
1045 subset_strict_test(S1,S2,R,WF) :- % tools_printing:print_term_summary(subset_test(_S1,S2,R,WF)), %%
1046 S1==[],!,eq_empty_set_attr_wf(S2,Empty,WF), bool_pred:negate(Empty,R).
1047 subset_strict_test(S1,S2,R,WF) :- subset_strict_test0(S1,S2,R,WF).
1048
1049 :- use_module(kernel_objects,[strict_subset_of_wf/3, not_strict_subset_of_wf/3]).
1050 :- block subset_strict_test0(-,?,-,?).
1051 subset_strict_test0(S1,S2,R,WF) :- % tools_printing:print_term_summary(subset_test0(S1,S2,R,WF)), %%
1052 nonvar(R),!,
1053 (R==pred_true -> strict_subset_of_wf(S1,S2,WF)
1054 ; R==pred_false -> not_strict_subset_of_wf(S1,S2,WF)
1055 ; add_error_fail(subset_strict_test0,'Illegal result value: ',R)).
1056 subset_strict_test0(S1,S2,R,WF) :-
1057 subset_test(S1,S2,IsSubset,WF),
1058 (IsSubset==pred_false -> R=pred_false
1059 ; conjoin_test(IsSubset,NotEqual,R,WF),
1060 bool_pred:negate(NotEqual,Equal),
1061 equality_objects_wf(S1,S2,Equal,WF)
1062 ).
1063
1064 conjoin_test(A,B,AB,WF) :-
1065 ? conjoin(A,B,AB,b(truth,pred,[conjoin_test]),b(truth,pred,[conjoin_test]),WF).
1066 % Note: predicate controls get_priority_of_boolean_expression
1067
1068 % ----------------------
1069
1070 % check if we can decidate equality by Prolog unification:
1071 % see predicate: can_be_used_for_unification in b_interpreter
1072 % one argument has to satisfy this predicate, the other should be ground (or also satisfy this predicate)
1073 equality_can_be_decided_by_unification(V) :- var(V),!,fail.
1074 equality_can_be_decided_by_unification(pred_false).
1075 equality_can_be_decided_by_unification(pred_true).
1076 equality_can_be_decided_by_unification(int(N)) :- integer(N).
1077 equality_can_be_decided_by_unification(string(S)) :- atom(S).
1078 equality_can_be_decided_by_unification(fd(N,GS)) :- atom(GS),integer(N).
1079 equality_can_be_decided_by_unification((A,B)) :-
1080 equality_can_be_decided_by_unification(A),equality_can_be_decided_by_unification(B).
1081 % TODO: records ?
1082