| 1 | % (c) 2009-2010 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(interval, []). | |
| 6 | ||
| 7 | :- use_module(probsrc(b_global_sets)). | |
| 8 | ||
| 9 | :- use_module(probsrc(module_information)). | |
| 10 | :- module_info(group,plugin_absint). | |
| 11 | :- module_info(description,'Integer interval analysis for the experimental abstract interpretation plugin. This domain abstracts integers by intervals and sets by the cardinality.'). | |
| 12 | :- module_info(revision,'$Rev$'). | |
| 13 | :- module_info(lastchanged,'$LastChangedDate$'). | |
| 14 | ||
| 15 | % ------------ | |
| 16 | % GLB and LUB | |
| 17 | % ------------ | |
| 18 | :- public glb/1, lub/1. | |
| 19 | glb(interval_glb). | |
| 20 | lub(lub). | |
| 21 | ||
| 22 | % --------- | |
| 23 | % Mappings | |
| 24 | % --------- | |
| 25 | :- public map_alpha/2, map_unary_operator/2, map_binary_operator/2, map_nary_operator/2, map_binary_test_operator/2. | |
| 26 | map_alpha(alpha,alpha). | |
| 27 | ||
| 28 | map_unary_operator(card,acard). | |
| 29 | map_unary_operator(domain,adomain). | |
| 30 | map_unary_operator(range,arange). | |
| 31 | ||
| 32 | map_binary_operator(add,aadd). | |
| 33 | map_binary_operator(div,adiv). | |
| 34 | map_binary_operator(intersection,aintersection). | |
| 35 | map_binary_operator(interval,ainterval). | |
| 36 | map_binary_operator(minus,aminus). | |
| 37 | map_binary_operator(multiplication,amultiplication). | |
| 38 | map_binary_operator(set_subtraction,aset_subtraction). | |
| 39 | map_binary_operator(union,aunion). | |
| 40 | ||
| 41 | ||
| 42 | map_nary_operator(set_extension,aset_extension). | |
| 43 | ||
| 44 | map_binary_test_operator(equal,aequal). | |
| 45 | map_binary_test_operator(greater,agreater). | |
| 46 | map_binary_test_operator(less,aless). | |
| 47 | map_binary_test_operator(less_equal,aless_equal). | |
| 48 | map_binary_test_operator(member,amember). | |
| 49 | map_binary_test_operator(not_equal,anot_equal). | |
| 50 | map_binary_test_operator(not_member,anot_member). | |
| 51 | ||
| 52 | % ------------------ | |
| 53 | % Alpha transitions | |
| 54 | % ------------------ | |
| 55 | ||
| 56 | :- public alpha/4. | |
| 57 | % based on types: Initial values | |
| 58 | alpha(boolean,_Type,_Infos,boolean) :- !. | |
| 59 | alpha(boolean_true,_Type,_Infos,boolean_true) :- !. | |
| 60 | alpha(boolean_false,_Type,_Infos,boolean_false) :- !. | |
| 61 | ||
| 62 | alpha(global(X),_Type,_Infos,global(X)) :- !. | |
| 63 | ||
| 64 | alpha(string,_Type,_Infos,string) :- !. | |
| 65 | ||
| 66 | alpha(integer,_Type,_Infos,integer([MinInt,MaxInt])) :- !, | |
| 67 | preferences:get_preference(minint,MinInt), | |
| 68 | preferences:get_preference(maxint,MaxInt). | |
| 69 | ||
| 70 | alpha(couple(X,Y),_Type,_Infos,couple(AbsX,AbsY)) :- !, | |
| 71 | alpha(X,X,[],AbsX), alpha(Y,Y,[],AbsY). | |
| 72 | ||
| 73 | alpha(set(_X),Type,Infos,Abs) :- !, | |
| 74 | alpha(empty_set,Type,Infos,Abs). | |
| 75 | ||
| 76 | % based on expressions | |
| 77 | alpha(integer(X),_Type,_Infos,integer([X,X])) :- !. | |
| 78 | ||
| 79 | alpha(empty_set,set(SetOfType),_Infos,set(AbsType,[0,0],MaxCard)) :- !, | |
| 80 | alpha(SetOfType,SetOfType,[],AbsType), | |
| 81 | max_cardinality(SetOfType,MaxCard). | |
| 82 | ||
| 83 | % ------------------ | |
| 84 | % LUB | |
| 85 | % ------------------ | |
| 86 | ||
| 87 | :- public lub/3. | |
| 88 | lub(X,X,X). | |
| 89 | ||
| 90 | lub(integer([CurMinA,CurMaxA]), | |
| 91 | integer([CurMinB,CurMaxB]), | |
| 92 | integer([CurMinC,CurMaxC])) :- | |
| 93 | CurMinC is min(CurMinA,CurMinB), CurMaxC is max(CurMaxA,CurMaxB). | |
| 94 | ||
| 95 | % ------------------ | |
| 96 | % Abstract Operations | |
| 97 | % ------------------ | |
| 98 | ||
| 99 | :- public acard/2. | |
| 100 | acard(set(_Contents,[CurMinCard,CurMaxCard],_MaxCard), integer([CurMinCard,CurMaxCard])). | |
| 101 | ||
| 102 | :- public adomain/2, arange/2. | |
| 103 | adomain(SV1,set(Value,[CurMinCard,CurMaxCard],MaxCard)) :- | |
| 104 | !, SV1 = set(couple(Value,_X),[SetCurMinCard,SetCurMaxCard],_SetMaxCard), | |
| 105 | max_cardinality(Value,MaxCard), | |
| 106 | CurMinCard = SetCurMinCard, CurMaxCard is min(SetCurMaxCard,MaxCard). | |
| 107 | ||
| 108 | arange(SV1,set(Value,[CurMinCard,CurMaxCard],MaxCard)) :- | |
| 109 | !, SV1 = set(couple(_X,Value),[SetCurMinCard,SetCurMaxCard],_SetMaxCard), | |
| 110 | max_cardinality(Value,MaxCard), | |
| 111 | CurMinCard = SetCurMinCard, CurMaxCard is min(SetCurMaxCard,MaxCard). | |
| 112 | ||
| 113 | :- public aadd/3. | |
| 114 | aadd(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinC,MaxC])) :- | |
| 115 | MinCT is MinA + MinB, MaxCT is MaxA + MaxB, | |
| 116 | bound_ints(MinCT,MaxCT,MinC,MaxC). | |
| 117 | ||
| 118 | :- public aminus/3. | |
| 119 | aminus(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinC,MaxC])) :- | |
| 120 | MinCT is MinA - MaxB, MaxCT is MaxA - MinB, | |
| 121 | bound_ints(MinCT,MaxCT,MinC,MaxC). | |
| 122 | ||
| 123 | :- public amultiplication/3. | |
| 124 | amultiplication(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinC,MaxC])) :- | |
| 125 | multi_min([MinA * MinB, MaxA * MaxB, MinA * MaxB, MaxA * MinB], MinCT), | |
| 126 | multi_max([MinA * MinB, MaxA * MaxB, MinA * MaxB, MaxA * MinB], MaxCT), | |
| 127 | bound_ints(MinCT,MaxCT,MinC,MaxC). | |
| 128 | ||
| 129 | :- public adiv/3. | |
| 130 | adiv(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinCR,MaxCR])) :- | |
| 131 | % todo: div by zero | |
| 132 | (MaxB \= 0 -> MinC is MinA/MaxB ; MinC is MinA), | |
| 133 | (MinB \= 0 -> MaxC is MaxA/MinB ; MaxC is MaxA), | |
| 134 | MinCR is floor(MinC), MaxCR is floor(MaxC). | |
| 135 | ||
| 136 | aunion(set(X,[CurMinCardX,CurMaxCardX],MaxCardX), set(Y,[CurMinCardY,CurMaxCardY],MaxCardY),Out) :- | |
| 137 | lub(X,Y,Z), CurMinCardZ is max(CurMinCardX,CurMinCardY), | |
| 138 | % if the type did not change, maxcard still applies | |
| 139 | (X=Y -> MaxCardZ = MaxCardX ; MaxCardZ is MaxCardX + MaxCardY), | |
| 140 | CurMaxCardZ is min(MaxCardZ,CurMaxCardX + CurMaxCardY), | |
| 141 | Out = set(Z,[CurMinCardZ,CurMaxCardZ],MaxCardZ). | |
| 142 | ||
| 143 | :- public aintersection/3. | |
| 144 | aintersection(set(X,[CurMinCardX,CurMaxCardX],MaxCardX), set(Y,[_CurMinCardY,CurMaxCardY],_MaxCardY),Out) :- | |
| 145 | lub(X,Y,Z), CurMinCardZ is max(0,CurMinCardX-CurMaxCardY), | |
| 146 | CurMaxCardZ is CurMaxCardX, MaxCardZ is MaxCardX, | |
| 147 | Out = set(Z,[CurMinCardZ,CurMaxCardZ],MaxCardZ). | |
| 148 | ||
| 149 | :- public aset_subtraction/3. | |
| 150 | aset_subtraction(set(X,[CurMinCardX,CurMaxCardX],MaxCardX), set(_Y,[_CurMinCardY,CurMaxCardY],_MaxCardY),Out) :- | |
| 151 | CurMinCardZ is max(0,CurMinCardX - CurMaxCardY), | |
| 152 | Out = set(X,[CurMinCardZ,CurMaxCardX],MaxCardX). | |
| 153 | ||
| 154 | :- public aset_extension/2. | |
| 155 | aset_extension([AbsVal|AbsVals],Set) :- | |
| 156 | aset_extension(set(AbsVal,[1,1],1),AbsVals,Set). | |
| 157 | aset_extension(SetIn,[],SetIn). | |
| 158 | aset_extension(SetIn,[AbsVal|AbsVals],SetOut) :- | |
| 159 | aunion(SetIn,set(AbsVal,[1,1],1),UpdatedSet), | |
| 160 | aset_extension(UpdatedSet,AbsVals,SetOut). | |
| 161 | ||
| 162 | :- public ainterval/3. | |
| 163 | ainterval(Int1,Int2,set(Int3,[MaxCard,MaxCard],[MaxCard])) :- | |
| 164 | lub(Int1,Int2,Int3), max_cardinality(Int3,MaxCard). | |
| 165 | ||
| 166 | % ------------------ | |
| 167 | % Tests | |
| 168 | % ------------------ | |
| 169 | ||
| 170 | :- public aequal/5. | |
| 171 | aequal(A,A,A,A,true). | |
| 172 | aequal(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinA,MaxA]),integer([MinB,MaxB]),false) :- | |
| 173 | (MaxA < MinB ; MaxB < MinA), !. | |
| 174 | aequal(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinOut,MaxOut]),integer([MinOut,MaxOut]),true) :- | |
| 175 | MinOut is max(MinA,MinB), MaxOut is min(MaxA,MaxB). | |
| 176 | ||
| 177 | aequal(set(Type,[0,0],MaxCard),set(Type,[0,0],MaxCard),set(Type,[0,0],MaxCard),set(Type,[0,0],MaxCard),true). | |
| 178 | ||
| 179 | :- public anot_equal/5. | |
| 180 | anot_equal(E1,S1,E2,S2,Res) :- | |
| 181 | aequal(E1,S1,E2,S2,Res2), | |
| 182 | Res2 = true -> Res = false ; Res = true. | |
| 183 | ||
| 184 | :- public agreater/5. | |
| 185 | agreater(A,B,C,D,Res) :- aless(B,A,D,C,Res). | |
| 186 | ||
| 187 | aless(integer([MinA,MaxA]),integer([MinB,MaxB]),integer([MinA,MaxA]),integer([MinB,MaxB]),true) :- | |
| 188 | MaxA < MinB. | |
| 189 | aless(integer([MinA,_MaxA]),integer([MinB,MaxB]),integer([MinA,MaxAOut]),integer([MinB,MaxB]),true) :- | |
| 190 | MaxAOut is MinB - 1, MaxAOut > MinA. | |
| 191 | aless(integer([MinA,MaxA]),integer([_MinB,MaxB]),integer([MinA,MaxA]),integer([MinBOut,MaxB]),true) :- | |
| 192 | MinBOut is MaxA + 1, MinBOut < MaxB. | |
| 193 | ||
| 194 | :- public aless_equal/5. | |
| 195 | aless_equal(A,B,C,D,E) :- aless(A,B,C,D,E) ; aequal(A,B,C,D,E). | |
| 196 | ||
| 197 | amember(integer(X),set(integer(Y),[CurMinCard,CurMaxCard],MaxCard),integer(X),set(integer(Y),[CurMinCard,CurMaxCard],MaxCard),true) :- | |
| 198 | CurMinCard > 0, lub(integer(X),integer(Y),integer(Y)). | |
| 199 | amember(Elem,set(Type,[CurMinCard,CurMaxCard],MaxCard),Elem,set(Type,[CurMinCard,CurMaxCard],MaxCard),true) :- | |
| 200 | CurMinCard > 0. | |
| 201 | amember(Elem,set(Type,[CurMinCard,CurMaxCard],MaxCard),Elem,set(Type,[CurMinCard,CurMaxCard],MaxCard),false) :- | |
| 202 | CurMinCard = 0. | |
| 203 | ||
| 204 | :- public anot_member/5. | |
| 205 | anot_member(E1,S1,E2,S2,Res) :- | |
| 206 | amember(E1,S1,E2,S2,Res2), | |
| 207 | Res2 = true -> Res = false ; Res = true. | |
| 208 | ||
| 209 | ||
| 210 | % ------------------ | |
| 211 | % Helpers | |
| 212 | % ------------------ | |
| 213 | ||
| 214 | multi_min([A,B],Min) :- !, | |
| 215 | Min is min(A,B). | |
| 216 | multi_min([H|T], Min) :- | |
| 217 | multi_min(T,Min2), | |
| 218 | Min is min(H,Min2). | |
| 219 | ||
| 220 | multi_max([A,B],Max) :- !, | |
| 221 | Max is max(A,B). | |
| 222 | multi_max([H|T], Max) :- | |
| 223 | multi_max(T,Max2), | |
| 224 | Max is max(H,Max2). | |
| 225 | ||
| 226 | bound_ints(MinC,MaxC,MinCOut,MaxCOut) :- | |
| 227 | bound_by_min_int(MinC,MinC2), bound_by_max_int(MinC2,MinCOut), | |
| 228 | bound_by_min_int(MaxC,MaxC2), bound_by_max_int(MaxC2,MaxCOut). | |
| 229 | ||
| 230 | bound_by_min_int(MinCandidate,Min) :- | |
| 231 | preferences:get_preference(minint,MinInt), | |
| 232 | (MinInt > MinCandidate -> Min = MinInt ; Min = MinCandidate). | |
| 233 | ||
| 234 | bound_by_max_int(MaxCandidate,Max) :- | |
| 235 | preferences:get_preference(maxint,MaxInt), | |
| 236 | (MaxInt < MaxCandidate -> Max = MaxInt ; Max = MaxCandidate). | |
| 237 | ||
| 238 | max_cardinality(integer([A,B]), Card) :- | |
| 239 | !, Card is B - A + 1. | |
| 240 | max_cardinality(integer,Card) :- | |
| 241 | !, preferences:get_preference(minint,MinInt), | |
| 242 | preferences:get_preference(maxint,MaxInt), | |
| 243 | Card is MaxInt - MinInt + 1. | |
| 244 | max_cardinality(couple(X,Y),Card) :- | |
| 245 | !, max_cardinality(X,CardX), | |
| 246 | max_cardinality(Y, CardY), | |
| 247 | Card is CardX * CardY. | |
| 248 | max_cardinality(global(X),Card) :- | |
| 249 | b_global_set_cardinality(X,Card). | |
| 250 | max_cardinality(boolean,2). |