예제 #1
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def construct_trace_net(trace,
                        trace_name_key=xes_util.DEFAULT_NAME_KEY,
                        activity_key=xes_util.DEFAULT_NAME_KEY):
    """
    Creates a trace net, i.e. a trace in Petri net form.

    Parameters
    ----------
    trace: :class:`list` input trace, assumed to be a list of events
    trace_name_key: :class:`str` key of the attribute that defines the name of the trace
    activity_key: :class:`str` key of the attribute of the events that defines the activity name

    Returns
    -------
    tuple: :class:`tuple` of the net, initial marking and the final marking

    """
    net = PetriNet('trace net of %s' %
                   trace.attributes[trace_name_key] if trace_name_key in
                   trace.attributes else ' ')
    place_map = {0: PetriNet.Place('p_0')}
    net.places.add(place_map[0])
    for i in range(0, len(trace)):
        t = PetriNet.Transition('t_' + trace[i][activity_key] + '_' + str(i),
                                trace[i][activity_key])
        # 16/02/2021: set the trace index as property of the transition of the trace net
        t.properties[properties.TRACE_NET_TRANS_INDEX] = i
        net.transitions.add(t)
        place_map[i + 1] = PetriNet.Place('p_' + str(i + 1))
        # 16/02/2021: set the place index as property of the place of the trace net
        place_map[i + 1].properties[properties.TRACE_NET_PLACE_INDEX] = i + 1
        net.places.add(place_map[i + 1])
        add_arc_from_to(place_map[i], t, net)
        add_arc_from_to(t, place_map[i + 1], net)
    return net, Marking({place_map[0]: 1}), Marking({place_map[len(trace)]: 1})
예제 #2
0
def __copy_into(source_net, target_net, upper, skip):
    t_map = {}
    p_map = {}
    for t in source_net.transitions:
        name = (t.name, skip) if upper else (skip, t.name)
        label = (t.label, skip) if upper else (skip, t.label)
        t_map[t] = PetriNet.Transition(name, label)
        if properties.TRACE_NET_TRANS_INDEX in t.properties:
            # 16/02/2021: copy the index property from the transition of the trace net
            t_map[t].properties[properties.TRACE_NET_TRANS_INDEX] = t.properties[properties.TRACE_NET_TRANS_INDEX]
        target_net.transitions.add(t_map[t])

    for p in source_net.places:
        name = (p.name, skip) if upper else (skip, p.name)
        p_map[p] = PetriNet.Place(name)
        if properties.TRACE_NET_PLACE_INDEX in p.properties:
            # 16/02/2021: copy the index property from the place of the trace net
            p_map[p].properties[properties.TRACE_NET_PLACE_INDEX] = p.properties[properties.TRACE_NET_PLACE_INDEX]
        target_net.places.add(p_map[p])

    for t in source_net.transitions:
        for a in t.in_arcs:
            add_arc_from_to(p_map[a.source], t_map[t], target_net)
        for a in t.out_arcs:
            add_arc_from_to(t_map[t], p_map[a.target], target_net)

    return t_map, p_map
예제 #3
0
def construct(pn1, im1, fm1, pn2, im2, fm2, skip):
    """
    Constructs the synchronous product net of two given Petri nets.


    :param pn1: Petri net 1
    :param im1: Initial marking of Petri net 1
    :param fm1: Final marking of Petri net 1
    :param pn2: Petri net 2
    :param im2: Initial marking of Petri net 2
    :param fm2: Final marking of Petri net 2
    :param skip: Symbol to be used as skip

    Returns
    -------
    :return: Synchronous product net and associated marking labels are of the form (a,>>)
    """
    sync_net = PetriNet('synchronous_product_net of %s and %s' % (pn1.name, pn2.name))
    t1_map, p1_map = __copy_into(pn1, sync_net, True, skip)
    t2_map, p2_map = __copy_into(pn2, sync_net, False, skip)

    for t1 in pn1.transitions:
        for t2 in pn2.transitions:
            if t1.label == t2.label:
                sync = PetriNet.Transition((t1.name, t2.name), (t1.label, t2.label))
                sync_net.transitions.add(sync)
                # copy the properties of the transitions inside the transition of the sync net
                for p1 in t1.properties:
                    sync.properties[p1] = t1.properties[p1]
                for p2 in t2.properties:
                    sync.properties[p2] = t2.properties[p2]
                for a in t1.in_arcs:
                    add_arc_from_to(p1_map[a.source], sync, sync_net)
                for a in t2.in_arcs:
                    add_arc_from_to(p2_map[a.source], sync, sync_net)
                for a in t1.out_arcs:
                    add_arc_from_to(sync, p1_map[a.target], sync_net)
                for a in t2.out_arcs:
                    add_arc_from_to(sync, p2_map[a.target], sync_net)

    sync_im = Marking()
    sync_fm = Marking()
    for p in im1:
        sync_im[p1_map[p]] = im1[p]
    for p in im2:
        sync_im[p2_map[p]] = im2[p]
    for p in fm1:
        sync_fm[p1_map[p]] = fm1[p]
    for p in fm2:
        sync_fm[p2_map[p]] = fm2[p]

    # update 06/02/2021: to distinguish the sync nets that are output of this method, put a property in the sync net
    sync_net.properties[properties.IS_SYNC_NET] = True

    return sync_net, sync_im, sync_fm
예제 #4
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def add_transition(net, name=None, label=None):
    name = name if name is not None else 't_' + str(len(
        net.transitions)) + '_' + str(time.time()) + str(
            random.randint(0, 10000))
    t = PetriNet.Transition(name=name, label=label)
    net.transitions.add(t)
    return t
예제 #5
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def merge(trgt=None, nets=None):
    trgt = trgt if trgt is not None else PetriNet()
    nets = nets if nets is not None else list()
    for net in nets:
        trgt.transitions.update(net.transitions)
        trgt.places.update(net.places)
        trgt.arcs.update(net.arcs)
    return trgt
예제 #6
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def get_strongly_connected_subnets(net):
    """
    Get the strongly connected components subnets in the Petri net

    Parameters
    -------------
    net
        Petri net

    Returns
    -------------
    strongly_connected_transitions
        List of strongly connected transitions of the Petri net
    """
    import networkx as nx

    graph, inv_dictionary = create_networkx_directed_graph(net)
    sccg = list(nx.strongly_connected_components(graph))
    strongly_connected_subnets = []
    for sg in list(sccg):
        if len(sg) > 1:
            subnet = PetriNet()
            imarking = Marking()
            fmarking = Marking()
            corr = {}
            for node in sg:
                if node in inv_dictionary:
                    if type(inv_dictionary[node]) is PetriNet.Transition:
                        prev_trans = inv_dictionary[node]
                        new_trans = PetriNet.Transition(
                            prev_trans.name, prev_trans.label)
                        corr[node] = new_trans
                        subnet.transitions.add(new_trans)
                    if type(inv_dictionary[node]) is PetriNet.Place:
                        prev_place = inv_dictionary[node]
                        new_place = PetriNet.Place(prev_place.name)
                        corr[node] = new_place
                        subnet.places.add(new_place)
            for edge in graph.edges:
                if edge[0] in sg and edge[1] in sg:
                    add_arc_from_to(corr[edge[0]], corr[edge[1]], subnet)
            strongly_connected_subnets.append([subnet, imarking, fmarking])

    return strongly_connected_subnets
예제 #7
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def add_arc_from_to(fr, to, net, weight=1):
    """
    Adds an arc from a specific element to another element in some net. Assumes from and to are in the net!

    Parameters
    ----------
    fr: transition/place from
    to:  transition/place to
    net: net to use
    weight: weight associated to the arc

    Returns
    -------
    None
    """
    a = PetriNet.Arc(fr, to, weight)
    net.arcs.add(a)
    fr.out_arcs.add(a)
    to.in_arcs.add(a)

    return a
예제 #8
0
파일: utils.py 프로젝트: pm4py/pm4py-core
def add_place(net, name=None):
    name = name if name is not None else 'p_' + str(len(
        net.places)) + '_' + str(time.time()) + str(random.randint(0, 10000))
    p = PetriNet.Place(name=name)
    net.places.add(p)
    return p
예제 #9
0
def decompose(net, im, fm):
    places = {x.name: x for x in net.places}
    inv_trans = {x.name: x for x in net.transitions if x.label is None}
    tmap = {}
    for t in net.transitions:
        if t.label is not None:
            if t.label not in tmap:
                tmap[t.label] = []
            tmap[t.label].append(t)
    trans_dup_label = {
        x.label: x
        for x in net.transitions
        if x.label is not None and len(tmap[x.label]) > 1
    }
    trans_labels = {x.name: x.label for x in net.transitions}
    conn_comp = get_graph_components(places, inv_trans, trans_dup_label, tmap)
    list_nets = []
    for cmp in conn_comp:
        net_new = PetriNet("")
        im_new = Marking()
        fm_new = Marking()
        lmap = {}
        for el in cmp:
            if el in places:
                lmap[el] = PetriNet.Place(el)
                net_new.places.add(lmap[el])
            elif el in inv_trans:
                lmap[el] = PetriNet.Transition(el, None)
                net_new.transitions.add(lmap[el])
            elif el in trans_labels:
                lmap[el] = PetriNet.Transition(el, trans_labels[el])
                net_new.transitions.add(lmap[el])
        for el in cmp:
            if el in places:
                old_place = places[el]
                for arc in old_place.in_arcs:
                    st = arc.source
                    if st.name not in lmap:
                        lmap[st.name] = PetriNet.Transition(
                            st.name, trans_labels[st.name])
                        net_new.transitions.add(lmap[st.name])
                    add_arc_from_to(lmap[st.name], lmap[el], net_new)
                for arc in old_place.out_arcs:
                    st = arc.target
                    if st.name not in lmap:
                        lmap[st.name] = PetriNet.Transition(
                            st.name, trans_labels[st.name])
                        net_new.transitions.add(lmap[st.name])
                    add_arc_from_to(lmap[el], lmap[st.name], net_new)
                if old_place in im:
                    im_new[lmap[el]] = im[old_place]
                if old_place in fm:
                    fm_new[lmap[el]] = fm[old_place]
        lvis_labels = sorted(
            [t.label for t in net_new.transitions if t.label is not None])
        t_tuple = tuple(
            sorted(
                list(
                    int(
                        hashlib.md5(t.name.encode(
                            constants.DEFAULT_ENCODING)).hexdigest(), 16)
                    for t in net_new.transitions)))
        net_new.lvis_labels = lvis_labels
        net_new.t_tuple = t_tuple

        if len(net_new.places) > 0 or len(net_new.transitions) > 0:
            list_nets.append((net_new, im_new, fm_new))

    return list_nets
예제 #10
0
def merge_comp(comp1, comp2):
    net = PetriNet("")
    im = Marking()
    fm = Marking()
    places = {}
    trans = {}

    for pl in comp1[0].places:
        places[pl.name] = PetriNet.Place(pl.name)
        net.places.add(places[pl.name])
        if pl in comp1[1]:
            im[places[pl.name]] = comp1[1][pl]
        if pl in comp1[2]:
            fm[places[pl.name]] = comp1[2][pl]

    for pl in comp2[0].places:
        places[pl.name] = PetriNet.Place(pl.name)
        net.places.add(places[pl.name])
        if pl in comp2[1]:
            im[places[pl.name]] = comp2[1][pl]
        if pl in comp2[2]:
            fm[places[pl.name]] = comp2[2][pl]

    for tr in comp1[0].transitions:
        trans[tr.name] = PetriNet.Transition(tr.name, tr.label)
        net.transitions.add(trans[tr.name])

    for tr in comp2[0].transitions:
        if not tr.name in trans:
            trans[tr.name] = PetriNet.Transition(tr.name, tr.label)
            net.transitions.add(trans[tr.name])

    for arc in comp1[0].arcs:
        if type(arc.source) is PetriNet.Place:
            add_arc_from_to(places[arc.source.name], trans[arc.target.name],
                            net)
        else:
            add_arc_from_to(trans[arc.source.name], places[arc.target.name],
                            net)

    for arc in comp2[0].arcs:
        if type(arc.source) is PetriNet.Place:
            add_arc_from_to(places[arc.source.name], trans[arc.target.name],
                            net)
        else:
            add_arc_from_to(trans[arc.source.name], places[arc.target.name],
                            net)

    lvis_labels = sorted(
        [t.label for t in net.transitions if t.label is not None])
    t_tuple = tuple(
        sorted(
            list(
                int(
                    hashlib.md5(t.name.encode(
                        constants.DEFAULT_ENCODING)).hexdigest(), 16)
                for t in net.transitions)))
    net.lvis_labels = lvis_labels
    net.t_tuple = t_tuple

    return (net, im, fm)
예제 #11
0
def import_net_from_xml_object(root, parameters=None):
    """
    Import a Petri net from an etree XML object

    Parameters
    ----------
    root
        Root object of the XML
    parameters
        Other parameters of the algorithm
    """
    if parameters is None:
        parameters = {}

    net = PetriNet('imported_' + str(time.time()))
    marking = Marking()
    fmarking = Marking()

    nett = None
    page = None
    finalmarkings = None

    stochastic_information = {}

    for child in root:
        nett = child

    places_dict = {}
    trans_dict = {}

    if nett is not None:
        for child in nett:
            if "page" in child.tag:
                page = child
            if "finalmarkings" in child.tag:
                finalmarkings = child

    if page is None:
        page = nett

    if page is not None:
        for child in page:
            if "place" in child.tag:
                position_X = None
                position_Y = None
                dimension_X = None
                dimension_Y = None
                place_id = child.get("id")
                place_name = place_id
                number = 0
                for child2 in child:
                    if child2.tag.endswith('name'):
                        for child3 in child2:
                            if child3.text:
                                place_name = child3.text
                    if child2.tag.endswith('initialMarking'):
                        for child3 in child2:
                            if child3.tag.endswith("text"):
                                number = int(child3.text)
                    if child2.tag.endswith('graphics'):
                        for child3 in child2:
                            if child3.tag.endswith('position'):
                                position_X = float(child3.get("x"))
                                position_Y = float(child3.get("y"))
                            elif child3.tag.endswith("dimension"):
                                dimension_X = float(child3.get("x"))
                                dimension_Y = float(child3.get("y"))
                places_dict[place_id] = PetriNet.Place(place_id)
                places_dict[place_id].properties[constants.PLACE_NAME_TAG] = place_name
                net.places.add(places_dict[place_id])
                if position_X is not None and position_Y is not None and dimension_X is not None and dimension_Y is not None:
                    places_dict[place_id].properties[constants.LAYOUT_INFORMATION_PETRI] = (
                        (position_X, position_Y), (dimension_X, dimension_Y))
                if number > 0:
                    marking[places_dict[place_id]] = number
                del place_name

    if page is not None:
        for child in page:
            if child.tag.endswith("transition"):
                position_X = None
                position_Y = None
                dimension_X = None
                dimension_Y = None
                trans_id = child.get("id")
                trans_name = trans_id
                trans_visible = True

                random_variable = None

                for child2 in child:
                    if child2.tag.endswith("name"):
                        for child3 in child2:
                            if child3.text:
                                if trans_name == trans_id:
                                    trans_name = child3.text
                    if child2.tag.endswith("graphics"):
                        for child3 in child2:
                            if child3.tag.endswith("position"):
                                position_X = float(child3.get("x"))
                                position_Y = float(child3.get("y"))
                            elif child3.tag.endswith("dimension"):
                                dimension_X = float(child3.get("x"))
                                dimension_Y = float(child3.get("y"))
                    if child2.tag.endswith("toolspecific"):
                        tool = child2.get("tool")
                        if "ProM" in tool:
                            activity = child2.get("activity")
                            if "invisible" in activity:
                                trans_visible = False
                        elif "StochasticPetriNet" in tool:
                            distribution_type = None
                            distribution_parameters = None
                            priority = None
                            weight = None

                            for child3 in child2:
                                key = child3.get("key")
                                value = child3.text

                                if key == "distributionType":
                                    distribution_type = value
                                elif key == "distributionParameters":
                                    distribution_parameters = value
                                elif key == "priority":
                                    priority = int(value)
                                elif key == "weight":
                                    weight = float(value)

                            random_variable = RandomVariable()
                            random_variable.read_from_string(distribution_type, distribution_parameters)
                            random_variable.set_priority(priority)
                            random_variable.set_weight(weight)

                # 15/02/2021: the name associated in the PNML to invisible transitions was lost.
                # at least save that as property.
                if trans_visible:
                    trans_label = trans_name
                else:
                    trans_label = None

                trans_dict[trans_id] = PetriNet.Transition(trans_id, trans_label)
                trans_dict[trans_id].properties[constants.TRANS_NAME_TAG] = trans_name
                net.transitions.add(trans_dict[trans_id])

                if random_variable is not None:
                    trans_dict[trans_id].properties[constants.STOCHASTIC_DISTRIBUTION] = random_variable
                if position_X is not None and position_Y is not None and dimension_X is not None and dimension_Y is not None:
                    trans_dict[trans_id].properties[constants.LAYOUT_INFORMATION_PETRI] = (
                        (position_X, position_Y), (dimension_X, dimension_Y))

    if page is not None:
        for child in page:
            if child.tag.endswith("arc"):
                arc_source = child.get("source")
                arc_target = child.get("target")
                arc_weight = 1

                for arc_child in child:
                    if arc_child.tag.endswith("inscription"):
                        for text_arcweight in arc_child:
                            if text_arcweight.tag.endswith("text"):
                                arc_weight = int(text_arcweight.text)

                if arc_source in places_dict and arc_target in trans_dict:
                    add_arc_from_to(places_dict[arc_source], trans_dict[arc_target], net, weight=arc_weight)
                elif arc_target in places_dict and arc_source in trans_dict:
                    add_arc_from_to(trans_dict[arc_source], places_dict[arc_target], net, weight=arc_weight)

    if finalmarkings is not None:
        for child in finalmarkings:
            for child2 in child:
                place_id = child2.get("idref")
                for child3 in child2:
                    if child3.tag.endswith("text"):
                        number = int(child3.text)
                        if number > 0:
                            fmarking[places_dict[place_id]] = number

    # generate the final marking in the case has not been found
    if len(fmarking) == 0:
        fmarking = final_marking.discover_final_marking(net)

    return net, marking, fmarking