예제 #1
0
 def deltaBox(self, f: LDLfFormula, i: PLInterpretation, epsilon=False):
     if epsilon:
         return PLTrue()
     if self.pl_formula.truth(i):
         # return PLAtomic(Symbol(str(_expand(f))))
         return _expand(f)
     else:
         return PLTrue()
예제 #2
0
    def delta(self, i: PLInterpretation, epsilon=False):

        f = self.to_nnf()
        d = f._delta(i, epsilon)
        if epsilon:
            # By definition, if epsilon=True, then the result must be either PLTrue or PLFalse
            # Now, the output is a Propositional Formula with only PLTrue or PLFalse as atomics
            # Hence, we just evaluate the formula with a dummy PLInterpretation
            d = PLTrue() if d.truth(PLFalseInterpretation()) else PLFalse()
        return d
예제 #3
0
 def p_propositional(self, p):
     """propositional : propositional EQUIVALENCE propositional
                      | propositional IMPLIES propositional
                      | propositional OR propositional
                      | propositional AND propositional
                      | NOT propositional
                      | FALSE
                      | TRUE
                      | ATOM"""
     if len(p) == 4:
         if p[2] == Symbols.EQUIVALENCE.value:
             p[0] = PLEquivalence([p[1], p[3]])
         elif p[2] == Symbols.IMPLIES.value:
             p[0] = PLImplies([p[1], p[3]])
         elif p[2] == Symbols.OR.value:
             p[0] = PLOr([p[1], p[3]])
         elif p[2] == Symbols.AND.value:
             p[0] = PLAnd([p[1], p[3]])
         else:
             raise ValueError
         # else:
         #     p[0] = p[2]
     elif len(p) == 3:
         p[0] = PLNot(p[2])
     elif len(p) == 2:
         if p[1] == Symbols.TRUE.value:
             p[0] = PLTrue()
         elif p[1] == Symbols.FALSE.value:
             p[0] = PLFalse()
         else:
             p[0] = PLAtomic(Symbol(p[1]))
     else:
         raise ValueError
 def p_formula_atom(self, p):
     """formula : ATOM
                | TRUE
                | FALSE"""
     if p[1] == Symbols.TRUE.value:
         p[0] = PLTrue()
     elif p[1] == Symbols.FALSE.value:
         p[0] = PLFalse()
     else:
         p[0] = PLAtomic(Symbol(p[1]))
예제 #5
0
 def _delta(self, i:PLInterpretation, epsilon=False):
     if epsilon:
         return PLTrue()
     f1 = self.formulas[0]
     f2 = LTLfRelease(self.formulas[1:]) if len(self.formulas) > 2 else self.formulas[1]
     return PLAnd([
         f2._delta(i, epsilon),
         PLOr([
             f1._delta(i, epsilon),
             LTLfWeakNext(self)._delta(i, epsilon)
         ])
     ])
    def _make_transition(Q, i: PLInterpretation):
        actions_set = i.true_propositions
        new_macrostate = set()

        for q in Q:
            # delta function applied to every formula in the macro state Q
            delta_formulas = [f.delta(actions_set) for f in q]

            # find the list of atoms, which are "true" atoms (i.e. propositional atoms) or LDLf formulas
            atomics = [s for subf in delta_formulas for s in find_atomics(subf)]

            atom2id = {v: k for k, v in enumerate(atomics)}
            id2atom = {v: k for k, v in atom2id.items()}

            # "freeze" the found atoms as symbols and build a mapping from symbols to formulas
            symbol2formula = {atom2id[f] for f in atomics if f != PLTrue() and f != PLFalse()}

            # build a map from formula to a "freezed" propositional Atomic Formula
            formula2atomic_formulas = {
                f: PLAtomic(atom2id[f])
                if f != PLTrue() and f != PLFalse()  # and not isinstance(f, PLAtomic)
                else f for f in atomics
            }

            # the final list of Propositional Atomic Formulas, one for each formula in the original macro state Q
            transformed_delta_formulas = [_transform_delta(f, formula2atomic_formulas) for f in delta_formulas]

            # the empy conjunction stands for true
            if len(transformed_delta_formulas) == 0:
                conjunctions = PLTrue()
            elif len(transformed_delta_formulas) == 1:
                conjunctions = transformed_delta_formulas[0]
            else:
                conjunctions = PLAnd(transformed_delta_formulas)

            # the model in this case is the smallest set of symbols s.t. the conjunction of "freezed" atomic formula
            # is true.
            models = frozenset(conjunctions.minimal_models(Alphabet(symbol2formula)))

            for min_model in models:
                q_prime = frozenset({id2atom[s] for s in min_model.true_propositions})

                new_macrostate.add(q_prime)

        return frozenset(new_macrostate)
예제 #7
0
 def to_LDLf(self):
     # return self._convert().to_LDLf()
     return LDLfDiamond(RegExpStar(RegExpPropositional(PLTrue())), LDLfAnd([self.f.to_LDLf(), LDLfNot(LDLfEnd())]))
예제 #8
0
 def _delta(self, i: PLInterpretation, epsilon=False):
     return PLTrue()
예제 #9
0
 def _convert(self):
     return LDLfDiamond(RegExpPropositional(PLTrue()), LDLfEnd()._convert())
예제 #10
0
 def _convert(self):
     return LDLfBox(RegExpPropositional(PLTrue()), LDLfLogicalFalse())
def to_automaton_(f, labels:Set[Symbol]=None):
    """
    DEPRECATED
    From a LDLfFormula, build the automaton.
    :param f:               a LDLfFormula;
    :param labels:          a set of Symbol, the fluents of our domain. If None, retrieve them from the formula;
    :param determinize:     True if you need to determinize the NFA, obtaining a DFA;
    :param minimize:        True if you need to minimize the DFA (if determinize is False this flag has no effect.)
    :return:                a NFA or a DFA which accepts the same traces that makes the formula True.
    """

    nnf = f.to_nnf()

    if labels is None:
        # if the labels of the formula are not specified in input,
        # retrieve them from the formula
        labels = nnf.find_labels()

    # the alphabet is the powerset of the set of fluents
    alphabet = powerset(labels)
    initial_state = MacroState({nnf})
    final_states = {MacroState()}
    delta = set()

    d = f.delta(PLFalseInterpretation(), epsilon=True)
    if d.truth(d):
        final_states.add(initial_state)

    states = {MacroState(), initial_state}

    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 function applied to every formula in the macro state Q
                delta_formulas = [f.delta(actions_set) for f in q]

                # find the list of atoms, which are "true" atoms (i.e. propositional atoms) or LDLf formulas
                atomics = [s for subf in delta_formulas for s in find_atomics(subf)]

                # "freeze" the found atoms as symbols and build a mapping from symbols to formulas
                symbol2formula = {Symbol(str(f)): f for f in atomics if f != PLTrue() and f != PLFalse()}

                # build a map from formula to a "freezed" propositional Atomic Formula
                formula2atomic_formulas = {
                    f: PLAtomic(Symbol(str(f)))
                    if f != PLTrue() and f != PLFalse()# and not isinstance(f, PLAtomic)
                    else f for f in atomics
                }

                # the final list of Propositional Atomic Formulas, one for each formula in the original macro state Q
                transformed_delta_formulas = [_transform_delta(f, formula2atomic_formulas) for f in delta_formulas]

                # the empty conjunction stands for true
                if len(transformed_delta_formulas) == 0:
                    conjunctions = PLTrue()
                elif len(transformed_delta_formulas) == 1:
                    conjunctions = transformed_delta_formulas[0]
                else:
                    conjunctions = PLAnd(transformed_delta_formulas)

                # the model in this case is the smallest set of symbols s.t. the conjunction of "freezed" atomic formula
                # is true.
                models = frozenset(conjunctions.minimal_models(Alphabet(symbol2formula)))

                if len(models) == 0:
                    continue
                for min_model in models:
                    q_prime = MacroState(
                        {symbol2formula[s] for s in min_model.true_propositions})

                    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:
                        subf_deltas = [subf.delta(PLFalseInterpretation(), epsilon=True) for subf in q_prime]
                        if len(subf_deltas)==1:
                            q_prime_delta_conjunction = subf_deltas[0]
                        else:
                            q_prime_delta_conjunction = PLAnd(subf_deltas)

                        if q_prime_delta_conjunction.truth(PLFalseInterpretation()):
                            final_states.add(q_prime)


    alphabet = PythomataAlphabet({PLInterpretation(set(sym)) for sym in alphabet})
    delta = frozenset((i, PLInterpretation(set(a)), o) for i, a, o in delta)


    nfa = NFA.fromTransitions(
        alphabet=alphabet,
        states=frozenset(states),
        initial_state=initial_state,
        accepting_states=frozenset(final_states),
        transitions=delta
    )

    return nfa
예제 #12
0
 def __init__(self):
     super().__init__(Symbol(Symbols.TRUE.value))
     self.a = PLTrue()
예제 #13
0
 def _delta(self, i:PLInterpretation, epsilon=False):
     if epsilon:
         return PLFalse()
     return PLTrue() if self.a.truth(i) else PLFalse()
예제 #14
0
 def to_LDLf(self):
     f1 = self.formulas[0].to_LDLf()
     f2 = LTLfUntil(self.formulas[1:]).to_LDLf() if len(self.formulas) > 2 else self.formulas[1].to_LDLf()
     return LDLfDiamond(RegExpStar(RegExpSequence([RegExpTest(f1), RegExpPropositional(PLTrue())])), LDLfAnd([f2, LDLfNot(LDLfEnd())]))
예제 #15
0
 def _delta(self, i: PLInterpretation, epsilon=False):
     if epsilon:
         return PLTrue()
     else:
         return PLOr([self.f, LTLfEnd().to_nnf()])
예제 #16
0
 def to_LDLf(self):
     return LDLfDiamond(RegExpPropositional(PLTrue()), LDLfAnd([self.f.to_LDLf(), LDLfNot(LDLfEnd())]))
예제 #17
0
 def _delta(self, i: PLInterpretation, epsilon=False):
     if isinstance(self.f, LTLfAtomic) or isinstance(self.f, LTLfEnd):
         return PLTrue() if self.f._delta(i, epsilon)==PLFalse() else PLFalse()
     else:
         # the formula must be in NNF form!!!
         raise Exception