master > master: allgemeine Aufräumung

This commit is contained in:
RD
2021-05-10 14:32:52 +02:00
parent a0dee82659
commit 61ec2d7df3
17 changed files with 303 additions and 244 deletions

View File

@@ -1,37 +0,0 @@
%import common.WS
%import common.NUMBER
%import common.WORD
%ignore WS
// Schemata für Ausdrücke
// 'open' = äußerste Klammern fehlen, wenn nötig.
// 'closed' = sonst
?expr: open | closed
?closed: atomic | not | "(" open ")"
?open: and | and_long | or | or_long | impl
// Schemata für atomische Ausdrücke
?atomic: false | true | atom | generic
?false: /0|false/ -> kontr
?true: /1|true/ -> taut
?atom: /A[0-9]+/ -> atom
// als 'generische' Formeln schreibe bspw. {F}, {G}, {F1}, usw.
?generic: "{" /((?!({|})).)+/ "}" -> beliebig
// Symbole (erlaube mehrere Varianten)
?symb_not: /!|~|not/ -> symb
?symb_and: /&+|\^|and/ -> symb
?symb_or: /\|+|v|or/ -> symb
?symb_impl: /->|=>/ -> symb
// Schema für Negation: ¬ F
?not: symb_not closed -> neg
// Schemata für Konjunktion: F1 ⋀ F2 bzw. F1 ⋀ F2 ⋀ ... ⋀ Fn
?and: closed symb_and closed -> konj
?and_long: [ closed ( symb_and closed )+ ] -> konj_lang
// Schemata für Disjunktion: F1 F2 bzw. F1 F2 ... Fn
?or: closed symb_or closed -> disj
?or_long: [ closed ( symb_or closed )+ ] -> disj_lang
// Schema für Implikation: F1 ⟶ F2
?impl: closed symb_impl closed -> impl

View File

@@ -5,21 +5,9 @@
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations
from lark import Tree;
from typing import List;
from aussagenlogik.schema import isAtom;
from aussagenlogik.schema import isBeliebig;
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 SyntaxBaum;
from aussagenlogik.syntaxbaum import SyntaxBaum;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBALE KONSTANTEN
@@ -31,53 +19,69 @@ from aussagenlogik.schema import SyntaxBaum;
# METHODEN
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def rekursiv_eval(fml: SyntaxBaum, I: List[str]) -> int:
def rekursivEval(fml: SyntaxBaum, I: List[str]) -> int:
subfml = fml.children;
if isAtom(fml):
########
# FÄLLE AUS DER VORLESUNG
########
# Fall Atom
if fml.isAtom():
name = fml.expr;
return 1 if (name in I) else 0;
if isBeliebig(fml):
name = fml.expr;
return 1 if (name in I) else 0;
elif isTrueSymbol(fml):
return 1;
elif isFalseSymbol(fml):
return 0;
elif isNegation(fml):
val0 = rekursiv_eval(subfml[0], I);
# Fall ¬F
elif fml.isNegation():
val0 = rekursivEval(subfml[0], I);
return 1 - val0;
elif isConjunction(fml):
val0 = rekursiv_eval(subfml[0], I);
val1 = rekursiv_eval(subfml[1], I);
# Fall F1 ⋀ F2
elif fml.isConjunction2():
val0 = rekursivEval(subfml[0], I);
val1 = rekursivEval(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(subfml[0], I);
val1 = rekursiv_eval(subfml[1], I);
# Fall F1 F2
elif fml.isDisjunction2():
val0 = rekursivEval(subfml[0], I);
val1 = rekursivEval(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(subfml[0], I);
val1 = rekursiv_eval(subfml[1], I);
########
# WEITERE FÄLLE NICHT IN VORLESUNG
########
# Sonderfall: generische Formel als Variable
if fml.isGeneric():
name = fml.expr;
return 1 if (name in I) else 0;
# Sonderfall: Tautologiesymbol
elif fml.isTautologySymbol():
return 1;
# Sonderfall: Kontradiktionssymbol
elif fml.isContradictionSymbol():
return 0;
# Fall Implikation: F1 ⟶ F2
elif fml.isImplication():
val0 = rekursivEval(subfml[0], I);
val1 = rekursivEval(subfml[1], I);
return 0 if val0 == 1 and val1 == 0 else 1;
# Fall F1 ⋀ F2 ⋀ ... ⋀ Fn
elif fml.isConjunction():
values = [rekursivEval(t, I) for t in subfml];
return min(values);
# Fall F1 F2 ... Fn
elif fml.isDisjunction():
values = [rekursivEval(t, I) for t in subfml];
return max(values);
raise Exception('Evaluation nicht möglich!');
def rekursiv_atoms(fml: Tree) -> List[str]:
def rekursivAtoms(fml: SyntaxBaum) -> List[str]:
## Herausforderung: schreibe diese Funktion!
return [];
def rekursiv_depth(fml: Tree) -> int:
def rekursivDepth(fml: SyntaxBaum) -> int:
## Herausforderung: schreibe diese Funktion!
return 0;
def rekursiv_length(fml: Tree) -> int:
def rekursivLength(fml: SyntaxBaum) -> int:
## Herausforderung: schreibe diese Funktion!
return 0;
def rekursiv_parentheses(fml: Tree) -> int:
def rekursivParentheses(fml: SyntaxBaum) -> int:
## Herausforderung: schreibe diese Funktion!
return 0

View File

@@ -6,8 +6,6 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
# install: lark; lark-parser; lark-parser[regex].
# https://lark-parser.readthedocs.io/en/latest/grammar.html
from lark import Lark;
from aussagenlogik.syntaxbaum import SyntaxBaum;
@@ -16,10 +14,10 @@ from aussagenlogik.syntaxbaum import SyntaxBaum;
# GLOBALE KONSTANTEN
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## lexer
with open('aussagenlogik/grammar.lark', 'r') as fp:
# lexer durch LARK erzeugen
with open('grammars/grammar.lark', 'r') as fp:
grammar = ''.join(fp.readlines());
lexerAussagenlogik = Lark(grammar, start='expr', regex=True);
lexer = Lark(grammar, start='expr', regex=True);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODE: string -> Syntaxbaum
@@ -27,43 +25,6 @@ with open('aussagenlogik/grammar.lark', 'r') as fp:
def stringToSyntaxbaum(expr: str) -> SyntaxBaum:
try:
return SyntaxBaum(lexerAussagenlogik.parse(expr));
return SyntaxBaum(lexer.parse(expr));
except:
raise Exception('Ausdruck \033[1m{}\033[0m konnte nicht erkannt werden!'.format(expr));
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODEN: Erkennung von Formeltypen
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def isAtom(fml: SyntaxBaum) -> bool:
return fml.kind == 'atom';
def isLiteral(fml: SyntaxBaum) -> bool:
return isAtom(fml) or (isNegation(fml) and isAtom(fml.child));
def isBeliebig(fml: SyntaxBaum) -> bool:
return fml.kind == 'beliebig';
def isTrueSymbol(fml: SyntaxBaum) -> bool:
return fml.kind == 'taut';
def isFalseSymbol(fml: SyntaxBaum) -> bool:
return fml.kind == 'kontr';
def isNegation(fml: SyntaxBaum) -> bool:
return fml.kind == 'neg';
def isConjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'konj';
def isLongConjunction(fml: SyntaxBaum) -> bool:
return fml.kind in ['konj', 'konj_lang'];
def isDisjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'disj';
def isLongDisjunction(fml: SyntaxBaum) -> bool:
return fml.kind in ['disj', 'disj_lang'];
def isImplication(fml: SyntaxBaum) -> bool:
return fml.kind == 'impl';

View File

@@ -6,7 +6,7 @@
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from lark import Tree;
from lark import Tree as larkTree;
from typing import Generator;
from typing import List;
@@ -21,37 +21,31 @@ from typing import List;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SyntaxBaum(object):
expr: str;
kind: str;
expr: str;
valence: int;
children: List[SyntaxBaum];
tree: Tree;
def __init__(self, fml: Tree):
def __init__(self, fml: larkTree):
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 subfml in fml.children:
if isinstance(subfml, str):
signature_parts.append(subfml);
elif subfml.data == 'symb':
symb = str(subfml.children[0]);
signature_parts.append(symb);
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' ]:
lbrace = '(' if self.expr.startswith('(') else '( ';
rbrace = ')' if self.expr.endswith(')') else ' )';
self.expr = lbrace + self.expr + rbrace;
self.children = [];
self.valence = 0;
expr_parts = []
for child in fml.children:
if isinstance(child, str):
expr_parts.append(child);
## subfml is instance larkTree:
elif child.data == 'symb':
symb = str(child.children[0]);
expr_parts.append(symb);
else:
subtree = SyntaxBaum(child);
self.children.append(subtree);
self.valence += 1;
expr_parts.append(subtree.expr);
self.expr = ' '.join(expr_parts);
if self.valence > 1:
self.expr = '(' + self.expr + ')';
return;
def __str__(self):
@@ -65,5 +59,58 @@ class SyntaxBaum(object):
def child(self) -> SyntaxBaum:
return self.children[0];
def pretty(self):
return self.tree.pretty(indent_str='- ');
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD: Pretty
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def pretty(self, preindent: str = '', tab: str = ' ', prepend: str = '', depth: int = 0) -> str:
indent = preindent + tab*depth;
if self.valence == 0 and self.kind in [ 'atom', 'generic' ]:
return indent + prepend + self.kind + ' ' + self.expr;
return '\n'.join(
[indent + prepend + self.kind] \
+ [subtree.pretty(preindent, tab, '|__ ', depth+1) for subtree in self.children]
);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS: Erkennung von Formeltypen
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def isIrreducible(self) -> bool:
return self.valence == 0;
def isAtom(self) -> bool:
return self.kind == 'atom';
def isLiteral(self) -> bool:
return self.isAtom() or (self.isNegation() and self.child.isAtom());
def isGeneric(self) -> bool:
return self.kind == 'generic';
def isTautologySymbol(self) -> bool:
return self.kind == 'taut';
def isContradictionSymbol(self) -> bool:
return self.kind == 'contradiction';
def isConnective(self) -> bool:
return self.valence > 0;
def isNegation(self) -> bool:
return self.kind == 'not';
def isConjunction2(self) -> bool:
return self.kind == 'and2';
def isConjunction(self) -> bool:
return self.kind in ['and', 'and2'];
def isDisjunction2(self) -> bool:
return self.kind == 'or2';
def isDisjunction(self) -> bool:
return self.kind in ['or', 'or2'];
def isImplication(self) -> bool:
return self.kind == 'implies';