Beispiel #1
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
Beispiel #2
0
 def expand_formula(self, f: Formula):
     """Manage the case when we have a propositional formula."""
     # Check first if it is a propositional
     pl = PL(self.alphabet)
     if pl.is_formula(f):
         return super().expand_formula(
             PathExpressionEventually(f, LogicalTrue()))
     else:
         return super().expand_formula(f)
Beispiel #3
0
 def _expand_formula(self, f: Formula):
     if isinstance(f, AtomicFormula):
         return f
     elif isinstance(f, And):
         return And(self.expand_formula(f.f1), self.expand_formula(f.f2))
     elif isinstance(f, Not):
         return Not(self.expand_formula(f.f))
     elif isinstance(f, PathExpressionEventually):
         return PathExpressionEventually(f.p, self.expand_formula(f.f))
     else:
         raise ValueError("Not valid Formula to expand")
Beispiel #4
0
    def _truth(self, f: Formula, trace: FiniteTrace, position: int):
        assert trace.alphabet == self.alphabet
        truth = self._truth
        # LDLfFormulas
        if isinstance(f, AtomicFormula):
            return f.symbol in trace.get(position)
        elif isinstance(f, Not):
            return not self.truth(f.f, trace, position)
        elif isinstance(f, And):
            return self.truth(f.f1, trace, position) and self.truth(f.f2, trace, position)
        elif isinstance(f, PathExpressionEventually):
            path = f.p
            assert self._is_path(path)
            if isinstance(path, PathExpressionTest):
                return truth(path.f, trace, position) and truth(f.f, trace, position)
            elif isinstance(path, PathExpressionUnion):
                return truth(PathExpressionEventually(path.p1, f.f), trace, position) or truth(
                    PathExpressionEventually(path.p2, f.f), trace, position)
            elif isinstance(path, PathExpressionSequence):
                return truth(PathExpressionEventually(path.p1, PathExpressionEventually(path.p2, f.f)), trace, position)
            elif isinstance(path, PathExpressionStar):
                return truth(f.f, trace, position) or (
                    position < trace.last()
                    and truth(PathExpressionEventually(path.p, PathExpressionEventually(path, f.f)), trace, position)
                    and not self._is_testonly(path)
                )

            # Should be a Propositional Formula
            else:
                pl, I = PL._from_set_of_propositionals(trace.get(position), trace.alphabet)
                return position < trace.last() and pl.truth(path, I) and truth(f.f, trace, position + 1)
        else:
            raise ValueError("Argument not a valid Formula")
Beispiel #5
0
 def to_equivalent_formula(self, derived_formula: Formula):
     if isinstance(derived_formula, Or):
         return Not(And(Not(derived_formula.f1), Not(derived_formula.f2)))
     elif isinstance(derived_formula, PathExpressionAlways):
         return Not(PathExpressionEventually(derived_formula.p, Not(derived_formula.f)))
     elif isinstance(derived_formula, FalseFormula):
         return And(Not(DUMMY_ATOMIC), DUMMY_ATOMIC)
     elif isinstance(derived_formula, TrueFormula):
         return Not(FalseFormula())
     elif isinstance(derived_formula, LDLfLast):
         return PathExpressionAlways(TrueFormula(), FalseFormula())
     else:
         raise ValueError("Derived formula not recognized")
Beispiel #6
0
    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)
Beispiel #7
0
 def _is_formula(self, f: Formula):
     """Check if a formula is legal in the current formal system"""
     # Check first if it is a propositional
     pl = PL(self.alphabet)
     if pl.is_formula(f):
         return self.is_formula(PathExpressionEventually(f, LogicalTrue()))
     elif isinstance(f, LogicalTrue):
         return True
     elif isinstance(f, Not):
         return self.is_formula(f.f)
     elif isinstance(f, And):
         return self.is_formula(f.f1) and self.is_formula(f.f2)
     elif isinstance(f, PathExpressionEventually):
         return self._is_path(f.p) and self.is_formula(f.f)
     else:
         return False
Beispiel #8
0
 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
Beispiel #9
0
 def to_equivalent_formula(self, derived_formula: Formula):
     # make lines shorter
     ef = self.to_equivalent_formula
     if isinstance(derived_formula, AtomicFormula):
         return PathExpressionEventually(derived_formula, LogicalTrue())
     elif isinstance(derived_formula, LogicalFalse):
         return Not(LogicalTrue())
     elif isinstance(derived_formula, Or):
         return Not(And(Not(derived_formula.f1), Not(derived_formula.f2)))
     elif isinstance(derived_formula, PathExpressionAlways):
         return Not(
             PathExpressionEventually(derived_formula.p,
                                      Not(derived_formula.f)))
     elif isinstance(derived_formula, Next):
         return PathExpressionEventually(
             TrueFormula(), And(derived_formula.f, Not(ef(End()))))
     elif isinstance(derived_formula, End):
         return ef(PathExpressionAlways(TrueFormula(), ef(LogicalFalse())))
     elif isinstance(derived_formula, Until):
         return PathExpressionEventually(
             PathExpressionStar(
                 PathExpressionSequence(
                     PathExpressionTest(derived_formula.f1),
                     ef(TrueFormula()))),
             And(derived_formula.f2, Not(ef(End()))))
     elif isinstance(derived_formula, FalseFormula):
         return FalseFormula()
     elif isinstance(derived_formula, TrueFormula):
         return TrueFormula()
     elif isinstance(derived_formula, LDLfLast):
         return PathExpressionEventually(ef(TrueFormula()), ef(End()))
     # propositional
     elif isinstance(derived_formula, Formula):
         pl = PL(self.alphabet)
         assert pl.is_formula(derived_formula)
         f = pl.to_nnf(derived_formula)
         return PathExpressionEventually(f, LogicalTrue())
     else:
         raise ValueError("Derived formula not recognized")
Beispiel #10
0
 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
Beispiel #11
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)