1 | :- module(kodkod_tools,[ extract_finite_integer_range/3 | |
2 | , unique_identifier/1 | |
3 | , unique_identifier/2 | |
4 | , unique_identifier/3 | |
5 | , merge_integer_info/3 | |
6 | , kodkod_conjunction/2 | |
7 | , kodkod_implication/3 | |
8 | , disassemble_conjunction/2 | |
9 | ||
10 | , pow2integer_relation_kodkod_name/1 | |
11 | , intset_relation_kodkod_name/1 | |
12 | ||
13 | , is_inconsistent_expression/1 | |
14 | ]). | |
15 | ||
16 | :- use_module(probsrc(tools), [ajoin/2]). | |
17 | :- use_module(probsrc(module_information)). | |
18 | :- use_module(probsrc(translate), [translate_bexpression/2]). | |
19 | :- use_module(probsrc(bsyntaxtree)). | |
20 | :- use_module(probsrc(predicate_analysis), [info_disjunct/3]). | |
21 | ||
22 | :- module_info(group,kodkod). | |
23 | :- module_info(description,'This module contains helper predicates for the Kodkod translation part of ProB'). | |
24 | ||
25 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
26 | % constants | |
27 | pow2integer_relation_kodkod_name(p2i). | |
28 | intset_relation_kodkod_name(is). | |
29 | ||
30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
31 | % helper to extract the integer range of a type expression | |
32 | extract_finite_integer_range(TExpr,ScopeList,IRange) :- | |
33 | convert_scopelist_to_scope(ScopeList,interval,Scope), | |
34 | extract_finite_integer_range2(TExpr,Scope,IRange). | |
35 | convert_scopelist_to_scope([],Scope,Scope). | |
36 | convert_scopelist_to_scope([Access|Rest],OScope,Scope) :- | |
37 | functor(NScope,Access,1),arg(1,NScope,OScope), | |
38 | convert_scopelist_to_scope(Rest,NScope,Scope). | |
39 | extract_finite_integer_range2(TExpr,Scope,IRange) :- | |
40 | get_texpr_info(TExpr,Info), | |
41 | memberchk(analysis(Analysis),Info), | |
42 | memberchk(Scope:IRange0,Analysis), | |
43 | ( is_inconsistent_intrange(IRange0) -> | |
44 | IRange = irange(0,0) % throwing an exception is not really sensible, e.g. | |
45 | % if we have an inconsistent range of a variable in a | |
46 | % comprehension set - then the set would just be empty | |
47 | % We can safely(?) assume a larger range (here 0..0) | |
48 | ; otherwise -> | |
49 | is_finite(IRange0),IRange0=IRange),!. | |
50 | extract_finite_integer_range2(TExpr,_Scope,_IRange) :- | |
51 | translate_bexpression(TExpr,SExpr), | |
52 | ajoin(['integer without upper and lower bound in: ', SExpr], Msg), | |
53 | throw(kodkod(unsupported_int(Msg))). | |
54 | is_finite(irange(Min,Max)) :- number(Min),number(Max). | |
55 | is_inconsistent_intrange(irange(Min,Max)) :- | |
56 | number(Min),number(Max),Max < Min. | |
57 | is_inconsistent_expression(TExpr) :- | |
58 | get_texpr_info(TExpr,Info), | |
59 | memberchk(analysis(Analysis),Info), | |
60 | member(_:IRange,Analysis), | |
61 | is_inconsistent_intrange(IRange),!. | |
62 | ||
63 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
64 | % unique identifier | |
65 | :- dynamic unique_counter/1, debug_identifier/0. | |
66 | ||
67 | ||
68 | unique_identifier(Prefix,Name,Id) :- | |
69 | ( debug_identifier -> | |
70 | increase_counter(C), | |
71 | ajoin([Prefix,C,'_',Name],Id) | |
72 | ; otherwise -> | |
73 | unique_identifier(Prefix,Id)). | |
74 | unique_identifier(Prefix,Id) :- | |
75 | increase_counter(C), | |
76 | ajoin([Prefix,C],Id). | |
77 | unique_identifier(Id) :- | |
78 | unique_identifier(tmpid__,Id). | |
79 | increase_counter(C2) :- | |
80 | ( retract(unique_counter(C)) -> true; C=0 ), | |
81 | C2 is C+1, | |
82 | assert(unique_counter(C2)). | |
83 | ||
84 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
85 | % merge two integer ranges | |
86 | merge_integer_info(none,A,A) :- !. | |
87 | merge_integer_info(A,none,A) :- !. | |
88 | merge_integer_info(IRangeA,IRangeB,IRange) :- | |
89 | info_disjunct(IRangeA,IRangeB,IRange). | |
90 | ||
91 | ||
92 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
93 | % combining Kodkod expressions | |
94 | ||
95 | kodkod_conjunction(List,Result) :- | |
96 | findall(E,(member(E,List),E \= true),L2), | |
97 | kodkod_conjunction2(L2,Result). | |
98 | kodkod_conjunction2([],true). | |
99 | kodkod_conjunction2([F],F) :- !. | |
100 | kodkod_conjunction2([A,B|R],and(A,F)) :- kodkod_conjunction2([B|R],F). | |
101 | ||
102 | kodkod_implication(true,Formula,Formula) :- !. | |
103 | kodkod_implication(false,_,true) :- !. | |
104 | kodkod_implication(F1,F2,implies(F1,F2)). | |
105 | ||
106 | disassemble_conjunction(Formula,Result) :- | |
107 | disassemble_conjunction2(Formula,Result,[]),!. | |
108 | disassemble_conjunction2(and(A,B)) --> | |
109 | disassemble_conjunction2(A), | |
110 | disassemble_conjunction2(B). | |
111 | disassemble_conjunction2(X) --> {X\=and(_,_)},[X]. |