def test_to_nnf_derived_formulas(self): fol = self.fol john = ConstantTerm.fromString("john") x = Variable.fromString("x") right_equal = Equal(x, john) true_ = TrueFormula() false_ = FalseFormula() or_ = Or(true_, Not(right_equal)) implies_ = Implies(or_, false_) equivalence_ = Equivalence(implies_, false_) forall_true_ = ForAll(x, true_) forall_not_or_ = ForAll(x, Not(or_)) forall_equivalence_ = ForAll(x, equivalence_) to_nnf_true_ = Equal(DUMMY_TERM, DUMMY_TERM) to_nnf_false_ = Not(Equal(DUMMY_TERM, DUMMY_TERM)) to_nnf_or_ = Or(to_nnf_true_, Not(right_equal)) to_nnf_not_or_ = And(Not(to_nnf_true_), right_equal) to_nnf_implies_ = Or(to_nnf_not_or_, to_nnf_false_) not_to_nnf_implies_ = And(to_nnf_or_, to_nnf_true_) positive_equivalence = And(to_nnf_implies_, to_nnf_false_) negative_equivalence = And(not_to_nnf_implies_, to_nnf_true_) to_nnf_equivalence_ = Or(positive_equivalence, negative_equivalence) self.assertEqual(fol.to_nnf(true_), to_nnf_true_) self.assertEqual(fol.to_nnf(false_), to_nnf_false_) self.assertEqual(fol.to_nnf(or_), to_nnf_or_) self.assertEqual(fol.to_nnf(implies_), to_nnf_implies_) self.assertEqual(fol.to_nnf(equivalence_), to_nnf_equivalence_) self.assertEqual(fol.to_nnf(forall_true_), ForAll(x, to_nnf_true_)) self.assertEqual(fol.to_nnf(forall_not_or_), ForAll(x, to_nnf_not_or_)) self.assertEqual(fol.to_nnf(forall_equivalence_), ForAll(x, to_nnf_equivalence_))
def test_truth_star(self): ref = self.ref a = self.a b = self.b c = self.c self.assertTrue(ref.truth(PathExpressionStar(a), self.trace_1, 0, 4)) self.assertFalse(ref.truth(PathExpressionStar(a), self.trace_1, 0, 5)) self.assertTrue( ref.truth(PathExpressionStar(Or(a, Or(b, c))), self.trace_1, 0, 5)) self.assertTrue(ref.truth(TrueFormula(), self.trace_1, 0, 1))
def test_to_nnf(self): f1 = Not( PathExpressionEventually( PathExpressionSequence(PathExpressionTest(Not(self.a_and_b)), PathExpressionStar(TrueFormula())), self.abc)) nnf_f1 = PathExpressionAlways( PathExpressionSequence( PathExpressionTest(Or(Not(self.a), Not(self.b))), # PathExpressionStar(Or(DUMMY_ATOMIC, Not(DUMMY_ATOMIC))) PathExpressionStar(TrueFormula())), Or(Not(self.a), Or(Not(self.b), Not(self.c)))) self.assertEqual(self.ldlf.to_nnf(f1), nnf_f1)
def test_find_atomics(self): a = Symbol("a") b = Symbol("b") c = Symbol("c") atomic_a = AtomicFormula(a) atomic_b = AtomicFormula(b) atomic_c = AtomicFormula(c) self.assertEqual( PL.find_atomics(And(atomic_a, And(atomic_b, atomic_c))), {atomic_a, atomic_b, atomic_c}) self.assertEqual(PL.find_atomics(Or(atomic_a, Or(atomic_b, atomic_c))), {atomic_a, atomic_b, atomic_c}) self.assertEqual( PL.find_atomics(Equivalence(atomic_a, Or(atomic_b, atomic_c))), {atomic_a, atomic_b, atomic_c})
def setUp(self): """Set up test fixtures, if any.""" self.a_sym = Symbol("a") self.b_sym = Symbol("b") self.c_sym = Symbol("c") self.alphabet = Alphabet({self.a_sym, self.b_sym, self.c_sym}) # Propositions self.a = AtomicFormula(self.a_sym) self.b = AtomicFormula(self.b_sym) self.c = AtomicFormula(self.c_sym) self.not_a = Not(self.a) self.not_a_and_b = And(self.not_a, self.b) self.not_a_or_c = Or(self.not_a, self.c) self.true = TrueFormula() self.false = FalseFormula() self.symbol2truth = { self.a_sym: True, self.b_sym: False, self.c_sym: True } self.I = PLInterpretation(self.alphabet, self.symbol2truth) self.PL = PL(self.alphabet)
def test_expand_formula_derived_formulas(self): fol = self.fol john = ConstantTerm.fromString("john") x = Variable.fromString("x") right_equal = Equal(x, john) true_ = TrueFormula() false_ = FalseFormula() or_ = Or(true_, Not(right_equal)) implies_ = Implies(or_, false_) equivalence_ = Equivalence(implies_, false_) forall_ = ForAll(x, equivalence_) expanded_true = Equal(DUMMY_TERM, DUMMY_TERM) expanded_false = Not(Equal(DUMMY_TERM, DUMMY_TERM)) expanded_or_ = Not(And(Not(expanded_true), Not(Not(right_equal)))) expanded_implies_ = Not(And(expanded_or_, Not(expanded_false))) positive_equivalence = And(expanded_implies_, expanded_false) negative_equivalence = And(Not(expanded_implies_), Not(expanded_false)) expanded_equivalence_ = Not( And(Not(positive_equivalence), Not(negative_equivalence))) self.assertEqual(fol.expand_formula(true_), expanded_true) self.assertEqual(fol.expand_formula(false_), expanded_false) self.assertEqual(fol.expand_formula(or_), expanded_or_) self.assertEqual(fol.expand_formula(implies_), expanded_implies_) self.assertEqual(fol.expand_formula(equivalence_), expanded_equivalence_) self.assertEqual(fol.expand_formula(forall_), Not(Exists(x, Not(expanded_equivalence_))))
def to_nnf(self, f: Formula): # assert self.is_formula(f) # formula = self.expand_formula(f) formula = f if isinstance(formula, AtomicFormula) or isinstance( formula, TrueFormula) or isinstance(formula, FalseFormula): return formula elif isinstance(formula, And) or isinstance(formula, Or): return type(formula)(self.to_nnf(formula.f1), self.to_nnf(formula.f2)) elif type(formula) in self.derived_formulas: return self.to_nnf(self.derived_formulas[type(formula)](formula)) elif isinstance(formula, Not): subformula = formula.f if isinstance(subformula, Not): return self.to_nnf(subformula.f) elif isinstance(subformula, And): return Or(self.to_nnf(Not(subformula.f1)), self.to_nnf((Not(subformula.f2)))) elif isinstance(subformula, Or): return And(self.to_nnf(Not(subformula.f1)), self.to_nnf((Not(subformula.f2)))) elif isinstance(subformula, AtomicFormula) or isinstance( formula, TrueFormula) or isinstance(formula, FalseFormula): return formula elif type(subformula) in self.derived_formulas: return self.to_nnf( Not(self.derived_formulas[type(subformula)](subformula))) else: raise ValueError else: raise ValueError
def to_nnf(self, f: Formula): assert self.is_formula(f) formula = self.expand_formula(f) if isinstance(formula, PredicateFormula) or isinstance(formula, Equal): return formula elif isinstance(formula, And): return And(self.to_nnf(formula.f1), self.to_nnf(formula.f2)) if isinstance(formula, Exists): return Exists(formula.v, self.to_nnf(formula.f)) if isinstance(formula, Not): subformula = formula.f if isinstance(subformula, Not): return self.to_nnf(subformula.f) elif isinstance(subformula, And): return Or(self.to_nnf(Not(subformula.f1)), self.to_nnf((Not(subformula.f2)))) elif isinstance(subformula, Exists): return ForAll(subformula.v, self.to_nnf(Not(subformula.f))) elif isinstance(subformula, PredicateFormula) or isinstance( subformula, Equal): return formula else: raise ValueError else: raise ValueError
def test_to_nnf_allowed_formulas_not_normalized(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.to_nnf(Not(Not(b))), b) self.assertEqual(pl.to_nnf(Not(And(a, Not(b)))), Or(Not(a), b))
def test_to_nnf_derived_formula(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.to_nnf(Not(Or(b, Not(a)))), And(Not(b), a)) self.assertEqual(pl.to_nnf(Not(Implies(b, Not(a)))), And(b, a))
def test_is_formula_derived(self): fol = self.fol john = ConstantTerm.fromString("john") not_a_term = ConstantTerm.fromString("NotATerm") x = Variable.fromString("x") y = Variable.fromString("y") right_equal = Equal(x, john) wrong_equal = Equal(x, not_a_term) self.assertTrue(fol.is_formula(TrueFormula())) self.assertTrue(fol.is_formula(FalseFormula())) self.assertTrue(fol.is_formula(Or(right_equal, right_equal))) self.assertFalse(fol.is_formula(Or(right_equal, wrong_equal))) self.assertTrue(fol.is_formula(Or(right_equal, right_equal))) self.assertFalse(fol.is_formula(Or(right_equal, wrong_equal))) self.assertTrue(fol.is_formula(Implies(right_equal, right_equal))) self.assertFalse(fol.is_formula(Implies(right_equal, wrong_equal))) self.assertTrue(fol.is_formula(Equivalence(right_equal, right_equal))) self.assertFalse(fol.is_formula(Equivalence(right_equal, wrong_equal))) self.assertTrue( fol.is_formula( ForAll(x, PredicateFormula(PredicateSymbol("Person", 2), john, x)))) self.assertFalse( fol.is_formula( ForAll( x, PredicateFormula(PredicateSymbol("Person", 3), john, x, john)))) self.assertFalse( fol.is_formula( ForAll( x, PredicateFormula(PredicateSymbol("Person_fake", 2), john, x))))
def to_nnf(self, formula: Formula) -> Formula: if isinstance(formula, AtomicFormula): return formula elif isinstance(formula, And): return And(self.to_nnf(formula.f1), self.to_nnf(formula.f2)) elif isinstance(formula, Or): return Or(self.to_nnf(formula.f1), self.to_nnf(formula.f2)) elif isinstance(formula, PathExpressionFormula): return type(formula)(self.to_nnf_path(formula.p), self.to_nnf(formula.f)) elif isinstance(formula, Not): return self._not_to_nnf(formula) else: raise ValueError
def _not_to_nnf(self, not_formula: Not): subformula = not_formula.f if isinstance(subformula, AtomicFormula): return not_formula if isinstance(subformula, Not): # skip two consecutive Not new_formula = subformula.f return self.to_nnf(new_formula) elif isinstance(subformula, And): return Or(self.to_nnf(Not(subformula.f1)), self.to_nnf(Not(subformula.f2))) elif isinstance(subformula, Or): return And(self.to_nnf(Not(subformula.f1)), self.to_nnf(Not(subformula.f2))) elif isinstance(subformula, PathExpressionEventually): return PathExpressionAlways(self.to_nnf_path(subformula.p), self.to_nnf(Not(subformula.f))) elif isinstance(subformula, PathExpressionAlways): return PathExpressionEventually(self.to_nnf_path(subformula.p), self.to_nnf(Not(subformula.f))) else: raise ValueError
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 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))))))
def test_minimal_models(self): a = Symbol("a") b = Symbol("b") c = Symbol("c") alphabet = Alphabet({a, b, c}) pl = PL(alphabet) atomic_a = AtomicFormula(a) atomic_b = AtomicFormula(b) atomic_c = AtomicFormula(c) self.assertEqual( pl.minimal_models(TrueFormula()), {PLInterpretation(alphabet, { a: False, b: False, c: False })}) self.assertEqual(pl.minimal_models(FalseFormula()), set()) self.assertEqual( pl.minimal_models(atomic_a), {PLInterpretation(alphabet, { a: True, b: False, c: False })}) self.assertEqual( pl.minimal_models(Not(atomic_a)), {PLInterpretation(alphabet, { a: False, b: False, c: False })}) self.assertEqual( pl.minimal_models(And(atomic_a, atomic_b)), {PLInterpretation(alphabet, { a: True, b: True, c: False })}) self.assertEqual(pl.minimal_models(And(atomic_a, Not(atomic_a))), set()) self.assertEqual( pl.minimal_models(Or(atomic_a, atomic_b)), { PLInterpretation(alphabet, { a: False, b: True, c: False }), PLInterpretation(alphabet, { a: True, b: False, c: False }) }) self.assertEqual( pl.minimal_models(And.chain([atomic_a, atomic_b, atomic_c])), {PLInterpretation(alphabet, { a: True, b: True, c: True })})
def setUp(self): """Set up test fixtures, if any.""" # Symbols self.a_sym = Symbol("a") self.b_sym = Symbol("b") self.c_sym = Symbol("c") # Propositions self.a = AtomicFormula(self.a_sym) self.b = AtomicFormula(self.b_sym) self.c = AtomicFormula(self.c_sym) # Propositionals self.not_a = Not(self.a) self.not_b = Not(self.b) self.not_c = Not(self.c) self.a_and_b = And(self.a, self.b) self.a_and_c = And(self.a, self.c) self.b_and_c = And(self.b, self.c) self.abc = And(self.a, And(self.b, self.c)) self.b_or_c = Or(self.b, self.c) self.a_or_b = Or(self.a, self.b) self.not_abc = Not(And(self.a, And(self.b, self.c))) ### Path expression # Tests self.test_a = PathExpressionTest(self.a) self.test_b = PathExpressionTest(self.b) self.test_not_a = PathExpressionTest(self.not_a) self.test_not_b = PathExpressionTest(self.not_b) # Union self.path_a_or_b = PathExpressionUnion(self.a, self.b) self.path_b_or_c = PathExpressionUnion(self.b, self.c) # Sequence self.path_seq_a_and_b__a_and_c = PathExpressionSequence( self.a_and_b, self.a_and_c) self.path_a_or_b__b_or_c = PathExpressionSequence( self.path_a_or_b, self.path_b_or_c) # Stars self.path_b_or_c_star = PathExpressionStar(self.path_b_or_c) self.path_not_abc = PathExpressionStar(self.not_abc) # Modal connective self.eventually_propositional_a_and_b__a_and_c = PathExpressionEventually( self.a_and_b, self.a_and_c) self.eventually_test_a__c = PathExpressionEventually( self.test_a, self.c) self.eventually_test_a__b = PathExpressionEventually( self.test_a, self.b) self.eventually_seq_a_and_b__a_and_c__not_c = PathExpressionEventually( self.path_seq_a_and_b__a_and_c, self.not_c) self.eventually_seq_a_and_b__a_and_c__c = PathExpressionEventually( self.path_seq_a_and_b__a_and_c, self.c) self.eventually_b_or_c_star__b_and_c = PathExpressionEventually( self.path_b_or_c_star, self.b_and_c) self.next_a_and_c = PathExpressionEventually(TrueFormula(), self.a_and_c) self.liveness_b_and_c = PathExpressionEventually( PathExpressionStar(TrueFormula()), self.b_and_c) self.liveness_abc = PathExpressionEventually( PathExpressionStar(TrueFormula()), self.abc) self.always_true__a = PathExpressionAlways( PathExpressionStar(TrueFormula()), self.a) self.always_true__b_or_c = PathExpressionAlways( PathExpressionStar(TrueFormula()), self.b_or_c) self.alphabet = Alphabet({self.a_sym, self.b_sym, self.c_sym}) # Traces self.ldlf = LDLf(self.alphabet) self.trace_1_list = [ {self.a_sym, self.b_sym}, {self.a_sym, self.c_sym}, {self.a_sym, self.b_sym}, {self.a_sym, self.c_sym}, {self.b_sym, self.c_sym}, ] self.trace_1 = FiniteTrace(self.trace_1_list, self.alphabet)
def setUp(self): """Set up symbols, terms and formulas. Both legal and illegal, according to some FOL system""" # Symbols self.a_sym = Symbol('a') self.b_sym = Symbol('b') self.const_sym = ConstantSymbol("Const") self.fun_sym = FunctionSymbol("Fun", 3) self.predicate_sym = PredicateSymbol("Predicate", 2) self.A = PredicateSymbol("A", 1) # Terms self.a = Variable(self.a_sym) self.b = Variable(self.b_sym) self.c = Variable.fromString("c") self.const = ConstantTerm(self.const_sym) self.fun_abc = FunctionTerm(self.fun_sym, self.a, self.b, self.c) # Formulas self.predicate_ab = PredicateFormula(self.predicate_sym, self.a, self.b) self.predicate_ac = PredicateFormula(self.predicate_sym, self.a, self.c) self.A_a = PredicateFormula(self.A, self.a) self.a_equal_a = Equal(self.a, self.a) self.b_equal_c = Equal(self.b, self.c) self.neg_a_equal_a = Not(self.a_equal_a) self.neg_Aa = Not(self.A_a) self.Aa_and_b_equal_c = And(self.A_a, self.b_equal_c) self.Aa_or_b_equal_c = Or(self.A_a, self.b_equal_c) self.Aa_implies_b_equal_c = Implies(self.A_a, self.b_equal_c) self.exists_a_predicate_ab = Exists(self.a, self.predicate_ab) self.forall_b_exists_a_predicate_ab = ForAll( self.b, self.exists_a_predicate_ab) # FOL self.vars = {self.a, self.b, self.c} self.functions = {self.const_sym, self.fun_sym} self.predicates = {self.predicate_sym, self.A} self.alphabet = FOLAlphabet(self.functions, self.predicates) self.myFOL = FOL(self.alphabet) # define dummy stuff # does not belong to myFOL. They are used for test membership to myFOL self.dummy_variable = Variable.fromString( "ThisVariableDoesNotBelongToFOLSystem") self.dummy_fun_sym = FunctionSymbol( "ThisFunctionDoesNotBelongToFOLSystem", 3) self.dummy_constant_sym = ConstantSymbol( "ThisConstDoesNotBelongToFOLSystem") self.dummy_predicate_sym = PredicateSymbol( "ThisPredicateDoesNotBelongToFOLSystem", 2) self.dummy_fun = FunctionTerm(self.dummy_fun_sym, self.a, self.b, self.dummy_variable) self.dummy_constant = ConstantTerm(self.dummy_constant_sym) self.dummy_predicate = PredicateFormula(self.dummy_predicate_sym, self.a, self.b) self.dummy_predicate_only_one_symbol_false = PredicateFormula( self.predicate_sym, self.dummy_variable, self.dummy_constant) self.dummy_equal = Equal(self.c, self.dummy_constant) self.dummy_neg = Not(self.dummy_predicate_only_one_symbol_false) self.dummy_and = And(self.dummy_predicate, self.predicate_ab) self.dummy_or = Or(self.dummy_predicate_only_one_symbol_false, self.predicate_ac) self.dummy_exists = Exists(self.dummy_variable, self.dummy_predicate_only_one_symbol_false) self.dummy_forall = ForAll(self.b, self.dummy_predicate)
def test_truth(self): w = Variable.fromString("w") Person_x_20 = PredicateFormula(self.Person_pred_sym, self.x, ConstantTerm.fromString("20")) Person_x_y = PredicateFormula(self.Person_pred_sym, self.x, self.y) not_Person_x_21 = Not( PredicateFormula(self.Person_pred_sym, self.x, ConstantTerm.fromString("21"))) y_equal_20 = Equal(self.y, ConstantTerm.fromString("20")) x_equal_john = Equal(self.x, ConstantTerm.fromString("john")) x_equal_x = Equal(self.x, self.x) x_equal_y = Equal(self.x, self.y) x_equal_z = Equal(self.x, self.z) x_lives_w = PredicateFormula(self.Lives_pred_sym, self.x, w) x_lives_y = PredicateFormula(self.Lives_pred_sym, self.x, self.y) x_lives_ny = PredicateFormula(self.Lives_pred_sym, self.x, ConstantTerm.fromString("ny")) x_lives_paris = PredicateFormula(self.Lives_pred_sym, self.x, ConstantTerm.fromString("paris")) w_lives_z = PredicateFormula(self.Lives_pred_sym, w, self.z) exists_w__x_lives_w = Exists(w, x_lives_w) exists_y__x_lives_y = Exists(self.y, x_lives_y) exists_z_exists_w__w_lives_z = Exists(self.z, Exists(w, w_lives_z)) exists_x__x_equal_x = Exists(self.x, x_equal_x) exists_x__x_equal_y = Exists(self.x, x_equal_y) exists_x__x_equal_john_and_Lives_x_paris = Exists( self.x, And(x_equal_john, x_lives_paris)) exists_x__x_equal_john_and_exists_x__Lives_x_ny = And( Exists(self.x, x_equal_john), Exists(self.x, x_lives_ny)) exists_x__x_equal_x_and_exists_x__Lives_x_ny = And( exists_x__x_equal_x, Exists(self.x, x_lives_ny)) forall_x__x_equal_x = ForAll(self.x, x_equal_x) forall_x__x_equal_y = ForAll(self.x, x_equal_y) not_forall_x__x_equal_x = Not(forall_x__x_equal_x) # Person(x, 20) # x = "john" self.assertTrue(self.FOL.truth(Person_x_20, self.assignment)) # ~Person(x, 21) # x = "john" self.assertTrue(self.FOL.truth(not_Person_x_21, self.assignment)) # Equals self.assertTrue(self.FOL.truth(y_equal_20, self.assignment)) self.assertTrue(self.FOL.truth(x_equal_x, self.assignment)) self.assertFalse(self.FOL.truth(x_equal_y, self.assignment)) self.assertFalse(self.FOL.truth(x_equal_z, self.assignment)) # y == 20 and x == "john" and Person(x, y) self.assertTrue( self.FOL.truth(And(y_equal_20, And(x_equal_john, Person_x_y)), self.assignment)) self.assertTrue( self.FOL.truth(Or(Person_x_20, x_equal_john), self.assignment)) # De Morgan on previous formula # Not (Not y == 20 or Not x == "john" ot Not Person(x, y) self.assertTrue( self.FOL.truth( Not(Or(Not(y_equal_20), Or(Not(x_equal_john), Not(Person_x_y)))), self.assignment)) # Or with the last formula true self.assertTrue( self.FOL.truth( Or(Equal(self.x, self.y), Or(Equal(self.x, self.y), Equal(self.z, self.z))), self.assignment)) # (y==20 and x=="john") => Person(x,y) self.assertTrue( self.FOL.truth(Implies(And(y_equal_20, x_equal_john), Person_x_y), self.assignment)) self.assertTrue( self.FOL.truth(Implies(Not(x_equal_x), Person_x_y), self.assignment)) # Exists self.assertTrue(self.FOL.truth(exists_w__x_lives_w, self.assignment)) self.assertTrue(self.FOL.truth(exists_x__x_equal_x, self.assignment)) self.assertTrue(self.FOL.truth(exists_x__x_equal_y, self.assignment)) # quantified variable not present in the formula self.assertTrue(self.FOL.truth(exists_y__x_lives_y, self.assignment)) # 2 quantified variables self.assertTrue( self.FOL.truth(exists_z_exists_w__w_lives_z, self.assignment)) # annidate exists self.assertTrue( self.FOL.truth(exists_x__x_equal_john_and_exists_x__Lives_x_ny, self.assignment)) self.assertTrue( self.FOL.truth(exists_x__x_equal_x_and_exists_x__Lives_x_ny, self.assignment)) self.assertFalse( self.FOL.truth(exists_x__x_equal_john_and_Lives_x_paris, self.assignment)) # ForAll self.assertTrue(self.FOL.truth(forall_x__x_equal_x, self.assignment)) self.assertFalse(self.FOL.truth(forall_x__x_equal_y, self.assignment)) self.assertFalse( self.FOL.truth(not_forall_x__x_equal_x, self.assignment))
def delta(self, f: Formula, action: FrozenSet[Symbol], epsilon=False): # TODO: should return [True|False]Formula or simply True/False? pl, I = PL._from_set_of_propositionals(action, self.alphabet) if pl.is_formula(f): return self.delta(PathExpressionEventually(f, LogicalTrue()), action, epsilon) elif isinstance(f, LogicalTrue): return TrueFormula() elif isinstance(f, LogicalFalse): return FalseFormula() elif isinstance(f, And): return And(self.delta(f.f1, action), self.delta(f.f2, action, epsilon)) elif isinstance(f, Or): return Or(self.delta(f.f1, action), self.delta(f.f2, action, epsilon)) elif isinstance(f, PathExpressionEventually): if pl.is_formula(f.p): if not epsilon and pl.truth(f.p, I): return self._expand(f.f) else: return FalseFormula() elif isinstance(f.p, PathExpressionTest): return And(self.delta(f.p.f, action, epsilon), self.delta(f.f, action, epsilon)) elif isinstance(f.p, PathExpressionUnion): return Or( self.delta(PathExpressionEventually(f.p.p1, f.f), action, epsilon), self.delta(PathExpressionEventually(f.p.p2, f.f), action, epsilon)) elif isinstance(f.p, PathExpressionSequence): e2 = PathExpressionEventually(f.p.p2, f.f) e1 = PathExpressionEventually(f.p.p1, e2) return self.delta(e1, action, epsilon) elif isinstance(f.p, PathExpressionStar): o1 = self.delta(f.f, action, epsilon) o2 = self.delta(PathExpressionEventually(f.p.p, F(f)), action, epsilon) return Or(o1, o2) elif isinstance(f, PathExpressionAlways): if pl.is_formula(f.p): if not epsilon and pl.truth(f.p, I): return self._expand(f.f) else: return TrueFormula() elif isinstance(f.p, PathExpressionTest): o1 = self.delta(self.to_nnf(Not(f.p.f)), action, epsilon) o2 = self.delta(f.f, action, epsilon) return Or(o1, o2) elif isinstance(f.p, PathExpressionUnion): return And( self.delta(PathExpressionAlways(f.p.p1, f.f), action, epsilon), self.delta(PathExpressionAlways(f.p.p2, f.f), action, epsilon)) elif isinstance(f.p, PathExpressionSequence): return self.delta( PathExpressionAlways(f.p.p1, PathExpressionAlways(f.p.p2, f.f)), action, epsilon) elif isinstance(f.p, PathExpressionStar): a1 = self.delta(f.f, action, epsilon) a2 = self.delta(PathExpressionAlways(f.p.p, T(f)), action, epsilon) return And(a1, a2) elif isinstance(f, F): return FalseFormula() elif isinstance(f, T): return TrueFormula() else: raise ValueError
def _implies_to_or(f: Implies) -> Formula: equivalent_formula = Or(Not(f.f1), f.f2) return _or_to_and(equivalent_formula)