Source code for witnesscheck

# -*- encoding: utf-8 -*-
"""
This module provide functionality for checking the correctness of
witnesses from the forbidden pattern algorithm.
"""

__author__ = "Alexander Weigl <weigla@fh-trier.de>"
__date__ = "2012-06-12"

from dfa import valid_witness

[docs]class WitnessChecker(object): """ Describes an checker for witnesses. Can be constructed by a string specification and a list of other WitnessChecker. A WitnessChecker has to implement the protocol: >>> MyChecker(object): >>> def __call__(self, dea, witness): >>> raise Exception("...") # if a constraint was violated >>> return True # if every constraint was hit Also __str__ and __repr__ should be implemented for nice printing. """ def __init__(self, spec=None, usecheckers=None): """ """ if usecheckers: self.call_checkers = usecheckers else: self.call_checkers = [] self.spec = spec self.checks = [] if spec: self.checks = parseSpecification(spec) def __iadd__(self, other): print("__iadd__") if type(other) is (list, tuple): self.checks += other else: self.checks.append(other) def __str__(self): string = "" if self.spec: string = "created from spec: \n %s \n#end spec\n" % self.spec if self.call_checkers: string += "rules from other checkers:\n+" + "-" * 20 + "\n|\t" for witness in self.call_checkers: string += str(witness).replace("\n", "\n|\t") + "\n+" + "-" * 20 string += "\n" if self.checks: string += "checks:\n" for checker in self.checks: string += "\t" + str(checker) + "\n" return string def __repr__(self): return "WitnessChecker(%s,%s)" %\ (repr(self.spec), repr(self.call_checkers)) def __call__(self, dea, witness): if not valid_witness(witness): return False for chck in self.call_checkers: chck(dea, witness) for checker in self.checks: checker(dea, witness) #False by Exception return True
[docs]def generateParser(): import ply.yacc as yacc import ply.lex as lex literals = ("-", ",", '#') tokens = ["DELIM", "NAME", "ANTI", "ARROW", "SMALLER"] t_DELIM = r"(\n|;)" t_ANTI = r"<[#]>" t_ARROW = r"->" t_ignore = " \t" t_SMALLER = r"<=" def t_NAME(t): r'[a-zA-Z_0-9\']+' return t # def t_newline(t): # r"\n+" # t.lexer.lineno += t.value.count("\n") # t.type = "DELIM" def t_error(t): print("Illegal character '%s'" % t.value[0]) print(t) t.lexer.skip(1) start = "cnstrnts" def p_cnstrnts_recur(p): '''cnstrnts : cnstrnts DELIM def''' p[1].append(p[3]) p[0] = p[1] def p_cnstrnts_anchor(p): '''cnstrnts : def''' p[0] = list(( p[1], )) def p_def_path(p): '''def : NAME '-' NAME ARROW NAME | NAME '-' NAME ARROW NAME '-' NAME''' if len(p) == 8: p[5] = p[5] + "\\" + p[7] p[0] = path(p[1], p[3], p[5]) def p_def_antivalence(p): '''def : NAME ',' NAME ANTI NAME ',' NAME''' p[0] = antivalence(p[1], p[3], p[5], p[7]) def p_def_neq(p): '''def : NAME '#' NAME''' p[0] = neq(p[1], p[3]) def p_def_alpha(p): '''def : NAME SMALLER NAME''' p[0] = alpha(p[1], p[3]) def p_error(t): if t: print("Syntax error at value '%s' on line %d:%d" % (t, t.lineno, t.lexpos)) def find_column(input, token): last_cr = input.rfind('\n', 0, token.lexpos) if last_cr < 0: last_cr = 0 column = (token.lexpos - last_cr) + 1 return column lexer = lex.lex() yacc.yacc(debug=False, write_tables=False) return yacc
_parser = generateParser() parseSpecification = lambda spec: _parser.parse(spec.strip())
[docs]class composable(object): """ Defines the addition operator for building lists: >>> a,b,c = composable(),composable(),composable() >>> a + b + c [ a , b , c] """ def __add__(self, other): if type(other) in (list,): other.append(self) return other else: return list((self, other))
[docs]class alpha(composable): def __init__(self, *args): if len(args) == 1: self.word1, self.word2 = parseSpecification(args[0]) else: self.word1, self.word2 = args def _tuple(self): return self.word1, self.word2 def __repr__(self): return "alpha('{0} <= {1}')".format(*self._tuple()) def __str__(self): return "check if \alpha({0}) \subseteq \alpha({1})".format(*self._tuple()) def __call__(self, dea, witness, msg=""): w = witness[self.word1] v = witness[self.word2] if not set(w) <= set(v): raise Exception("alpha check failed for witness,v = (%s,%s) " % (witness, v)) #else: # print(str(self), "is satisfied") return True
[docs]class path(composable): def __init__(self, *args): if len(args) == 1: self.start, self.words, self.target = parseSpecification(args[0]) else: self.start, self.words, self.target = args self.start, self.words, self.target = map(str, self._tuple()) def _tuple(self): return self.start, self.words, self.target def __repr__(self): return "path('{0} - {1} -> {2}')".format(*self._tuple()) def __str__(self): return "check if \hat \delta({0}, {1}) = {2}".format(*self._tuple()) def __call__(self, dea, witness, msg=""): #word = [] #for witness in iterwords(self.words): # word += witness[witness] try: word = witness[self.words] start_state = witness[self.start] end_state = dea(start_state, word) if self.target == "F": ret = end_state in dea.F elif self.target in ("Q-F", "Q\\F"): ret = end_state in (dea.Q - dea.F) else: target_state = witness[self.target] ret = end_state == target_state if not msg: msg = "%s - %s -> %s" % (self.start, self.words, self.target) if not ret: raise Exception("path check failed: " + msg) #else: # print(str(self), "is satisfied") return True except KeyError as e: print(self._tuple(), witness, e) raise Exception("witness %s not found" % e)
[docs]class antivalence(composable): def __init__(self, *args): if len(args) == 1: self.state1, self.word1, self.state2, self.word2 = parseSpecification(args[0]) else: self.state1, self.word1, self.state2, self.word2 = args def _tuple(self): return self.state1, self.word1, self.state2, self.word2 def __repr__(self): return "path('{0},{1} <#> {2},{3}')".format(*self._tuple()) def __str__(self): return "check if \delta({0}, {1}) \in F <#> \delta({2},{3}) \\in F".format(*self._tuple()) def __call__(self, dea, witnesses, msg=""): # word = [] # for witness in iterwords(word1): # word += self.witness[witness] try: start1 = witnesses[self.state1] start2 = witnesses[self.state2] word1 = witnesses[self.word1] word2 = witnesses[self.word2] end1 = dea(start1, word1) end2 = dea(start2, word2) if not ((end1 in dea.F) ^ (end2 in dea.F )): raise Exception("failed: " + str(self)) except KeyError as e: print(self._tuple(), witnesses, e) raise Exception("witness %s not found" % e)
[docs]class neq(composable): def __init__(self, *args): if len(args) == 1: self.state1, self.state2 = parseSpecification(args[0]) else: self.state1, self.state2 = args def _tuple(self): return self.state1, self.state2 def __repr__(self): return "path('{0} # {1}')".format(*self._tuple()) def __str__(self): return "check if {0} \\neq {0}".format(*self._tuple()) def __call__(self, dea, witness): check = witness[self.state1] != witness[self.state2] if not check: raise Exception("neq failed: %s = %s" % (self.state1, self.state2))
checkWitnessL12 = WitnessChecker( """ p - w -> q p - z -> F q - z -> Q - F p # q """ ) checkWitnessB12 = WitnessChecker( """ p - v -> p q - v -> q """, (checkWitnessL12,)) checkWitnessL1_1 = WitnessChecker( """ p - w -> q q - v -> p p,z <#> q,z """) checkWitnessL1_2 = WitnessChecker(""" q - u -> p p - v -> r r - u -> p q - v -> s s - u -> t t - v -> s t,z <#> p,z p # t """) #=============================================================================== # {'q': 2, 'p': 1, 's': 3, 'r': 0, 'u': 'a', 't': 3, 'f': 3, 'v': 'bb', 'z': 'abb', 'd': 0} # 2 - a -> 1 # 1 - bb -> 0 # 0 - a -> 1 # 2 - bb -> 3 # 3 - a -> 3 # 3 - bb -> 3 # 3,abb <!=> 1,abb # 1 != 3 #=============================================================================== checkWitnessB1 = WitnessChecker(""" q1 - y -> q2 q2 - y' -> q1 q1 - w -> q1 q2 - w' -> q2 q1 - u -> q3 q3 - v -> q5 q5 - u -> q3 q3 - w -> q3 q5 - w' -> q5 q2 - v -> q4 q4 - u -> q6 q6 - v -> q4 q4 - w -> q4 q6 - w' -> q6 q3,z <#> q6,z """) checkWitnessL32 = WitnessChecker(""" p - v -> p q - v -> q p - w -> q p,z <#> q,z w <= v """)
[docs]def t(dea, witness): try: return checkWitnessL1_1(dea, witness[0]) and checkWitnessL1_2(dea, witness[1]), except Exception as e: raise e
CHECKERS = { 'l12': checkWitnessL12, 'b12': checkWitnessB12, 'l1': t, #lambda dea, witness: checkWitnessL1_1(dea,witness[0]) and checkWitnessL1_2(dea,witness[1]), 'b1': checkWitnessB1, 'l32': checkWitnessL32, } if __name__ == "__main__": print("Witness Checkers:") print(repr(checkWitnessL12)) print(checkWitnessB12) print(checkWitnessL1_1) print(checkWitnessL1_2) print(checkWitnessB1) print(checkWitnessL32)

This Page