Exemple #1
0
    def test_parse_assignment(self):
        pars = updateStatementParser.updateStatementParser("x = s")
        AST = pars.parseUpdateStatements()
        AST.visit()

        pars = updateStatementParser.updateStatementParser("x = s;")
        AST = pars.parseUpdateStatements()
        AST.visit()
    def test_parse_assignment(self):
        pars = updateStatementParser.updateStatementParser("x = s")
        AST = pars.parseUpdateStatements()
        AST.visit()

        pars = updateStatementParser.updateStatementParser("x = s;")
        AST = pars.parseUpdateStatements()
        AST.visit()
Exemple #3
0
 def analyze_live_variables(self):
     for t_idx, t in enumerate(self.nta.templates):
         local_collect_variables = partial(self._collect_variables,
                                           t_idx=t_idx)
         logger.debug("In template %s:", t.name)
         for l_idx, l in enumerate(t.locations):
             if l.invariant.value:
                 ast = expressionParser.parse_expression(l.invariant.value)
                 if ast:
                     ast.visit(local_collect_variables)
         #outgoing transitions
         for trans in t.transitions:
             #guard
             if trans.guard.value:
                 ast = expressionParser.parse_expression(trans.guard.value)
                 ast.visit(local_collect_variables)
             if trans.assignment.value:
                 myparser = updateStatementParser.updateStatementParser(
                     trans.assignment.value)
                 ast = myparser.parseUpdateStatements()
                 ast.visit(local_collect_variables)
         logger.debug("Live variables: \n %s", self.live_variables[t_idx])
Exemple #4
0
    def analyze_lower_upperbounds(self):
        """
        Location dependent lower-upper bounds analysis, as described in
        "Static Guard Analysis in Timed Automata Verification" by 
        Gerd Behrmann, Patricia Bouyer, Emmanuel Fleury and Kim G. Larsen
        and
        "Lower and Upper Bounds in Zone Based Abstractions of Timed Automata" by 
        Gerd Behrmann, Patricia Bouyer, Kim G. Larsen and Radek Pelanek

        Uses the more general form of analysis, which is O(n^3). If only certain 
        kinds of clock guards/resets are needed the O(n) algorithm can be implemented.

        Currently only handles updates of the form x := c, but could be expanded.
        Assumes all clocks are global.
        """

        #Collect inequalities
        for t_idx, t in enumerate(self.nta.templates):
            self.live_clocks[t_idx] = [
                c for c in self._clocks if c in self.live_variables[t_idx]
            ]
            logging.debug("Live clocks for %s: %s", t.name,
                          self.live_clocks[t_idx])
            numclocks = len(self.live_clocks[t_idx])
            clocks_reset_proto = {}
            for c in self.live_clocks[t_idx]:
                clocks_reset_proto[c] = False
            #init empty graph
            numlocs = len(t.locations)
            logger.debug("Matrix of size %dx%d (%d locations, %d clocks)",
                         numlocs * numclocks + 1, numlocs * numclocks + 1,
                         numlocs, numclocks)
            lower_eq_graph = numpy.empty(
                [numlocs * numclocks + 1, numlocs * numclocks + 1], dtype=int)
            lower_eq_graph.fill(-1)
            upper_eq_graph = numpy.empty(
                [numlocs * numclocks + 1, numlocs * numclocks + 1], dtype=int)
            upper_eq_graph.fill(-1)

            for l_idx, l in enumerate(t.locations):
                if not l.invariant.value:
                    continue
                logger.debug("At loc %s:", l)
                s = l.invariant.value
                ast = expressionParser.parse_expression(s)
                local_collect_comparisons = partial(
                    self._lu_collect_comparisons,
                    t_idx=t_idx,
                    l_idx=l_idx,
                    lower_eq_graph=lower_eq_graph,
                    upper_eq_graph=upper_eq_graph)
                ast.visit(local_collect_comparisons)

            #outgoing transitions
            for trans in t.transitions:
                source_id = t.locations.index(trans.source)
                target_id = t.locations.index(trans.target)
                #guard
                if trans.guard.value:
                    ast = expressionParser.parse_expression(trans.guard.value)
                    local_collect_comparisons = partial(
                        self._lu_collect_comparisons,
                        t_idx=t_idx,
                        l_idx=source_id,
                        lower_eq_graph=lower_eq_graph,
                        upper_eq_graph=upper_eq_graph)
                    ast.visit(local_collect_comparisons)

                #dependencies through non-resetting
                for c in self.live_clocks[t_idx]:
                    lower_eq_graph[self._calc_index(t_idx, source_id,
                                                    c)][self._calc_index(
                                                        t_idx, target_id,
                                                        c)] = -1
                    upper_eq_graph[self._calc_index(t_idx, source_id,
                                                    c)][self._calc_index(
                                                        t_idx, target_id,
                                                        c)] = -1
                if trans.assignment.value:
                    myparser = updateStatementParser.updateStatementParser(
                        trans.assignment.value)
                    ast = myparser.parseUpdateStatements()
                    if ast.children[0] is None:
                        logger.warning(
                            "couldn't parse update \"%s\", doing safe upper approximation",
                            trans.assignment.value)
                        for c in self.live_clocks[t_idx]:
                            lower_eq_graph[self._calc_index(t_idx, source_id, c)] \
                                    [self._calc_index(t_idx, target_id, c)] = 0
                            upper_eq_graph[self._calc_index(t_idx, source_id, c)] \
                                    [self._calc_index(t_idx, target_id, c)] = 0
                    else:
                        clocks_reset = dict(clocks_reset_proto)
                        local_collect_resets = partial(
                            self._collect_resets,
                            src_idx=source_id,
                            dst_idx=target_id,
                            clocks_reset=clocks_reset)
                        ast.visit(local_collect_resets)

                        for (c, reset) in clocks_reset.iteritems():
                            if not reset:
                                lower_eq_graph[self._calc_index(t_idx, source_id, c)] \
                                        [self._calc_index(t_idx, target_id, c)] = 0
                                upper_eq_graph[self._calc_index(t_idx, source_id, c)] \
                                        [self._calc_index(t_idx, target_id, c)] = 0
                else:
                    for c in self.live_clocks[t_idx]:
                        lower_eq_graph[self._calc_index(t_idx, source_id,
                                                        c)][self._calc_index(
                                                            t_idx, target_id,
                                                            c)] = 0
                        upper_eq_graph[self._calc_index(t_idx, source_id,
                                                        c)][self._calc_index(
                                                            t_idx, target_id,
                                                            c)] = 0

            #logger.debug("lower_eq_graph: \n %s", lower_eq_graph)
            #logger.debug("upper_eq_graph: \n %s", upper_eq_graph)

            #Invert graph weights, to find longest paths instead
            lower_eq_graph = lower_eq_graph * -1
            upper_eq_graph = upper_eq_graph * -1

            #"1" now means no edge
            lower_eq_graph = self._all_pairs_shortest_path(lower_eq_graph,
                                                           nan=1)
            upper_eq_graph = self._all_pairs_shortest_path(upper_eq_graph,
                                                           nan=1)

            #invert graph back
            lower_eq_graph = lower_eq_graph * -1
            upper_eq_graph = upper_eq_graph * -1

            #logger.debug("lower_eq_graph, longest paths: \n %s", lower_eq_graph)
            #logger.debug("upper_eq_graph, longest paths: \n %s", upper_eq_graph)

            #collect output
            for l_idx, l in enumerate(t.locations):
                for c in self.live_clocks[t_idx]:
                    #for backwards compatibility
                    self.max_constants[t_idx][l_idx][c] = max(
                        lower_eq_graph[self._calc_index(t_idx, l_idx, c)][0],
                        upper_eq_graph[self._calc_index(t_idx, l_idx, c)][0])
                    self.lowerbound[t_idx][l_idx][c] = lower_eq_graph[
                        self._calc_index(t_idx, l_idx, c)][0]
                    self.upperbound[t_idx][l_idx][c] = upper_eq_graph[
                        self._calc_index(t_idx, l_idx, c)][0]

            logger.debug("lower bounds: \n %s", self.lowerbound[t_idx])
            logger.debug("upper bounds: \n %s", self.upperbound[t_idx])
Exemple #5
0
 def test_parse_comma_separated_statements(self):
     pars = updateStatementParser.updateStatementParser("x = s, t= f();", lexer.lexer)
     AST = pars.parseUpdateStatements()
     AST.visit()
 def test_parse_comma_separated_statements(self):
     pars = updateStatementParser.updateStatementParser(
         "x = s, t= f();", lexer.lexer)
     AST = pars.parseUpdateStatements()
     AST.visit()