Example #1
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")
Example #2
0
 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)
Example #3
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
Example #4
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)
        }