1 % (c) 2009-2019 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(kodkod_translate,
6 [ kodkod_translate/4
7 , remove_optional_set/2
8 ]).
9
10 :- use_module(library(lists)).
11 :- use_module(library(avl)).
12 :- use_module(library(ordsets)).
13
14 :- use_module(probsrc(module_information),[module_info/2]).
15 :- use_module(probsrc(bsyntaxtree)).
16 :- use_module(probsrc(bmachine)).
17 :- use_module(probsrc(translate), [pretty_type/2,translate_bexpression/2]).
18 :- use_module(probsrc(custom_explicit_sets),[expand_custom_set_to_list/2]).
19 :- use_module(probsrc(tools),[foldl/4]).
20
21 :- use_module(kodkod_tools).
22
23 :- module_info(group,kodkod).
24 :- module_info(description,'This module contains the code to translate B expressions and predicates into Kodkod.').
25
26 kodkod_translate(TExpr,Typemap,Idmap,KExpr) :-
27 create_environment(Typemap,Idmap,KEnv),
28 kodkod_translate1(TExpr,KEnv,KExpr).
29
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 % the translation environment: It stores
32 % 1) the types (and represented by which relation),
33 % 2) the identifiers (and represented by which relation),
34 % 3) the quantified variables (and their relation)
35 create_environment(Typemap,Idmap,kenv(Typemap,Idmap,Varmap)) :-
36 empty_avl(Varmap).
37 lookup_type_relation(Type,kenv(Typemap,_,_),Relname) :-
38 avl_fetch(Type,Typemap,V),
39 V = relation(Relname,_Size,_Relspec).
40 lookup_id_relation(Id,kenv(_,Idmap,_),Relname,Types) :-
41 avl_fetch(Id,Idmap,reldef(Relname,Types,_,_,_)).
42 lookup_var(Id,kenv(_,_,Varmap),Varname) :-
43 avl_fetch(Id,Varmap,Varname).
44 add_var_to_environment(Id,Ref,kenv(Typemap,Idmap,VarmapIn),kenv(Typemap,Idmap,VarmapOut)) :-
45 avl_store(Id,VarmapIn,Ref,VarmapOut).
46
47 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
48 % initialise the Kodkod environment
49
50 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
51 % translate predicates and expressions
52 kodkod_translate1(TExpr,Env,KExpr) :-
53 get_texpr_expr(TExpr,Expr),
54 get_texpr_type(TExpr,Type1), remove_seq_type(Type1,Type),
55 get_texpr_info(TExpr,Info),
56 kodkod_translate2(Expr,Type,Info,Env,KExpr1),
57 % enforce the use of integer atoms for integers used in sets
58 ( Type = set(integer), KExpr1 \= _:_ ->
59 KExpr = KExpr1:rel([IntAtoms]),
60 intset_relation_kodkod_name(IntAtoms)
61 ; otherwise ->
62 KExpr = KExpr1).
63
64 remove_seq_type(seq(T),Set) :- !,Set=set(couple(integer,T)).
65 remove_seq_type(T,T).
66
67 :- use_module(probsrc(bsyntaxtree),[get_texpr_set_type/2]).
68
69 kodkod_translate2(member(BElem,BSet),pred,_,Env,K) :-
70 get_texpr_expr(BSet,BFun),
71 BFun =.. [FunFunctor,BDom,BRange],
72 KFun =.. [FunFunctor,KDom,KRange],
73 get_texpr_type(BSet,Type),
74 kodkod_translate_binary_membership(KFun,KElem,Type,K),!,
75 kodkod_translate1(BElem,Env,KElem),
76 kodkod_translate1(BDom,Env,KDom),
77 kodkod_translate1(BRange,Env,KRange).
78 kodkod_translate2(not_member(BElem,BSet),pred,Info,Env,not(K)) :-
79 !,kodkod_translate2(member(BElem,BSet),pred,Info,Env,K).
80 kodkod_translate2(domain_restriction(Dom,Rel),set(couple(_,RhType)),_,Env,
81 intersection(product(KDom,relref(KRhRel)),KRel)) :-
82 !,kodkod_translate1(Dom,Env,KDom),
83 kodkod_translate1(Rel,Env,KRel),
84 lookup_type_relation(RhType,Env,KRhRel).
85 kodkod_translate2(domain_subtraction(Dom,Rel),set(couple(_,RhType)),_,Env,
86 intersection(product(difference(univ,KDom),relref(KRhRel)),KRel)) :-
87 !,kodkod_translate1(Dom,Env,KDom),
88 kodkod_translate1(Rel,Env,KRel),
89 lookup_type_relation(RhType,Env,KRhRel).
90 kodkod_translate2(range_restriction(Rel,Dom),set(couple(LhType,_)),_,Env,
91 intersection(KRel,product(relref(KLhRel),KDom))) :-
92 !,kodkod_translate1(Dom,Env,KDom),
93 kodkod_translate1(Rel,Env,KRel),
94 lookup_type_relation(LhType,Env,KLhRel).
95 kodkod_translate2(range_subtraction(Rel,Dom),set(couple(LhType,_)),_,Env,
96 intersection(KRel,product(relref(KLhRel),difference(univ,KDom)))) :-
97 !,kodkod_translate1(Dom,Env,KDom),
98 kodkod_translate1(Rel,Env,KRel),
99 lookup_type_relation(LhType,Env,KLhRel).
100 kodkod_translate2(identifier(Id),_BType,_Info,Env,Ref) :- !,
101 ( lookup_var(Id,Env,Varname) ->
102 Ref = varref(Varname)
103 ; lookup_id_relation(Id,Env,Relname,_KTypes) ->
104 Ref = relref(Relname)
105 ; lookup_type_relation(global(Id),Env,Relname) ->
106 Ref = relref(Relname)).
107 kodkod_translate2(set_extension(List),_BType,_,Env,Result) :-
108 !, kodkod_translate_l(List,Env,KList),
109 kodkod_extension_set(KList,Result).
110 kodkod_translate2(forall(BIds,_,_),pred,_,_Env,true) :-
111 % If there is an identifier without possible solution, the result is always true
112 somechk(is_inconsistent_expression,BIds),!.
113 kodkod_translate2(forall(BIds, Condition, Predicate),pred,_,Env,
114 forall(Decls,Result)) :-
115 !,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
116 kodkod_translate1(Condition,Subenv,KCond),
117 kodkod_translate1(Predicate,Subenv,KPred),
118 kodkod_declarations2(ProvDecls,Env,KCond,NewKCond,Decls),
119 kodkod_implication(NewKCond,KPred,Result).
120 kodkod_translate2(exists(BIds,_),pred,_,_Env,false) :-
121 % If there is an identifier without possible solution, the result is always false
122 somechk(is_inconsistent_expression,BIds),!.
123 kodkod_translate2(exists([BId], Membership),pred,_,Env,some(KSet)) :-
124 % translate #e.e:M to some(M)
125 get_texpr_expr(Membership,member(Elem,Set)),
126 get_texpr_id(BId,Id),get_texpr_id(Elem,Id),!,
127 kodkod_translate1(Set,Env,KSet).
128 kodkod_translate2(exists(BIds, Predicate),pred,_,Env,exists(Decls,Result)) :-
129 !,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
130 kodkod_translate1(Predicate,Subenv,KPred),
131 kodkod_declarations2(ProvDecls,Env,KPred,Result,Decls).
132 kodkod_translate2(comprehension_set(BIds,_),BType,Info,Env,KEmptySet) :-
133 % If there is an identifier without possible solution, the result is always empty
134 somechk(is_inconsistent_expression,BIds),!,
135 kodkod_translate2(empty_set,BType,Info,Env,KEmptySet).
136 kodkod_translate2(comprehension_set(BIds,Predicate),set(_BType),_,Env,
137 comp(Decls,Result)) :-
138 !,kodkod_declarations1(BIds,Env,Subenv,ProvDecls),
139 kodkod_translate1(Predicate,Subenv,KPred),
140 kodkod_declarations2(ProvDecls,Env,KPred,Result,Decls).
141 kodkod_translate2(domain(Rel),_,_,Env,K) :-
142 !,get_texpr_type(Rel,RelType),
143 kodkod_domain(KRel,RelType,K),
144 kodkod_translate1(Rel,Env,KRel).
145 kodkod_translate2(range(Rel),_,_,Env,K) :-
146 !,get_texpr_type(Rel,RelType),
147 kodkod_range(KRel,RelType,K),
148 kodkod_translate1(Rel,Env,KRel).
149 kodkod_translate2(first_of_pair(Couple),Type,Info,Env,K) :-
150 !,kodkod_translate2(domain(Couple),Type,Info,Env,K).
151 kodkod_translate2(second_of_pair(Couple),Type,Info,Env,K) :-
152 !,kodkod_translate2(range(Couple),Type,Info,Env,K).
153 kodkod_translate2(composition(A,B),_BType,_,Env,join(KA,KB)) :-
154 get_texpr_set_type(A,couple(_,IType)),
155 type_arity(IType,1),!,
156 kodkod_translate1(A,Env,KA),
157 kodkod_translate1(B,Env,KB).
158 kodkod_translate2(function(BFun,BArg),_BType,_,Env,Res) :-
159 !, kodkod_function_application(BFun,BArg,Env,Res).
160 kodkod_translate2(image(BRel,BArg),_BType,_,Env,Res) :-
161 !, kodkod_function_application(BRel,BArg,Env,Res).
162 kodkod_translate2(reverse(BRel),_BType,_,Env,Res) :-
163 !, kodkod_reverse(BRel,Env,Res).
164 kodkod_translate2(integer(I),integer,_,_Env,int(I)) :- !.
165 kodkod_translate2(unary_minus(TExpr),integer,_,_Env,int(N)) :-
166 % Expressions of the form "-(1)" are translated to "-1"
167 % there is another rule below for other forms of unary minus (translating "-x" to "0-x")
168 get_texpr_expr(TExpr,integer(P)),!,N is -P.
169 kodkod_translate2(general_sum([TId],TPred,Expr),integer,_,Env,sum(KSet)) :-
170 % we support only a restricted sort of the general sum:
171 % SIGMA (x).(x:S|x)
172 % The rewriting rules (see kodkod2.pl) convert the more general form "SIGMA (x).(P|x)"
173 % into this form by "SIGMA (x).(x:{x|P}|x)"
174 % The expression must only contain the quantified variable:
175 get_texpr_id(TId,Id), get_texpr_id(Expr,Id),!,
176 % Simple form: the predicate is of the form x:S
177 get_texpr_expr(TPred,member(TElem,TSet)),get_texpr_id(TElem,Id),
178 kodkod_translate1(TSet,Env,KSet).
179 kodkod_translate2(boolean_true,boolean,_,Env,relref(Relname)) :- !,
180 lookup_id_relation('__kodkod__true',Env,Relname,_KTypes).
181 kodkod_translate2(boolean_false,boolean,_,Env,relref(Relname)) :- !,
182 lookup_id_relation('__kodkod__false',Env,Relname,_KTypes).
183 kodkod_translate2(bool_set,set(boolean),_,Env,relref(Relname)) :- !,
184 lookup_type_relation(boolean,Env,Relname).
185 kodkod_translate2(empty_set,set(T),_,Env,Empty) :- !,
186 kodkod_type_as_list(T,Env,Typelist),
187 create_empty_set(Typelist,Empty).
188 kodkod_translate2(partition(Set,Subsets),_,_,Env,and(KEquals,KDisjunct)) :- !,
189 kodkod_translate_l([Set|Subsets],Env,[KSet|KSubsets]),
190 kodkod_extension_set(KSubsets,KUnion),
191 KEquals = equals(KSet,KUnion),
192 all_disjunct(KSubsets,KDisjunct).
193 kodkod_translate2(convert_bool(BCond),boolean,_,Env,if(KCond,KTrue,KFalse)) :- !,
194 kodkod_translate1(BCond,Env,KCond),
195 kodkod_translate2(boolean_true,boolean,[],Env,KTrue),
196 kodkod_translate2(boolean_false,boolean,[],Env,KFalse).
197 kodkod_translate2(concat(BA,BB),_,_,Env,union(KA,join(Adder,KB))) :- !,
198 % To compute A^B, we use a form A \/ Adder[B]
199 kodkod_translate1(BA,Env,KA),
200 kodkod_translate1(BB,Env,KB),
201 intset_relation_kodkod_name(I),
202 % Adder is a set of the form {a,b | a=b+card(A)}
203 Adder = comp([decl(lhr,1,one,relref(I)),decl(rhr,1,one,relref(I))],
204 equals(sum(varref(lhr)),add(sum(varref(rhr)),card(KA)))).
205 kodkod_translate2(value(V),Type,_Info,Env,K) :- ground(V), %print(try_translate_value(V)),nl,
206 translate_value_to_kodkod(Type,Env,V,K),!.
207 kodkod_translate2(value(Val),Type,Infos,Env,K) :-
208 was_identifier(Val,Infos,ID),!, % identifier was compiled to value; this is a bit dangerous; we should ensure that the identifier ID is used only once
209 %print(kodkod_value_as_id(V,ID)),nl,
210 kodkod_translate2(identifier(ID),Type,Infos,Env,K).
211 kodkod_translate2(event_b_identity,set(couple(Type,Type)),Info,Env,K) :- !,
212 translate:type_set(Type,TSet),
213 kodkod_translate2(identity(TSet),set(couple(Type,Type)),Info,Env,K).
214 kodkod_translate2(external_pred_call('LEQ_SYM_BREAK',_),Type,Info,Env,K) :- !,
215 kodkod_translate2(truth,Type,Info,Env,K).
216 kodkod_translate2(Expr,_,_,Env,Result) :-
217 functor(Expr,Functor,Arity),
218 functor(Tmp,Functor,Arity),
219 kodkod_short(Tmp,_,SC),!,
220 check_side_condition(SC,Expr),
221 Expr =.. [Functor|Args],
222 same_length(Args,TArgs),
223 Lookup =.. [Functor|TArgs],
224 kodkod_translate_l(Args,Env,TArgs),
225 kodkod_short(Lookup,Result,_).
226 kodkod_translate2(E,T,I,_,_) :-
227 create_texpr(E,T,I,TE),
228 %print(expr(E,T)),nl,
229 throw(kodkod(unsupported_expression(TE))).
230
231 was_identifier(_V,Infos,ID) :- member(was_identifier(ID),Infos).
232 was_identifier(Val,_,GS) :- nonvar(Val), Val=global_set(GS).
233
234 check_side_condition(none,_Expr).
235 check_side_condition(cond(_,_),Expr) :-
236 kodkod_short(Expr,_,cond(Msg,Condition)),
237 ( call(Condition) -> true
238 ; otherwise ->
239 translate_bexpression(Expr,PPExpr),
240 throw(kodkod(side_condition(Msg,PPExpr)))).
241
242 translate_value_to_kodkod(integer,_Env,int(I),int(I)).
243 translate_value_to_kodkod(set(Type),Env,V,K) :-
244 kodkod_type_as_list(Type,Env,Typelist),
245 expand_custom_set_to_list(V,List),
246 maplist(translate_value_to_kodkod1(Type,Env),List,KList),
247 ( KList = [] -> create_empty_set(Typelist,K)
248 ; KList = [H|T] -> foldl(union_kvalues,T,H,K)).
249 translate_value_to_kodkod(couple(TA,TB),Env,V,K) :-
250 translate_value_to_kodkod1(couple(TA,TB),Env,V,K).
251 translate_value_to_kodkod(global(GS),Env,V,K) :-
252 translate_value_to_kodkod1(global(GS),Env,V,K).
253
254 :- use_module(probsrc(b_global_sets),[is_b_global_constant/3]).
255 translate_value_to_kodkod1(integer,_Env,int(I),int(I):rel([IntAtoms])) :-
256 intset_relation_kodkod_name(IntAtoms).
257 translate_value_to_kodkod1(couple(TA,TB),Env,(A,B),product(KA,KB)) :-
258 translate_value_to_kodkod1(TA,Env,A,KA),
259 translate_value_to_kodkod1(TB,Env,B,KB).
260 translate_value_to_kodkod1(global(GS),Env,fd(Nr,GS),Res) :-
261 is_b_global_constant(GS,Nr,CstId),
262 lookup_id_relation(CstId,Env,Relname,_KTypes), Res=relref(Relname).
263
264 union_kvalues(A,B,union(A,B)).
265
266 create_empty_set([Type],R) :- !,R=empty:rel([Type]).
267 create_empty_set([Type|Rest],product(empty:rel([Type]),R)) :-
268 create_empty_set(Rest,R).
269
270 :- use_module(probsrc(error_manager),[add_warning/3]).
271
272 kodkod_short(B,K,none) :- kodkod_short(B,K),!.
273 kodkod_short(B,K,cond(Msg,Cond)) :- kodkod_short(B,K,Msg,Cond).
274
275 kodkod_short(truth,true).
276 kodkod_short(falsity,false).
277 kodkod_short(negation(A),not(A)).
278 kodkod_short(conjunct(A,B),and(A,B)).
279 kodkod_short(disjunct(A,B), or(A,B)).
280 kodkod_short(implication(A,B),implies(A,B)).
281 kodkod_short(equivalence(A,B), iff(A,B)).
282
283 kodkod_short(equal(A,B),equals(A,B)).
284
285 kodkod_short(member(A,B),in(A,B)).
286 kodkod_short(subset(A,B),K) :- kodkod_short(member(A,B),K).
287 kodkod_short(not_subset(A,B),not(K)) :- kodkod_short(subset(A,B),K).
288 kodkod_short(subset_strict(A,B),and(in(A,B),not(equals(A,B)))).
289 kodkod_short(not_subset_strict(A,B),or(not(in(A,B)),equals(A,B))).
290
291 kodkod_short(cartesian_product(A,B),product(A,B)).
292 kodkod_short(intersection(A,B),intersection(A,B)).
293 kodkod_short(union(A,B),union(A,B)).
294 kodkod_short(closure(E),closure(E)).
295 kodkod_short(set_subtraction(A,B),difference(A,B)).
296 kodkod_short(overwrite(A,B),overwrite(A,B)).
297 kodkod_short(couple(A,B),product(A,B)).
298
299 kodkod_short(card(X),card(X)).
300 kodkod_short(size(X),card(X)).
301 kodkod_short(greater(A,B),gt(A,B)).
302 kodkod_short(greater_equal(A,B),gte(A,B)).
303 kodkod_short(less(A,B),lt(A,B)).
304 kodkod_short(less_equal(A,B),lte(A,B)).
305
306 kodkod_short(add(A,B),add(A,B)).
307 kodkod_short(minus(A,B),sub(A,B)).
308 kodkod_short(multiplication(A,B),mul(A,B)).
309 kodkod_short(div(A,B),div(A,B)).
310 kodkod_short(floored_div(A,B),div(A,B)) :-
311 add_warning(kodkod_translate,'Translating floored division as truncated division: ',div(A,B)).
312 kodkod_short(modulo(A,B),mod(A,B)).
313 kodkod_short(unary_minus(A),sub(int(0),A)).
314 %kodkod_short(event_b_identity,iden). % this leads to error in test 711; maybe iden is the function over all types
315
316 kodkod_short(identity(A),intersection(product(A,A),iden),
317 'Identity is supported only on unary sets',
318 side_condition_type_arity(A,1)).
319 kodkod_short(reflexive_closure(A),closure(union(intersection(product(All,All),iden),A)),
320 'Reflexive closure is supported only on binary relations on unary sets',
321 side_condition_type_arity(A,2)) :- All=union(prj([0],A),prj([1],A)).
322
323 :- public side_condition_type_arity/2.
324 side_condition_type_arity(Expr,Arity) :-
325 get_texpr_type(Expr,Type),
326 type_arity(Type,Arity).
327
328 kodkod_translate_l([],_,[]).
329 kodkod_translate_l([E|ERest],Env,[K|KRest]) :-
330 kodkod_translate1(E,Env,K),
331 kodkod_translate_l(ERest,Env,KRest).
332
333 kodkod_translate_binary_membership(partial_function(D,R),F,T,pfunc(F,D,R)) :- is_binary_relation(T).
334 kodkod_translate_binary_membership(total_function(D,R),F,T,func(F,D,R)) :- is_binary_relation(T).
335 kodkod_translate_binary_membership(partial_injection(D,R),F,T,and(pfunc(F,D,R),Inj)) :-
336 is_binary_relation(T),k_is_injective(F,Inj).
337 kodkod_translate_binary_membership(total_injection(D,R),F,T,and(func(F,D,R),Inj)) :-
338 is_binary_relation(T),k_is_injective(F,Inj).
339 kodkod_translate_binary_membership(partial_surjection(D,R),F,T,and(pfunc(F,D,R),Surj)) :-
340 is_binary_relation(T),k_is_surjective(F,R,T,Surj).
341 kodkod_translate_binary_membership(total_surjection(D,R),F,T,and(func(F,D,R),Surj)) :-
342 is_binary_relation(T),k_is_surjective(F,R,T,Surj).
343 kodkod_translate_binary_membership(partial_bijection(D,R),F,T,and(pfunc(F,D,R),Bij)) :-
344 is_binary_relation(T),k_is_bijective(F,R,T,Bij).
345 kodkod_translate_binary_membership(total_bijection(D,R),F,T,and(func(F,D,R),Bij)) :-
346 is_binary_relation(T),k_is_bijective(F,R,T,Bij).
347 kodkod_translate_binary_membership(total_relation(D,R),F,set(T),and(equals(Dom,D),in(Ran,R))) :-
348 kodkod_domain(F,T,Dom), kodkod_range(F,T,Ran).
349 kodkod_translate_binary_membership(surjection_relation(D,R),F,set(T),and(in(Dom,D),equals(Ran,R))) :-
350 kodkod_domain(F,T,Dom), kodkod_range(F,T,Ran).
351
352 is_binary_relation(Type) :- type_arity(Type,2),!.
353 is_binary_relation(Type) :-
354 pretty_type(Type,PType),
355 throw(kodkod(side_condition('Functions are only supported for binary relations',PType))).
356
357 k_is_injective(F,in(join(F,transpose(F)),iden)).
358 k_is_surjective(F,R,set(Type),in(R,Range)) :-
359 kodkod_range(F,Type,Range).
360 k_is_bijective(F,R,Type,and(Inj,Surj)) :-
361 k_is_injective(F,Inj), k_is_surjective(F,R,Type,Surj).
362
363 kodkod_domain(KRel,BType,prj(Positions,KRel)) :-
364 remove_optional_set(BType,couple(DType,_RType)),
365 type_arity(DType,Arity),enumerate(Arity,0,Positions).
366 kodkod_range(KRel,BType,prj(Positions,KRel)) :-
367 remove_optional_set(BType,couple(DType,RType)),
368 type_arity(DType,Start),type_arity(RType,Arity),
369 enumerate(Arity,Start,Positions).
370
371 % function application / relational image
372 % kodkod_function_application(+BFun,+BArg,+Env,-K):
373 % translate a function application f(x) where BFun is f and x is BArg to Kodkod
374 % Usually a function application f(x) can be translated to join(kx,kf)
375 % when kx is unary. But for n-ary kx (n>1) we have to apply several joins manually
376 kodkod_function_application(BFun,BArg,Env,K) :-
377 kodkod_translate1(BFun,Env,KFun),
378 kodkod_translate1(BArg,Env,KArg),
379 get_texpr_type(BArg,ArgType), type_arity(ArgType,ArgArity),
380 get_texpr_type(BFun,FunType), type_arity(FunType,FunArity),
381 kodkod_function_application_aux(ArgArity,FunArity,KFun,KArg,K).
382 kodkod_function_application_aux(1,_,KFun,KArg,K) :- !,
383 K = join(KArg,KFun).
384 kodkod_function_application_aux(ArgArity,FunArity,KFun,KArg,K) :-
385 % We translate f(x) resp. f[{x}] to
386 % prj( nx..(nf-1), { e : f | prj( 0..(nx-1), e ) = x } )
387 % with nf resp. nx being the arity of f resp. x
388 K = prj(RightPos,CompSet),
389 CompSet = comp([decl(KId,FunArity,one,KFun)],equals(prj(LeftPos,varref(KId)),KArg)),
390 % LeftPos is 0..(nx-1) (contains ArgArity elements starting with 0)
391 enumerate(ArgArity,0,LeftPos),
392 % RightPos is nx..(nf-1) (contains FunArity-ArgArity elements starting with nx)
393 RemainingPos is FunArity-ArgArity,
394 enumerate(RemainingPos,ArgArity,RightPos),
395 % e is some unique identifier
396 unique_identifier(KId).
397
398 kodkod_reverse(BArg,Env,K) :-
399 kodkod_translate1(BArg,Env,KArg),
400 get_texpr_type(BArg,ArgType), type_arity(ArgType,ArgArity),
401 kodkod_reverse_aux(ArgArity,KArg,K).
402 kodkod_reverse_aux(2,KArg,transpose(KArg)) :- !.
403 kodkod_reverse_aux(Arity,KArg,prj(Rev,KArg)) :-
404 enumerate(Arity,0,Positions),
405 reverse(Positions,Rev).
406
407
408 % two-phase handling of declarations in forall, exists, etc.
409 kodkod_declarations1([],SubEnv,SubEnv,[]).
410 kodkod_declarations1([TExpr|IRest],
411 Env,Env2,
412 [provdecl(KId,Type,Analysis)|DRest]) :-
413 get_texpr_id(TExpr,Id),
414 get_texpr_type(TExpr,Type),
415 get_texpr_info(TExpr,Info),
416 ( memberchk(analysis(Analysis),Info) -> true
417 ; otherwise -> Analysis=[]),
418 unique_identifier(v,Id,KId),
419 add_var_to_environment(Id,KId,Env,SubEnv),
420 kodkod_declarations1(IRest,SubEnv,Env2,DRest).
421
422 kodkod_declarations2([],_,KCond,KCond,[]).
423 kodkod_declarations2([provdecl(KId,Type,Analysis)|PRest],
424 Env,KCond,KCond2,
425 [decl(KId,Arity,Mult,Expr)|DRest]) :-
426 type_arity(Type,Arity),
427 kodkod_declaration(Type,KId,Analysis,Env,KCond,NewKCond,Mult,Expr),
428 kodkod_declarations2(PRest,Env,NewKCond,KCond2,DRest).
429 kodkod_declaration(integer,_KId,_Analysis,_Env,KCond,KCond,Mult,Expr) :-
430 % TODO: we have to make a decision whether a quantified integer
431 % variable should be the bit-representation of the value
432 % (for variables that can take large values)
433 % or a the item of the integer relation.
434 % currently we do only the latter:
435 !,Mult = one,
436 intset_relation_kodkod_name(IntsetRelation),
437 Expr = relref(IntsetRelation).
438 kodkod_declaration(Type,KId,_Analysis,Env,KCond,NewKCond,Mult,Expr) :-
439 (Type=set(_) -> Mult=set; Mult=one),
440 ( find_in(KCond,KId,Expr,NewKCond) ->
441 true
442 ; otherwise ->
443 % here we have to insert a possible choice for
444 % integer variables. That possible choice should be returned
445 % as a variable and later its value determine the outcome
446 % of the choice.
447 kodkod_type(Type,Env,Expr),
448 NewKCond = KCond).
449
450 find_in(Formula,Id,Expression,NewFormula) :-
451 disassemble_conjunction(Formula,Parts),
452 find_in2(Parts,Id,Expression,Rest),
453 kodkod_conjunction(Rest,NewFormula).
454 find_in2([in(varref(Id),Expr)|Rest], Id, Expr, Rest) :- !.
455 find_in2([Pred|Rest], Id, Expr, [Pred|Result]) :-
456 find_in2(Rest,Id,Expr,Result).
457
458 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
459 % A Kodkod environment contains two maps:
460 % a) The first one maps Kodkod types to references to relations that will
461 % represents all elements to the given type
462 % b) The second one maps an identifier to a reference to the relations that
463 % represents the variable in
464
465 %kodkod_subenv(Id,Ref,kenv(Types,OldBinds),kenv(Types,NewBinds)) :-
466 % avl_store(Id,OldBinds,Ref,NewBinds).
467
468 % End: Environment
469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470
471 kodkod_type(T,Env,K) :-
472 remove_optional_set(T,T2),
473 kodkod_type2(T2,T2,Env,K).
474 kodkod_type2(couple(A,B),_,Env,product(KA,KB)) :- !,
475 kodkod_type2(A,A,Env,KA),
476 kodkod_type2(B,B,Env,KB).
477 kodkod_type2(Type,_,Env,relref(Ref)) :-
478 lookup_type_relation(Type,Env,Ref),!.
479 kodkod_type2(_,T,_Env,_Ref) :-
480 throw(kodkod(unsupported_type(T))).
481
482 kodkod_type_as_list(T,Env,TypeList) :-
483 remove_optional_set(T,T2),
484 kodkod_type_as_list2(T2,Env,TypeList).
485 kodkod_type_as_list2(couple(A,B),Env,TypeList) :- !,
486 kodkod_type_as_list2(A,Env,ATL),
487 kodkod_type_as_list2(B,Env,BTL),
488 append(ATL,BTL,TypeList).
489 kodkod_type_as_list2(BType,Env,[KType]) :-
490 lookup_type_relation(BType,Env,KType).
491
492 remove_optional_set(set(A),B) :- !,A=B.
493 remove_optional_set(T,T).
494
495 type_arity(set(T),A) :- type_arity(T,A).
496 type_arity(integer,1).
497 type_arity(boolean,1).
498 type_arity(global(_),1).
499 type_arity(couple(A,B),Arity) :-
500 type_arity(A,AA),type_arity(B,AB),Arity is AA+AB.
501
502 % extension sets
503 kodkod_extension_set([],none) :- !.
504 kodkod_extension_set([Elem],Elem) :- !.
505 kodkod_extension_set([Elem|Rest],union(Elem,Ext)) :-
506 kodkod_extension_set(Rest,Ext).
507
508 all_disjunct(Sets,K) :-
509 all_disjunct2(Sets,Dis,[]),
510 kodkod_conjunction(Dis,K).
511 all_disjunct2([]) --> !.
512 all_disjunct2([S|Rest]) -->
513 all_disjunct3(Rest,S),
514 all_disjunct2(Rest).
515 all_disjunct3([],_) --> !.
516 all_disjunct3([B|Rest],A) -->
517 [no(intersection(A,B))],
518 all_disjunct3(Rest,A).
519
520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
521 % helper predicates
522
523
524 enumerate(0,_,[]) :- !.
525 enumerate(N,S,[S|Rest]) :- N2 is N-1, S2 is S+1, enumerate(N2,S2,Rest).
526