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()
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
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]))
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)
def to_LDLf(self): # return self._convert().to_LDLf() return LDLfDiamond(RegExpStar(RegExpPropositional(PLTrue())), LDLfAnd([self.f.to_LDLf(), LDLfNot(LDLfEnd())]))
def _delta(self, i: PLInterpretation, epsilon=False): return PLTrue()
def _convert(self): return LDLfDiamond(RegExpPropositional(PLTrue()), LDLfEnd()._convert())
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
def __init__(self): super().__init__(Symbol(Symbols.TRUE.value)) self.a = PLTrue()
def _delta(self, i:PLInterpretation, epsilon=False): if epsilon: return PLFalse() return PLTrue() if self.a.truth(i) else PLFalse()
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())]))
def _delta(self, i: PLInterpretation, epsilon=False): if epsilon: return PLTrue() else: return PLOr([self.f, LTLfEnd().to_nnf()])
def to_LDLf(self): return LDLfDiamond(RegExpPropositional(PLTrue()), LDLfAnd([self.f.to_LDLf(), LDLfNot(LDLfEnd())]))
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