Exemple #1
0
    def test_misc(self):
        a, b = self.a, self.b
        i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab

        material_implication = PLEquivalence(
            [PLOr([PLNot(a), b]), PLNot(PLAnd([a, PLNot(b)])), PLImplies([a, b])]
        )

        # the equivalence is valid (i.e. satisfied for every interpretation)
        assert material_implication.truth(i_)
        assert material_implication.truth(i_a)
        assert material_implication.truth(i_b)
        assert material_implication.truth(i_ab)

        a_and_false_and_true = PLAnd([a, PLFalse(), PLTrue()])
        assert not a_and_false_and_true.truth(i_)
        assert not a_and_false_and_true.truth(i_a)
        assert not a_and_false_and_true.truth(i_b)
        assert not a_and_false_and_true.truth(i_ab)

        a_or_false_or_true = PLOr([a, PLFalse(), PLTrue()])
        assert a_or_false_or_true.truth(i_)
        assert a_or_false_or_true.truth(i_a)
        assert a_or_false_or_true.truth(i_b)
        assert a_or_false_or_true.truth(i_ab)
Exemple #2
0
def test_delta():
    parser = LDLfParser()
    sa, sb, sc = "A", "B", "C"
    a, b, c = PLAtomic(sa), PLAtomic(sb), PLAtomic(sc)

    i_ = PLFalseInterpretation()
    i_a = PLInterpretation({sa})
    i_b = PLInterpretation({sb})
    i_ab = PLInterpretation({sa, sb})

    true = PLTrue()
    false = PLFalse()
    tt = LDLfLogicalTrue()
    ff = LDLfLogicalFalse()

    assert parser("<A>tt").delta(i_) == false
    assert parser("<A>tt").delta(i_a) == PLAtomic(tt)
    assert parser("<A>tt").delta(i_b) == false
    assert parser("<A>tt").delta(i_ab) == PLAtomic(tt)

    assert parser("[B]ff").delta(i_) == true
    assert parser("[B]ff").delta(i_a) == true
    assert parser("[B]ff").delta(i_b) == PLAtomic(ff)
    assert parser("[B]ff").delta(i_ab) == PLAtomic(ff)

    f = parser("!(<!(A<->B)+(B;A)*+(!last)?>[(true)*]end)")
    assert f.delta(i_) == f.to_nnf().delta(i_)
    assert f.delta(i_ab) == f.to_nnf().delta(i_ab)

    assert f.delta(i_, epsilon=True) == f.to_nnf().delta(i_, epsilon=True)
    assert f.delta(i_ab, epsilon=True) == f.to_nnf().delta(i_ab, epsilon=True)
    # with epsilon=True, the result is either PLTrue or PLFalse
    assert f.delta(i_, epsilon=True) in [PLTrue(), PLFalse()]
Exemple #3
0
def test_delta():
    parser = LDLfParser()
    i_ = {}
    i_a = {"A": True}
    i_b = {"B": True}
    i_ab = {"A": True, "B": True}

    true = PLTrue()
    false = PLFalse()
    tt = PLAtomic(LDLfLogicalTrue())
    ff = PLAtomic(LDLfLogicalFalse())

    assert parser("<A>tt").delta(i_) == false
    assert parser("<A>tt").delta(i_a) == tt
    assert parser("<A>tt").delta(i_b) == false
    assert parser("<A>tt").delta(i_ab) == tt

    assert parser("[B]ff").delta(i_) == true
    assert parser("[B]ff").delta(i_a) == true
    assert parser("[B]ff").delta(i_b) == ff
    assert parser("[B]ff").delta(i_ab) == ff

    f = parser("!(<?(!last)>end)")
    assert f.delta(i_) == f.to_nnf().delta(i_)
    assert f.delta(i_ab) == f.to_nnf().delta(i_ab)

    assert f.delta(i_, epsilon=True) == f.to_nnf().delta(i_, epsilon=True)
    assert f.delta(i_ab, epsilon=True) == f.to_nnf().delta(i_ab, epsilon=True)
    # with epsilon=True, the result is either PLTrue or PLFalse
    assert f.delta(i_, epsilon=True) in [PLTrue(), PLFalse()]
Exemple #4
0
def _make_transition(Q: FrozenSet[FrozenSet[PLAtomic]], 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.s.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)}  # type: Dict[int, PLAtomic]
        id2atom = {v: k
                   for k, v in atom2id.items()}  # type: Dict[PLAtomic, int]

        # "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 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.
        alphabet = frozenset(symbol2formula)
        models = frozenset(conjunctions.minimal_models(alphabet))

        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)
Exemple #5
0
 def delta_diamond(self,
                   f: LDLfFormula,
                   i: PLInterpretation,
                   epsilon=False):
     if epsilon:
         return PLFalse()
     if self.pl_formula.truth(i):
         return PLAtomic(_expand(f))
     else:
         return PLFalse()
Exemple #6
0
 def _delta(self, i: PLInterpretation, epsilon=False):
     if isinstance(self.f, LTLfAtomic) or isinstance(self.f, LTLfEnd):
         if epsilon:
             return PLFalse()
         else:
             return PLTrue() if self.f._delta(
                 i, epsilon) == PLFalse() else PLFalse()
     else:
         # the formula must be in NNF form!!!
         raise Exception
Exemple #7
0
    def _delta(self, i: PropositionalInterpretation, epsilon=False):
        """Apply the delta function."""
        if epsilon:
            return PLFalse()

        result = self.f._delta(i, epsilon=epsilon)
        if result == PLTrue():
            return PLFalse()
        else:
            return PLTrue()
Exemple #8
0
 def delta_diamond(self,
                   f: LDLfFormula,
                   i: PropositionalInterpretation,
                   epsilon=False):
     """Apply delta function for regular expressions in the diamond operator."""
     if epsilon:
         return PLFalse()
     if self.pl_formula.truth(i):
         return PLAtomic(_expand(f))
     else:
         return PLFalse()
Exemple #9
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(p[1])
     else:
         raise ValueError
Exemple #10
0
 def _delta(self, i: PLInterpretation, epsilon=False):
     if epsilon:
         return PLFalse()
     else:
         return PLAnd(
             [PLAtomic(self.f),
              PLAtomic(LTLfNot(LTLfEnd()).to_nnf())])
Exemple #11
0
 def _delta(self, i: PropositionalInterpretation, epsilon=False):
     """Apply the delta function."""
     if epsilon:
         return PLFalse()
     else:
         return PLAnd(
             [PLAtomic(self.f),
              PLAtomic(LTLfNot(LTLfEnd()).to_nnf())])
Exemple #12
0
 def delta(self, i: PLInterpretation, epsilon=False) -> PLFormula:
     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(None) else PLFalse()
     return d
Exemple #13
0
 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(p[1])
Exemple #14
0
 def _delta(self, i: PLInterpretation, epsilon: bool = False):
     if epsilon:
         return PLFalse()
     f1 = self.formulas[0]
     f2 = LTLfUntil(
         self.formulas[1:]) if len(self.formulas) > 2 else self.formulas[1]
     return PLOr([
         f2._delta(i, epsilon),
         PLAnd([f1._delta(i, epsilon),
                LTLfNext(self)._delta(i, epsilon)])
     ])
Exemple #15
0
 def delta(self,
           i: PropositionalInterpretation,
           epsilon=False) -> PLFormula:
     """Apply the delta function."""
     f = self.to_nnf()
     d = f._delta(i, epsilon=epsilon)
     if epsilon:
         # By definition, if epsilon=True, then the result must be either True or False.
         # The output is a Propositional Formula with only True or False as atomics.
         # Hence, we just evaluate the formula with the empty propositional interpretation.
         d = PLTrue() if d.truth({}) else PLFalse()
     return d
Exemple #16
0
 def _delta(self, i: PropositionalInterpretation, epsilon: bool = False):
     """Apply the delta function."""
     if epsilon:
         return PLFalse()
     f1 = self.formulas[0]
     f2 = (LTLfUntil(self.formulas[1:])
           if len(self.formulas) > 2 else self.formulas[1])
     return PLOr([
         f2._delta(i, epsilon),
         PLAnd([f1._delta(i, epsilon),
                LTLfNext(self)._delta(i, epsilon)]),
     ])
Exemple #17
0
def _is_true(Q: FrozenSet[FrozenSet]):
    if frozenset() in Q:
        return True
    conj = [
        PLAnd([subf.s.delta(None, epsilon=True)
               for subf in q]) if len(q) >= 2 else next(iter(q)).s.delta(
                   None, epsilon=True) if len(q) == 1 else PLFalse() for q in Q
    ]
    if len(conj) == 0:
        return False
    else:
        pl_conj = PLOr(conj) if len(conj) >= 2 else conj[0]
        result = pl_conj.truth({})
        return result
Exemple #18
0
 def setup_class(cls):
     cls.parser = LTLfParser()
     cls.i_, cls.i_a, cls.i_b, cls.i_ab = (
         {},
         {
             "a": True
         },
         {
             "b": True
         },
         {
             "a": True,
             "b": True
         },
     )
     cls.true = PLTrue()
     cls.false = PLFalse()
Exemple #19
0
def test_parser():
    parser = PLParser()
    sa, sb = "A", "B"
    a, b = PLAtomic(sa), PLAtomic(sb)

    a_and_b = parser("A & B")
    true_a_and_b = PLAnd([a, b])
    assert a_and_b == true_a_and_b

    material_implication = parser("!A | B <-> !(A & !B) <-> A->B")
    true_material_implication = PLEquivalence(
        [PLOr([PLNot(a), b]), PLNot(PLAnd([a, PLNot(b)])), PLImplies([a, b])]
    )

    assert material_implication == true_material_implication

    true_a_and_false_and_true = PLAnd([a, PLFalse(), PLTrue()])
    a_and_false_and_true = parser("A & false & true")

    assert a_and_false_and_true == true_a_and_false_and_true
Exemple #20
0
 def _delta(self, i: PLInterpretation, epsilon: bool = False):
     return PLFalse()
Exemple #21
0
 def _delta(self, i: PLInterpretation, epsilon: bool = False):
     if epsilon:
         return PLFalse()
     else:
         return PLTrue()
Exemple #22
0
 def prop_false(self, args):
     assert len(args) == 1
     return PLFalse()
Exemple #23
0
 def _delta(self, i: PropositionalInterpretation, epsilon: bool = False):
     """Apply the delta function."""
     if epsilon:
         return PLFalse()
     return PLTrue() if PLAtomic(self.s).truth(i) else PLFalse()
Exemple #24
0
 def setup_class(cls):
     cls.parser = LTLfParser()
     cls.i_, cls.i_a, cls.i_b, cls.i_ab = \
         PLFalseInterpretation(), PLInterpretation({"A"}), PLInterpretation({"B"}), PLInterpretation({"A", "B"})
     cls.true = PLTrue()
     cls.false = PLFalse()
Exemple #25
0
 def _delta(self, i: PropositionalInterpretation, epsilon: bool = False):
     """Apply the delta function."""
     return PLFalse()
Exemple #26
0
 def _delta(self, i: PLInterpretation, epsilon: bool = False):
     if epsilon:
         return PLFalse()
     return PLTrue() if PLAtomic(self.s).truth(i) else PLFalse()
Exemple #27
0
def test_parser():
    parser = LDLfParser()
    a, b = PLAtomic("A"), PLAtomic("B")

    tt = LDLfLogicalTrue()
    ff = LDLfLogicalFalse()
    true = PLTrue()
    false = PLFalse()
    r_true = RegExpPropositional(true)
    r_false = RegExpPropositional(false)

    assert tt == parser("tt")
    assert ff == parser("ff")
    assert LDLfDiamond(r_true, tt) == parser("<true>tt")
    assert LDLfDiamond(r_false, tt) == parser("<false>tt")
    assert parser("!tt & <!A&B>tt") == LDLfAnd([
        LDLfNot(tt),
        LDLfDiamond(RegExpPropositional(PLAnd([PLNot(a), b])), tt)
    ])
    assert parser("[true*]([true]ff | <!A>tt | <(true)*><B>tt)") == LDLfBox(
        RegExpStar(r_true),
        LDLfOr([
            LDLfBox(r_true, ff),
            LDLfDiamond(RegExpPropositional(PLNot(a)), tt),
            LDLfDiamond(RegExpStar(r_true),
                        (LDLfDiamond(RegExpPropositional(b), tt))),
        ]),
    )

    assert parser("[A&B&A]ff <-> <A&B&A>tt") == LDLfEquivalence([
        LDLfBox(RegExpPropositional(PLAnd([a, b, a])), ff),
        LDLfDiamond(RegExpPropositional(PLAnd([a, b, a])), tt),
    ])

    assert parser("<A+B>tt") == LDLfDiamond(
        RegExpUnion([RegExpPropositional(a),
                     RegExpPropositional(b)]), tt)
    assert parser("<A;B>tt") == LDLfDiamond(
        RegExpSequence([RegExpPropositional(a),
                        RegExpPropositional(b)]), tt)
    assert parser("<A+(B;A)>end") == LDLfDiamond(
        RegExpUnion([
            RegExpPropositional(a),
            RegExpSequence([RegExpPropositional(b),
                            RegExpPropositional(a)]),
        ]),
        LDLfEnd(),
    )

    assert parser("!(<(!(A<->D))+((B;C)*)+(?!last)>[(true)*]end)") == LDLfNot(
        LDLfDiamond(
            RegExpUnion([
                RegExpPropositional(PLNot(PLEquivalence([a, PLAtomic("D")]))),
                RegExpStar(
                    RegExpSequence([
                        RegExpPropositional(PLAtomic("B")),
                        RegExpPropositional(PLAtomic("C")),
                    ])),
                RegExpTest(LDLfNot(LDLfLast())),
            ]),
            LDLfBox(RegExpStar(RegExpPropositional(PLTrue())), LDLfEnd()),
        ))
Exemple #28
0
def _make_transition(marco_q: FrozenSet[FrozenSet[PLAtomic]],
                     i: PropositionalInterpretation):
    new_macrostate = set()

    for q in marco_q:
        # delta function applied to every formula in the macro state Q
        delta_formulas = [cast(Delta, f.s).delta(i) for f in q]

        # find atomics -> so also ldlf formulas
        # replace atomic with custom object
        # convert to sympy

        # 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: str(k)
                   for k, v in enumerate(atomics)}  # type: Dict[PLAtomic, str]
        id2atom = {v: k
                   for k, v in atom2id.items()}  # type: Dict[str, PLAtomic]

        # 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 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)  # type: ignore

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

        formula = to_sympy(conjunctions, replace=atom2id)  # type: ignore
        all_models = list(sympy.satisfiable(formula, all_models=True))
        if len(all_models) == 1 and all_models[0] == BooleanFalse():
            models = []  # type: List[Set[str]]
        elif len(all_models) == 1 and all_models[0] == {True: True}:
            models = [set()]
        else:
            models = list(
                map(lambda x: {k
                               for k, v in x.items()
                               if v is True}, all_models))

        for min_model in models:
            q_prime = frozenset({id2atom[s] for s in map(str, min_model)})
            new_macrostate.add(q_prime)

    return frozenset(new_macrostate)
Exemple #29
0
 def to_nnf(self) -> LDLfFormula:
     """Transform to NNF."""
     return LDLfDiamond(RegExpPropositional(PLFalse()), LDLfLogicalTrue())