def test_expand_formula_error(self): a_sym = Symbol("a") alphabet = Alphabet({a_sym}) a = Next(AtomicFormula(a_sym)) pl = PL(alphabet) with self.assertRaises(ValueError) as ve: pl.expand_formula(a)
def test_expand_formula_allowed_formulas(self): a_sym = Symbol("a") b_sym = Symbol("b") alphabet = Alphabet({a_sym, b_sym}) a = AtomicFormula(a_sym) b = AtomicFormula(b_sym) pl = PL(alphabet) self.assertEqual(pl.expand_formula(a), a) self.assertEqual(pl.expand_formula(Not(b)), Not(b)) self.assertEqual(pl.expand_formula(And(a, b)), And(a, b))
def test_expand_formula_composed(self): a_sym = Symbol("a") alphabet = Alphabet({a_sym}) a = AtomicFormula(a_sym) # T = Not(And(Not(DUMMY_ATOMIC), DUMMY_ATOMIC)) # F = And(Not(DUMMY_ATOMIC), DUMMY_ATOMIC) T = TrueFormula() F = FalseFormula() pl = PL(alphabet) self.assertEqual(pl.expand_formula(And(TrueFormula(), FalseFormula())), And(T, F)) self.assertEqual(pl.expand_formula(Or(TrueFormula(), FalseFormula())), Not(And(Not(T), Not(F)))) self.assertEqual( pl.expand_formula(Implies(TrueFormula(), FalseFormula())), Not(And(Not(Not(T)), Not(F)))) self.assertEqual( pl.expand_formula(Equivalence(TrueFormula(), FalseFormula())), Not(And(Not(And(T, F)), Not(And(Not(T), Not(F))))))
def _expand_path(self, p: PathExpression) -> PathExpression: if isinstance(p, PathExpressionUnion) or isinstance( p, PathExpressionSequence): return type(p)(self._expand_path(p.p1), self._expand_path(p.p2)) elif isinstance(p, PathExpressionTest): return PathExpressionTest(self.expand_formula(p.f)) elif isinstance(p, PathExpressionStar): return PathExpressionStar(self._expand_path(p.p)) elif isinstance(p, Formula): pl = PL(self.alphabet) return pl.expand_formula(p) else: raise ValueError
def test_expand_formula_derived_formulas(self): a_sym = Symbol("a") b_sym = Symbol("b") alphabet = Alphabet({a_sym, b_sym}) a = AtomicFormula(a_sym) b = AtomicFormula(b_sym) # T = Not(And(Not(DUMMY_ATOMIC), DUMMY_ATOMIC)) # F = And(Not(DUMMY_ATOMIC), DUMMY_ATOMIC) T = TrueFormula() F = FalseFormula() pl = PL(alphabet) self.assertEqual(pl.expand_formula(TrueFormula()), T) self.assertEqual(pl.expand_formula(FalseFormula()), F) self.assertEqual(pl.expand_formula(Or(a, b)), Not(And(Not(a), Not(b)))) self.assertEqual(pl.expand_formula(Implies(a, b)), Not(And(Not(Not(a)), Not(b)))) self.assertEqual(pl.expand_formula(Implies(b, a)), Not(And(Not(Not(b)), Not(a)))) # A === B = (A AND B) OR (NOT A AND NOT B) = NOT( NOT(A AND B) AND NOT(NOT A AND NOT B) ) self.assertEqual(pl.expand_formula(Equivalence(a, b)), Not(And(Not(And(a, b)), Not(And(Not(a), Not(b))))))
class REf(FormalSystem): def __init__(self, alphabet: Alphabet): super().__init__(alphabet) self.pl = PL(self.alphabet) allowed_formulas = { PathExpressionUnion, PathExpressionSequence, PathExpressionStar, AtomicFormula, And, Not } derived_formulas = {Or, Implies, Equivalence, TrueFormula, FalseFormula} def _is_formula(self, f: Formula): """Check if a formula is legal in the current formal system""" if isinstance(f, PathExpressionUnion): return self.is_formula(f.p1) and self.is_formula(f.p2) elif isinstance(f, PathExpressionSequence): return self._is_formula(f.p1) and self._is_formula(f.p2) elif isinstance(f, PathExpressionStar): return self._is_formula(f.p) else: pl = PL(self.alphabet) return pl.is_formula(f) def _truth(self, f: Formula, trace: FiniteTrace, start: int, end: int): assert self._is_formula(f) assert trace.alphabet == self.alphabet truth = self.truth if isinstance(f, PathExpressionUnion): return truth(f.p1, trace, start, end) or truth( f.p2, trace, start, end) if isinstance(f, PathExpressionSequence): return any( truth(f.p1, trace, start, k) and truth(f.p2, trace, k, end) for k in range(start, end + 1)) if isinstance(f, PathExpressionStar): return end == start or any( truth(f.p, trace, start, k) and truth(f, trace, k, end) for k in range(start, end + 1)) else: pl, I = PL._from_set_of_propositionals(trace.get(start), self.alphabet) assert pl.is_formula(f) return end == start + 1 and end <= trace.length() and pl.truth( f, I) def to_nnf(self, f: Formula): if isinstance(f, PathExpressionUnion): return PathExpressionUnion(self.to_nnf(f.p1), self.to_nnf(f.p2)) elif isinstance(f, PathExpressionSequence): return PathExpressionSequence(self.to_nnf(f.p1), self.to_nnf(f.p2)) elif isinstance(f, PathExpressionStar): return PathExpressionStar(self.to_nnf(f.p)) elif isinstance(f, Formula): pl = PL(self.alphabet) assert pl.is_formula(f) return f else: raise ValueError def to_equivalent_formula(self, derived_formula: Formula): return self.pl.to_equivalent_formula(derived_formula) def _expand_formula(self, f: Formula): if self.pl.is_formula(f): return self.pl.expand_formula(f) else: return f