master > master: Schema robuster gemacht; simple class, um Aspekte leichter aufzurufen
This commit is contained in:
		
							parent
							
								
									6f6de00296
								
							
						
					
					
						commit
						28a1e313b3
					
				| @ -5,7 +5,7 @@ | ||||
| # IMPORTS | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| from __future__ import annotations; | ||||
| from __future__ import annotations | ||||
| from lark import Tree; | ||||
| from typing import List; | ||||
| 
 | ||||
| @ -15,10 +15,12 @@ from aussagenlogik.schema import isTrueSymbol; | ||||
| from aussagenlogik.schema import isFalseSymbol; | ||||
| from aussagenlogik.schema import isNegation; | ||||
| from aussagenlogik.schema import isConjunction; | ||||
| from aussagenlogik.schema import isLongConjunction; | ||||
| from aussagenlogik.schema import isDisjunction; | ||||
| from aussagenlogik.schema import isLongDisjunction; | ||||
| from aussagenlogik.schema import isImplication; | ||||
| from aussagenlogik.schema import getTeilformeln; | ||||
| from aussagenlogik.schema import getName; | ||||
| from aussagenlogik.schema import SyntaxBaum; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # GLOBALE KONSTANTEN | ||||
| @ -30,8 +32,8 @@ from aussagenlogik.schema import getName; | ||||
| # METHODEN | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def rekursiv_eval(fml: Tree, I: List[str]) -> int: | ||||
|     teilfml = getTeilformeln(fml); | ||||
| def rekursiv_eval(fml: SyntaxBaum, I: List[str]) -> int: | ||||
|     subfml = fml.children; | ||||
|     if isAtom(fml): | ||||
|         name = getName(fml); | ||||
|         return 1 if (name in I) else 0; | ||||
| @ -43,19 +45,25 @@ def rekursiv_eval(fml: Tree, I: List[str]) -> int: | ||||
|     elif isFalseSymbol(fml): | ||||
|         return 0; | ||||
|     elif isNegation(fml): | ||||
|         val0 = rekursiv_eval(teilfml[0], I); | ||||
|         val0 = rekursiv_eval(subfml[0], I); | ||||
|         return 1 - val0; | ||||
|     elif isConjunction(fml): | ||||
|         val0 = rekursiv_eval(teilfml[0], I); | ||||
|         val1 = rekursiv_eval(teilfml[1], I); | ||||
|         val0 = rekursiv_eval(subfml[0], I); | ||||
|         val1 = rekursiv_eval(subfml[1], I); | ||||
|         return min(val0, val1); | ||||
|     elif isLongConjunction(fml): | ||||
|         values = [rekursiv_eval(t, I) for t in subfml]; | ||||
|         return min(values); | ||||
|     elif isDisjunction(fml): | ||||
|         val0 = rekursiv_eval(teilfml[0], I); | ||||
|         val1 = rekursiv_eval(teilfml[1], I); | ||||
|         val0 = rekursiv_eval(subfml[0], I); | ||||
|         val1 = rekursiv_eval(subfml[1], I); | ||||
|         return max(val0, val1); | ||||
|     elif isLongDisjunction(fml): | ||||
|         values = [rekursiv_eval(t, I) for t in subfml]; | ||||
|         return max(values); | ||||
|     elif isImplication(fml): | ||||
|         val0 = rekursiv_eval(teilfml[0], I); | ||||
|         val1 = rekursiv_eval(teilfml[1], I); | ||||
|         val0 = rekursiv_eval(subfml[0], I); | ||||
|         val1 = rekursiv_eval(subfml[1], I); | ||||
|         return 0 if val0 == 1 and val1 == 0 else 1; | ||||
|     raise Exception('Evaluation nicht möglich!'); | ||||
| 
 | ||||
|  | ||||
| @ -11,6 +11,7 @@ from __future__ import annotations; | ||||
| from lark import Lark; | ||||
| from lark import Tree; | ||||
| from typing import List; | ||||
| from typing import Union; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # GLOBALE KONSTANTEN | ||||
| @ -24,42 +25,84 @@ lexerAussagenlogik = Lark( | ||||
|     %import common.WORD | ||||
|     %ignore WS | ||||
| 
 | ||||
|     ?start: expr | ||||
|     ?start: expr | open | ||||
| 
 | ||||
|     ?expr:    atomic | expr_not | expr_and | expr_or | expr_implies | ||||
|     ?literal: atomic | "not" atomic | ||||
|     ?expr:     atomic | not | closed | ||||
|     ?open:     and | and_long | or | or_long | impl | ||||
|     ?closed:   "(" open ")" | ||||
| 
 | ||||
|     // atomische Ausdrücke | ||||
|     ?atomic:    false | true | atom | generic | ||||
|     ?false:     "0"                         -> wahr | ||||
|     ?true:      "1"                         -> falsch | ||||
|     ?atom:      /A[0-9]+/                -> atom | ||||
|     ?generic:   "{" /((?!({|})).)+/ "}"     -> beliebig | ||||
|     ?false:     "0"                     -> kontr | ||||
|     ?true:      "1"                     -> taut | ||||
|     ?atom:      /A[0-9]+/               -> atom | ||||
|     ?generic:   "{" /((?!({|})).)+/ "}" -> beliebig | ||||
| 
 | ||||
|     // Symbole | ||||
|     ?conn_not:  "!"     -> junktor | ||||
|     ?conn_and:  /&+/    -> junktor | ||||
|     ?conn_or:   /\\|+/  -> junktor | ||||
|     ?conn_impl: /->|=>/ -> junktor | ||||
|     ?symb_not:  /!/     -> symb | ||||
|     ?symb_and:  /&+/    -> symb | ||||
|     ?symb_or:   /\\|+/  -> symb | ||||
|     ?symb_impl: /->|=>/ -> symb | ||||
| 
 | ||||
|     // Junktoren | ||||
|     ?expr_not:     conn_not expr                -> negation | ||||
|     ?expr_and:     "(" expr conn_and   expr ")" -> konjunktion | ||||
|     ?expr_or:      "(" expr conn_or    expr ")" -> disjunktion | ||||
|     ?expr_implies: "(" expr conn_impl  expr ")" -> implikation | ||||
|     ?not:               symb_not   expr      -> neg | ||||
|     ?and:        expr   symb_and   expr      -> konj | ||||
|     ?and_long: [ expr ( symb_and   expr )+ ] -> konj_lang | ||||
|     ?or:         expr   symb_or    expr      -> disj | ||||
|     ?or_long:  [ expr ( symb_or    expr )+ ] -> disj_lang | ||||
|     ?impl:       expr   symb_impl  expr      -> impl | ||||
|     ''', | ||||
|     start="expr", | ||||
|     regex=True | ||||
| ); | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # KLASSE: Syntaxbaum | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| class SyntaxBaum(object): | ||||
|     expr: str; | ||||
|     kind: str; | ||||
|     children: List[SyntaxBaum]; | ||||
|     tree: Tree; | ||||
| 
 | ||||
|     def __init__(self, fml: Tree): | ||||
|         self.kind = fml.data; | ||||
|         if len(fml.children) == 1 and isinstance(fml.children[0], str): | ||||
|             self.expr = fml.children[0]; | ||||
|             self.children = []; | ||||
|             self.tree = Tree(self.kind, fml.children); | ||||
|         else: | ||||
|             self.children = [ SyntaxBaum(child) for child in fml.children if isinstance(child, Tree) and child.data != 'symb' ]; | ||||
|             self.tree = Tree(self.kind, [child.tree for child in self.children]); | ||||
|             signature_parts = []; | ||||
|             i = 0; | ||||
|             for teilfml in fml.children: | ||||
|                 if isinstance(teilfml, str): | ||||
|                     signature_parts.append(teilfml); | ||||
|                 elif teilfml.data == 'symb': | ||||
|                     signature_parts.append(getText(teilfml)); | ||||
|                 else: | ||||
|                     signature_parts.append('{{{}}}'.format(i)); | ||||
|                     i += 1; | ||||
|             signature = ' '.join(signature_parts); | ||||
|             self.expr = signature.format(*self.children); | ||||
|             if self.kind in [ 'konj', 'konj_lang', 'disj', 'disj_lang', 'impl' ]: | ||||
|                 self.expr = '( {} )'.format(self.expr); | ||||
|         return; | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         return self.expr; | ||||
| 
 | ||||
|     def pretty(self): | ||||
|         return self.tree.pretty(); | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # METHODE: string -> Syntaxbaum | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def stringToSyntaxbaum(u: str) -> Tree: | ||||
| def stringToSyntaxbaum(u: str) -> SyntaxBaum: | ||||
|     try: | ||||
|         u_lexed = lexerAussagenlogik.parse(u); | ||||
|         return u_lexed; | ||||
|         return SyntaxBaum(lexerAussagenlogik.parse(u)); | ||||
|     except: | ||||
|         raise Exception('Ausdruck \033[1m{}\033[0m konnte nicht erkannt werden!'.format(u)); | ||||
| 
 | ||||
| @ -67,47 +110,52 @@ def stringToSyntaxbaum(u: str) -> Tree: | ||||
| # METHODEN: Erkennung von Formeltypen | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def isAtom(fml: Tree) -> bool: | ||||
|     return fml.data == 'atom'; | ||||
| def isAtom(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'atom'; | ||||
| 
 | ||||
| def isBeliebig(fml: Tree) -> bool: | ||||
|     return fml.data == 'beliebig'; | ||||
| def isBeliebig(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'beliebig'; | ||||
| 
 | ||||
| def isTrueSymbol(fml: Tree) -> bool: | ||||
|     return fml.data == 'wahr'; | ||||
| def isTrueSymbol(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'taut'; | ||||
| 
 | ||||
| def isFalseSymbol(fml: Tree) -> bool: | ||||
|     return fml.data == 'falsch'; | ||||
| def isFalseSymbol(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'kontr'; | ||||
| 
 | ||||
| def isNegation(fml: Tree) -> bool: | ||||
|     return fml.data == 'negation'; | ||||
| def isNegation(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'neg'; | ||||
| 
 | ||||
| def isConjunction(fml: Tree) -> bool: | ||||
|     return fml.data == 'konjunktion'; | ||||
| def isConjunction(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'konj'; | ||||
| 
 | ||||
| def isDisjunction(fml: Tree) -> bool: | ||||
|     return fml.data == 'disjunktion'; | ||||
| def isLongConjunction(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'konj_lang'; | ||||
| 
 | ||||
| def isImplication(fml: Tree) -> bool: | ||||
|     return fml.data == 'implikation'; | ||||
| def isDisjunction(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'disj'; | ||||
| 
 | ||||
| def isLongDisjunction(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'disj_lang'; | ||||
| 
 | ||||
| def isImplication(fml: SyntaxBaum) -> bool: | ||||
|     return fml.kind == 'impl'; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # METHODEN: Formel -> Teilformeln | ||||
| # METHODEN: Formel -> Textinhalt | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def getTeilformeln(fml: Tree) -> List[Tree]: | ||||
|     return [ | ||||
|         part for part in fml.children | ||||
|         if isinstance(part, Tree) | ||||
|         and not part.data == 'junktor' | ||||
|     ]; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # METHODEN: Formel (Atom/Beliebig) -> Name | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def getName(fml: Tree) -> str: | ||||
| def getText(fml: Tree) -> str: | ||||
|     text = fml.children[0]; | ||||
|     if isinstance(text, str): | ||||
|         return text; | ||||
|     raise Exception('Konnte Textinhalt nicht ablesen!'); | ||||
| 
 | ||||
| def getName(fml: SyntaxBaum) -> str: | ||||
|     return fml.expr; | ||||
| 
 | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| # METHODEN: Formel -> Textinhalt | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| def prettifyTree(fml: Union[Tree, SyntaxBaum]) -> str: | ||||
|     return fml.pretty(); | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| # expr = "( A0 && A1 )" | ||||
| # expr = "( A0 || A1 )" | ||||
| # expr = "( A0 -> A1 )" | ||||
| expr = "( A0 -> ((A0 && A3) || ! A2) )" | ||||
| expr = "( A0 -> ((A0 && A3 && A4) || ! A2) )" | ||||
| # expr = "( A0 -> ((A0 && A3) || A2) )" | ||||
| # expr = "(( {G} || !{G} ) -> A5)" | ||||
| interpretation = "[ 'A0', 'A2' ]" | ||||
|  | ||||
							
								
								
									
										28
									
								
								code/main.py
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								code/main.py
									
									
									
									
									
								
							| @ -5,7 +5,6 @@ | ||||
| # IMPORTS | ||||
| # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| 
 | ||||
| from __future__ import annotations; | ||||
| import os; | ||||
| import sys; | ||||
| # sys.tracebacklimit = 0; | ||||
| @ -16,7 +15,9 @@ from typing import List; | ||||
| 
 | ||||
| sys.path.insert(0, os.getcwd()); | ||||
| 
 | ||||
| from aussagenlogik.schema import prettifyTree; | ||||
| from aussagenlogik.schema import stringToSyntaxbaum; | ||||
| from aussagenlogik.schema import SyntaxBaum; | ||||
| from aussagenlogik.rekursion import rekursiv_eval; | ||||
| from aussagenlogik.rekursion import rekursiv_atoms; | ||||
| from aussagenlogik.rekursion import rekursiv_depth; | ||||
| @ -37,17 +38,17 @@ def main(): | ||||
|     ## Daten einlesen: | ||||
|     expr, I = getData(); | ||||
|     ## Formel in Teilformeln zerlegen: | ||||
|     tree = stringToSyntaxbaum(expr); | ||||
|     fml = stringToSyntaxbaum(expr); | ||||
|     ## Methoden ausführen: | ||||
|     results = dict( | ||||
|         eval  = rekursiv_eval(tree, I), | ||||
|         atoms = rekursiv_atoms(tree), | ||||
|         d     = rekursiv_depth(tree), | ||||
|         l     = rekursiv_length(tree), | ||||
|         p     = rekursiv_parentheses(tree), | ||||
|         eval  = rekursiv_eval(fml, I), | ||||
|         atoms = rekursiv_atoms(fml), | ||||
|         d     = rekursiv_depth(fml), | ||||
|         l     = rekursiv_length(fml), | ||||
|         p     = rekursiv_parentheses(fml), | ||||
|     ); | ||||
|     ## Resultate anzeigen: | ||||
|     display_results(expr, tree, I, results); | ||||
|     display_results(expr, fml, I, results); | ||||
|     return; | ||||
| 
 | ||||
| 
 | ||||
| @ -61,17 +62,18 @@ def getData(): | ||||
|     I = eval(data['interpretation'] or '[]'); | ||||
|     return expr, I; | ||||
| 
 | ||||
| def display_results(expr: str, tree: Tree, I: List[str], results: dict): | ||||
| def display_results(expr: str, fml: SyntaxBaum, I: List[str], results: dict): | ||||
|     print(dedent( | ||||
|         ''' | ||||
|         Syntaxbaum von | ||||
|             F := \033[92;1m{F}\033[0m: | ||||
|         '''.format(F=expr) | ||||
|         '''.format(F=fml) | ||||
|     )); | ||||
|     print(tree.pretty()); | ||||
|     print(prettifyTree(fml)); | ||||
|     print(dedent( | ||||
|         ''' | ||||
|         eval(F, I)      = \033[94;1m{eval}\033[0m; | ||||
|         Für I = [{I}] und F wie oben gilt | ||||
|         eval(F, I)      = \033[94;1m{eval}\033[0m, | ||||
|         \033[2matoms(F)        = \033[94;1m{atoms}\033[0m; \033[91;1m<- *\033[0m | ||||
|         \033[2mdepth(F)        = \033[94;1m{d}\033[0m;  \033[91;1m<- *\033[0m | ||||
|         \033[2mlength(F)       = \033[94;1m{l}\033[0m;  \033[91;1m<- *\033[0m | ||||
| @ -79,7 +81,7 @@ def display_results(expr: str, tree: Tree, I: List[str], results: dict): | ||||
| 
 | ||||
|         \033[91;1m*\033[0m \033[2mnoch nicht implementiert!\033[0m | ||||
|         \033[1;2;4mChallenge:\033[0m \033[2mschreibe diese Methoden! (siehe README.md)\033[0m | ||||
|         '''.format(**results) | ||||
|         '''.format(**results, I=', '.join(I)) | ||||
|     )); | ||||
|     return; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user