def get_state_id(self, places, petri_net):
        '''get the state_id from his marked places ids
        for example "<s1>" or "<s1,s2>" or "<s1,s2,s3>" sorted
        "<s2,s1>"--it is wrong!  it must be "<s1,s2>"
        @return: state_id
        @rtype: str
        '''

        places_dict = petri_net.places_dict

        state_id = ""
        places_ids = [place.pt_id for place in places]
        # "p6" < "p11"
        places_ids.sort(self.my_cmp)
        for pt_id in places_ids:
            place = places_dict[pt_id]
            if place.tokens > 1:
                temp = "," + pt_id + "(" + str(place.tokens) + ")"
            elif place.tokens == 1:
                temp = "," + pt_id
            else:
                log.show_error("no tokens in the place")
            state_id += temp
        # delete the first ","-----",s1,s2"-->"s1,s2"
        state_id = state_id[1:]
        state_id = "<" + state_id + ">"
        return state_id
    def _get_new_id(self, pt_element, pt_elements_dict):
        '''get the new ID of P or T, for example, "p3","t4"..
        for example EAID_BB946565_CBA6_4ee7_820E_8D19061435F6 (the id in xml)--> p1
        @param pt_element: place or transition
        @type pt_element: object of petri_net_element.Place or petri_net_element.Transition
        @param pt_elements_dict: places_dict or transitions_dict
        @type pt_elements_dict: dict
        @return: new_id --"p3","t4"..
        @rtype: new_id--str
        '''
        new_id = None
        num = 1
        for pt_id in pt_elements_dict:
            element = pt_elements_dict[pt_id]
            if element.id_changed is True:
                num += 1
        if isinstance(pt_element, petri_net_element.Place):
            new_id = "p" + str(num)
        elif isinstance(pt_element, petri_net_element.Transition):
            new_id = "t" + str(num)
        else:
            log.show_error("the pt_element type is wrong")

        if new_id in pt_elements_dict:
            log.show_error("the new id " + new_id + " exist already..._get_new_id()")
        return new_id
    def determine_marking(self, places, transition, places_dict, arcs_dict):
        '''fire t and determine the marking m' after firing.
        get the next state, in the state which places are marked
        @param places: the current marked places, pre-places. attention: do not change places!!!
        @type places: list
        @param transition: the next enabled transition,here just one transition from our definition
        @type transition: petri_net_element.Transition
        '''
        pre_places = places[:]
        incomings = transition.incomings
        for incoming in incomings:
            arc = arcs_dict[incoming]
            source = arc.source
            place = places_dict[source]
            if place in pre_places:
                place.tokens -= 1
                # not any more tokens,remove it
                if place.tokens == 0:
                    pre_places.remove(place)
            else:
                log.show_error(place.pt_id + " is not marked")
        outgoings = transition.outgoings
        for outgoing in outgoings:
            arc = arcs_dict[outgoing]
            target = arc.target
            place = places_dict[target]
            place.tokens += 1
            if place not in pre_places:
                pre_places.append(place)

        return pre_places
    def get_state_id(self, places, petri_net):
        '''get the state_id from his marked places ids
        for example "<s1>" or "<s1,s2>" or "<s1,s2,s3>" sorted
        "<s2,s1>"--it is wrong!  it must be "<s1,s2>"
        @return: state_id
        @rtype: str
        '''

        places_dict = petri_net.places_dict

        state_id = ""
        places_ids = [place.pt_id for place in places]
        # "p6" < "p11"
        places_ids.sort(self.my_cmp)
        for pt_id in places_ids:
            place = places_dict[pt_id]
            if place.tokens > 1:
                temp = "," + pt_id + "(" + str(place.tokens) + ")"
            elif place.tokens == 1:
                temp = "," + pt_id
            else:
                log.show_error("no tokens in the place")
            state_id += temp
        # delete the first ","-----",s1,s2"-->"s1,s2"
        state_id = state_id[1:]
        state_id = "<" + state_id + ">"
        return state_id
 def _get_nodes_from_edge(self, edge, activity):
     '''get the node1, node2 from the edge.
     also, node1-->edge-->node2
     @param edge: a edge instance in activity
     @type edge: a instance of edge, not the id of the edge
     '''
     nodes_dict = activity.nodes_dict
     pins_dict = activity.pins_dict
     # node1 and node2
     node1 = None
     node2 = None
     # the id of source and target
     source = edge.source
     target = edge.target
     # if source is node_id
     if source in nodes_dict:
         node1 = nodes_dict[source]
     else:
         # source is pout id
         pin = pins_dict[source]
         node1_id = pin.host
         node1 = nodes_dict[node1_id]
     # if target is node_id
     if target in nodes_dict:
         node2 = nodes_dict[target]
     else:
         # target is pin id
         pin = pins_dict[target]
         node2_id = pin.host
         node2 = nodes_dict[node2_id]
     # if node1 or node2 is None,it is error
     if node1 is None or node2 is None:
         log.show_error("the node1 or node2 is None")
     return node1, node2
    def determine_marking(self, places, transition, places_dict, arcs_dict):
        '''fire t and determine the marking m' after firing.
        get the next state, in the state which places are marked
        @param places: the current marked places, pre-places. attention: do not change places!!!
        @type places: list
        @param transition: the next enabled transition,here just one transition from our definition
        @type transition: petri_net_element.Transition
        '''
        pre_places = places[:]
        incomings = transition.incomings
        for incoming in incomings:
            arc = arcs_dict[incoming]
            source = arc.source
            place = places_dict[source]
            if place in pre_places:
                place.tokens -= 1
                # not any more tokens,remove it
                if place.tokens == 0:
                    pre_places.remove(place)
            else:
                log.show_error(place.pt_id + " is not marked")
        outgoings = transition.outgoings
        for outgoing in outgoings:
            arc = arcs_dict[outgoing]
            target = arc.target
            place = places_dict[target]
            place.tokens += 1
            if place not in pre_places:
                pre_places.append(place)

        return pre_places
    def _get_new_id(self, pt_element, pt_elements_dict):
        '''get the new ID of P or T, for example, "p3","t4"..
        for example EAID_BB946565_CBA6_4ee7_820E_8D19061435F6 (the id in xml)--> p1
        @param pt_element: place or transition
        @type pt_element: object of petri_net_element.Place or petri_net_element.Transition
        @param pt_elements_dict: places_dict or transitions_dict
        @type pt_elements_dict: dict
        @return: new_id --"p3","t4"..
        @rtype: new_id--str
        '''
        new_id = None
        num = 1
        for pt_id in pt_elements_dict:
            element = pt_elements_dict[pt_id]
            if element.id_changed is True:
                num += 1
        if isinstance(pt_element, petri_net_element.Place):
            new_id = "p" + str(num)
        elif isinstance(pt_element, petri_net_element.Transition):
            new_id = "t" + str(num)
        else:
            log.show_error("the pt_element type is wrong")

        if new_id in pt_elements_dict:
            log.show_error("the new id " + new_id +
                           " exist already..._get_new_id()")
        return new_id
Example #8
0
 def get_outgoings(self, node):
     '''get the outgoings list of the xml-node.
     create instances of uml_activity_diagram_element.Outgoing
     outgoing = uml_activity_diagram_element.Outgoing(xmi_idref)
     and put them in the outgoings list
     @param node: xml node
     @type node: xml.dom.Node (attention: it is not a instance of
         uml_activity_diagram_element.ActivityNode)
     @return: outgoings
     @rtype: list [instance1 of uml_activity_diagram_element.Outgoing,
         instance2 of uml_activity_diagram_element.Outgoing...]
     '''
     outgoings = []
     # get the outgoings of the node
     node_outgoings = self.get_child_nodes(node, 'outgoing')
     # outgoingsTag = node.getElementsByTagName('outgoing')
     for node_outgoing in node_outgoings:
         if node_outgoing.hasAttribute("xmi:idref"):
             xmi_idref = node_outgoing.getAttribute("xmi:idref")
             outgoing = uml_element.Outgoing(xmi_idref)
             if outgoing not in outgoings:
                 outgoings.append(outgoing)
         else:
             log.show_error("node's outgoing has no id")
     return outgoings
 def _get_nodes_from_edge(self, edge, activity):
     """get the node1, node2 from the edge.
     also, node1-->edge-->node2
     @param edge: a edge instance in activity
     @type edge: a instance of edge, not the id of the edge
     """
     nodes_dict = activity.nodes_dict
     pins_dict = activity.pins_dict
     # node1 and node2
     node1 = None
     node2 = None
     # the id of source and target
     source = edge.source
     target = edge.target
     # if source is node_id
     if source in nodes_dict:
         node1 = nodes_dict[source]
     else:
         # source is pout id
         pin = pins_dict[source]
         node1_id = pin.host
         node1 = nodes_dict[node1_id]
     # if target is node_id
     if target in nodes_dict:
         node2 = nodes_dict[target]
     else:
         # target is pin id
         pin = pins_dict[target]
         node2_id = pin.host
         node2 = nodes_dict[node2_id]
     # if node1 or node2 is None,it is error
     if node1 is None or node2 is None:
         log.show_error("the node1 or node2 is None")
     return node1, node2
Example #10
0
 def get_outgoings(self, node):
     """get the outgoings list of the xml-node.
     create instances of uml_activity_diagram_element.Outgoing
     outgoing = uml_activity_diagram_element.Outgoing(xmi_idref)
     and put them in the outgoings list
     @param node: xml node
     @type node: xml.dom.Node (attention: it is not a instance of
         uml_activity_diagram_element.ActivityNode)
     @return: outgoings
     @rtype: list [instance1 of uml_activity_diagram_element.Outgoing,
         instance2 of uml_activity_diagram_element.Outgoing...]
     """
     outgoings = []
     # get the outgoings of the node
     node_outgoings = self.get_child_nodes(node, "outgoing")
     # outgoingsTag = node.getElementsByTagName('outgoing')
     for node_outgoing in node_outgoings:
         if node_outgoing.hasAttribute("xmi:idref"):
             xmi_idref = node_outgoing.getAttribute("xmi:idref")
             outgoing = uml_element.Outgoing(xmi_idref)
             if outgoing not in outgoings:
                 outgoings.append(outgoing)
         else:
             log.show_error("node's outgoing has no id")
     return outgoings
Example #11
0
    def draw_petri_net(self, petri_net):
        '''draw Petri Net from the 3 dicts
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict
        # G=pgv.AGraph(directed=True,strict=True,splines="polyline")
        # G = pgv.AGraph(directed=True, strict=True, splines=False)
        G = pgv.AGraph(directed=True, strict=True)
        G.graph_attr['label'] = petri_net.label + petri_net.probs

        for pt_id in places_dict:
            place = places_dict[pt_id]
            place_xlabel = place.xlabel
            G.add_node(pt_id, shape="circle", label="", xlabel=place_xlabel)
        for pt_id in transitions_dict:
            transition = transitions_dict[pt_id]
            # get the max number of the incomings and outgoings
            number = max(len(transition.incomings), len(transition.outgoings))
            transition_width = 0.5 * number
            transition_xlabel = transition.xlabel

            transition_type = transition.transition_type
            # Deterministic transitions are drawn as black filled rectangles.
            if transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                G.add_node(pt_id, shape="box", style="filled", label="", \
                            xlabel=transition_xlabel, height=0.3, \
                            width=transition_width, fillcolor="#000000")  # color:black
            # Exponential transitions are drawn as empty rectangles.
            elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                G.add_node(pt_id, shape="box", label="",
                           xlabel=transition_xlabel, height=0.3,
                           width=transition_width, fillcolor="#000000")  # color:black
            # Immediate transitions are drawn as thin bars.
            elif transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                G.add_node(pt_id, shape="box", style="filled", label="",
                           xlabel=transition_xlabel, height=0.08,
                           width=transition_width, fillcolor="#000000")  # color:black
            else:
                log.show_error("the transition type is not defined")
        for pt_id in arcs_dict:
            arc = arcs_dict[pt_id]
            source = arc.source
            target = arc.target
            G.add_edge(source, target)
            # draw the arc with probability
            # if arc.prob == 1:
            #    G.add_edge(source, target)
            # else:
            #    G.add_edge(source, target, label=arc.prob)

        # print G.string()  # print dot file to standard output
        png_name = self.get_png_name()
        # G.write("Pt"+png_name + ".dot")
        G.layout('dot')  # layout with dot
        G.draw("Pt" + "_" + petri_net.name + png_name + ".png")  # write to file
        log.show_info("the Petri Net Diagram is created.name:%s" % petri_net.name)
Example #12
0
 def _scan(self, buf):
     text = zlib.decompress(buf)
     content = json.loads(text)
     if not content or type(content) != dict:
         show_error(self, 'invalid content')
         return
     files = self._extract(content)
     if files:
         if not self._do_scan(files):
             raise Exception('this package contains invalid files')
     return content.get('description')
Example #13
0
 def _extract(self, content):
     if content.get('app'):
         files = content.get('app')
     elif content.get('driver'):
         files = content.get('driver')
     else:
         show_error(self, 'cannot extract')
         return
     filenames = filter(lambda f: f.endswith('.py'), files)
     info = {}
     for name in filenames:
         file = files.get(name)
         info.update({name: file})
     return info
Example #14
0
    def _get_cf_prob_from_text(self, guard):
        '''get the cf_prob from text of guard.
        for example: 
        [...prob:0.25]
        [...prob=0.25]
        [...pro:0.25]
        [...pro=0.25]
        [...pr:0.25]
        [...pr=0.25]
        '''
        prob = 1
        if guard is None:
            # cf_prob is default 1, also edge.prob =1
            return 1
        # delete the " "
        guard_body = guard.body.replace(' ', '')
        possibles = ["prob:", "prob=", "pro:", "pro=", "pr:", "pr="]
        index = -1
        for possible_str in possibles:
            # find it from right
            index = guard_body.rfind(possible_str)
            if index != -1:
                # the length
                num = len(possible_str)
                break

        if index != -1:
            # find the number_str, such as "0.5"
            prob_str = guard_body[(index + num):]
            try:
            # str to float
                prob = float(prob_str)
            except ValueError:
                log.show_error("the prob is invalid,Please modify it " + prob_str)
            # if it is less than 0 or more than one
            if (prob <= 0.0) or (prob > 1.0):
                log.show_error("the prob should be a number between 0 and 1")
            # if it is not default one
            if prob != 1:
                # show info
                log.show_info("the guard:%s, has cf_prob:%f" % (guard_body, prob))
        return prob
Example #15
0
    def _get_cf_prob_from_text(self, guard):
        """get the cf_prob from text of guard.
        for example: 
        [...prob:0.25]
        [...prob=0.25]
        [...pro:0.25]
        [...pro=0.25]
        [...pr:0.25]
        [...pr=0.25]
        """
        prob = 1
        if guard is None:
            # cf_prob is default 1, also edge.prob =1
            return 1
        # delete the " "
        guard_body = guard.body.replace(" ", "")
        possibles = ["prob:", "prob=", "pro:", "pro=", "pr:", "pr="]
        index = -1
        for possible_str in possibles:
            # find it from right
            index = guard_body.rfind(possible_str)
            if index != -1:
                # the length
                num = len(possible_str)
                break

        if index != -1:
            # find the number_str, such as "0.5"
            prob_str = guard_body[(index + num) :]
            try:
                # str to float
                prob = float(prob_str)
            except ValueError:
                log.show_error("the prob is invalid,Please modify it " + prob_str)
            # if it is less than 0 or more than one
            if (prob <= 0.0) or (prob > 1.0):
                log.show_error("the prob should be a number between 0 and 1")
            # if it is not default one
            if prob != 1:
                # show info
                log.show_info("the guard:%s, has cf_prob:%f" % (guard_body, prob))
        return prob
Example #16
0
def calculate_probability(lam1, distributions):
    '''calculate the probability with 2 exponential distributions.
    for example: calculate_probability(10,[10,20])
    '''
    # calculate with 2 exponential distributions
    if len(distributions) != 2:
        log.show_error("it can just calculate with 2 exponential distributions")
    if lam1 not in distributions:
        log.show_error("lam1 is not in the tup")
    lam2 = 0
    # get the first number, if it equals lam1, set the second number to lam2
    # if it not equals lam1, set it to lam2
    temp = distributions[0]
    if temp == lam1:
        lam2 = distributions[1]
    else:
        lam2 = temp

    pro = float(lam2) / (lam1 + lam2)  
    pro = round(pro, 3)

    return pro  
 def _get_object_next_node(self, object_node, activity):
     """get the action or control node after the object node.
     """
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     node = None
     outgoings = object_node.outgoings
     num = len(outgoings)
     if num == 0:
         log.show_warn("the object node has no ougoings")
     elif num == 1:
         outgoing = outgoings[0]
         edge_id = outgoing.xmi_idref
         edge = edges_dict[edge_id]
         node_id = edge.target
         node = nodes_dict[node_id]
     elif num > 1:
         log.show_error("the object node has more ougoings")
     # if the node after the object node is also object node.show error
     if isinstance(node, uml_element.ObjectNode):
         log.show_error("the node after the object node:%s is object node" % str(object_node.name))
     return node
Example #18
0
    def set_next_place_tokens(self, place, tokens_num, petri_net):
        '''set the place.max_tokens after the place.
        tokens_num = place.max_tokens
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        place_outgoings = place.outgoings
        for place_outgoing in place_outgoings:
            arc1 = arcs_dict[place_outgoing]
            next_transiton_id = arc1.target
            next_transition = transitions_dict[next_transiton_id]
            for transition_outgoing in next_transition.outgoings:
                arc2 = arcs_dict[transition_outgoing]
                next_place_id = arc2.target
                # get the next_place after the place
                next_place = places_dict[next_place_id]
                if next_place.max_tokens == 1:
                    next_place.max_tokens = tokens_num
                    self.set_next_place_tokens(next_place, tokens_num, petri_net)
                else:
                    log.show_error("the place.max_tokens is already not 1 ")
Example #19
0
def calculate_probability(lam1, distributions):
    '''calculate the probability with 2 exponential distributions.
    for example: calculate_probability(10,[10,20])
    '''
    # calculate with 2 exponential distributions
    if len(distributions) != 2:
        log.show_error(
            "it can just calculate with 2 exponential distributions")
    if lam1 not in distributions:
        log.show_error("lam1 is not in the tup")
    lam2 = 0
    # get the first number, if it equals lam1, set the second number to lam2
    # if it not equals lam1, set it to lam2
    temp = distributions[0]
    if temp == lam1:
        lam2 = distributions[1]
    else:
        lam2 = temp

    pro = float(lam2) / (lam1 + lam2)
    pro = round(pro, 3)

    return pro
 def _get_object_next_node(self, object_node, activity):
     '''get the action or control node after the object node.
     '''
     nodes_dict = activity.nodes_dict
     edges_dict = activity.edges_dict
     node = None
     outgoings = object_node.outgoings
     num = len(outgoings)
     if num == 0:
         log.show_warn("the object node has no ougoings")
     elif num == 1:
         outgoing = outgoings[0]
         edge_id = outgoing.xmi_idref
         edge = edges_dict[edge_id]
         node_id = edge.target
         node = nodes_dict[node_id]
     elif num > 1:
         log.show_error("the object node has more ougoings")
     # if the node after the object node is also object node.show error
     if isinstance(node, uml_element.ObjectNode):
         log.show_error("the node after the object node:%s is object node" %
                        str(object_node.name))
     return node
Example #21
0
    def set_next_place_tokens(self, place, tokens_num, petri_net):
        '''set the place.max_tokens after the place.
        tokens_num = place.max_tokens
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        place_outgoings = place.outgoings
        for place_outgoing in place_outgoings:
            arc1 = arcs_dict[place_outgoing]
            next_transiton_id = arc1.target
            next_transition = transitions_dict[next_transiton_id]
            for transition_outgoing in next_transition.outgoings:
                arc2 = arcs_dict[transition_outgoing]
                next_place_id = arc2.target
                # get the next_place after the place
                next_place = places_dict[next_place_id]
                if next_place.max_tokens == 1:
                    next_place.max_tokens = tokens_num
                    self.set_next_place_tokens(next_place, tokens_num,
                                               petri_net)
                else:
                    log.show_error("the place.max_tokens is already not 1 ")
Example #22
0
 def get_time(self, str_time):
     """get the real time.
     @param str_time: the time str, such as "20ms","25s"
     @type str_time: str
     @return: time
     @rtype: float
     """
     if str_time is None:
         return
     original_str = str_time
     time = None
     unit = None
     # factor: ms-->0.01, s-->1, min-->60
     # default is "s"
     factor = None
     # delete all ' ', for example " 20 m s"-->"20ms"
     str_time = str_time.replace(" ", "")
     # if it is ""
     if len(str_time) == 0:
         log.show_error("the time is empty string,Please modify it ")
     elif str_time.endswith("ms"):
         unit = "ms"
         factor = 0.001
     elif str_time.endswith("s"):
         unit = "s"
         factor = 1
     elif str_time.endswith("min"):
         unit = "min"
         factor = 60
     elif str_time.endswith("h"):
         unit = "h"
         factor = 60 * 60
     elif str_time.endswith("d"):
         unit = "d"
         factor = 60 * 60 * 24
     elif str_time.endswith("mon"):
         unit = "mon"
         factor = 60 * 60 * 24 * 30
     elif str_time.endswith("y"):
         unit = "y"
         factor = 60 * 60 * 24 * 30 * 12
     else:
         log.show_error("the unit of the time is invalid,Please modify it " + original_str)
         exit(0)
     # delete the unit from the right end of the str_time
     str_time = str_time.rstrip(unit)
     try:
         # str to float
         time = float(str_time)
     except ValueError:
         log.show_error("the time is invalid,Please modify it " + original_str)
     time = time * factor
     return time
Example #23
0
 def get_time(self, str_time):
     '''get the real time.
     @param str_time: the time str, such as "20ms","25s"
     @type str_time: str
     @return: time
     @rtype: float
     '''
     if str_time is None:
         return
     original_str = str_time
     time = None
     unit = None
     # factor: ms-->0.01, s-->1, min-->60
     # default is "s"
     factor = None
     # delete all ' ', for example " 20 m s"-->"20ms"
     str_time = str_time.replace(' ', '')
     # if it is ""
     if len(str_time) == 0:
         log.show_error("the time is empty string,Please modify it ")
     elif str_time.endswith('ms'):
         unit = "ms"
         factor = 0.001
     elif str_time.endswith('s'):
         unit = "s"
         factor = 1
     elif str_time.endswith('min'):
         unit = "min"
         factor = 60
     elif str_time.endswith('h'):
         unit = "h"
         factor = 60 * 60
     elif str_time.endswith('d'):
         unit = "d"
         factor = 60 * 60 * 24
     elif str_time.endswith('mon'):
         unit = "mon"
         factor = 60 * 60 * 24 * 30
     elif str_time.endswith('y'):
         unit = "y"
         factor = 60 * 60 * 24 * 30 * 12
     else:
         log.show_error("the unit of the time is invalid,Please modify it " + original_str)
         exit(0)
     # delete the unit from the right end of the str_time
     str_time = str_time.rstrip(unit)
     try:
         # str to float
         time = float(str_time)
     except ValueError:
         log.show_error("the time is invalid,Please modify it " + original_str)
     time = time * factor
     return time
Example #24
0
    def xml_parse(self, xml_path):
        """start the parsing
        @param xml_path: the path of the xml
        @attention: the different between windows and Linux
        """
        # use minidom to open the xml
        try:
            DOMTree = minidom.parse(xml_path)
            # collection = DOMTree.documentElement
        except IOError:
            log.show_error("the xml is wrong")

        # get the root tag of the xml
        root = DOMTree.documentElement

        # get the tag: <xmi:Documentation>
        # get the exporter(Magic Draw or EA) and exporterVersion
        documentation = self.get_child_nodes(root, "xmi:Documentation")[0]
        exporter, export_version = self.get_exporter_version(documentation)

        log.show_info("exporter:" + exporter + ".exportVersion:" + export_version)

        # get <uml:Model  />
        model_node = self.get_child_nodes(root, "uml:Model")[0]
        # the 4 parameters: xmi_id, xmi_type, name, activitys_dict
        xmi_id, name, xmi_type = self.get_id_name_type(model_node)

        activitys_dict = {}
        # create the model
        model = uml_element.Model(xmi_id, xmi_type, name, activitys_dict)
        # get <packagedElement>
        # packaged_elements = self.get_child_nodes(model_node, "packagedElement")
        packaged_elements = model_node.getElementsByTagName("packagedElement")

        InstanceSpecification_nodes = []
        activity_id = None
        for packaged_element in packaged_elements:
            xmi_id, name, xmi_type = self.get_id_name_type(packaged_element)
            # get the activity diagram "uml:Activity"
            if xmi_type == uml_element.Types.ACTIVITY:
                # xmi_id:ActivityNode (class UmlActivityDiagramElement.ActivityNode)
                nodes_dict = {}
                # xmi_id:ActivityEdge (class uml_activity_diagram_element.ActivityEdge)
                edges_dict = {}
                # Result and Argument
                pins_dict = {}
                # create activity
                activity = uml_element.Activity(xmi_id, xmi_type, name, nodes_dict, edges_dict, pins_dict)
                # put it in the activitys_dict
                activitys_dict[xmi_id] = activity
                # activity_id
                activity_id = xmi_id
                # get all the nodes
                nodes = self.get_child_nodes(packaged_element, "node")
                # get every node
                for node in nodes:
                    # get the id, name, type of the node
                    xmi_id, name, xmi_type = self.get_id_name_type(node)
                    # get behavior
                    behavior = self.get_behavior(node)
                    # get incomings of the node
                    incomings = self.get_incomings(node)
                    # get outgoings of the node
                    outgoings = self.get_outgoings(node)
                    # get the results of the node
                    results = self.get_results(node, xmi_id)
                    # get the arguments of the node
                    arguments = self.get_arguments(node, xmi_id)
                    # create node object
                    self.create_node_object(
                        nodes_dict, xmi_id, xmi_type, name, incomings, outgoings, results, arguments, behavior
                    )
                    # put all the results and arguments in the pins_dict
                    # if not all empty
                    if results or arguments:
                        self.__set_pins_dict(pins_dict, results, arguments)
                # get all the edges
                edges = self.get_child_nodes(packaged_element, "edge")
                # get every node
                for edge in edges:
                    # get the id,name,type of the edge
                    xmi_id, name, xmi_type = self.get_id_name_type(edge)
                    # get the target, source of the edge
                    target, source = self.get_target_source(edge)
                    # get the guard of the edge
                    guard = self.get_guard(edge)
                    # create edge object
                    self.create_edge_object(edges_dict, xmi_id, xmi_type, name, target, source, guard)
            # <packagedElement name="UserData" xmi:type="uml:InstanceSpecification" xmi:id="EAID_C3D4C"/>
            elif xmi_type == "uml:InstanceSpecification":
                InstanceSpecification_node = uml_element.InstanceSpecification_node(xmi_id, xmi_type, name, [], [])
                InstanceSpecification_nodes.append(InstanceSpecification_node)

        for InstanceSpecification_node in InstanceSpecification_nodes:
            model.activitys_dict[activity_id].nodes_dict[InstanceSpecification_node.xmi_id] = InstanceSpecification_node

        if exporter == "MagicDraw UML":
            # time parser
            data_times = self.get_child_nodes(root, "Data:Time")
            for data_time in data_times:
                str_time, base_element, time_type = self.get_time_base_element(data_time)
                self.set_time(str_time, base_element, time_type, model)

            # for from EA imported xml
            thecustomprofile_times = self.get_child_nodes(root, "thecustomprofile:time")
            for thecustomprofile_time in thecustomprofile_times:
                str_time, base_element, time_type = self.get_time_base_element(thecustomprofile_time)
                self.set_time(str_time, base_element, time_type, model)

        elif exporter == "Enterprise Architect":
            # get the tag "time" for EA
            extension = self.get_child_nodes(root, "xmi:Extension")[0]
            elements = self.get_child_nodes(extension, "elements")[0]
            element_tags = self.get_child_nodes(elements, "element")
            for element in element_tags:
                tags = self.get_child_nodes(element, "tags")
                if len(tags) > 0:
                    tags = tags[0]
                    tag_elements = self.get_child_nodes(tags, "tag")
                    for tag in tag_elements:
                        if tag.hasAttribute("name"):
                            name = tag.getAttribute("name")
                            if name == "time":
                                if tag.hasAttribute("value"):
                                    str_time = tag.getAttribute("value")
                                    base_element = element.getAttribute("xmi:idref")
                                    # TODO
                                    self.set_time(str_time, base_element, "exp", model)
        else:
            log.show_error("the exporter is not supported in the code")

        return model
    def get_next_state(self, places, transitions, petri_net, rg_graph, unreach_list, reach, probs):
        '''fire t and determine the marking m' after firing.
        1b).if 2 transitions t1,t2 can be enabled, so from the node < m > will create 2 arrows.
        fire t1,go to step2(until stop),then fire t2, go to step2.
        step2. fire t and determine the marking m' after firing. if m' is already a node in G,
        then add the new arrow(m,t,m') to G, stop.
        step3. if m' is not a node in G, add m' as a new node and (m,t,m')
        as a new arrow to G and go to step 1.
        get the next states, it can be more states.
        @param places: the current marked places,pre-places
        @type places: list
        '''

        places_dict = petri_net.places_dict
        arcs_dict = petri_net.arcs_dict
        states_dict = rg_graph.states_dict
        edges_dict = rg_graph.edges_dict

        # pre_state_id: '<s1,s2>'
        pre_state_id = self.get_state_id(places, petri_net)

        reset_tokens = False

        # parallel, or decision
        if len(transitions) > 1:

            reset_tokens = True
            tokens_list = [place.tokens for place in places]

        if pre_state_id not in states_dict:
            pre_state = Rg.State(pre_state_id, pre_state_id, [], [])
            states_dict[pre_state_id] = pre_state
            # it is for unreach diagram, show in color blue
            if not reach:
                pre_state.reachability = False
        else:
            pre_state = states_dict[pre_state_id]
        # every time just one transition can be enabled.
        index = -1
        for transition in transitions:
            index += 1
            # reset the places 's tokens
            if reset_tokens:
                self.reset_tokens(places, tokens_list, places_dict)

            # get the next state-places, change id, and get the state id
            next_places = self.determine_marking(places, transition, places_dict, arcs_dict)
            for place in next_places:
                if not place.id_changed:
                    self.change_pt_id(place, places_dict, arcs_dict, petri_net)
            next_state_id = self.get_state_id(next_places, petri_net)
            # "<p1,p2><p3>"
            # edge_id = "pre_state_id + next_state_id"
            # "edge0","edge1","edge2","edge3"...
            edge_id = "edge" + str(len(edges_dict))
            if edge_id not in edges_dict:
                # pre_state.outgoings is list, append the edge_id
                pre_state.outgoings.append(edge_id)
                edge = Rg.Edge(edge_id, edge_id, pre_state_id, next_state_id)
                # TODO
                edge.prob = probs[index]
                edge.label = transition.pt_id + "(" + str(edge.prob) + ")"
                edges_dict[edge_id] = edge
                #
                if not reach:
                    edge.reachability = False
            # multiedge, for example, p4-t5-p5,p4-t6-p5,p4-t7-p5
            else:
                log.show_error("edge id error in RG")
                # edge = edges_dict[edge_id]
                # edge.label = edge.label + " or " + transition.pt_id

            # step 3. if m' is not a node in G
            if next_state_id not in states_dict:
                next_state = Rg.State(next_state_id, next_state_id, [], [])
                # pre_state.incomings is list, append the edge_id
                next_state.incomings.append(edge_id)
                states_dict[next_state_id] = next_state
                #
                if not reach:
                    next_state.reachability = False
            # if m' is already a node in G,then add the new arrow(m,t,m') to G, stop.
            else:
                # next state exist, just incomings append the edge_id
                next_state = states_dict[next_state_id]
                if edge_id not in next_state.incomings:
                    next_state.incomings.append(edge_id)
                continue
            # step 3a) if m' has final node, stop
            if self.final_in_places(next_places):
                continue
            if len(next_places) > 0:
                # go to step 1
                self.find_enabled_transitions(next_places, petri_net, rg_graph, unreach_list, reach)
    def find_enabled_transitions(self, places, petri_net, rg_graph, unreach_list, reach):
        ''' first,get the next following transition from the current marked places,
        second, see if it can be enabled(see function-is_transition_enabled),
        and save the transitions in one list, for example [s1,s2]
        @param places: the current marked places,pre-places
        @type places: list
        @param reach: True, for the reachability_graph diagram.
        False, unreach_list=[],for the unreachability_graph.
        @type reach: Boolean
        @see: algorithm- step1
        '''
        # [t1,t2,t3...]
        transitions = []
        # [[t1],[t2,t3]...]
        # t1 fire from place1, t2,t3 fire from place2(decision)
        transitions_slices = []
        # the probs to fire the transition
        # [prob1,prob2,prob3...], the sum must be 1
        probs = []
        # [[prob1],[prob2,prob3]...]
        # prob1 is 1, sum of prob2 and prob3 is 1
        probs_slices = []
        # petri_net
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        # get the next transition from the place, and see if it can be enabled
        for place in places:
            # [t1] or [t2,t3]
            transitions_slice = []
            # [1] or [0.3,0.7]
            probs_slice = []
            outgoings = place.outgoings
            for outgoing in outgoings:
                arc = arcs_dict[outgoing]
                target = arc.target
                transition = transitions_dict[target]
                # if the transition can be enabled
                if self.is_transition_enabled(transition, places, places_dict, arcs_dict):
                    # get the prob from the arc
                    prob = arc.prob
                    # put the transition in the transitions_slice
                    if transition not in transitions_slice:
                        transitions_slice.append(transition)
                        # put the prob in the probs_slice
                        probs_slice.append(prob)
                    else:
                        # show error
                        log.show_error("more than 1 arcs between the place and the transition:find_enabled_transitions()")
                    # put it in the transitions
                    if transition not in transitions:
                        transitions.append(transition)
                        probs.append(prob)
                    # change the id of transition,which can be enabled
                    if not transition.id_changed:
                        self.change_pt_id(transition, transitions_dict, arcs_dict, petri_net)
            # if it is not []
            if transitions_slice:
                transitions_slices.append(transitions_slice)
                probs_slices.append(probs_slice)
        if reach:
            # parallel find the min(delay), 
            # if just decision len(transitions) > 1 and len(transitions_slices)=1
            # if len(transitions_slices) > 1, but len(transitions) = 1-->join:
            # len(transitions_slices) >1 ,-->parallel
            if len(transitions) > 1 and len(transitions_slices) > 1:
                # delete the same type
                types_set = set([transition.transition_type for transition in transitions])
                types_list = list(types_set)
                # TODO
                if len(types_list) == 1:
                    # get the type of the transitions
                    transition_type = types_list[0]

                    # all are immediate transition
                    if transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                        pass
                    # all are DeterministicTransition
                    elif transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                        execute_transition = self.get_execute_transition(transitions)

                        transitions.remove(execute_transition)
                        #
                        tokens_list = [place.tokens for place in places]
                        unreach_list.append(places)
                        unreach_list.append(tokens_list)
                        unreach_list.append(transitions)
                        #
                        transitions = [execute_transition]
                    # all are EXPONENTIAL_TRANSITION
                    elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                        if len(transitions_slices) == 2:
                            self._calculate_probability(transitions_slices, probs_slices, transitions, probs)
                        else:
                            log.show_error("the code can not analyse 3 parallel exp distribution process")
                    else:
                        log.show_error("the type of the transition is not defined")

                # all are ExponentialTransition
                else:
                    log.show_warn("the types of the enabled transitions are not the same")

        # see algorithm- step1a)
        if len(transitions) > 0:
            # fire t and determine the marking m' after firing.
            self.get_next_state(places, transitions, petri_net, rg_graph, unreach_list, reach, probs)
    def check_names(self, activity):
        """check the name of action and object.
        1.if it is None or "",it will cause a error when it transforms to epf.
        set the name "node1","node2"
        2.if two nodes(action or object) have the same name, it will also cause a error
        when it transforms to epf. for example "get info" and "get_info"
        3.change the name to the corrected name
        # TODO check the name of pin
        @return: check_ok, if checks ok
        @rtype: boolean
        """
        check_ok = True
        names = []
        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict

        # action, object, initial, final
        node_types = (
            uml_element.ExecutableNode,
            uml_element.ObjectNode,
            uml_element.InitialNode,
            uml_element.FinalNode,
            uml_element.Fork,
            uml_element.Join,
        )
        # for node
        num1 = 0
        # for pin,pout
        num2 = 0
        # it checks the name of pout, do not need to check the name of pin
        for pin_id in pins_dict:
            pin = pins_dict[pin_id]
            # if it is a pout(Result)
            if isinstance(pin, uml_element.Result):
                name = pin.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the pin has no name, set the name "pin1","pin2"...
                    num2 += 1
                    pin.name = "pin" + str(num2)
                    log.show_warn("the pin has no name.id:%s" % pin.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    pin.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the pin has the same name.name:%s" % name)
                    else:
                        names.append(corrected_name)

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is a action or object,initial,final
            # The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
            # isinstance(x, A) or isinstance(x, B) or ... (etc.).
            if isinstance(node, node_types):
                name = node.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the node has no name, set the name "node1","node2"...
                    num1 += 1
                    node.name = "node" + str(num1)
                    log.show_warn("the node has no name.id:%s" % node.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    node.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the nodes has the same name.name:%s" % name)
                    else:
                        names.append(corrected_name)
        return check_ok
    def get_init_final_num(self, activity):
        """ verify, if the uml activity diagram has just(genau)
        one Initial Node, and one or more ActivityFinal. if a node has no incoming or no outgoing,
        it is a error, except init node and final node and flow final.
        """
        nodes_dict = activity.nodes_dict
        initial_num = 0
        final_num = 0
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            incomings = node.incomings
            outgoings = node.outgoings
            in_num = len(incomings)
            out_num = len(outgoings)
            # initial node, just one and it must have outgoing
            if node.xmi_type == uml_element.Types.INITIAL_NODE:
                initial_num += 1
                if out_num == 0:
                    log.show_error(
                        "the Initial Node has no outgoing." + "name:" + str(node.name) + " id:" + node.xmi_id
                    )
            # final node, one or more, and it must have incoming
            elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                final_num += 1
                if in_num == 0:
                    log.show_error("the final Node has no incoming." + "name:" + str(node.name) + " id:" + node.xmi_id)
            # flow final, it must have incoming
            elif node.xmi_type == uml_element.Types.FLOW_FINAL_NODE:
                if len(incomings) == 0:
                    log.show_error("the final Node has no incoming." + "name:" + str(node.name) + " id:" + node.xmi_id)
            elif isinstance(node, uml_element.ObjectNode):
                if not isinstance(node, uml_element.InstanceSpecification_node):
                    if len(incomings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn("the object Node has no incoming.name:%s,id:%s" % (str(node.name), node.xmi_id))
                    if len(outgoings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn("the object Node has no outgoins.name:%s,id:%s" % (str(node.name), node.xmi_id))
            # if the node has no incoming or no outgoing
            # it is a error(except initial,final,object node)
            else:
                # incoming and outgoing of a node
                if in_num == 0:
                    # action has no incoming, but it has argument, and the argument has incoming
                    if isinstance(node, uml_element.ExecutableNode):
                        arguments = node.arguments
                        for argument in arguments:
                            # if the argument has no incoming
                            if len(argument.incomings) == 0:
                                log.show_error(
                                    "the action node's argument in "
                                    + "uml activity diagram has no incoming."
                                    + "name:"
                                    + str(node.name)
                                    + " id:"
                                    + node.xmi_id
                                )
                    # it is not a action
                    else:
                        log.show_error(
                            "the node in uml activity diagram has no incoming."
                            + "name:"
                            + str(node.name)
                            + " id:"
                            + node.xmi_id
                        )
                if out_num == 0:
                    # action has no outgoing, but it has result, and the result has outgoing
                    if isinstance(node, uml_element.ExecutableNode):
                        results = node.results
                        for result in results:
                            # if the result has no outgoing
                            if len(result.outgoings) == 0:
                                log.show_error(
                                    "the action node's result in "
                                    + "uml activity diagram has no incoming."
                                    + +"name:"
                                    + str(node.name)
                                    + " id:"
                                    + node.xmi_id
                                )
                    # it is not a action
                    else:
                        log.show_error(
                            "the node in uml activity diagram has no outgoing."
                            + "name:"
                            + str(node.name)
                            + " id:"
                            + node.xmi_id
                        )
        # initial node just one
        if initial_num == 0:
            log.show_error("the uml activity diagram has no Initial Node")
        elif initial_num > 1:
            log.show_error("the uml activity diagram has " + str(initial_num) + " Initial Nodes")
        # final node one or more than one
        if final_num == 0:
            log.show_warn("the uml activity diagram has no final Node")

        return initial_num, final_num
Example #29
0
    def xml_parse(self, xml_path):
        '''start the parsing
        @param xml_path: the path of the xml
        @attention: the different between windows and Linux
        '''
        # use minidom to open the xml
        try:
            DOMTree = minidom.parse(xml_path)
            # collection = DOMTree.documentElement
        except IOError:
            log.show_error("the xml is wrong")

        # get the root tag of the xml
        root = DOMTree.documentElement

        # get the tag: <xmi:Documentation>
        # get the exporter(Magic Draw or EA) and exporterVersion
        documentation = self.get_child_nodes(root, "xmi:Documentation")[0]
        exporter, export_version = self.get_exporter_version(documentation)

        log.show_info("exporter:" + exporter + ".exportVersion:" + export_version)

        # get <uml:Model  />
        model_node = self.get_child_nodes(root, "uml:Model")[0]
        # the 4 parameters: xmi_id, xmi_type, name, activitys_dict
        xmi_id, name, xmi_type = self.get_id_name_type(model_node)

        activitys_dict = {}
        # create the model
        model = uml_element.Model(xmi_id, xmi_type, name, activitys_dict)
        # get <packagedElement>
        # packaged_elements = self.get_child_nodes(model_node, "packagedElement")
        packaged_elements = model_node.getElementsByTagName("packagedElement")


        InstanceSpecification_nodes = []
        activity_id = None
        for packaged_element in packaged_elements:
            xmi_id, name, xmi_type = self.get_id_name_type(packaged_element)
            # get the activity diagram "uml:Activity"
            if xmi_type == uml_element.Types.ACTIVITY:
                # xmi_id:ActivityNode (class UmlActivityDiagramElement.ActivityNode)
                nodes_dict = {}
                # xmi_id:ActivityEdge (class uml_activity_diagram_element.ActivityEdge)
                edges_dict = {}
                # Result and Argument
                pins_dict = {}
                # create activity
                activity = uml_element.Activity(xmi_id, xmi_type, name,
                                                nodes_dict, edges_dict, pins_dict)
                # put it in the activitys_dict
                activitys_dict[xmi_id] = activity
                # activity_id
                activity_id = xmi_id
                # get all the nodes
                nodes = self.get_child_nodes(packaged_element, "node")
                # get every node
                for node in nodes:
                    # get the id, name, type of the node
                    xmi_id, name, xmi_type = self.get_id_name_type(node)
                    # get behavior
                    behavior = self.get_behavior(node)
                    # get incomings of the node
                    incomings = self.get_incomings(node)
                    # get outgoings of the node
                    outgoings = self.get_outgoings(node)
                    # get the results of the node
                    results = self.get_results(node, xmi_id)
                    # get the arguments of the node
                    arguments = self.get_arguments(node, xmi_id)
                    # create node object
                    self.create_node_object(nodes_dict, xmi_id, xmi_type, name, \
                                           incomings, outgoings, results, arguments, behavior)
                    # put all the results and arguments in the pins_dict
                    # if not all empty
                    if (results or arguments):
                        self.__set_pins_dict(pins_dict, results, arguments)
                # get all the edges
                edges = self.get_child_nodes(packaged_element, "edge")
                # get every node
                for edge in edges:
                    # get the id,name,type of the edge
                    xmi_id, name, xmi_type = self.get_id_name_type(edge)
                    # get the target, source of the edge
                    target, source = self.get_target_source(edge)
                    # get the guard of the edge
                    guard = self.get_guard(edge)
                    # create edge object
                    self.create_edge_object(edges_dict, xmi_id, xmi_type, name, \
                                           target, source, guard)
            # <packagedElement name="UserData" xmi:type="uml:InstanceSpecification" xmi:id="EAID_C3D4C"/>
            elif xmi_type == "uml:InstanceSpecification":
                InstanceSpecification_node = uml_element.InstanceSpecification_node(xmi_id, xmi_type, name, [], [])
                InstanceSpecification_nodes.append(InstanceSpecification_node)
        
        for InstanceSpecification_node in InstanceSpecification_nodes:
            model.activitys_dict[activity_id].nodes_dict[InstanceSpecification_node.xmi_id] = InstanceSpecification_node
        
        if exporter == "MagicDraw UML":
            # time parser
            data_times = self.get_child_nodes(root, "Data:Time")
            for data_time in data_times:
                str_time, base_element , time_type = self.get_time_base_element(data_time)
                self.set_time(str_time, base_element, time_type, model)

            # for from EA imported xml
            thecustomprofile_times = self.get_child_nodes(root, "thecustomprofile:time")
            for thecustomprofile_time in thecustomprofile_times:
                str_time, base_element, time_type = self.get_time_base_element(thecustomprofile_time)
                self.set_time(str_time, base_element, time_type, model)

        elif exporter == "Enterprise Architect":
            # get the tag "time" for EA
            extension = self.get_child_nodes(root, "xmi:Extension")[0]
            elements = self.get_child_nodes(extension, "elements")[0]
            element_tags = self.get_child_nodes(elements, "element")
            for element in element_tags:
                tags = self.get_child_nodes(element, "tags")
                if len(tags) > 0:
                    tags = tags[0]
                    tag_elements = self.get_child_nodes(tags, "tag")
                    for tag in tag_elements:
                        if tag.hasAttribute("name"):
                            name = tag.getAttribute("name")
                            if name == "time":
                                if tag.hasAttribute("value"):
                                    str_time = tag.getAttribute("value")
                                    base_element = element.getAttribute("xmi:idref")
                                    # TODO 
                                    self.set_time(str_time, base_element, "exp", model)
        else:
            log.show_error("the exporter is not supported in the code")

        return model
    def check_names(self, activity):
        '''check the name of action and object.
        1.if it is None or "",it will cause a error when it transforms to epf.
        set the name "node1","node2"
        2.if two nodes(action or object) have the same name, it will also cause a error
        when it transforms to epf. for example "get info" and "get_info"
        3.change the name to the corrected name
        # TODO check the name of pin
        @return: check_ok, if checks ok
        @rtype: boolean
        '''
        check_ok = True
        names = []
        nodes_dict = activity.nodes_dict
        pins_dict = activity.pins_dict

        # action, object, initial, final
        node_types = (uml_element.ExecutableNode, uml_element.ObjectNode,
                      uml_element.InitialNode, uml_element.FinalNode,
                      uml_element.Fork, uml_element.Join)
        # for node
        num1 = 0
        # for pin,pout
        num2 = 0
        # it checks the name of pout, do not need to check the name of pin
        for pin_id in pins_dict:
            pin = pins_dict[pin_id]
            # if it is a pout(Result)
            if isinstance(pin, uml_element.Result):
                name = pin.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the pin has no name, set the name "pin1","pin2"...
                    num2 += 1
                    pin.name = "pin" + str(num2)
                    log.show_warn("the pin has no name.id:%s" % pin.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    pin.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the pin has the same name.name:%s" %
                                       name)
                    else:
                        names.append(corrected_name)

        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            # if it is a action or object,initial,final
            # The form using a tuple, isinstance(x, (A, B, ...)), is a shortcut for
            # isinstance(x, A) or isinstance(x, B) or ... (etc.).
            if isinstance(node, node_types):
                name = node.name
                # if it has no name, see condition1
                if name is None or name.strip() == "":
                    # if the node has no name, set the name "node1","node2"...
                    num1 += 1
                    node.name = "node" + str(num1)
                    log.show_warn("the node has no name.id:%s" % node.xmi_id)
                else:
                    corrected_name = self.__get_corrected_name(name)
                    # change the name of node to corrected name
                    node.name = corrected_name
                    # see condition2
                    if corrected_name in names:
                        check_ok = False
                        log.show_error("the nodes has the same name.name:%s" %
                                       name)
                    else:
                        names.append(corrected_name)
        return check_ok
    def get_init_final_num(self, activity):
        ''' verify, if the uml activity diagram has just(genau)
        one Initial Node, and one or more ActivityFinal. if a node has no incoming or no outgoing,
        it is a error, except init node and final node and flow final.
        '''
        nodes_dict = activity.nodes_dict
        initial_num = 0
        final_num = 0
        for node_id in nodes_dict:
            node = nodes_dict[node_id]
            incomings = node.incomings
            outgoings = node.outgoings
            in_num = len(incomings)
            out_num = len(outgoings)
            # initial node, just one and it must have outgoing
            if node.xmi_type == uml_element.Types.INITIAL_NODE:
                initial_num += 1
                if out_num == 0:
                    log.show_error("the Initial Node has no outgoing." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            # final node, one or more, and it must have incoming
            elif node.xmi_type == uml_element.Types.ACTIVITY_FINAL_NODE:
                final_num += 1
                if in_num == 0:
                    log.show_error("the final Node has no incoming." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            # flow final, it must have incoming
            elif node.xmi_type == uml_element.Types.FLOW_FINAL_NODE:
                if len(incomings) == 0:
                    log.show_error("the final Node has no incoming." + \
                                   "name:" + str(node.name) + " id:" + node.xmi_id)
            elif isinstance(node, uml_element.ObjectNode):
                if not isinstance(node,
                                  uml_element.InstanceSpecification_node):
                    if len(incomings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn(
                            "the object Node has no incoming.name:%s,id:%s" %
                            (str(node.name), node.xmi_id))
                    if len(outgoings) == 0:
                        # @see example Order
                        # show warn info, not error info
                        log.show_warn(
                            "the object Node has no outgoins.name:%s,id:%s" %
                            (str(node.name), node.xmi_id))
            # if the node has no incoming or no outgoing
            # it is a error(except initial,final,object node)
            else:
                # incoming and outgoing of a node
                if in_num == 0:
                    # action has no incoming, but it has argument, and the argument has incoming
                    if isinstance(node, uml_element.ExecutableNode):
                        arguments = node.arguments
                        for argument in arguments:
                            # if the argument has no incoming
                            if len(argument.incomings) == 0:
                                log.show_error("the action node's argument in " + \
                                                "uml activity diagram has no incoming." + \
                                                "name:" + str(node.name) + \
                                                " id:" + node.xmi_id)
                    # it is not a action
                    else:
                        log.show_error("the node in uml activity diagram has no incoming."\
                                       + "name:" + str(node.name) + " id:" + node.xmi_id)
                if out_num == 0:
                    # action has no outgoing, but it has result, and the result has outgoing
                    if isinstance(node, uml_element.ExecutableNode):
                        results = node.results
                        for result in results:
                            # if the result has no outgoing
                            if len(result.outgoings) == 0:
                                log.show_error("the action node's result in " + \
                                                "uml activity diagram has no incoming." + \
                                                + "name:" + str(node.name) + " id:" + node.xmi_id)
                    # it is not a action
                    else:
                        log.show_error("the node in uml activity diagram has no outgoing."\
                                       + "name:" + str(node.name) \
                                        + " id:" + node.xmi_id)
        # initial node just one
        if initial_num == 0:
            log.show_error("the uml activity diagram has no Initial Node")
        elif initial_num > 1:
            log.show_error("the uml activity diagram has " + str(initial_num) +
                           " Initial Nodes")
        # final node one or more than one
        if final_num == 0:
            log.show_warn("the uml activity diagram has no final Node")

        return initial_num, final_num
    def get_next_state(self, places, transitions, petri_net, rg_graph,
                       unreach_list, reach, probs):
        '''fire t and determine the marking m' after firing.
        1b).if 2 transitions t1,t2 can be enabled, so from the node < m > will create 2 arrows.
        fire t1,go to step2(until stop),then fire t2, go to step2.
        step2. fire t and determine the marking m' after firing. if m' is already a node in G,
        then add the new arrow(m,t,m') to G, stop.
        step3. if m' is not a node in G, add m' as a new node and (m,t,m')
        as a new arrow to G and go to step 1.
        get the next states, it can be more states.
        @param places: the current marked places,pre-places
        @type places: list
        '''

        places_dict = petri_net.places_dict
        arcs_dict = petri_net.arcs_dict
        states_dict = rg_graph.states_dict
        edges_dict = rg_graph.edges_dict

        # pre_state_id: '<s1,s2>'
        pre_state_id = self.get_state_id(places, petri_net)

        reset_tokens = False

        # parallel, or decision
        if len(transitions) > 1:

            reset_tokens = True
            tokens_list = [place.tokens for place in places]

        if pre_state_id not in states_dict:
            pre_state = Rg.State(pre_state_id, pre_state_id, [], [])
            states_dict[pre_state_id] = pre_state
            # it is for unreach diagram, show in color blue
            if not reach:
                pre_state.reachability = False
        else:
            pre_state = states_dict[pre_state_id]
        # every time just one transition can be enabled.
        index = -1
        for transition in transitions:
            index += 1
            # reset the places 's tokens
            if reset_tokens:
                self.reset_tokens(places, tokens_list, places_dict)

            # get the next state-places, change id, and get the state id
            next_places = self.determine_marking(places, transition,
                                                 places_dict, arcs_dict)
            for place in next_places:
                if not place.id_changed:
                    self.change_pt_id(place, places_dict, arcs_dict, petri_net)
            next_state_id = self.get_state_id(next_places, petri_net)
            # "<p1,p2><p3>"
            # edge_id = "pre_state_id + next_state_id"
            # "edge0","edge1","edge2","edge3"...
            edge_id = "edge" + str(len(edges_dict))
            if edge_id not in edges_dict:
                # pre_state.outgoings is list, append the edge_id
                pre_state.outgoings.append(edge_id)
                edge = Rg.Edge(edge_id, edge_id, pre_state_id, next_state_id)
                # TODO
                edge.prob = probs[index]
                edge.label = transition.pt_id + "(" + str(edge.prob) + ")"
                edges_dict[edge_id] = edge
                #
                if not reach:
                    edge.reachability = False
            # multiedge, for example, p4-t5-p5,p4-t6-p5,p4-t7-p5
            else:
                log.show_error("edge id error in RG")
                # edge = edges_dict[edge_id]
                # edge.label = edge.label + " or " + transition.pt_id

            # step 3. if m' is not a node in G
            if next_state_id not in states_dict:
                next_state = Rg.State(next_state_id, next_state_id, [], [])
                # pre_state.incomings is list, append the edge_id
                next_state.incomings.append(edge_id)
                states_dict[next_state_id] = next_state
                #
                if not reach:
                    next_state.reachability = False
            # if m' is already a node in G,then add the new arrow(m,t,m') to G, stop.
            else:
                # next state exist, just incomings append the edge_id
                next_state = states_dict[next_state_id]
                if edge_id not in next_state.incomings:
                    next_state.incomings.append(edge_id)
                continue
            # step 3a) if m' has final node, stop
            if self.final_in_places(next_places):
                continue
            if len(next_places) > 0:
                # go to step 1
                self.find_enabled_transitions(next_places, petri_net, rg_graph,
                                              unreach_list, reach)
    def find_enabled_transitions(self, places, petri_net, rg_graph,
                                 unreach_list, reach):
        ''' first,get the next following transition from the current marked places,
        second, see if it can be enabled(see function-is_transition_enabled),
        and save the transitions in one list, for example [s1,s2]
        @param places: the current marked places,pre-places
        @type places: list
        @param reach: True, for the reachability_graph diagram.
        False, unreach_list=[],for the unreachability_graph.
        @type reach: Boolean
        @see: algorithm- step1
        '''
        # [t1,t2,t3...]
        transitions = []
        # [[t1],[t2,t3]...]
        # t1 fire from place1, t2,t3 fire from place2(decision)
        transitions_slices = []
        # the probs to fire the transition
        # [prob1,prob2,prob3...], the sum must be 1
        probs = []
        # [[prob1],[prob2,prob3]...]
        # prob1 is 1, sum of prob2 and prob3 is 1
        probs_slices = []
        # petri_net
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict

        # get the next transition from the place, and see if it can be enabled
        for place in places:
            # [t1] or [t2,t3]
            transitions_slice = []
            # [1] or [0.3,0.7]
            probs_slice = []
            outgoings = place.outgoings
            for outgoing in outgoings:
                arc = arcs_dict[outgoing]
                target = arc.target
                transition = transitions_dict[target]
                # if the transition can be enabled
                if self.is_transition_enabled(transition, places, places_dict,
                                              arcs_dict):
                    # get the prob from the arc
                    prob = arc.prob
                    # put the transition in the transitions_slice
                    if transition not in transitions_slice:
                        transitions_slice.append(transition)
                        # put the prob in the probs_slice
                        probs_slice.append(prob)
                    else:
                        # show error
                        log.show_error(
                            "more than 1 arcs between the place and the transition:find_enabled_transitions()"
                        )
                    # put it in the transitions
                    if transition not in transitions:
                        transitions.append(transition)
                        probs.append(prob)
                    # change the id of transition,which can be enabled
                    if not transition.id_changed:
                        self.change_pt_id(transition, transitions_dict,
                                          arcs_dict, petri_net)
            # if it is not []
            if transitions_slice:
                transitions_slices.append(transitions_slice)
                probs_slices.append(probs_slice)
        if reach:
            # parallel find the min(delay),
            # if just decision len(transitions) > 1 and len(transitions_slices)=1
            # if len(transitions_slices) > 1, but len(transitions) = 1-->join:
            # len(transitions_slices) >1 ,-->parallel
            if len(transitions) > 1 and len(transitions_slices) > 1:
                # delete the same type
                types_set = set(
                    [transition.transition_type for transition in transitions])
                types_list = list(types_set)
                # TODO
                if len(types_list) == 1:
                    # get the type of the transitions
                    transition_type = types_list[0]

                    # all are immediate transition
                    if transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                        pass
                    # all are DeterministicTransition
                    elif transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                        execute_transition = self.get_execute_transition(
                            transitions)

                        transitions.remove(execute_transition)
                        #
                        tokens_list = [place.tokens for place in places]
                        unreach_list.append(places)
                        unreach_list.append(tokens_list)
                        unreach_list.append(transitions)
                        #
                        transitions = [execute_transition]
                    # all are EXPONENTIAL_TRANSITION
                    elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                        if len(transitions_slices) == 2:
                            self._calculate_probability(
                                transitions_slices, probs_slices, transitions,
                                probs)
                        else:
                            log.show_error(
                                "the code can not analyse 3 parallel exp distribution process"
                            )
                    else:
                        log.show_error(
                            "the type of the transition is not defined")

                # all are ExponentialTransition
                else:
                    log.show_warn(
                        "the types of the enabled transitions are not the same"
                    )

        # see algorithm- step1a)
        if len(transitions) > 0:
            # fire t and determine the marking m' after firing.
            self.get_next_state(places, transitions, petri_net, rg_graph,
                                unreach_list, reach, probs)
Example #34
0
    def draw_petri_net(self, petri_net):
        '''draw Petri Net from the 3 dicts
        '''
        places_dict = petri_net.places_dict
        transitions_dict = petri_net.transitions_dict
        arcs_dict = petri_net.arcs_dict
        # G=pgv.AGraph(directed=True,strict=True,splines="polyline")
        # G = pgv.AGraph(directed=True, strict=True, splines=False)
        G = pgv.AGraph(directed=True, strict=True)
        G.graph_attr['label'] = petri_net.label + petri_net.probs

        for pt_id in places_dict:
            place = places_dict[pt_id]
            place_xlabel = place.xlabel
            G.add_node(pt_id, shape="circle", label="", xlabel=place_xlabel)
        for pt_id in transitions_dict:
            transition = transitions_dict[pt_id]
            # get the max number of the incomings and outgoings
            number = max(len(transition.incomings), len(transition.outgoings))
            transition_width = 0.5 * number
            transition_xlabel = transition.xlabel

            transition_type = transition.transition_type
            # Deterministic transitions are drawn as black filled rectangles.
            if transition_type == petri_net_element.TransitionTypes.DETERMINISTIC_TRANSITION:
                G.add_node(pt_id, shape="box", style="filled", label="", \
                            xlabel=transition_xlabel, height=0.3, \
                            width=transition_width, fillcolor="#000000")  # color:black
            # Exponential transitions are drawn as empty rectangles.
            elif transition_type == petri_net_element.TransitionTypes.EXPONENTIAL_TRANSITION:
                G.add_node(pt_id,
                           shape="box",
                           label="",
                           xlabel=transition_xlabel,
                           height=0.3,
                           width=transition_width,
                           fillcolor="#000000")  # color:black
            # Immediate transitions are drawn as thin bars.
            elif transition_type == petri_net_element.TransitionTypes.IMMEDIATE_TRANSITION:
                G.add_node(pt_id,
                           shape="box",
                           style="filled",
                           label="",
                           xlabel=transition_xlabel,
                           height=0.08,
                           width=transition_width,
                           fillcolor="#000000")  # color:black
            else:
                log.show_error("the transition type is not defined")
        for pt_id in arcs_dict:
            arc = arcs_dict[pt_id]
            source = arc.source
            target = arc.target
            G.add_edge(source, target)
            # draw the arc with probability
            # if arc.prob == 1:
            #    G.add_edge(source, target)
            # else:
            #    G.add_edge(source, target, label=arc.prob)

        # print G.string()  # print dot file to standard output
        png_name = self.get_png_name()
        # G.write("Pt"+png_name + ".dot")
        G.layout('dot')  # layout with dot
        G.draw("Pt" + "_" + petri_net.name + png_name +
               ".png")  # write to file
        log.show_info("the Petri Net Diagram is created.name:%s" %
                      petri_net.name)