1 % (c) 2009-2022 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_printer,[kkp_problem/6
6 ,kkp_request/5
7 ,kkp_list/3]).
8
9 :- use_module(library(lists)).
10
11 :- use_module(probsrc(module_information),[module_info/2]).
12 :- use_module(probsrc(tools),[print_message/1]).
13
14 :- module_info(group,kodkod).
15 :- module_info(description,'This module contains code to print the description of a Kodkod problem, used to send it to a seperate process.').
16
17 :- dynamic output_stream/1.
18
19 set_stream(Stream) :-
20 retractall(output_stream(_)),
21 assertz(output_stream(Stream)).
22
23 kkp_problem(Stream,Timeout,Symmetry,Solver,Id,P) :-
24 set_stream(Stream),
25 call_cleanup( (kkp_problem2(Timeout,Symmetry,Solver,Id,P),!), retractall(output_stream(_)) ).
26 kkp_problem2(Timeout,Symmetry,Solver,Id,problem(Types,Relations,Formula,_,_IntRange)) :-
27 problem_id(Id,PID),
28 kprint([t('problem '),id(PID),space,t(Timeout),space,t(Symmetry),space,t(Solver)]),
29 % will output something like "problem p2 2500 0 sat4j"
30 kkp_types(Types),
31 kkp_relations(Relations),
32 kkp_formula(Formula),
33 kprint(stop).
34
35 kkp_types(Types) :- kprint(popen), kkp_types2(Types), kprint(pclose).
36 kkp_types2([]).
37 kkp_types2([Type|TRest]) :- kkp_type(Type), kkp_types2(TRest).
38 kkp_type(type(Id,Size)) :- kprint([popen,id(Id),space,t(Size),pclose]).
39 % TODO: Maybe it would be better to convert the problem to "falsity" instead
40 kkp_type(inttype(PowName,PowMin,PowMax)) :-
41 PowMax<PowMin,!,
42 print_message('Translation to Kodkod: Inconsistent integer range: Relaxing to avoid exceptions'),
43 kkp_type(inttype(PowName,PowMin,PowMin)). % relax in
44 kkp_type(inttype(PowName,PowMin,PowMax)) :-
45 kkp_inttype_part1(PowName,PowMin,PowMax),kkp_inttype_part2.
46 kkp_type(inttype(PowName,PowMin,PowMax,IntsetName,Min,Max)) :-
47 PowMax<PowMin,!,
48 print_message('Translation to Kodkod: Inconsistent integer range: Relaxing to avoid exceptions'),
49 kkp_type(inttype(PowName,PowMin,PowMin,IntsetName,Min,Max)).
50 kkp_type(inttype(PowName,PowMin,PowMax,IntsetName,Min,Max)) :-
51 Max<Min,!,
52 print_message('Translation to Kodkod: Inconsistent integer range: Relaxing to avoid exceptions'),
53 kkp_type(inttype(PowName,PowMin,PowMax,IntsetName,Min,Min)).
54 kkp_type(inttype(PowName,PowMin,PowMax,IntsetName,Min,Max)) :-
55 kkp_inttype_part1(PowName,PowMin,PowMax),
56 kprint([popen,id(IntsetName),space,t(Min),space,t(Max),pclose]),
57 kkp_inttype_part2.
58 kkp_inttype_part1(PowName,PowMin,PowMax) :-
59 kprint([popen,t(inttype),popen,id(PowName),space,t(PowMin),space,t(PowMax),pclose]).
60 kkp_inttype_part2 :-
61 kprint(pclose).
62
63 kkp_relations(Relations) :-
64 kprint(popen), kkp_relations2(Relations), kprint(pclose).
65 kkp_relations2([]).
66 kkp_relations2([Rel|Rrest]) :-
67 kkp_relation(Rel), kkp_relations2(Rrest).
68 kkp_relation(reldef(Id,Types,SetOrSingleton,SubsetExact,Set)) :-
69 kprint([popen,id(Id),space]),
70 ( SetOrSingleton==single -> kprint(t('singleton ')); true),
71 kprint([t(SubsetExact)]),kkp_typerefs(Types),
72 kkp_tupleset(Set),
73 kprint(pclose).
74 kkp_typerefs([]).
75 kkp_typerefs([Type|Trest]) :-
76 kprint([space,t(Type)]),
77 kkp_typerefs(Trest).
78 kkp_tupleset(full) :- !.
79 kkp_tupleset(TupleSet) :- is_list(TupleSet),!,
80 kprint(popen),kkp_tupleset2(TupleSet),kprint(pclose).
81 kkp_tupleset2([]).
82 kkp_tupleset2([tuple(Tuple)|Trest]) :-
83 kprint(tuple(Tuple)),kkp_tupleset2(Trest).
84
85 kkp_formula(F) :- kprint(popen), kkp_formula2(F), kprint(pclose).
86 kkp_formula2(true) :- !,kprint(t(true)).
87 kkp_formula2(false) :- !,kprint(t(false)).
88 kkp_formula2(one(E)) :- !,kkp_formula_mult(one, E).
89 kkp_formula2(some(E)) :- !,kkp_formula_mult(some,E).
90 kkp_formula2(no(E)) :- !,kkp_formula_mult(no, E).
91 kkp_formula2(lone(E)) :- !,kkp_formula_mult(lone,E).
92 kkp_formula2(set(E)) :- !,kkp_formula_mult(set, E).
93 kkp_formula2(in(A,B)) :- !,kkp_opexpr(in,[A,B]).
94 kkp_formula2(equals(A,B)) :- !,kkp_opexpr(equals,[A,B]).
95 kkp_formula2(not(F)) :- !,kkp_opform(not,[F]).
96 kkp_formula2(and(A,B)) :- !,flatten_subformulas(and(A,B),Args), kkp_opform(and,Args).
97 kkp_formula2(or(A,B)) :- !,kkp_opform(or, [A,B]).
98 kkp_formula2(implies(A,B)) :- !,kkp_opform(implies,[A,B]).
99 kkp_formula2(iff(A,B)) :- !,kkp_opform(iff,[A,B]).
100 kkp_formula2(forall(Decls,Formula)) :- !,kkp_quantifier(all, Decls, Formula).
101 kkp_formula2(exists(Decls,Formula)) :- !,kkp_quantifier(exists, Decls, Formula).
102 kkp_formula2(gt(A,B)) :- !,kkp_opexpr(gt, [A,B]).
103 kkp_formula2(gte(A,B)) :- !,kkp_opexpr(gte,[A,B]).
104 kkp_formula2(lt(A,B)) :- !,kkp_opexpr(lt, [A,B]).
105 kkp_formula2(lte(A,B)) :- !,kkp_opexpr(lte,[A,B]).
106 kkp_formula2(pfunc(E,D,R)) :- !,kkp_opexpr(pfunc,[E,D,R]).
107 kkp_formula2(func(E,D,R)) :- !,kkp_opexpr(func,[E,D,R]).
108 kkp_formula2(F) :- throw(unknown_construct(formula,F)).
109
110 flatten_subformulas(F,Args) :- flatten_subformulas2(F,Args,[]).
111 flatten_subformulas2(and(A,B)) -->
112 !,flatten_subformulas2(A),flatten_subformulas2(B).
113 flatten_subformulas2(F) --> [F].
114
115
116 kkp_formula_l([]).
117 kkp_formula_l([F|Rest]) :- kkp_formula(F),kkp_formula_l(Rest).
118
119 kkp_formula_mult(M,E) :- kkp_opexpr(M,[E]).
120 %kkp_formula_binlog(Op,A,B) :- kprint(t(Op)),kkp_formula(A),kkp_formula(B).
121
122 kkp_opexpr(Op,Expressions) :- kprint(t(Op)),kkp_expression_l(Expressions).
123 kkp_opform(Op,Formulas) :- kprint(t(Op)),kkp_formula_l(Formulas).
124
125 kkp_quantifier(Type,Decls,Formula) :-
126 kprint(id(Type)),kkp_decls(Decls),kkp_formula(Formula).
127 kkp_decls(Decls) :- kprint(popen),kkp_decls2(Decls),kprint(pclose).
128 kkp_decls2([]).
129 kkp_decls2([D|Drest]) :- kkp_decl(D),kkp_decls2(Drest).
130 kkp_decl(decl(V,Arity,Mult,Expr)) :-
131 !, kprint([popen,id(V),space,t(Arity),space,t(Mult)]),
132 kkp_expression(Expr),kprint(pclose).
133
134 :- use_module(probsrc(error_manager),[add_warning/3]).
135 /* expressions */
136 kkp_expression(E) :- kprint(popen), kkp_expression2(E), kprint(pclose).
137 kkp_expression2(empty) :- !,kkp_opexpr(empty,[]).
138 kkp_expression2(iden) :- !,kkp_opexpr(iden,[]).
139 kkp_expression2(univ) :- !,kkp_opexpr(univ,[]).
140 kkp_expression2(transpose(E)) :- !,kkp_opexpr(transpose,[E]).
141 kkp_expression2(closure(E)) :- !,kkp_opexpr(closure,[E]).
142 kkp_expression2(reflexive_closure(E)) :-!,kkp_opexpr(reflexive_closure,[E]).
143 kkp_expression2(union(A,B)) :- !,kkp_fopexpr(union,union(A,B)).
144 kkp_expression2(intersection(A,B)) :- !,kkp_fopexpr(intersection,intersection(A,B)).
145 kkp_expression2(difference(A,B)) :- !,kkp_opexpr(difference,[A,B]).
146 kkp_expression2(join(A,B)) :- !,kkp_opexpr(join,[A,B]).
147 kkp_expression2(product(A,B)) :- !,kkp_fopexpr(product,product(A,B)).
148 kkp_expression2(overwrite(A,B)) :- !,kkp_opexpr(overwrite,[A,B]).
149 kkp_expression2(relref(I)) :- !,kprint([t('relref '),id(I)]).
150 kkp_expression2(varref(I)) :- !,kprint([t('varref '),id(I)]).
151 kkp_expression2(comp(Decls,Formula)) :- !,kkp_quantifier(comp, Decls, Formula).
152 kkp_expression2(prj(Is,Expr)) :- !,kprint(t(prj)),kkp_ints(Is),kkp_expression(Expr).
153 kkp_expression2(int2pow2(E)) :- !,kkp_opexpr(int2pow2,[E]).
154 kkp_expression2(int2intset(E)) :- !,kkp_opexpr(int2intset,[E]).
155 kkp_expression2(if(Cond,Then,Else)) :- !,kprint(t(if)),kkp_formula(Cond),kkp_expression_l([Then,Else]).
156 /* integer expressions */
157 kkp_expression2(card(E)) :- !,kkp_opexpr(card,[E]).
158 kkp_expression2(add(A,B)) :- !,kkp_opexpr(add,[A,B]).
159 kkp_expression2(sub(A,B)) :- !,kkp_opexpr(sub,[A,B]).
160 kkp_expression2(mul(A,B)) :- !,kkp_opexpr(mul,[A,B]).
161 kkp_expression2(div(A,B)) :- !,kkp_opexpr(div,[A,B]).
162 kkp_expression2(floored_div(A,B)) :- !, add_warning(kodkod_printer,'Translating floored division as truncated division: ',div(A,B)),
163 kkp_opexpr(div,[A,B]).
164 kkp_expression2(mod(A,B)) :- !,kkp_opexpr(mod,[A,B]).
165 kkp_expression2(sum(E)) :- !,kkp_opexpr(expr2int,[E]).
166 kkp_expression2(expr2int(E)) :- !,kkp_opexpr(expr2int,[E]).
167 kkp_expression2(int(I)) :- !,kprint(t(I)).
168 kkp_expression2(E) :- throw(unknown_construct(expression,E)).
169
170 kkp_fopexpr(Op,Expr) :-
171 flatten_subexpressions(Expr,Op,Subs,[]),
172 kkp_opexpr(Op,Subs).
173 flatten_subexpressions(Expr,Op) -->
174 {functor(Expr,Op,2),!,arg(1,Expr,A),arg(2,Expr,B)},
175 flatten_subexpressions(A,Op), flatten_subexpressions(B,Op).
176 flatten_subexpressions(Expr,_) --> [Expr].
177
178 kkp_expression_l([]).
179 kkp_expression_l([E|Erest]) :-
180 kkp_expression(E),kkp_expression_l(Erest).
181
182 kkp_ints(Ints) :- kkp_ints2(Ints,P),kprint([popen|P]).
183 kkp_ints2([],[pclose]).
184 kkp_ints2([I|Irest],[t(I),space|Prest]) :- kkp_ints2(Irest,Prest).
185
186 % send a problem request to Kodkod
187 % MaxLength is the maximum number of solutions
188 kkp_request(Id, Signum, MaxLength, Values, Stream) :- %print(kkp_request(Id, Signum, MaxLength, Values, Stream)),nl,
189 set_stream(Stream),
190 problem_id(Id,PID),
191 kprint([t('request '),id(PID),space,
192 t(MaxLength),space,t(Signum),
193 space,popen]),
194 kkp_values(Values),
195 kprint([pclose,stop]).
196 kkp_values([]).
197 kkp_values([kout(Name,Value)|VRest]) :-
198 kprint([popen,id(Name)]),
199 kkp_tupleset2(Value),
200 kprint(pclose),
201 kkp_values(VRest).
202
203 kkp_list(Id,MaxLength,Stream) :-
204 set_stream(Stream),
205 problem_id(Id,PID),
206 kprint([t('list '),id(PID),space,t(MaxLength),stop]).
207
208 :- use_module(probsrc(debug),[debug_mode/1]).
209 kprint(Out) :-
210 (debug_mode(on) -> kprint2(Out,user_output) ; true),
211 output_stream(Stream),
212 kprint2(Out,Stream).
213 kprint2([],_Stream) :- !.
214 kprint2([E|Rest],Stream) :-
215 !,kprint2(E,Stream),kprint2(Rest,Stream).
216 kprint2(E,S) :- kprint_trans(E,N),!,kprint2(N,S).
217 kprint2(t(T),S) :- dwrite(S,T).
218 kprint2(char(C),S) :- dput_char(S,C).
219 kprint2(tuple(Ints),S) :- dput_char(S,'<'),
220 kprint_ints(Ints,S),dput_char(S,'>').
221
222 kprint_trans(id(Id),t(Id)).
223 kprint_trans(space,char(' ')).
224 kprint_trans(popen,char('(')).
225 kprint_trans(pclose,char(')')).
226 kprint_trans(stop,t('.\n')).
227
228 kprint_ints([],_).
229 kprint_ints([I|Irest],S) :-
230 dwrite(S,I),dput_char(S,' '),
231 kprint_ints(Irest,S).
232
233
234 %dwrite(S,I) :- write(I), write(S,I).
235 %dput_char(S,C) :- put_char(C), put_char(S,C).
236 dwrite(S,I) :- write(S,I).
237 dput_char(S,C) :- put_char(S,C).
238
239
240 problem_id(Num,Id) :-
241 % don't know why the parser does not accept pure numbers
242 number_codes(Num,Codes),
243 % 112 is the ASCII code for p
244 atom_codes(Id,[112|Codes]).