Beispiel #1
0
 def testIsATreeAcceptedByANonTerminalOfOurUVWGrammar(self):
     listOfTestCases = [
         ("LTL a", "Phi", True),
         ("LTL G F G a", "Phi", False),
         ("LTL G F b", "Phi", True),
         ("LTL ~ G F b", "Phi", False),
         ("LTL F G b", "Phi", False),
         ("LTL F b", "Psi", True),
         ("LTL G F b", "Psi", False),
         ("LTL U a U b c", "Phi", True),
         ("LTL G U & F p G q & ! p G k", "Phi",
          False),  # Maidl's original grammar
         ("LTL G U & p G q & ! F k G k", "Phi",
          False),  # Maidl's original grammar
         ("LTL G U & p G q & ! p G k", "Phi",
          True),  # Maidl's original grammar
         ("LTL G U & p G q & r G k", "Phi",
          False),  # Maidl's original grammar
         ("LTL G U & & p q G r & ! & p q G k", "Phi",
          True),  # Maidl's original grammar
         ("LTL G U & & p q G r & | ! p ! q G k", "Phi",
          True),  # Maidl's original grammar
         ("LTL G U & & p q G r & | ! p q G k", "Phi",
          False),  # Maidl's original grammar
     ]
     for (ltl, nonterminal, shouldBeAccepted) in listOfTestCases:
         tree1 = parser.parse(ltl)
         tree2 = parser.simplifyTree(tree1)
         tree3 = parser.elimImplies(tree2)
         tree4 = parser.computeNNF(tree3)
         isAccepted = parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(
             tree4, nonterminal)
         assert isAccepted == shouldBeAccepted
Beispiel #2
0
 def testSimplify(self):
     listOfTestCases = [("LTL G G F a", "LTL G F a"),
                        ("LTL F F ~ ~ a", "LTL F a")]
     for (before, after) in listOfTestCases:
         tree1 = parser.parse(before)
         tree2 = parser.parse(after)
         simpler = parser.simplifyTree(tree1)
         assert str(simpler) == str(tree2)
Beispiel #3
0
    def testSomeErrorCases(self):

        # Illegal UVW parsing from strings
        uvw = uvwBuilder.UVW()
        uvw.ddMgr.declare('a', 'b')
        uvwBuilder.UVW.parseFromUVWDescription(uvw.ddMgr,
                                               "2(i)-[a]->2,2(i)-[b]->2")
        with self.assertRaises(Exception):
            uvwBuilder.UVW.parseFromUVWDescription(
                uvw.ddMgr, "2(i)-[a]->2,2(i)-[b]->2,1(ik)-[True]->1")

        # Throw exception if not in NNF
        with self.assertRaises(Exception):
            formulaNode = parser.simplifyTree(parser.parse("LTL G ~ G a"))
            uvw = uvwBuilder.constructUVW(formulaNode)

        # Throw exception if there is still a "->" in the LTL formula
        with self.assertRaises(Exception):
            formulaNode = parser.simplifyTree(parser.parse("LTL G -> a b"))
            uvw = uvwBuilder.constructUVW(formulaNode)
Beispiel #4
0
 def testUVWSizeUnminimized(self):
     listOfTestCases = [
         ("LTL G F a", 3),
         ("LTL || a b", 2),
         ("LTL || G a G b", 5),  # The error state gets duplicated
     ]
     for (ltl, expectedSize) in listOfTestCases:
         formulaNode = parser.computeNNF(
             parser.simplifyTree(parser.elimImplies(parser.parse(ltl))))
         uvw = uvwBuilder.constructUVW(formulaNode)
         uvw.removeUnreachableStates()
         assert len(uvw.stateNames) == expectedSize
Beispiel #5
0
 def testUVWSizeMinimized(self):
     listOfTestCases = [
         ("LTL G F a", 3), ("LTL || a b", 2), ("LTL || G a G b", 4),
         ("LTL && G a G b", 2), ("LTL || G F a G F b", 3),
         ("LTL && G F a G F b", 4), ("LTL || || G a G b G c", 8),
         ("LTL || G a G ~ a", 4), ("LTL F || F a F b", 2),
         ("LTL F && ~ a a", 1), ("LTL U && ~ a G b && a F d", 4),
         ("LTL U ! buttonB.click & buttonB.click U ! idle buttonA.enable",
          3),
         ("LTL | G ! buttonB.click U ! buttonB.click & buttonB.click U ! idle buttonA.enable",
          3),
         ("LTL G | G ! buttonB.click U ! buttonB.click & buttonB.click U ! idle buttonA.enable",
          3)
     ]
     for (ltl, expectedSize) in listOfTestCases:
         formulaNode = parser.computeNNF(
             parser.simplifyTree(parser.elimImplies(parser.parse(ltl))))
         assert parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(
             formulaNode, "Phi")
         uvw = uvwBuilder.constructUVW(formulaNode)
         #print(uvw)
         uvw.removeUnreachableStates()
         #print(uvw)
         uvw.simulationBasedMinimization()
         uvw.removeUnreachableStates()
         #print(uvw)
         uvw.mergeEquivalentlyReachableStates()
         #print(uvw)
         uvw.removeForwardReachableBackwardSimulatingStates()
         #print(uvw)
         if len(uvw.stateNames) != expectedSize:
             print("Unexpected size:")
             print(ltl)
             print(uvw)
             sys.stdout.flush()
         assert len(uvw.stateNames) == expectedSize
        print("Error: Need a formula file name!", file=sys.stderr)
        sys.exit(1)

    with open(sys.argv[1], "r") as inFile:
        formulaTxt = inFile.readlines()

# Assuming the LTL specification is for a never claim

    for line in formulaTxt:
        line = line.strip()
        if len(line) > 0:
            assert line[0:4] == "LTL "
            #line = "LTL ! "+line[4:]

            formulaNode = parser.computeNNF(
                parser.simplifyTree(parser.elimImplies(parser.parse(line))))
            assert parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(
                formulaNode, "Phi")

            # formulaTxt = "LTL F && c F && b F a" ----> Does not work according to the grammar
            print("================Constructing UVW================",
                  file=sys.stderr)
            uvw = uvwBuilder.constructUVW(formulaNode)
            print("================Original Automaton================",
                  file=sys.stderr)
            # print(uvw)
            uvw.removeUnreachableStates()
            print("================Removed Unreachable States================",
                  file=sys.stderr)
            # print(uvw)
            uvw.simulationBasedMinimization()
Beispiel #7
0
            if not filename is None:
                print("Error: Multiple file names given.",file=sys.stderr)
                sys.exit(1)
            filename = arg

    if filename is None:
        print("Error: Need a formula file name!",file=sys.stderr)
        sys.exit(1)

    with open(sys.argv[1],"r") as inFile:
    	formulaTxt = inFile.readline().strip()

    # Assuming the LTL specification is for a never claim
    assert formulaTxt[0:4]=="LTL "

    formulaNode = parser.computeNNF(parser.simplifyTree(parser.elimImplies(parser.parse(formulaTxt))))
    if not parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(formulaNode,"Phi"):
        print("Error: Input is not in the supported LTL fragment.",file=sys.stderr)
        parser.printTreeWithSupportedAnnotatedNonterminalsForUVWGrammar(formulaNode)
        sys.exit(1)

    print("================Constructing UVW================",file=sys.stderr)
    uvw = constructUVW(formulaNode)
    if singleActionOptimization:
        uvw.restrictToTheCaseThatThereCanOnlyBeOneActionAtATime()
    print("================Original Automaton================",file=sys.stderr)
    # print(uvw,file=sys.stderr)
    # These two are needed in case "restrictToTheCaseThatThereCanOnlyBeOneActionAtATime" disconnected states
    # as otherwise the later simulationBasedMinimization may fail.
    uvw.removeUnreachableStates()
    uvw.removeStatesWithoutOutgoingTransitions()
Beispiel #8
0
 def testTreesinUVWGrammar(self):
     listOfTestCases = [
         #Spinroot Example:Blue Spec TM Specification
         ("LTL G | ! a X U ! b c", True),
         ("LTL G | & ! a ! b X U ! c | a d", True),
         ("LTL G | & ! a ! b X U ! c a", True),
         ("LTL G | | ! a ! b X U ! c d", True),
         ("LTL G | | ! a ! b X U ! c & a d", True),
         #Spinroot Example: CORBA General Inter-Orb Protocol
         ("LTL | G ! p U q r", True),
         ("LTL G | | ! q G ! r U ! r p", True),
         ("LTL G | ! p F s", True),
         ("LTL | G ! p U ! p & ! p s", True),
         ("LTL G | | ! q G ! r U ! p r", True),
         ("LTL G | | ! q G ! r U & ! p ! r | r U & p ! r | r U ! p r",
          True),
         #Spinroot Example:PLC Control Schedule
         ("LTL & G F | ! a b G F | ! a c", True),
         #Spinroot Example:Space Craft Controller
         ("LTL G | ! a F b", True),
         ("LTL G | ! a F | b c", True),
         #Spinroot Example:Group Address Registration Protocol
         ("LTL G | ! p F G q", False),
         #Spinroot Example: Needham-Schroeder Public Key Protocol
         ("LTL G | G ! p U ! p q", True),
         #Spinroot Example: Cardiac pacemaker model
         ("LTL G | ! p F & & q r s", True),
         ("LTL G | ! p r", True),
         ("LTL G & | ! p ! q | ! r s", True),
         ("LTL G & p | ! q r", True),
         ("LTL G | | ! p ! q & r s", True),
         ("LTL G | & & ! p ! q ! r F x", True),
         #Example Anderson from paper 'IS THERE A BEST BUCHI AUTOMATA FOR EXPLICIT MC'
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | ap0 ap1", True),
         ("LTL ! G F | ap0 ap1", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | ap0 ap1 ap2", True),
         ("LTL ! G F | | ap0 ap1 ap2", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | ap0 ap1 ap2", True),
         ("LTL ! G F | | ap0 ap1 ap2", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | | ap0 ap1 ap2 ap3", True),
         ("LTL ! G F | | | ap0 ap1 ap2 ap3", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | | | ap0 ap1 ap2 ap3 ap4", True),
         ("LTL ! G F | | | | ap0 ap1 ap2 ap3 ap4", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | | | | ap0 ap1 ap2 ap3 ap4 ap5", True),
         ("LTL ! G F | | | | | ap0 ap1 ap2 ap3 ap4 ap5", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | | | | ap0 ap1 ap2 ap3 ap4 ap5", True),
         ("LTL ! G F | | | | | ap0 ap1 ap2 ap3 ap4 ap5", False),
         ("LTL G -> | | ap0 ap1 ap2 F ap3", True),
         ("LTL ! G -> | | ap0 ap1 ap2 F ap3", False),
         ("LTL G -> ! ap0 F ap0", True),
         ("LTL ! G -> ! ap0 F ap0", False),
         ("LTL G F | | | | | | ap0 ap1 ap2 ap3 ap4 ap5 ap6", True),
         ("LTL ! G F | | | | | | ap0 ap1 ap2 ap3 ap4 ap5 ap6", False),
     ]
     for (ltl, shouldBeAccepted) in listOfTestCases:
         tree1 = parser.parse(ltl)
         tree2 = parser.simplifyTree(tree1)
         tree3 = parser.elimImplies(tree2)
         tree4 = parser.computeNNF(tree3)
         isAccepted = parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(
             tree4, "Phi")
         assert isAccepted == shouldBeAccepted
Beispiel #9
0
    def testSimpleChainDecomposition(self):
        listOfTestCases = [
            ("LTL G F a", ["1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2"], True),
            ("LTL && G a G F b", [
                "1(i)-[True]->1,1-[~a]->0",
                "1(i)-[True]->1,1-[~b]->2,2(r)-[~b]->2"
            ], True),
            ("LTL && X G a G F b", [
                "2(i)-[True]->1,1-[True]->1,1-[~a]->0",
                "1(i)-[True]->1,1-[~b]->2,2(r)-[~b]->2"
            ], True),
            ("LTL && G a G F b", ["1(i)-[True]->1,1-[~a]->0"], False),
            ("LTL && G F a G F b", [
                "1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2",
                "1(i)-[True]->1,1-[~b]->2,2(r)-[~b]->2"
            ], True),
            ("LTL && && G F ~ c G F a G F b", [
                "1(i)-[True]->1,1-[c]->2,2(r)-[c]->2",
                "1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2",
                "1(i)-[True]->1,1-[~b]->2,2(r)-[~b]->2"
            ], True),
            ("LTL U U a b c", [
                "1(ir)-[~c]->1,1-[~b & ~c]->2,2(r)-[~b]->2,2-[~a & ~b]->0",
                "1(ir)-[~c]->1,1-[~c & ~b & ~a]->0"
            ], True)
        ]

        for (ltl, expectedChains, should) in listOfTestCases:
            formulaNode = parser.computeNNF(
                parser.simplifyTree(parser.parse(ltl)))
            uvw = uvwBuilder.constructUVW(
                parser.Node(
                    parser.NodeTypes.OR,
                    [formulaNode]))  # Test single-element or along the way
            uvw.removeUnreachableStates()
            uvw.simulationBasedMinimization()
            uvw.removeUnreachableStates()
            uvw.mergeEquivalentlyReachableStates()
            uvw.removeForwardReachableBackwardSimulatingStates()
            decomposedUVWs = uvw.decomposeIntoSimpleChains()
            expectedUVWs = [
                uvwBuilder.UVW.parseFromUVWDescription(uvw.ddMgr, a)
                for a in expectedChains
            ]

            #print("----orig----",file=sys.stderr)
            #print(uvw,file=sys.stderr)

            #print("----decomposed----",file=sys.stderr)
            #for a in decomposedUVWs:
            #    print(a,file=sys.stderr)

            # Check if for every expected UVW, there is an equivalent UVW in the decomposed chains
            # and vice versa
            foundAll = True
            for (set1, set2) in [(expectedUVWs, decomposedUVWs),
                                 (decomposedUVWs, expectedUVWs)]:
                for a in set1:
                    foundThisOne = False
                    for b in set2:
                        if uvwBuilder.UVW.isBisimulationEquivalent(a, b):
                            foundThisOne = True
                    foundAll = foundAll and foundThisOne

            assert should == foundAll
Beispiel #10
0
    def testSomeConcreteTrees(self):
        listOfTestCases = [
            ("LTL G F a", "1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2", True),
            ("LTL G F a", "1(i)-[True]->1,1-[~a]->2,2(r)-[a]->2", False),
            ("LTL && G a G b", "1(i)-[True]->1,1-[~a | ~b]->0", True),
            ("LTL && G F a G F b", "1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2",
             False),
            ("LTL && G F a G F b",
             "1(i)-[True]->1,1-[~a]->2,2(r)-[~a]->2,1-[~b]->3,3(r)-[~b]->3",
             True),
            ("LTL U a b", "1(ir)-[a & ~b]->1,1-[~a & ~b]->0", True),
            ("LTL R b a", "1(i)-[a & ~b]->1,1-[~a]->0", True),
            ("LTL U a b", "1(i)-[a & ~b]->1,1-[~a & ~b]->0", False),
            ("LTL R b a", "1(ir)-[a & ~b]->1,1-[~a & ~b]->0", False),
            ("LTL X && G a G a", "1(ir)-[True]->2,2-[True]->2,2-[~a]->0",
             True),
            ("LTL && && X G b X G a X G && c ~ d",
             "1(ir)-[True]->2,2-[True]->2,2-[~a | ~b | ~c | d]->0", True),
            ("LTL X && && X X G a X G a X X X G a",
             "1(i)-[True]->2,2-[True]->3,3-[True]->3,3-[~a]->0", True),
            ("LTL F && ~ a a", "1(i)-[True]->0", True),
            ("LTL || a ~ a", "", True),
            ("LTL U a U b c",
             "1(ir)-[~c & a]->1,1-[~a & ~c]->2,1-[~a & ~b & ~c]->0,2(r)-[~c]->2,2-[~b & ~c]->0",
             True),
            ("LTL U U a b c",
             "1(ir)-[~c]->1,1-[~a & ~b & ~c]->0,1-[~b & ~c]->2,2(r)-[~b]->2,2-[~a & ~b]->0",
             True),
            ("LTL && G -> && a b F || c d G -> a F c",
             "1(i)-[True]->1,1-[a]->2,2(r)-[~c]->2", False),
            ("LTL && G -> && a b F || c d G -> a F c",
             "1(i)-[True]->1,1-[a & ~c]->2,2(r)-[~c]->2", True),
            ("LTL G R a b", "1(i)-[True]->1,1-[~b]->0", True),
            ("LTL G R a R b c", "1(i)-[True]->1,1-[~c]->0", True),
        ]
        for (ltl, expectedResult, should) in listOfTestCases:
            formulaNode = parser.computeNNF(
                parser.elimImplies(parser.simplifyTree(parser.parse(ltl))))
            uvw = uvwBuilder.constructUVW(formulaNode)
            uvw.removeUnreachableStates()
            uvw.simulationBasedMinimization()
            uvw.removeUnreachableStates()
            uvw.mergeEquivalentlyReachableStates()
            uvw.removeForwardReachableBackwardSimulatingStates()

            referenceUVW = uvwBuilder.UVW.parseFromUVWDescription(
                uvw.ddMgr, expectedResult)
            try:
                assert parser.isATreeAcceptedByANonTerminalOfOurUVWGrammar(
                    formulaNode, "Phi")
                assert should == uvwBuilder.UVW.isBisimulationEquivalent(
                    uvw, referenceUVW)
                if should:
                    assert len(uvw.transitions) <= len(
                        referenceUVW.transitions)  # Not too large
            except AssertionError:
                print("LTL:", ltl)
                print("Expected:", referenceUVW)
                print("Got:", uvw)
                raise

            # Test if this terminates
            uvw.toNeverClaim()