Franck Pommereau

added setup.py

1 +/build
2 +*~
3 +__pycache__
1 +"""libDDD-based model-checker for (AR)CTL with(out) fairness
2 +"""
3 +
1 from ddd import ddd, sdd, shom 4 from ddd import ddd, sdd, shom
2 from tl import parse, Phi 5 from tl import parse, Phi
3 from functools import reduce, lru_cache 6 from functools import reduce, lru_cache
...@@ -12,17 +15,17 @@ def fixpoint(fonction, start): ...@@ -12,17 +15,17 @@ def fixpoint(fonction, start):
12 current = fonction(current) 15 current = fonction(current)
13 return current 16 return current
14 17
15 - 18 +
16 - 19 +
17 ####################### CTL ####################### 20 ####################### CTL #######################
18 - 21 +
19 class CTL_model_checker(object): 22 class CTL_model_checker(object):
20 """ 23 """
21 Object which can symbolically compute the subset of the universe where a given CTL formula is satisfied. 24 Object which can symbolically compute the subset of the universe where a given CTL formula is satisfied.
22 - 25 +
23 Attributes : 26 Attributes :
24 - variables : the list of the variables 27 - variables : the list of the variables
25 - 28 +
26 Methods : 29 Methods :
27 - check(formula) : returns the sdd representing the subset of the universe where the input formula is satisfied 30 - check(formula) : returns the sdd representing the subset of the universe where the input formula is satisfied
28 - atom(var) : returns the sdd representing the subset of the universe where var is True 31 - atom(var) : returns the sdd representing the subset of the universe where var is True
...@@ -38,12 +41,12 @@ class CTL_model_checker(object): ...@@ -38,12 +41,12 @@ class CTL_model_checker(object):
38 assert isinstance(succ, shom), "succ must be of type shom" 41 assert isinstance(succ, shom), "succ must be of type shom"
39 42
40 self.logic = "CTL" 43 self.logic = "CTL"
41 - 44 +
42 self.variables = next(iter(universe))[0].vars() # c'est tres sale mais je trouve pas d'autre solution pour l'instant 45 self.variables = next(iter(universe))[0].vars() # c'est tres sale mais je trouve pas d'autre solution pour l'instant
43 46
44 self.CTL_True = universe 47 self.CTL_True = universe
45 self.CTL_False = sdd.empty() 48 self.CTL_False = sdd.empty()
46 - self.neg = lambda phi : self.CTL_True - phi 49 + self.neg = lambda phi : self.CTL_True - phi
47 self.gfp = lambda fonction : fixpoint(fonction, self.CTL_True) 50 self.gfp = lambda fonction : fixpoint(fonction, self.CTL_True)
48 self.lfp = lambda fonction : fixpoint(fonction, self.CTL_False) 51 self.lfp = lambda fonction : fixpoint(fonction, self.CTL_False)
49 52
...@@ -53,7 +56,7 @@ class CTL_model_checker(object): ...@@ -53,7 +56,7 @@ class CTL_model_checker(object):
53 self.EG = lambda phi : self.gfp(lambda Z : phi & (self.EX(Z) | self.deadlock)) 56 self.EG = lambda phi : self.gfp(lambda Z : phi & (self.EX(Z) | self.deadlock))
54 self.EU = lambda phi1, phi2 : self.lfp(lambda Z : phi2 | (phi1 & self.EX(Z))) 57 self.EU = lambda phi1, phi2 : self.lfp(lambda Z : phi2 | (phi1 & self.EX(Z)))
55 self.EW = lambda phi1, phi2 : self.gfp(lambda Z : phi2 | (phi1 & (self.EX(Z) | self.deadlock))) 58 self.EW = lambda phi1, phi2 : self.gfp(lambda Z : phi2 | (phi1 & (self.EX(Z) | self.deadlock)))
56 - self.ER = lambda phi1, phi2 : self.gfp(lambda Z : phi2 & (phi1 | self.EX(Z) | self.deadlock)) 59 + self.ER = lambda phi1, phi2 : self.gfp(lambda Z : phi2 & (phi1 | self.EX(Z) | self.deadlock))
57 self.EM = lambda phi1, phi2 : self.lfp(lambda Z : phi2 & (phi1 | self.EX(Z))) 60 self.EM = lambda phi1, phi2 : self.lfp(lambda Z : phi2 & (phi1 | self.EX(Z)))
58 61
59 self.AX = lambda phi : self.EX(self.CTL_True) & self.neg(self.EX(self.neg(phi))) 62 self.AX = lambda phi : self.EX(self.CTL_True) & self.neg(self.EX(self.neg(phi)))
...@@ -72,7 +75,7 @@ class CTL_model_checker(object): ...@@ -72,7 +75,7 @@ class CTL_model_checker(object):
72 """ 75 """
73 Input : 76 Input :
74 - var : string 77 - var : string
75 - 78 +
76 Output : 79 Output :
77 The sdd representing the subset of the universe where var is True. 80 The sdd representing the subset of the universe where var is True.
78 """ 81 """
...@@ -85,7 +88,7 @@ class CTL_model_checker(object): ...@@ -85,7 +88,7 @@ class CTL_model_checker(object):
85 d = ddd.from_range(v, 0, 1, d) 88 d = ddd.from_range(v, 0, 1, d)
86 return sdd.mkz(d) & self.CTL_True 89 return sdd.mkz(d) & self.CTL_True
87 90
88 - 91 +
89 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves) 92 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves)
90 def _phi2sdd(self, phi): 93 def _phi2sdd(self, phi):
91 if phi.kind == 'bool': 94 if phi.kind == 'bool':
...@@ -113,12 +116,12 @@ class CTL_model_checker(object): ...@@ -113,12 +116,12 @@ class CTL_model_checker(object):
113 else: 116 else:
114 raise ValueError(repr(phi) + "is not a " + self.logic + " sub formula") 117 raise ValueError(repr(phi) + "is not a " + self.logic + " sub formula")
115 118
116 - 119 +
117 def check(self, formula): 120 def check(self, formula):
118 """ 121 """
119 Input : 122 Input :
120 - formula : string or tl.Phi object 123 - formula : string or tl.Phi object
121 - 124 +
122 Output : 125 Output :
123 The sdd representing the subset of the universe where the formula is satisfied. 126 The sdd representing the subset of the universe where the formula is satisfied.
124 """ 127 """
...@@ -130,7 +133,7 @@ class CTL_model_checker(object): ...@@ -130,7 +133,7 @@ class CTL_model_checker(object):
130 133
131 134
132 ####################### Fair CTL ####################### 135 ####################### Fair CTL #######################
133 - 136 +
134 class FairCTL_model_checker(CTL_model_checker): 137 class FairCTL_model_checker(CTL_model_checker):
135 def __init__ (self, universe, succ, fairness): 138 def __init__ (self, universe, succ, fairness):
136 """ 139 """
...@@ -158,10 +161,10 @@ class FairCTL_model_checker(CTL_model_checker): ...@@ -158,10 +161,10 @@ class FairCTL_model_checker(CTL_model_checker):
158 raise TypeError("Fairness constraints must be CTL formulae or SDD") 161 raise TypeError("Fairness constraints must be CTL formulae or SDD")
159 162
160 self.fairness = [fairness_preprocess(f) for f in fairness] 163 self.fairness = [fairness_preprocess(f) for f in fairness]
161 - 164 +
162 self.EG_fair = lambda phi : self.gfp(lambda Z : phi & (self.deadlock | self.EX(reduce(sdd.__and__ , [self.EU(Z, Z & f) for f in self.fairness], self.CTL_True)))) 165 self.EG_fair = lambda phi : self.gfp(lambda Z : phi & (self.deadlock | self.EX(reduce(sdd.__and__ , [self.EU(Z, Z & f) for f in self.fairness], self.CTL_True))))
163 - CTL_model_checker.__init__(self, self.EG_fair(self.CTL_True), succ) 166 + CTL_model_checker.__init__(self, self.EG_fair(self.CTL_True), succ)
164 - 167 +
165 # EX, AX, EU, EF, EM do not need to be redefined once universe = EG_fair(True) 168 # EX, AX, EU, EF, EM do not need to be redefined once universe = EG_fair(True)
166 self.EX_fair = self.EX 169 self.EX_fair = self.EX
167 self.EF_fair = self.EF 170 self.EF_fair = self.EF
...@@ -179,7 +182,7 @@ class FairCTL_model_checker(CTL_model_checker): ...@@ -179,7 +182,7 @@ class FairCTL_model_checker(CTL_model_checker):
179 self.AW_fair = lambda phi1, phi2 : self.neg(self.EU_fair(self.neg(phi2), self.neg(phi1) & self.neg(phi2))) 182 self.AW_fair = lambda phi1, phi2 : self.neg(self.EU_fair(self.neg(phi2), self.neg(phi1) & self.neg(phi2)))
180 self.AR_fair = lambda phi1, phi2 : self.AW_fair(phi2, phi1 & phi2) 183 self.AR_fair = lambda phi1, phi2 : self.AW_fair(phi2, phi1 & phi2)
181 self.AM_fair = lambda phi1, phi2 : self.AU_fair(phi2, phi1 & phi2) 184 self.AM_fair = lambda phi1, phi2 : self.AU_fair(phi2, phi1 & phi2)
182 - 185 +
183 self.unarymod = {"EX" : self.EX_fair, "EF" : self.EF_fair, "EG" : self.EG_fair, "AX" : self.AX_fair, "AF" : self.AF_fair, "AG" : self.AG_fair} 186 self.unarymod = {"EX" : self.EX_fair, "EF" : self.EF_fair, "EG" : self.EG_fair, "AX" : self.AX_fair, "AF" : self.AF_fair, "AG" : self.AG_fair}
184 self.binarymod = {"EU" : self.EU_fair, "ER" : self.ER_fair, "EW" : self.EW_fair, "EM" : self.EM_fair, "AU" : self.AU_fair, "AR" : self.AR_fair, "AW" : self.AW_fair, "AM" : self.AM_fair} 187 self.binarymod = {"EU" : self.EU_fair, "ER" : self.ER_fair, "EW" : self.EW_fair, "EM" : self.EM_fair, "AU" : self.AU_fair, "AR" : self.AR_fair, "AW" : self.AW_fair, "AM" : self.AM_fair}
185 188
...@@ -187,22 +190,22 @@ class FairCTL_model_checker(CTL_model_checker): ...@@ -187,22 +190,22 @@ class FairCTL_model_checker(CTL_model_checker):
187 190
188 ####################### ARCTL ####################### 191 ####################### ARCTL #######################
189 192
190 -import functools 193 +import functools
191 from ddd import shom 194 from ddd import shom
192 195
193 def build_labeled_succ(v): 196 def build_labeled_succ(v):
194 # v.model.spec.rules contains a list of Rule objects (ecco.rr.st.py) representing the rules 197 # v.model.spec.rules contains a list of Rule objects (ecco.rr.st.py) representing the rules
195 # v.g.m.transitions() returns a dict of {"R15" : shom} 198 # v.g.m.transitions() returns a dict of {"R15" : shom}
196 - 199 +
197 res = dict() 200 res = dict()
198 labels = list(set([label for r in v.model.spec.rules if r.label for label in r.label.split(",")]))# build a list of unique value of Rule labels 201 labels = list(set([label for r in v.model.spec.rules if r.label for label in r.label.split(",")]))# build a list of unique value of Rule labels
199 labels.sort() # sort this list for better display 202 labels.sort() # sort this list for better display
200 # add a special key "_None" in the dict associated to unlabeld 203 # add a special key "_None" in the dict associated to unlabeld
201 unlabeled_rules = [r.name() for r in v.model.spec.rules if not r.label] 204 unlabeled_rules = [r.name() for r in v.model.spec.rules if not r.label]
202 if unlabeled_rules: 205 if unlabeled_rules:
203 - assert "_None" not in labels, 'there is a rule labeled "_None" but it is a restricted label for rules without label' 206 + assert "_None" not in labels, 'there is a rule labeled "_None" but it is a restricted label for rules without label'
204 unlabeled_shoms = [v.g.m.transitions()[i] for i in unlabeled_rules] 207 unlabeled_shoms = [v.g.m.transitions()[i] for i in unlabeled_rules]
205 - # build the union of those shoms 208 + # build the union of those shoms
206 res["_None"] = functools.reduce(shom.__or__, unlabeled_shoms, shom.empty()) 209 res["_None"] = functools.reduce(shom.__or__, unlabeled_shoms, shom.empty())
207 # rules with labels 210 # rules with labels
208 for label in labels: 211 for label in labels:
...@@ -229,7 +232,7 @@ class ARCTL_model_checker(CTL_model_checker): ...@@ -229,7 +232,7 @@ class ARCTL_model_checker(CTL_model_checker):
229 for e in succ_dict : # for each key of the dictionnary 232 for e in succ_dict : # for each key of the dictionnary
230 assert isinstance(e, str), "every key of succ_dict must be of type string" 233 assert isinstance(e, str), "every key of succ_dict must be of type string"
231 assert isinstance(succ_dict[e], shom), "every value of succ_dict must be of type shom" 234 assert isinstance(succ_dict[e], shom), "every value of succ_dict must be of type shom"
232 - 235 +
233 self.succ_dict = succ_dict 236 self.succ_dict = succ_dict
234 if tau_label in succ_dict: 237 if tau_label in succ_dict:
235 self.tau_label = tau_label 238 self.tau_label = tau_label
...@@ -238,7 +241,7 @@ class ARCTL_model_checker(CTL_model_checker): ...@@ -238,7 +241,7 @@ class ARCTL_model_checker(CTL_model_checker):
238 self.succ = functools.reduce(shom.__or__, self.succ_dict.values(), shom.empty()) 241 self.succ = functools.reduce(shom.__or__, self.succ_dict.values(), shom.empty())
239 CTL_model_checker.__init__(self, universe, self.succ) 242 CTL_model_checker.__init__(self, universe, self.succ)
240 self.logic = "ARCTL" 243 self.logic = "ARCTL"
241 - 244 +
242 def build_succ_alpha(self, alpha): 245 def build_succ_alpha(self, alpha):
243 if alpha.kind == 'bool': 246 if alpha.kind == 'bool':
244 assert isinstance(alpha.value, bool), repr(alpha) + " is of kind bool but its value is not a boolean" 247 assert isinstance(alpha.value, bool), repr(alpha) + " is of kind bool but its value is not a boolean"
...@@ -256,12 +259,12 @@ class ARCTL_model_checker(CTL_model_checker): ...@@ -256,12 +259,12 @@ class ARCTL_model_checker(CTL_model_checker):
256 return reduce(shom.__or__, [self.build_succ_alpha(child) for child in alpha.children], shom.empty()) 259 return reduce(shom.__or__, [self.build_succ_alpha(child) for child in alpha.children], shom.empty())
257 else: 260 else:
258 raise ValueError(repr(actions) + "is not an action sub formula") 261 raise ValueError(repr(actions) + "is not an action sub formula")
259 - 262 +
260 def check(self, formula): 263 def check(self, formula):
261 """ 264 """
262 Input : 265 Input :
263 - formula : string or tl.Phi object 266 - formula : string or tl.Phi object
264 - 267 +
265 Output : 268 Output :
266 The sdd representing the subset of the universe where the formula is satisfied. 269 The sdd representing the subset of the universe where the formula is satisfied.
267 """ 270 """
...@@ -269,7 +272,7 @@ class ARCTL_model_checker(CTL_model_checker): ...@@ -269,7 +272,7 @@ class ARCTL_model_checker(CTL_model_checker):
269 if isinstance(formula , str): 272 if isinstance(formula , str):
270 formula = parse(formula).arctl() 273 formula = parse(formula).arctl()
271 return self._phi2sdd(formula) 274 return self._phi2sdd(formula)
272 - 275 +
273 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves) 276 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves)
274 def _phi2sdd(self, phi): 277 def _phi2sdd(self, phi):
275 if phi.actions: 278 if phi.actions:
...@@ -283,15 +286,15 @@ class ARCTL_model_checker(CTL_model_checker): ...@@ -283,15 +286,15 @@ class ARCTL_model_checker(CTL_model_checker):
283 else: 286 else:
284 return CTL_model_checker._phi2sdd(self, phi) 287 return CTL_model_checker._phi2sdd(self, phi)
285 288
286 - 289 +
287 - 290 +
288 ####################### Fair ARCTL ####################### 291 ####################### Fair ARCTL #######################
289 - 292 +
290 class FairARCTL_model_checker(ARCTL_model_checker, FairCTL_model_checker): 293 class FairARCTL_model_checker(ARCTL_model_checker, FairCTL_model_checker):
291 def __init__ (self, universe, succ_dict, fairness, true_label="_None"): 294 def __init__ (self, universe, succ_dict, fairness, true_label="_None"):
292 ARCTL_model_checker.__init__(self, universe, succ_dict, true_label) 295 ARCTL_model_checker.__init__(self, universe, succ_dict, true_label)
293 FairCTL_model_checker.__init__ (self, universe, self.succ, fairness) 296 FairCTL_model_checker.__init__ (self, universe, self.succ, fairness)
294 - 297 +
295 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves) 298 # recursive function that builds the sdd along the syntax tree (bottom-up, going-up from the tree leaves)
296 def _phi2sdd(self, phi): 299 def _phi2sdd(self, phi):
297 if phi.actions: 300 if phi.actions:
...@@ -303,4 +306,4 @@ class FairARCTL_model_checker(ARCTL_model_checker, FairCTL_model_checker): ...@@ -303,4 +306,4 @@ class FairARCTL_model_checker(ARCTL_model_checker, FairCTL_model_checker):
303 elif phi.kind in self.binarymod: 306 elif phi.kind in self.binarymod:
304 return FairCTL_model_checker(self.CTL_True, succ, self.fairness).binarymod[phi.kind](self._phi2sdd(phi.children[0]), self._phi2sdd(phi.children[1])) 307 return FairCTL_model_checker(self.CTL_True, succ, self.fairness).binarymod[phi.kind](self._phi2sdd(phi.children[0]), self._phi2sdd(phi.children[1]))
305 else: 308 else:
306 - return FairCTL_model_checker._phi2sdd(self, phi)
...\ No newline at end of file ...\ No newline at end of file
309 + return FairCTL_model_checker._phi2sdd(self, phi)
......
1 +from setuptools import setup, find_packages
2 +import pathlib, inspect
3 +import pymc
4 +
5 +long_description = pathlib.Path("README.md").read_text(encoding="utf-8")
6 +description = inspect.cleandoc(pymc.__doc__).splitlines()[0]
7 +
8 +setup(name="pymc",
9 + description=description,
10 + long_description=long_description,
11 + url="https://forge.ibisc.univ-evry.fr/cthomas/pyits_model_checker",
12 + author="Franck Pommereau",
13 + author_email="franck.pommereau@univ-evry.fr",
14 + classifiers=["Development Status :: 4 - Beta",
15 + "Intended Audience :: Developers",
16 + "Topic :: Scientific/Engineering",
17 + "Programming Language :: Python :: 3",
18 + "Operating System :: OS Independent"],
19 + packages=find_packages(where="."),
20 + python_requires=">=3.7",
21 +)