예제 #1
0
    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)
예제 #2
0
 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))
예제 #3
0
 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))
예제 #4
0
 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))
예제 #5
0
 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})
예제 #6
0
    def _build_automata(self):
        rows = self.row_symbols
        atoms = [AtomicFormula(r) for r in rows]
        alphabet = Alphabet(set(rows))
        ldlf = LDLf_EmptyTraces(alphabet)
        f = PathExpressionEventually(
            PathExpressionSequence.chain([
                PathExpressionStar(
                    And.chain([Not(atoms[0]),
                               Not(atoms[1]),
                               Not(atoms[2])])),
                PathExpressionStar(
                    And.chain([atoms[0],
                               Not(atoms[1]),
                               Not(atoms[2])])),
                # Not(atoms[3]), Not(atoms[4]), Not(atoms[5])]),
                PathExpressionStar(
                    And.chain([atoms[0], atoms[1],
                               Not(atoms[2])])),
                # Not(atoms[3]), Not(atoms[4]), Not(atoms[5])]),
                # And.chain([atoms[0],      atoms[1],      atoms[2]]),  # Not(atoms[3]), Not(atoms[4]), Not(atoms[5])]),
                # And.chain([atoms[0],     atoms[1],      atoms[2],      atoms[3],  Not(atoms[4]), Not(atoms[5])]),
                # And.chain([atoms[0],     atoms[1],      atoms[2],      atoms[3],      atoms[4],  Not(atoms[5])]),
                # And.chain([atoms[0],     atoms[1],      atoms[2],      atoms[3],      atoms[4],      atoms[5] ])
            ]),
            And.chain([atoms[0], atoms[1], atoms[2]]))
        nfa = ldlf.to_nfa(f)
        dfa = _to_pythomata_dfa(nfa)

        return dfa
예제 #7
0
    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)
예제 #8
0
 def test_is_formula_composed(self):
     a_sym = Symbol("a")
     alphabet = Alphabet({a_sym})
     a = AtomicFormula(a_sym)
     pl = PL(alphabet)
     self.assertTrue(
         pl.is_formula(
             Implies(Not(a), And(TrueFormula(), Not(FalseFormula())))))
     self.assertFalse(
         pl.is_formula(
             Implies(Not(a), And(TrueFormula(), Next(FalseFormula())))))
예제 #9
0
    def setUp(self):
        # 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)
        self.alphabet = Alphabet({self.a_sym, self.b_sym, self.c_sym})

        self.ref = REf(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)
예제 #10
0
 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))))))
예제 #11
0
 def _is_formula(self, f: Formula):
     """Check if a formula is legal in the current formal system"""
     if isinstance(f, AtomicFormula):
         return f.symbol in self.alphabet.symbols or f == AtomicFormula(
             DUMMY_SYMBOL)
     elif isinstance(f, UnaryOperator):
         return self.is_formula(f.f)
     elif isinstance(f, BinaryOperator):
         return self.is_formula(f.f1) and self.is_formula(f.f2)
     elif isinstance(f, TrueFormula) or isinstance(f, FalseFormula):
         return True
     else:
         raise ValueError("Argument not a valid Formula")
예제 #12
0
 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))))))
예제 #13
0
 def test_chain(self):
     a_sym, b_sym, c_sym = [Symbol(s) for s in ["a", "b", "c"]]
     a, b, c = [AtomicFormula(s) for s in [a_sym,b_sym,c_sym]]
     and_chain = And.chain([a, b, c])
     self.assertEqual(and_chain, And(a, And(b, And(c, TrueFormula()))))
예제 #14
0
 def test_sequence(self):
     alphabet = Alphabet.fromStrings({"a", "b"})
     a = AtomicFormula.fromName("a")
     b = AtomicFormula.fromName("b")
     ref = REf(alphabet)
     self.assertTrue(ref.is_formula(PathExpressionSequence(a, b)))
예제 #15
0
 def test_is_formula_error(self):
     a_sym = Symbol("a")
     alphabet = Alphabet({a_sym})
     a = Next(AtomicFormula(a_sym))
     pl = PL(alphabet)
     self.assertFalse(pl.is_formula(a))
예제 #16
0
 def test_star(self):
     alphabet = Alphabet.fromStrings({"a"})
     a = AtomicFormula.fromName("a")
     ref = REf(alphabet)
     self.assertTrue(ref.is_formula(PathExpressionStar(a)))
예제 #17
0
 def test_is_formula_atomic(self):
     a_sym = Symbol("a")
     alphabet = Alphabet({a_sym})
     a = AtomicFormula(a_sym)
     pl = PL(alphabet)
     self.assertTrue(pl.is_formula(a))
예제 #18
0
    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
            })})
예제 #19
0
    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)
예제 #20
0
    def to_nfa(self, f: Formula):
        # TODO: optimize!!!
        assert self.is_formula(f)
        nnf_f = self.to_nnf(f)

        alphabet = powerset(self.alphabet.symbols)
        initial_states = {frozenset([nnf_f])}
        final_states = {frozenset()}
        delta = set()

        pl, I = PL._from_set_of_propositionals(set(), Alphabet(set()))
        d = self.delta(nnf_f, frozenset(), epsilon=True)
        if pl.truth(d, I):
            final_states.add(frozenset([nnf_f]))

        states = {frozenset(), frozenset([nnf_f])}

        states_changed, delta_changed = True, True
        while states_changed or delta_changed:

            states_changed, delta_changed = False, False
            for actions_set in alphabet:
                states_list = list(states)
                for q in states_list:

                    delta_formulas = [
                        self.delta(subf, actions_set) for subf in q
                    ]
                    atomics = [
                        s for subf in delta_formulas
                        for s in PL.find_atomics(subf)
                    ]

                    symbol2formula = {
                        Symbol(str(f)): f
                        for f in atomics
                        if f != TrueFormula() and f != FalseFormula()
                    }
                    formula2atomic_formulas = {
                        f: AtomicFormula.fromName(str(f))
                        if f != TrueFormula() and f != FalseFormula() else f
                        for f in atomics
                    }
                    transformed_delta_formulas = [
                        self._tranform_delta(f, formula2atomic_formulas)
                        for f in delta_formulas
                    ]
                    conjunctions = And.chain(transformed_delta_formulas)

                    models = frozenset(
                        PL(Alphabet(
                            set(symbol2formula))).minimal_models(conjunctions))
                    if len(models) == 0:
                        continue
                    for min_model in models:
                        q_prime = frozenset({
                            symbol2formula[s]
                            for s in min_model.symbol2truth
                            if min_model.symbol2truth[s]
                        })

                        len_before = len(states)
                        states.add(q_prime)
                        if len(states) == len_before + 1:
                            states_list.append(q_prime)
                            states_changed = True

                        len_before = len(delta)
                        delta.add((q, actions_set, q_prime))
                        if len(delta) == len_before + 1:
                            delta_changed = True

                        # check if q_prime should be added as final state
                        if len(q_prime) == 0:
                            final_states.add(q_prime)
                        else:
                            q_prime_delta_conjunction = And.chain([
                                self.delta(subf, frozenset(), epsilon=True)
                                for subf in q_prime
                            ])
                            pl, I = PL._from_set_of_propositionals(
                                set(), Alphabet(set()))
                            if pl.truth(q_prime_delta_conjunction, I):
                                final_states.add(q_prime)

        return {
            "alphabet": alphabet,
            "states": frozenset(states),
            "initial_states": frozenset(initial_states),
            "transitions": delta,
            "accepting_states": frozenset(final_states)
        }
예제 #21
0
 def test_propositional_is_formula(self):
     alphabet = Alphabet.fromStrings({"a"})
     a = AtomicFormula.fromName("a")
     ref = REf(alphabet)
     self.assertTrue(ref.is_formula(a))