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 deltaBox(self, f: LDLfFormula, i: PLInterpretation, epsilon=False): # subf = LDLfBox(self.f, T(LDLfBox(self, f))) # k = subf._delta(i, epsilon) # l = [f._delta(i, epsilon), subf] # ff = PLAnd(l) return PLAnd([ f._delta(i, epsilon), LDLfBox(self.f, T(LDLfBox(self, f)))._delta(i, epsilon) ])
def _is_true(Q): if frozenset() in Q: return True conj = [PLAnd([subf.delta(None, epsilon=True) for subf in q]) if len(q) >= 2 else next(iter(q)).delta(None, epsilon=True) if len(q) == 1 else PLFalse() for q in Q] if len(conj) == 0: return False else: conj = PLOr(conj) if len(conj) >= 2 else conj[0] return conj.truth(None)
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 deltaBox(self, f: LDLfFormula, i: PLInterpretation, epsilon=False): return PLAnd( [LDLfBox(r, f)._delta(i, epsilon) for r in self.formulas_set])
def deltaDiamond(self, f: LDLfFormula, i: PLInterpretation, epsilon=False): return PLAnd([self.f._delta(i, epsilon), f._delta(i, epsilon)])
def _delta(self, i: PLInterpretation, epsilon=False): return PLAnd([f._delta(i, epsilon) for f in self.formulas])
def _delta(self, i: PLInterpretation, epsilon=False): if epsilon: return PLFalse() else: return PLAnd([self.f, LTLfNot(LTLfEnd()).to_nnf()])
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 p_formula_and(self, p): 'formula : formula AND formula' p[0] = PLAnd([p[1], p[3]])