def test_always(self): parser = self.parser i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab true = self.true false = self.false assert parser("G a").delta(i_a) == PLAnd([ true, PLOr([ false, PLOr([ PLAtomic(LTLfRelease([LTLfFalse(), LTLfAtomic("a")])), PLAtomic(LTLfRelease([LTLfFalse(), LTLfFalse()])), ]), ]), ]) assert parser("G a").delta(i_a) == PLAnd([ true, PLOr([ false, PLOr([ PLAtomic(LTLfRelease([LTLfFalse(), LTLfAtomic("a")])), PLAtomic(LTLfRelease([LTLfFalse(), LTLfFalse()])), ]), ]), ]) assert parser("G a").delta(i_a, epsilon=True) == true assert parser("G a").delta(i_, epsilon=True) == true
def test_persistence_and_response_on_empty_words(): formula_1 = LTLfAlways(LTLfEventually(LTLfAtomic("a"))) formula_2 = LTLfEventually(LTLfAlways(LTLfAtomic("a"))) recurrence_truth = formula_1.truth([], 0) persistence_truth = formula_2.truth([], 0) assert recurrence_truth assert not persistence_truth
def test_eventually(self): parser = self.parser i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab true = self.true false = self.false assert parser("F a").delta(i_a) == PLOr([ true, PLAnd([ true, PLAnd([ PLAtomic(LTLfUntil([LTLfTrue(), LTLfAtomic("a")])), PLAtomic(LTLfUntil([LTLfTrue(), LTLfTrue()])), ]), ]), ]) assert parser("F a").delta(i_) == PLOr([ false, PLAnd([ true, PLAnd([ PLAtomic(LTLfUntil([LTLfTrue(), LTLfAtomic("a")])), PLAtomic(LTLfUntil([LTLfTrue(), LTLfTrue()])), ]), ]), ]) assert parser("F a").delta(i_a, epsilon=True) == false assert parser("F a").delta(i_, epsilon=True) == false
def test_names(): good = ["a", "b", "name", "complex_name", "proposition10"] bad = ["Future", "X", "$", "", "40a", "niceName"] for name in good: str(LTLfAtomic(name)) == name for name in bad: with pytest.raises(ValueError): str(LTLfAtomic(name)) == name
def test_QuotedFormula(): from flloat.base import QuotedFormula from flloat.parser.ltlf import LTLfParser from flloat.ltlf import LTLfAtomic, LTLfAnd f = LTLfParser()("!(G a)") qf = QuotedFormula(f) atomf = LTLfAnd([LTLfAtomic(f), LTLfAtomic(f)]) assert qf.wrapped is f dir_qf = dir(qf) for member in dir(f): assert member in dir_qf assert hasattr(qf, member)
def test_release(self): parser = self.parser i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab true = self.true false = self.false assert parser("A R B").delta(i_a) == PLAnd([ false, PLOr([ true, PLAtomic(LTLfRelease([LTLfAtomic("A"), LTLfAtomic("B")])), PLAtomic(LTLfAlways(LTLfFalse()).to_nnf()) ]) ]) assert parser("A R B").delta(i_ab, epsilon=True) == true
def test_until(self): parser = self.parser i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab true = self.true false = self.false assert parser("A U B").delta(i_a) == PLOr([ false, PLAnd([ true, PLAtomic(LTLfUntil([LTLfAtomic("A"), LTLfAtomic("B")])), PLAtomic(LTLfEventually(LTLfTrue()).to_nnf()) ]) ]) assert parser("A U B").delta(i_ab, epsilon=True) == false
def test_next(self): parser = self.parser i_, i_a, i_b, i_ab = self.i_, self.i_a, self.i_b, self.i_ab true = self.true false = self.false assert parser("X A").delta(i_) == PLAnd( [PLAtomic(LTLfAtomic("A")), PLAtomic(LTLfEventually(LTLfTrue()).to_nnf())]) assert parser("X A").delta(i_a) == PLAnd( [PLAtomic(LTLfAtomic("A")), PLAtomic(LTLfEventually(LTLfTrue()).to_nnf())]) assert parser("X A").delta(i_b) == PLAnd( [PLAtomic(LTLfAtomic("A")), PLAtomic(LTLfEventually(LTLfTrue()).to_nnf())]) assert parser("X A").delta(i_ab) == PLAnd( [PLAtomic(LTLfAtomic("A")), PLAtomic(LTLfEventually(LTLfTrue()).to_nnf())]) assert parser("X A").delta(i_, epsilon=True) == false
def p_formula(self, p): """formula : formula EQUIVALENCE formula | formula IMPLIES formula | formula OR formula | formula AND formula | formula UNTIL formula | formula RELEASE formula | EVENTUALLY formula | ALWAYS formula | NEXT formula | WEAK_NEXT formula | NOT formula | TRUE | FALSE | END | ATOM""" if len(p) == 2: if p[1] == Symbols.TRUE.value: p[0] = LTLfTrue() elif p[1] == Symbols.FALSE.value: p[0] = LTLfFalse() elif p[1] == Symbols.END.value: p[0] = LTLfEnd() else: p[0] = LTLfAtomic(p[1]) elif len(p) == 3: if p[1] == Symbols.NEXT.value: p[0] = LTLfNext(p[2]) elif p[1] == Symbols.WEAK_NEXT.value: p[0] = LTLfWeakNext(p[2]) elif p[1] == Symbols.EVENTUALLY.value: p[0] = LTLfEventually(p[2]) elif p[1] == Symbols.ALWAYS.value: p[0] = LTLfAlways(p[2]) elif p[1] == Symbols.NOT.value: p[0] = LTLfNot(p[2]) elif len(p) == 4: l, o, r = p[1:] if o == Symbols.EQUIVALENCE.value: p[0] = LTLfEquivalence([l, r]) elif o == Symbols.IMPLIES.value: p[0] = LTLfImplies([l, r]) elif o == Symbols.OR.value: p[0] = LTLfOr([l, r]) elif o == Symbols.AND.value: p[0] = LTLfAnd([l, r]) elif o == Symbols.UNTIL.value: p[0] = LTLfUntil([l, r]) elif o == Symbols.RELEASE.value: p[0] = LTLfRelease([l, r]) else: raise ValueError else: raise ValueError
def test_parser(): parser = LTLfParser() a, b, c = [LTLfAtomic(c) for c in "abc"] assert parser("!a | b <-> !(a & !b) <-> a->b") == LTLfEquivalence([ LTLfOr([LTLfNot(a), b]), LTLfNot(LTLfAnd([a, LTLfNot(b)])), LTLfImplies([a, b]), ]) assert parser("(X a) & (WX !b)") == LTLfAnd( [LTLfNext(a), LTLfWeakNext(LTLfNot(b))]) assert parser("(F (a&b)) <-> !(G (!a | !b) )") == LTLfEquivalence([ LTLfEventually(LTLfAnd([a, b])), LTLfNot(LTLfAlways(LTLfOr([LTLfNot(a), LTLfNot(b)]))), ]) assert parser("(a U b U c) <-> !(!a R !b R !c)") == LTLfEquivalence([ LTLfUntil([a, b, c]), LTLfNot(LTLfRelease([LTLfNot(a), LTLfNot(b), LTLfNot(c)])), ])
def test_nnf(): parser = LTLfParser() a, b, c = [LTLfAtomic(c) for c in "abc"] f = parser("!(a & !b)") assert f.to_nnf() == LTLfOr([LTLfNot(a), b]) f = parser("!(!a | b)") assert f.to_nnf() == LTLfAnd([a, LTLfNot(b)]) f = parser("!(a <-> b)") assert f.to_nnf() == LTLfAnd( [LTLfOr([LTLfNot(a), LTLfNot(b)]), LTLfOr([a, b])]) # Next and Weak Next f = parser("!(X (a & b))") assert f.to_nnf() == LTLfWeakNext(LTLfOr([LTLfNot(a), LTLfNot(b)])) f = parser("!(WX (a & b))") assert f.to_nnf() == LTLfNext(LTLfOr([LTLfNot(a), LTLfNot(b)])) # Eventually and Always f = parser("!(F (a | b))") assert f.to_nnf() == LTLfAlways(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf() # Until and Release f = parser("!(a U b)") assert f.to_nnf() == LTLfRelease([LTLfNot(a), LTLfNot(b)]) f = parser("!(a R b)") assert f.to_nnf() == LTLfUntil([LTLfNot(a), LTLfNot(b)]) f = parser("!(F (a | b))") assert f.to_nnf() == LTLfAlways(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf() f = parser("!(G (a | b))") assert f.to_nnf() == LTLfEventually(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf()
def test_nnf(): parser = LTLfParser() a, b, c = [LTLfAtomic(c) for c in "ABC"] f = parser("!(A & !B)") assert f.to_nnf() == LTLfOr([LTLfNot(a), b]) f = parser("!(!A | B)") assert f.to_nnf() == LTLfAnd([a, LTLfNot(b)]) f = parser("!( (A->B) <-> (!A | B))") assert f.to_nnf() == LTLfAnd([ LTLfAnd([a, LTLfNot(b)]), LTLfOr([LTLfNot(a), b]), ]) # Next and Weak Next f = parser("!(X (A & B))") assert f.to_nnf() == LTLfWeakNext(LTLfOr([LTLfNot(a), LTLfNot(b)])) f = parser("!(WX (A & B))") assert f.to_nnf() == LTLfNext(LTLfOr([LTLfNot(a), LTLfNot(b)])) # Eventually and Always f = parser("!(F (A | B))") assert f.to_nnf() == LTLfAlways(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf() f = parser("!(F (A | B))") assert f.to_nnf() == LTLfAlways(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf() f = parser("!(G (A | B))") assert f.to_nnf() == LTLfEventually(LTLfAnd([LTLfNot(a), LTLfNot(b)])).to_nnf() # Until and Release f = parser("!(A U B)") assert f.to_nnf() == LTLfRelease([LTLfNot(a), LTLfNot(b)]) f = parser("!(A R B)") assert f.to_nnf() == LTLfUntil([LTLfNot(a), LTLfNot(b)])
def test_parser(): parser = LTLfParser() a, b, c = [LTLfAtomic(c) for c in "ABC"] assert parser("!A | B <-> !(A & !B) <-> A->B") == LTLfEquivalence([ LTLfOr([LTLfNot(a), b]), LTLfNot(LTLfAnd([a, LTLfNot(b)])), LTLfImplies([a, b]) ]) assert parser("(X A) & (WX !B)") == LTLfAnd([ LTLfNext(a), LTLfWeakNext(LTLfNot(b)) ]) assert parser("(F (A&B)) <-> !(G (!A | !B) )") == LTLfEquivalence([ LTLfEventually(LTLfAnd([a, b])), LTLfNot(LTLfAlways(LTLfOr([LTLfNot(a), LTLfNot(b)]))) ]) assert parser("(A U B U C) <-> !(!A R !B R !C)") == LTLfEquivalence([ LTLfUntil([a, b, c]), LTLfNot(LTLfRelease([LTLfNot(a), LTLfNot(b), LTLfNot(c)])) ])
def ltlf_symbol(self, args): assert len(args) == 1 token = args[0] symbol = str(token) return LTLfAtomic(symbol)
def test_persistence_is_equivalent_to_response_on_nonempty_words(word): formula_1 = LTLfAlways(LTLfEventually(LTLfAtomic("a"))) formula_2 = LTLfEventually(LTLfAlways(LTLfAtomic("a"))) assert formula_1.truth(word, 0) == formula_2.truth(word, 0)