Source code for ggsolver.logic.ltl

from abc import ABC

import spot
import ggsolver.logic.base as base
from ggsolver.logic.formula import BaseFormula, ParsingError
from ggsolver.logic.automata import DFA
# import ggsolver.interfaces.i_spot as i_spot
# import ggsolver.logic.automata as automata
# from ggsolver.util import apply_atoms_limit, powerset


[docs]class LTL(BaseFormula): """ LTL formula is internally represented as spot.formula instance. """ __hash__ = BaseFormula.__hash__ def __init__(self, f_str, atoms=None): super(LTL, self).__init__(f_str, atoms) self._repr = spot.formula(f_str) self._atoms = self._collect_atoms() def __str__(self): return str(self.f_str) def __eq__(self, other: BaseFormula): try: return spot.are_equivalent(self.f_str, other.f_str) except Exception: return False def _collect_atoms(self): atoms = set() def traversal(node: spot.formula, atoms_): if node.is_literal(): if "!" not in node.to_str(): atoms_.add(node.to_str()) return True return False self._repr.traverse(traversal, atoms) return self._atoms | atoms # ================================================================== # IMPLEMENTATION OF ABSTRACT METHODS # ================================================================== def translate(self): return base.SpotAutomaton(formula=self.f_str, atoms=self.atoms()) def substitute(self, subs_map=None): raise NotImplementedError("To be implemented in future.")
[docs] def evaluate(self, true_atoms): """ Evaluates a propositional logic formula given the set of true atoms. :param true_atoms: (Iterable[str]) A propositional logic formula. :return: (bool) True if formula is true, otherwise False. """ # Define a transform to apply to AST of spot.formula. def transform(node: spot.formula): if node.is_literal(): if "!" not in node.to_str(): if node.to_str() in true_atoms: return spot.formula.tt() else: return spot.formula.ff() return node.map(transform) # Apply the transform and return the result. # Since every literal is replaced by true or false, # the transformed formula is guaranteed to be either true or false. return True if transform(self._repr).is_tt() else False
def atoms(self): return self._atoms # ================================================================== # SPECIAL METHODS OF PL CLASS # ==================================================================
[docs] def simplify(self): """ Simplifies a propositional logic formula. We use the `boolean_to_isop=True` option for `spot.simplify`. See https://spot.lrde.epita.fr/doxygen/classspot_1_1tl__simplifier__options.html :return: (str) String representing simplified formula. """ return spot.simplify(self._repr, boolean_to_isop=True).to_str()
[docs]class ScLTL(LTL): """ ScLTL formula is internally represented as spot.formula instance. """ __hash__ = LTL.__hash__ def __init__(self, f_str, atoms=None): super(ScLTL, self).__init__(f_str, atoms) mp_class = spot.mp_class(self._repr).upper() if mp_class not in ["B", "G"]: raise ParsingError(f"Given formula:{f_str} is not an ScLTL formula.") def __eq__(self, other: BaseFormula): try: return spot.are_equivalent(self.f_str, other.f_str) except Exception: return False def translate(self): aut = super(ScLTL, self).translate() dfa = DFA() dfa.from_automaton(aut) return dfa def substitute(self, subs_map=None): raise NotImplementedError("Will be implemented in future. ")