Exemplo n.º 1
0
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})
Exemplo n.º 2
0
def remove_initial_hidden_if_possible(net: PetriNet, im: Marking):
    """
    Remove initial hidden transition if possible

    Parameters
    ------------
    net
        Petri net
    im
        Initial marking

    Returns
    ------------
    net
        Petri net
    im
        Possibly different initial marking
    """
    source = list(im.keys())[0]
    first_hidden = list(source.out_arcs)[0].target
    target_places_first_hidden = [x.target for x in first_hidden.out_arcs]
    if len(target_places_first_hidden) == 1:
        target_place_first_hidden = target_places_first_hidden[0]
        if len(target_place_first_hidden.in_arcs) == 1:
            new_im = Marking()
            new_im[target_place_first_hidden] = 1
            remove_place(net, source)
            remove_transition(net, first_hidden)
            return net, new_im
    return net, im
Exemplo n.º 3
0
def execute_script():
    net = PetriNet("")
    source = PetriNet.Place("source")
    sink = PetriNet.Place("sink")
    p1 = PetriNet.Place("p1")
    p2 = PetriNet.Place("p2")
    p_inhibitor = PetriNet.Place("p_inhibitor")
    p_reset = PetriNet.Place("p_reset")
    trans_A = PetriNet.Transition("A", "A")
    trans_B = PetriNet.Transition("B", "B")
    trans_C = PetriNet.Transition("C", "C")
    trans_inhibitor = PetriNet.Transition("inhibitor", None)
    trans_free = PetriNet.Transition("free", None)
    net.places.add(source)
    net.places.add(sink)
    net.places.add(p1)
    net.places.add(p2)
    net.places.add(p_inhibitor)
    net.places.add(p_reset)
    net.transitions.add(trans_A)
    net.transitions.add(trans_B)
    net.transitions.add(trans_C)
    net.transitions.add(trans_free)
    net.transitions.add(trans_inhibitor)
    add_arc_from_to(source, trans_A, net)
    add_arc_from_to(trans_A, p1, net)
    add_arc_from_to(p1, trans_B, net)
    add_arc_from_to(trans_B, p2, net)
    add_arc_from_to(p2, trans_C, net)
    add_arc_from_to(trans_C, sink, net)
    add_arc_from_to(trans_inhibitor, p_inhibitor, net)
    inhibitor_arc = add_arc_from_to(p_inhibitor,
                                    trans_B,
                                    net,
                                    type="inhibitor")
    add_arc_from_to(trans_free, p_reset, net)
    reset_arc = add_arc_from_to(p_reset, trans_C, net, type="reset")
    im = Marking({source: 1})
    fm = Marking({sink: 1})
    pm4py.view_petri_net(net, im, fm, format="svg")
    m = semantics.execute(trans_A, net, im)
    print(m)
    # B is enabled in m because no tokens in the "inhibitor" place
    print(semantics.enabled_transitions(net, m))
    # if we put a token in the inhibitor place, B is not enabled anymore
    m2 = deepcopy(m)
    m2[p_inhibitor] = 1
    print(semantics.enabled_transitions(net, m2))
    # let's continue with m and fire B, and three times the "free" transition
    m = semantics.execute(trans_B, net, m)
    m = semantics.execute(trans_free, net, m)
    m = semantics.execute(trans_free, net, m)
    m = semantics.execute(trans_free, net, m)
    # we have three tokens in the 'reset' place. Firing C, all of them are removed because of the reset arc
    print(m)
    m = semantics.execute(trans_C, net, m)
    print(m)
    print(m == fm)
Exemplo n.º 4
0
 def test_figure415(self):
     net = PetriNet("figure_4_15")
     p_1 = PetriNet.Place("p_1")
     p_2 = PetriNet.Place("p_2")
     p_3 = PetriNet.Place("p_3")
     p_4 = PetriNet.Place("p_4")
     p_5 = PetriNet.Place("p_5")
     p_6 = PetriNet.Place("p_6")
     p_7 = PetriNet.Place("p_7")
     net.places.add(p_1)
     net.places.add(p_2)
     net.places.add(p_3)
     net.places.add(p_4)
     net.places.add(p_5)
     net.places.add(p_6)
     net.places.add(p_7)
     t_1 = PetriNet.Transition("t_1", "t_1")
     t_2 = PetriNet.Transition("t_2", "t_2")
     t_3 = PetriNet.Transition("t_3", "t_3")
     t_4 = PetriNet.Transition("t_4", "t_4")
     t_5 = PetriNet.Transition("t_5", "t_5")
     t_6 = PetriNet.Transition("t_6", "t_6")
     net.transitions.add(t_1)
     net.transitions.add(t_2)
     net.transitions.add(t_3)
     net.transitions.add(t_4)
     net.transitions.add(t_5)
     net.transitions.add(t_6)
     petri_utils.add_arc_from_to(p_1, t_1, net)
     petri_utils.add_arc_from_to(t_1, p_3, net)
     petri_utils.add_arc_from_to(t_1, p_2, net)
     petri_utils.add_arc_from_to(t_1, p_5, net)
     petri_utils.add_arc_from_to(p_5, t_2, net)
     petri_utils.add_arc_from_to(p_5, t_5, net)
     petri_utils.add_arc_from_to(p_3, t_2, net)
     petri_utils.add_arc_from_to(p_3, t_4, net)
     petri_utils.add_arc_from_to(t_2, p_6, net)
     petri_utils.add_arc_from_to(t_2, p_4, net)
     petri_utils.add_arc_from_to(t_5, p_5, net)
     petri_utils.add_arc_from_to(t_5, p_3, net)
     petri_utils.add_arc_from_to(p_2, t_2, net)
     petri_utils.add_arc_from_to(t_3, p_2, net)
     petri_utils.add_arc_from_to(t_3, p_3, net)
     petri_utils.add_arc_from_to(t_3, p_4, net)
     petri_utils.add_arc_from_to(p_6, t_5, net)
     petri_utils.add_arc_from_to(p_6, t_6, net)
     petri_utils.add_arc_from_to(p_6, t_3, net)
     petri_utils.add_arc_from_to(t_4, p_6, net)
     petri_utils.add_arc_from_to(t_4, p_5, net)
     petri_utils.add_arc_from_to(p_4, t_3, net)
     petri_utils.add_arc_from_to(p_4, t_6, net)
     petri_utils.add_arc_from_to(p_4, t_4, net)
     petri_utils.add_arc_from_to(t_6, p_7, net)
     initial_marking = Marking()
     initial_marking[p_1] = 1
     final_marking = Marking()
     final_marking[p_7] = 1
     self.assertTrue(woflan.apply(net, initial_marking, final_marking, parameters={"print_diagnostics": False}))
Exemplo n.º 5
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
Exemplo n.º 6
0
def project_net_on_place(place):
    """
    Project a Petri net on a place

    Parameters
    -------------
    place
        Place

    Returns
    -------------
    net
        (Place) net
    im
        Empty initial marking
    fm
        Empty final marking
    """
    place_net = PetriNet()
    place_net_im = Marking()
    place_net_fm = Marking()

    input_trans = [arc.source for arc in place.in_arcs]
    output_trans = [arc.target for arc in place.out_arcs]

    if len(input_trans) == 0 or len(output_trans) == 0:
        raise Exception("place projection not available on source/sink places")

    input_trans_visible = [trans for trans in input_trans if trans.label]
    output_trans_visible = [trans for trans in output_trans if trans.label]

    if not len(input_trans) == len(input_trans_visible) or not len(
            output_trans) == len(output_trans_visible):
        raise Exception(
            "place projection not available on places that have invisible transitions as preset/postset"
        )

    new_place = PetriNet.Place(place.name)
    place_net.places.add(new_place)

    for trans in input_trans:
        new_trans = PetriNet.Transition(trans.name, trans.label)
        place_net.transitions.add(new_trans)
        add_arc_from_to(new_trans, new_place, place_net)

    for trans in output_trans:
        new_trans = PetriNet.Transition(trans.name, trans.label)
        place_net.transitions.add(new_trans)
        add_arc_from_to(new_place, new_trans, place_net)

    return place_net, place_net_im, place_net_fm
Exemplo n.º 7
0
def execute_script():
    net = PetriNet("test")
    source = PetriNet.Place("source")
    sink = PetriNet.Place("sink")
    p1 = PetriNet.Place("p1")
    p2 = PetriNet.Place("p2")
    p3 = PetriNet.Place("p3")
    p4 = PetriNet.Place("p4")
    t1 = PetriNet.Transition("Confirmation of receipt",
                             "Confirmation of receipt")
    t2 = PetriNet.Transition("T02 Check confirmation of receipt",
                             "T02 Check confirmation of receipt")
    t3 = PetriNet.Transition("T04 Determine confirmation of receipt",
                             "T04 Determine confirmation of receipt")
    t4 = PetriNet.Transition("T05 Print and send confirmation of receipt",
                             "T05 Print and send confirmation of receipt")
    t5 = PetriNet.Transition("T06 Determine necessity of stop advice",
                             "T06 Determine necessity of stop advice")

    net.places.add(source)
    net.places.add(sink)
    net.places.add(p1)
    net.places.add(p2)
    net.places.add(p3)
    net.places.add(p4)
    net.transitions.add(t1)
    net.transitions.add(t2)
    net.transitions.add(t3)
    net.transitions.add(t4)
    net.transitions.add(t5)

    petri_utils.add_arc_from_to(source, t1, net)
    petri_utils.add_arc_from_to(t1, p1, net)
    petri_utils.add_arc_from_to(p1, t2, net)
    petri_utils.add_arc_from_to(t2, p2, net)
    petri_utils.add_arc_from_to(p2, t3, net)
    petri_utils.add_arc_from_to(t3, p3, net)
    petri_utils.add_arc_from_to(p3, t4, net)
    petri_utils.add_arc_from_to(t4, p4, net)
    petri_utils.add_arc_from_to(p4, t5, net)
    petri_utils.add_arc_from_to(t5, sink, net)

    im = Marking()
    im[source] = 1

    fm = Marking()
    fm[sink] = 1

    pm4py.view_petri_net(net, im, fm, format="svg")
Exemplo n.º 8
0
def add_markings(curr, add):
    m = Marking()
    for p in curr.items():
        m[p[0]] = p[1]
    for p in add.items():
        m[p[0]] += p[1]
        if m[p[0]] == 0:
            del m[p[0]]
    return m
Exemplo n.º 9
0
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
Exemplo n.º 10
0
 def decode_marking(self, ems):
     """
     Decodes a marking from a generic dictionary
     to a Marking object
     """
     em = eval(ems)
     mark = Marking()
     for p in em:
         mark[self.places_inv_dict[p]] = em[p]
     return mark
Exemplo n.º 11
0
def __get_model_marking_and_index(marking):
    """
    Transforms a marking on the synchronous product net
    to a marking in the model and an index in the trace
    """
    mm = Marking()
    index = -1
    for p in marking:
        if properties.TRACE_NET_PLACE_INDEX in p.properties:
            index = p.properties[properties.TRACE_NET_PLACE_INDEX]
        else:
            mm[p] = marking[p]
    return mm, index
Exemplo n.º 12
0
def transform_markings_from_sync_to_original_net(markings0,
                                                 net,
                                                 parameters=None):
    """
    Transform the markings of the sync net (in which alignment stops) into markings of the original net
    (in order to measure the precision)

    Parameters
    -------------
    markings0
        Markings on the sync net (expressed as place name with count)
    net
        Petri net
    parameters
        Parameters of the algorithm

    Returns
    -------------
    markings
        Markings of the original model (expressed as place with count)
    """
    if parameters is None:
        parameters = {}

    places_corr = {p.name: p for p in net.places}

    markings = []

    for i in range(len(markings0)):
        res_list = markings0[i]

        # res_list shall be a list of markings.
        # If it is None, then there is no correspondence markings
        # in the original Petri net
        if res_list is not None:
            # saves all the markings reached by the optimal alignment
            # as markings of the original net
            markings.append([])

            for j in range(len(res_list)):
                res = res_list[j]

                atm = Marking()
                for pl, count in res.items():
                    if pl[0] == utils.SKIP:
                        atm[places_corr[pl[1]]] = count
                markings[-1].append(atm)
        else:
            markings.append(None)

    return markings
Exemplo n.º 13
0
def decorate_transitions_prepostset(net: PetriNet):
    """
    Decorate transitions with sub and addition markings

    Parameters
    -------------
    net
        Petri net
    """
    from pm4py.objects.petri_net.obj import Marking
    for trans in net.transitions:
        sub_marking = Marking()
        add_marking = Marking()

        for arc in trans.in_arcs:
            sub_marking[arc.source] = arc.weight
            add_marking[arc.source] = -arc.weight
        for arc in trans.out_arcs:
            if arc.target in add_marking:
                add_marking[arc.target] = arc.weight + add_marking[arc.target]
            else:
                add_marking[arc.target] = arc.weight
        trans.sub_marking = sub_marking
        trans.add_marking = add_marking
Exemplo n.º 14
0
def remove_final_hidden_if_possible(net: PetriNet, fm: Marking):
    """
    Remove final hidden transition if possible

    Parameters
    -------------
    net
        Petri net
    fm
        Final marking

    Returns
    -------------
    net
        Petri net
    """
    sink = list(fm.keys())[0]
    last_hidden = list(sink.in_arcs)[0].source
    source_places_last_hidden = [x.source for x in last_hidden.in_arcs]
    removal_possible = len(source_places_last_hidden) == 1
    for place in source_places_last_hidden:
        if len(place.out_arcs) > 1:
            removal_possible = False
            break
        else:
            source_trans = set([x.source for x in place.in_arcs])
            for trans in source_trans:
                if len(trans.out_arcs) > 1:
                    removal_possible = False
                    break
    if removal_possible:
        all_sources = set()
        remove_transition(net, last_hidden)
        i = 0
        while i < len(source_places_last_hidden):
            place = source_places_last_hidden[i]
            source_trans = set([x.source for x in place.in_arcs])
            for trans in source_trans:
                if trans not in all_sources:
                    all_sources.add(trans)
                    add_arc_from_to(trans, sink, net)
            remove_place(net, place)
            i = i + 1
    return net
Exemplo n.º 15
0
def __align_trace_stop_marking(trace,
                               net,
                               marking,
                               final_marking,
                               parameters=None):
    sync_net, sync_initial_marking, sync_final_marking = build_sync_net(
        trace, net, marking, final_marking, parameters=parameters)
    stop_marking = Marking()
    for pl, count in sync_final_marking.items():
        if pl.name[1] == utils.SKIP:
            stop_marking[pl] = count
    cost_function = utils.construct_standard_cost_function(
        sync_net, utils.SKIP)

    # perform the alignment of the prefix
    res = precision_utils.__search(sync_net, sync_initial_marking,
                                   sync_final_marking, stop_marking,
                                   cost_function, utils.SKIP)

    return res
Exemplo n.º 16
0
def discover_initial_marking(petri):
    """
    Discovers initial marking from a Petri net

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

    Returns
    ------------
    initial_marking
        Initial marking of the Petri net
    """
    initial_marking = Marking()

    for place in petri.places:
        if len(place.in_arcs) == 0:
            initial_marking[place] = 1

    return initial_marking
Exemplo n.º 17
0
def discover_final_marking(petri):
    """
    Discovers final marking from a Petri net

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

    Returns
    -----------
    final_marking
        Final marking
    """
    final_marking = Marking()

    for place in petri.places:
        if len(place.out_arcs) == 0:
            final_marking[place] = 1

    return final_marking
Exemplo n.º 18
0
 def test_mcg(self):
     net = PetriNet("mcg")
     p_1 = PetriNet.Place("p_1")
     p_2 = PetriNet.Place("p_2")
     p_3 = PetriNet.Place("p_3")
     p_4 = PetriNet.Place("p_4")
     p_5 = PetriNet.Place("p_5")
     net.places.add(p_1)
     net.places.add(p_2)
     net.places.add(p_3)
     net.places.add(p_4)
     net.places.add(p_5)
     t_1 = PetriNet.Transition("t_1", "t_1")
     t_2 = PetriNet.Transition("t_2", "t_2")
     t_3 = PetriNet.Transition("t_3", "t_3")
     t_4 = PetriNet.Transition("t_4", "t_4")
     t_5 = PetriNet.Transition("t_5", "t_5")
     t_6 = PetriNet.Transition("t_6", "t_6")
     net.transitions.add(t_1)
     net.transitions.add(t_2)
     net.transitions.add(t_3)
     net.transitions.add(t_4)
     net.transitions.add(t_5)
     net.transitions.add(t_6)
     petri_utils.add_arc_from_to(p_1, t_1, net)
     petri_utils.add_arc_from_to(t_1, p_2, net)
     petri_utils.add_arc_from_to(p_2, t_3, net)
     petri_utils.add_arc_from_to(t_3, p_3, net, weight=2)
     petri_utils.add_arc_from_to(p_3, t_4, net)
     petri_utils.add_arc_from_to(t_4, p_2, net)
     petri_utils.add_arc_from_to(p_1, t_2, net)
     petri_utils.add_arc_from_to(t_2, p_4, net)
     petri_utils.add_arc_from_to(p_4, t_5, net)
     petri_utils.add_arc_from_to(t_5, p_5, net, weight=2)
     petri_utils.add_arc_from_to(p_5, t_6, net)
     petri_utils.add_arc_from_to(t_6, p_4, net)
     initial_marking = Marking()
     initial_marking[p_1] = 1
     mcg = minimal_coverability_graph.apply(net, initial_marking)
Exemplo n.º 19
0
def export_petri_tree(petrinet,
                      marking,
                      final_marking=None,
                      export_prom5=False,
                      parameters=None):
    """
    Export a Petrinet to a XML tree

    Parameters
    ----------
    petrinet: :class:`pm4py.entities.petri.petrinet.PetriNet`
        Petri net
    marking: :class:`pm4py.entities.petri.petrinet.Marking`
        Marking
    final_marking: :class:`pm4py.entities.petri.petrinet.Marking`
        Final marking (optional)
    export_prom5
        Enables exporting PNML files in a format that is ProM5-friendly
    parameters
        Other parameters of the algorithm

    Returns
    ----------
    tree
        XML tree
    """
    if parameters is None:
        parameters = {}

    if final_marking is None:
        final_marking = Marking()

    root = etree.Element("pnml")
    net = etree.SubElement(root, "net")
    net.set("id", "net1")
    net.set("type", "http://www.pnml.org/version-2009/grammar/pnmlcoremodel")
    if export_prom5 is True:
        page = net
    else:
        page = etree.SubElement(net, "page")
        page.set("id", "n0")
    places_map = {}
    for place in petrinet.places:
        places_map[place] = place.name
        pl = etree.SubElement(page, "place")
        pl.set("id", place.name)
        pl_name = etree.SubElement(pl, "name")
        pl_name_text = etree.SubElement(pl_name, "text")
        pl_name_text.text = place.properties[
            constants.
            PLACE_NAME_TAG] if constants.PLACE_NAME_TAG in place.properties else place.name
        if place in marking:
            pl_initial_marking = etree.SubElement(pl, "initialMarking")
            pl_initial_marking_text = etree.SubElement(pl_initial_marking,
                                                       "text")
            pl_initial_marking_text.text = str(marking[place])
        if constants.LAYOUT_INFORMATION_PETRI in place.properties:
            graphics = etree.SubElement(pl, "graphics")
            position = etree.SubElement(graphics, "position")
            position.set(
                "x",
                str(place.properties[constants.LAYOUT_INFORMATION_PETRI][0]
                    [0]))
            position.set(
                "y",
                str(place.properties[constants.LAYOUT_INFORMATION_PETRI][0]
                    [1]))
            dimension = etree.SubElement(graphics, "dimension")
            dimension.set(
                "x",
                str(place.properties[constants.LAYOUT_INFORMATION_PETRI][1]
                    [0]))
            dimension.set(
                "y",
                str(place.properties[constants.LAYOUT_INFORMATION_PETRI][1]
                    [1]))
    transitions_map = {}
    for transition in petrinet.transitions:
        transitions_map[transition] = transition.name
        trans = etree.SubElement(page, "transition")
        trans.set("id", transition.name)
        trans_name = etree.SubElement(trans, "name")
        trans_text = etree.SubElement(trans_name, "text")
        if constants.LAYOUT_INFORMATION_PETRI in transition.properties:
            graphics = etree.SubElement(trans, "graphics")
            position = etree.SubElement(graphics, "position")
            position.set(
                "x",
                str(transition.properties[constants.LAYOUT_INFORMATION_PETRI]
                    [0][0]))
            position.set(
                "y",
                str(transition.properties[constants.LAYOUT_INFORMATION_PETRI]
                    [0][1]))
            dimension = etree.SubElement(graphics, "dimension")
            dimension.set(
                "x",
                str(transition.properties[constants.LAYOUT_INFORMATION_PETRI]
                    [1][0]))
            dimension.set(
                "y",
                str(transition.properties[constants.LAYOUT_INFORMATION_PETRI]
                    [1][1]))
        if constants.STOCHASTIC_DISTRIBUTION in transition.properties:
            random_variable = transition.properties[
                constants.STOCHASTIC_DISTRIBUTION]
            stochastic_information = etree.SubElement(trans, "toolspecific")
            stochastic_information.set("tool", "StochasticPetriNet")
            stochastic_information.set("version", "0.2")
            distribution_type = etree.SubElement(stochastic_information,
                                                 "property")
            distribution_type.set("key", "distributionType")
            distribution_type.text = random_variable.get_distribution_type()
            if not random_variable.get_distribution_type() == "IMMEDIATE":
                distribution_parameters = etree.SubElement(
                    stochastic_information, "property")
                distribution_parameters.set("key", "distributionParameters")
                distribution_parameters.text = random_variable.get_distribution_parameters(
                )
            distribution_priority = etree.SubElement(stochastic_information,
                                                     "property")
            distribution_priority.set("key", "priority")
            distribution_priority.text = str(random_variable.get_priority())
            distribution_invisible = etree.SubElement(stochastic_information,
                                                      "property")
            distribution_invisible.set("key", "invisible")
            distribution_invisible.text = str(
                True if transition.label is None else False).lower()
            distribution_weight = etree.SubElement(stochastic_information,
                                                   "property")
            distribution_weight.set("key", "weight")
            distribution_weight.text = str(random_variable.get_weight())
        if transition.label is not None:
            trans_text.text = transition.label
        else:
            trans_text.text = transition.name
            tool_specific = etree.SubElement(trans, "toolspecific")
            tool_specific.set("tool", "ProM")
            tool_specific.set("version", "6.4")
            tool_specific.set("activity", "$invisible$")
            tool_specific.set("localNodeID", str(uuid.uuid4()))
        if export_prom5 is True:
            if transition.label is not None:
                prom5_specific = etree.SubElement(trans, "toolspecific")
                prom5_specific.set("tool", "ProM")
                prom5_specific.set("version", "5.2")
                log_event_prom5 = etree.SubElement(prom5_specific, "logevent")
                event_name = transition.label.split("+")[0]
                event_transition = transition.label.split("+")[1] if len(
                    transition.label.split("+")) > 1 else "complete"
                log_event_prom5_name = etree.SubElement(
                    log_event_prom5, "name")
                log_event_prom5_name.text = event_name
                log_event_prom5_type = etree.SubElement(
                    log_event_prom5, "type")
                log_event_prom5_type.text = event_transition
    for arc in petrinet.arcs:
        arc_el = etree.SubElement(page, "arc")
        arc_el.set("id", str(hash(arc)))
        if type(arc.source) is PetriNet.Place:
            arc_el.set("source", str(places_map[arc.source]))
            arc_el.set("target", str(transitions_map[arc.target]))
        else:
            arc_el.set("source", str(transitions_map[arc.source]))
            arc_el.set("target", str(places_map[arc.target]))

        if arc.weight > 1:
            inscription = etree.SubElement(arc_el, "inscription")
            arc_weight = etree.SubElement(inscription, "text")
            arc_weight.text = str(arc.weight)

    if len(final_marking) > 0:
        finalmarkings = etree.SubElement(net, "finalmarkings")
        marking = etree.SubElement(finalmarkings, "marking")

        for place in final_marking:
            placem = etree.SubElement(marking, "place")
            placem.set("idref", place.name)
            placem_text = etree.SubElement(placem, "text")
            placem_text.text = str(final_marking[place])
    tree = etree.ElementTree(root)

    return tree
Exemplo n.º 20
0
def graphviz_visualization(net,
                           image_format="png",
                           initial_marking=None,
                           final_marking=None,
                           decorations=None,
                           debug=False,
                           set_rankdir=None,
                           font_size="12",
                           bgcolor="transparent"):
    """
    Provides visualization for the petrinet

    Parameters
    ----------
    net: :class:`pm4py.entities.petri.petrinet.PetriNet`
        Petri net
    image_format
        Format that should be associated to the image
    initial_marking
        Initial marking of the Petri net
    final_marking
        Final marking of the Petri net
    decorations
        Decorations of the Petri net (says how element must be presented)
    debug
        Enables debug mode
    set_rankdir
        Sets the rankdir to LR (horizontal layout)

    Returns
    -------
    viz :
        Returns a graph object
    """
    if initial_marking is None:
        initial_marking = Marking()
    if final_marking is None:
        final_marking = Marking()
    if decorations is None:
        decorations = {}

    font_size = str(font_size)

    filename = tempfile.NamedTemporaryFile(suffix='.gv')
    viz = Digraph(net.name,
                  filename=filename.name,
                  engine='dot',
                  graph_attr={'bgcolor': bgcolor})
    if set_rankdir:
        viz.graph_attr['rankdir'] = set_rankdir
    else:
        viz.graph_attr['rankdir'] = 'LR'

    # transitions
    viz.attr('node', shape='box')
    for t in net.transitions:
        if t.label is not None:
            if t in decorations and "label" in decorations[
                    t] and "color" in decorations[t]:
                viz.node(str(id(t)),
                         decorations[t]["label"],
                         style='filled',
                         fillcolor=decorations[t]["color"],
                         border='1',
                         fontsize=font_size)
            else:
                viz.node(str(id(t)), str(t.label), fontsize=font_size)
        else:
            if debug:
                viz.node(str(id(t)), str(t.name), fontsize=font_size)
            elif t in decorations and "color" in decorations[
                    t] and "label" in decorations[t]:
                viz.node(str(id(t)),
                         decorations[t]["label"],
                         style='filled',
                         fillcolor=decorations[t]["color"],
                         fontsize=font_size)
            else:
                viz.node(str(id(t)),
                         "",
                         style='filled',
                         fillcolor="black",
                         fontsize=font_size)

    # places
    viz.attr('node', shape='circle', fixedsize='true', width='0.75')
    # add places, in order by their (unique) name, to avoid undeterminism in the visualization
    places_sort_list_im = sorted(
        [x for x in list(net.places) if x in initial_marking],
        key=lambda x: x.name)
    places_sort_list_fm = sorted([
        x for x in list(net.places)
        if x in final_marking and not x in initial_marking
    ],
                                 key=lambda x: x.name)
    places_sort_list_not_im_fm = sorted([
        x for x in list(net.places)
        if x not in initial_marking and x not in final_marking
    ],
                                        key=lambda x: x.name)
    # making the addition happen in this order:
    # - first, the places belonging to the initial marking
    # - after, the places not belonging neither to the initial marking and the final marking
    # - at last, the places belonging to the final marking (but not to the initial marking)
    # in this way, is more probable that the initial marking is on the left and the final on the right
    places_sort_list = places_sort_list_im + places_sort_list_not_im_fm + places_sort_list_fm

    for p in places_sort_list:
        if p in initial_marking:
            viz.node(str(id(p)),
                     str(initial_marking[p]),
                     style='filled',
                     fillcolor="green",
                     fontsize=font_size)
        elif p in final_marking:
            viz.node(str(id(p)),
                     "",
                     style='filled',
                     fillcolor="orange",
                     fontsize=font_size)
        else:
            if debug:
                viz.node(str(id(p)), str(p.name), fontsize=font_size)
            else:
                if p in decorations and "color" in decorations[
                        p] and "label" in decorations[p]:
                    viz.node(str(id(p)),
                             decorations[p]["label"],
                             style='filled',
                             fillcolor=decorations[p]["color"],
                             fontsize=font_size)
                else:
                    viz.node(str(id(p)), "")

    # add arcs, in order by their source and target objects names, to avoid undeterminism in the visualization
    arcs_sort_list = sorted(list(net.arcs),
                            key=lambda x: (x.source.name, x.target.name))
    for a in arcs_sort_list:
        if a in decorations and "label" in decorations[
                a] and "penwidth" in decorations[a]:
            viz.edge(str(id(a.source)),
                     str(id(a.target)),
                     label=decorations[a]["label"],
                     penwidth=decorations[a]["penwidth"],
                     fontsize=font_size)
        elif a in decorations and "color" in decorations[a]:
            viz.edge(str(id(a.source)),
                     str(id(a.target)),
                     color=decorations[a]["color"],
                     fontsize=font_size)
        else:
            viz.edge(str(id(a.source)), str(id(a.target)), fontsize=font_size)
    viz.attr(overlap='false')

    viz.format = image_format

    return viz
Exemplo n.º 21
0
def apply(heu_net, parameters=None):
    """
    Converts an Heuristics Net to a Petri net

    Parameters
    --------------
    heu_net
        Heuristics net
    parameters
        Possible parameters of the algorithm

    Returns
    --------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    """
    if parameters is None:
        parameters = {}
    net = PetriNet("")
    im = Marking()
    fm = Marking()
    source_places = []
    sink_places = []
    hid_trans_count = 0
    for index, sa_list in enumerate(heu_net.start_activities):
        source = PetriNet.Place("source" + str(index))
        source_places.append(source)
        net.places.add(source)
        im[source] = 1
    for index, ea_list in enumerate(heu_net.end_activities):
        sink = PetriNet.Place("sink" + str(index))
        sink_places.append(sink)
        net.places.add(sink)
        fm[sink] = 1
    act_trans = {}
    who_is_entering = {}
    who_is_exiting = {}
    for act1_name in heu_net.nodes:
        act1 = heu_net.nodes[act1_name]
        if act1_name not in act_trans:
            act_trans[act1_name] = PetriNet.Transition(act1_name, act1_name)
            net.transitions.add(act_trans[act1_name])
            who_is_entering[act1_name] = set()
            who_is_exiting[act1_name] = set()
            for index, sa_list in enumerate(heu_net.start_activities):
                if act1_name in sa_list:
                    who_is_entering[act1_name].add((None, index))
            for index, ea_list in enumerate(heu_net.end_activities):
                if act1_name in ea_list:
                    who_is_exiting[act1_name].add((None, index))
        for act2 in act1.output_connections:
            act2_name = act2.node_name
            if act2_name not in act_trans:
                act_trans[act2_name] = PetriNet.Transition(
                    act2_name, act2_name)
                net.transitions.add(act_trans[act2_name])
                who_is_entering[act2_name] = set()
                who_is_exiting[act2_name] = set()
                for index, sa_list in enumerate(heu_net.start_activities):
                    if act2_name in sa_list:
                        who_is_entering[act2_name].add((None, index))
                for index, ea_list in enumerate(heu_net.end_activities):
                    if act2_name in ea_list:
                        who_is_exiting[act2_name].add((None, index))
            who_is_entering[act2_name].add((act1_name, None))
            who_is_exiting[act1_name].add((act2_name, None))
    places_entering = {}
    for act1 in who_is_entering:
        cliques = find_bindings(heu_net.nodes[act1].and_measures_in)
        places_entering[act1] = {}
        entering_activities = list(who_is_entering[act1])
        entering_activities_wo_source = sorted(
            [x for x in entering_activities if x[0] is not None],
            key=lambda x: x[0])
        entering_activities_only_source = [
            x for x in entering_activities if x[0] is None
        ]
        if entering_activities_wo_source:
            master_place = PetriNet.Place("pre_" + act1)
            net.places.add(master_place)
            add_arc_from_to(master_place, act_trans[act1], net)
            if len(entering_activities) == 1:
                places_entering[act1][entering_activities[0]] = master_place
            else:
                for index, act in enumerate(entering_activities_wo_source):
                    if act[0] in heu_net.nodes[act1].and_measures_in:
                        z = 0
                        while z < len(cliques):
                            if act[0] in cliques[z]:
                                hid_trans_count = hid_trans_count + 1
                                hid_trans = PetriNet.Transition(
                                    "hid_" + str(hid_trans_count), None)
                                net.transitions.add(hid_trans)
                                add_arc_from_to(hid_trans, master_place, net)
                                for act2 in cliques[z]:
                                    if (act2,
                                            None) not in places_entering[act1]:
                                        s_place = PetriNet.Place("splace_in_" +
                                                                 act1 + "_" +
                                                                 act2 + "_" +
                                                                 str(index))
                                        net.places.add(s_place)
                                        places_entering[act1][(act2,
                                                               None)] = s_place
                                    add_arc_from_to(
                                        places_entering[act1][(act2, None)],
                                        hid_trans, net)
                                del cliques[z]
                                continue
                            z = z + 1
                        pass
                    elif act not in places_entering[act1]:
                        hid_trans_count = hid_trans_count + 1
                        hid_trans = PetriNet.Transition(
                            "hid_" + str(hid_trans_count), None)
                        net.transitions.add(hid_trans)
                        add_arc_from_to(hid_trans, master_place, net)
                        if act not in places_entering[act1]:
                            s_place = PetriNet.Place("splace_in_" + act1 +
                                                     "_" + str(index))
                            net.places.add(s_place)
                            places_entering[act1][act] = s_place
                        add_arc_from_to(places_entering[act1][act], hid_trans,
                                        net)
        for el in entering_activities_only_source:
            if len(entering_activities) == 1:
                add_arc_from_to(source_places[el[1]], act_trans[act1], net)
            else:
                hid_trans_count = hid_trans_count + 1
                hid_trans = PetriNet.Transition("hid_" + str(hid_trans_count),
                                                None)
                net.transitions.add(hid_trans)
                add_arc_from_to(source_places[el[1]], hid_trans, net)
                add_arc_from_to(hid_trans, master_place, net)
    for act1 in who_is_exiting:
        cliques = find_bindings(heu_net.nodes[act1].and_measures_out)
        exiting_activities = list(who_is_exiting[act1])
        exiting_activities_wo_sink = sorted(
            [x for x in exiting_activities if x[0] is not None],
            key=lambda x: x[0])
        exiting_activities_only_sink = [
            x for x in exiting_activities if x[0] is None
        ]
        if exiting_activities_wo_sink:
            if len(exiting_activities) == 1 and len(
                    exiting_activities_wo_sink) == 1:
                ex_act = exiting_activities_wo_sink[0]
                if (act1, None) in places_entering[ex_act[0]]:
                    add_arc_from_to(act_trans[act1],
                                    places_entering[ex_act[0]][(act1, None)],
                                    net)
            else:
                int_place = PetriNet.Place("intplace_" + str(act1))
                net.places.add(int_place)
                add_arc_from_to(act_trans[act1], int_place, net)
                for ex_act in exiting_activities_wo_sink:
                    if (act1, None) in places_entering[ex_act[0]]:
                        if ex_act[0] in heu_net.nodes[act1].and_measures_out:
                            z = 0
                            while z < len(cliques):
                                if ex_act[0] in cliques[z]:
                                    hid_trans_count = hid_trans_count + 1
                                    hid_trans = PetriNet.Transition(
                                        "hid_" + str(hid_trans_count), None)
                                    net.transitions.add(hid_trans)
                                    add_arc_from_to(int_place, hid_trans, net)
                                    for act in cliques[z]:
                                        add_arc_from_to(
                                            hid_trans,
                                            places_entering[act][(act1, None)],
                                            net)
                                    del cliques[z]
                                    continue
                                z = z + 1
                        else:
                            hid_trans_count = hid_trans_count + 1
                            hid_trans = PetriNet.Transition(
                                "hid_" + str(hid_trans_count), None)
                            net.transitions.add(hid_trans)
                            add_arc_from_to(int_place, hid_trans, net)
                            add_arc_from_to(
                                hid_trans,
                                places_entering[ex_act[0]][(act1, None)], net)
        for el in exiting_activities_only_sink:
            if len(exiting_activities) == 1:
                add_arc_from_to(act_trans[act1], sink_places[el[1]], net)
            else:
                hid_trans_count = hid_trans_count + 1
                hid_trans = PetriNet.Transition("hid_" + str(hid_trans_count),
                                                None)
                net.transitions.add(hid_trans)
                add_arc_from_to(int_place, hid_trans, net)
                add_arc_from_to(hid_trans, sink_places[el[1]], net)
    net = remove_rendundant_invisible_transitions(net)
    from pm4py.objects.petri_net.utils import reduction
    reduction.apply_simple_reduction(net)
    return net, im, fm
Exemplo n.º 22
0
def graphviz_visualization(net,
                           image_format="png",
                           initial_marking=None,
                           final_marking=None,
                           decorations=None,
                           debug=False,
                           set_rankdir=None,
                           font_size="12",
                           bgcolor="transparent"):
    """
    Provides visualization for the petrinet

    Parameters
    ----------
    net: :class:`pm4py.entities.petri.petrinet.PetriNet`
        Petri net
    image_format
        Format that should be associated to the image
    initial_marking
        Initial marking of the Petri net
    final_marking
        Final marking of the Petri net
    decorations
        Decorations of the Petri net (says how element must be presented)
    debug
        Enables debug mode
    set_rankdir
        Sets the rankdir to LR (horizontal layout)

    Returns
    -------
    viz :
        Returns a graph object
    """
    if initial_marking is None:
        initial_marking = Marking()
    if final_marking is None:
        final_marking = Marking()
    if decorations is None:
        decorations = {}

    font_size = str(font_size)

    filename = tempfile.NamedTemporaryFile(suffix='.gv')
    viz = Digraph(net.name,
                  filename=filename.name,
                  engine='dot',
                  graph_attr={'bgcolor': bgcolor})
    if set_rankdir:
        viz.graph_attr['rankdir'] = set_rankdir
    else:
        viz.graph_attr['rankdir'] = 'LR'

    # transitions
    viz.attr('node', shape='box')
    for t in net.transitions:
        if t.label is not None:
            if t in decorations and "label" in decorations[
                    t] and "color" in decorations[t]:
                viz.node(str(id(t)),
                         decorations[t]["label"],
                         style='filled',
                         fillcolor=decorations[t]["color"],
                         border='1',
                         fontsize=font_size)
            else:
                viz.node(str(id(t)), str(t.label), fontsize=font_size)
        else:
            if debug:
                viz.node(str(id(t)), str(t.name), fontsize=font_size)
            elif t in decorations and "color" in decorations[
                    t] and "label" in decorations[t]:
                viz.node(str(id(t)),
                         decorations[t]["label"],
                         style='filled',
                         fillcolor=decorations[t]["color"],
                         fontsize=font_size)
            else:
                viz.node(str(id(t)),
                         "",
                         style='filled',
                         fillcolor="black",
                         fontsize=font_size)

        if petri_properties.TRANS_GUARD in t.properties:
            guard = t.properties[petri_properties.TRANS_GUARD]
            viz.node(str(id(t)) + "guard", style="dotted", label=guard)
            viz.edge(str(id(t)) + "guard",
                     str(id(t)),
                     arrowhead="none",
                     style="dotted")

    # places
    # add places, in order by their (unique) name, to avoid undeterminism in the visualization
    places_sort_list_im = sorted(
        [x for x in list(net.places) if x in initial_marking],
        key=lambda x: x.name)
    places_sort_list_fm = sorted([
        x for x in list(net.places)
        if x in final_marking and not x in initial_marking
    ],
                                 key=lambda x: x.name)
    places_sort_list_not_im_fm = sorted([
        x for x in list(net.places)
        if x not in initial_marking and x not in final_marking
    ],
                                        key=lambda x: x.name)
    # making the addition happen in this order:
    # - first, the places belonging to the initial marking
    # - after, the places not belonging neither to the initial marking and the final marking
    # - at last, the places belonging to the final marking (but not to the initial marking)
    # in this way, is more probable that the initial marking is on the left and the final on the right
    places_sort_list = places_sort_list_im + places_sort_list_not_im_fm + places_sort_list_fm

    for p in places_sort_list:
        if p in initial_marking:
            if initial_marking[p] == 1:
                viz.node(str(id(p)),
                         "<&#9679;>",
                         fontsize="34",
                         fixedsize='true',
                         shape="circle",
                         width='0.75')
            else:
                viz.node(str(id(p)),
                         str(initial_marking[p]),
                         fontsize="34",
                         fixedsize='true',
                         shape="circle",
                         width='0.75')
        elif p in final_marking:
            # <&#9632;>
            viz.node(str(id(p)),
                     "<&#9632;>",
                     fontsize="32",
                     shape='doublecircle',
                     fixedsize='true',
                     width='0.75')
        else:
            if debug:
                viz.node(str(id(p)),
                         str(p.name),
                         fontsize=font_size,
                         shape="ellipse")
            else:
                if p in decorations and "color" in decorations[
                        p] and "label" in decorations[p]:
                    viz.node(str(id(p)),
                             decorations[p]["label"],
                             style='filled',
                             fillcolor=decorations[p]["color"],
                             fontsize=font_size,
                             shape="ellipse")
                else:
                    viz.node(str(id(p)),
                             "",
                             shape='circle',
                             fixedsize='true',
                             width='0.75')

    # add arcs, in order by their source and target objects names, to avoid undeterminism in the visualization
    arcs_sort_list = sorted(list(net.arcs),
                            key=lambda x: (x.source.name, x.target.name))

    # check if there is an arc with weight different than 1.
    # in that case, all the arcs in the visualization should have the arc weight visible
    arc_weight_visible = False
    for arc in arcs_sort_list:
        if arc.weight != 1:
            arc_weight_visible = True
            break

    for a in arcs_sort_list:
        arrowhead = "normal"
        if petri_properties.ARCTYPE in a.properties:
            if a.properties[
                    petri_properties.ARCTYPE] == petri_properties.RESET_ARC:
                arrowhead = "vee"
            elif a.properties[petri_properties.
                              ARCTYPE] == petri_properties.INHIBITOR_ARC:
                arrowhead = "dot"
        if a in decorations and "label" in decorations[
                a] and "penwidth" in decorations[a]:
            viz.edge(str(id(a.source)),
                     str(id(a.target)),
                     label=decorations[a]["label"],
                     penwidth=decorations[a]["penwidth"],
                     fontsize=font_size,
                     arrowhead=arrowhead)
        elif a in decorations and "color" in decorations[a]:
            viz.edge(str(id(a.source)),
                     str(id(a.target)),
                     color=decorations[a]["color"],
                     fontsize=font_size,
                     arrowhead=arrowhead)
        else:
            if arc_weight_visible:
                viz.edge(str(id(a.source)),
                         str(id(a.target)),
                         fontsize=font_size,
                         arrowhead=arrowhead,
                         label=str(a.weight))
            else:
                viz.edge(str(id(a.source)),
                         str(id(a.target)),
                         fontsize=font_size,
                         arrowhead=arrowhead)
    viz.attr(overlap='false')

    viz.format = image_format

    return viz
def apply(dfg, parameters=None):
    """
    Applies the DFG mining on a given object (if it is a Pandas dataframe or a log, the DFG is calculated)

    Parameters
    -------------
    dfg
        Object (DFG) (if it is a Pandas dataframe or a log, the DFG is calculated)
    parameters
        Parameters
    """
    if parameters is None:
        parameters = {}

    dfg = dfg
    start_activities = exec_utils.get_param_value(
        Parameters.START_ACTIVITIES, parameters,
        dfg_utils.infer_start_activities(dfg))
    end_activities = exec_utils.get_param_value(
        Parameters.END_ACTIVITIES, parameters,
        dfg_utils.infer_end_activities(dfg))
    activities = dfg_utils.get_activities_from_dfg(dfg)

    net = PetriNet("")
    im = Marking()
    fm = Marking()

    source = PetriNet.Place("source")
    net.places.add(source)
    im[source] = 1
    sink = PetriNet.Place("sink")
    net.places.add(sink)
    fm[sink] = 1

    places_corr = {}
    index = 0

    for act in activities:
        places_corr[act] = PetriNet.Place(act)
        net.places.add(places_corr[act])

    for act in start_activities:
        if act in places_corr:
            index = index + 1
            trans = PetriNet.Transition(act + "_" + str(index), act)
            net.transitions.add(trans)
            pn_util.add_arc_from_to(source, trans, net)
            pn_util.add_arc_from_to(trans, places_corr[act], net)

    for act in end_activities:
        if act in places_corr:
            index = index + 1
            inv_trans = PetriNet.Transition(act + "_" + str(index), None)
            net.transitions.add(inv_trans)
            pn_util.add_arc_from_to(places_corr[act], inv_trans, net)
            pn_util.add_arc_from_to(inv_trans, sink, net)

    for el in dfg.keys():
        act1 = el[0]
        act2 = el[1]

        index = index + 1
        trans = PetriNet.Transition(act2 + "_" + str(index), act2)
        net.transitions.add(trans)

        pn_util.add_arc_from_to(places_corr[act1], trans, net)
        pn_util.add_arc_from_to(trans, places_corr[act2], net)

    return net, im, fm
Exemplo n.º 24
0
def align_fake_log_stop_marking(fake_log, net, marking, final_marking, parameters=None):
    """
    Align the 'fake' log with all the prefixes in order to get the markings in which
    the alignment stops

    Parameters
    -------------
    fake_log
        Fake log
    net
        Petri net
    marking
        Marking
    final_marking
        Final marking
    parameters
        Parameters of the algorithm

    Returns
    -------------
    alignment
        For each trace in the log, return the marking in which the alignment stops (expressed as place name with count)
    """
    if parameters is None:
        parameters = {}

    show_progress_bar = exec_utils.get_param_value(Parameters.SHOW_PROGRESS_BAR, parameters, True)

    align_result = []

    progress = None
    if pkgutil.find_loader("tqdm") and show_progress_bar and len(fake_log) > 1:
        from tqdm.auto import tqdm
        progress = tqdm(total=len(fake_log), desc="computing precision with alignments, completed variants :: ")

    for i in range(len(fake_log)):
        trace = fake_log[i]
        sync_net, sync_initial_marking, sync_final_marking = build_sync_net(trace, net, marking, final_marking,
                                                                            parameters=parameters)
        stop_marking = Marking()
        for pl, count in sync_final_marking.items():
            if pl.name[1] == utils.SKIP:
                stop_marking[pl] = count
        cost_function = utils.construct_standard_cost_function(sync_net, utils.SKIP)

        # perform the alignment of the prefix
        res = precision_utils.__search(sync_net, sync_initial_marking, sync_final_marking, stop_marking, cost_function,
                                       utils.SKIP)

        if res is not None:
            align_result.append([])
            for mark in res:
                res2 = {}
                for pl in mark:
                    # transforms the markings for easier correspondence at the end
                    # (distributed engine friendly!)
                    res2[(pl.name[0], pl.name[1])] = mark[pl]

                align_result[-1].append(res2)
        else:
            # if there is no path from the initial marking
            # replaying the given prefix, then add None
            align_result.append(None)
        if progress is not None:
            progress.update()

    # gracefully close progress bar
    if progress is not None:
        progress.close()
    del progress

    return align_result
Exemplo n.º 25
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
Exemplo n.º 26
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)
Exemplo n.º 27
0
def apply(log, net, initial_marking, final_marking, parameters=None):
    """
    Method to apply token-based replay

    Parameters
    -----------
    log
        Log
    net
        Petri net
    initial_marking
        Initial marking
    final_marking
        Final marking
    parameters
        Parameters of the algorithm
    """
    if parameters is None:
        parameters = {}

    for t in net.transitions:
        ma = Marking()
        for a in t.out_arcs:
            p = a.target
            ma[p] = a.weight
        t.out_marking = ma

    for t in net.transitions:
        ma = Marking()
        for a in t.in_arcs:
            p = a.source
            ma[p] = a.weight
        t.in_marking = ma

    variants_idxs = variants_filter.get_variants_from_log_trace_idx(
        log, parameters=parameters)
    results = []

    tmap = {}
    bmap = {}
    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)

    for variant in variants_idxs:
        vlist = variants_util.get_activities_from_variant(variant)
        result = tr_vlist(vlist,
                          net,
                          initial_marking,
                          final_marking,
                          tmap,
                          bmap,
                          parameters=parameters)
        results.append(result)

    al_idx = {}
    for index_variant, variant in enumerate(variants_idxs):
        for trace_idx in variants_idxs[variant]:
            al_idx[trace_idx] = results[index_variant]

    ret = []
    for i in range(len(log)):
        ret.append(al_idx[i])

    return ret
Exemplo n.º 28
0
def apply_dfg_sa_ea(
    dfg: Dict[str, int],
    start_activities: Union[None, Dict[str, int]],
    end_activities: Union[None, Dict[str, int]],
    parameters: Optional[Dict[Union[str, Parameters], Any]] = None
) -> Tuple[PetriNet, Marking, Marking]:
    """
    Applying Alpha Miner starting from the knowledge of the Directly Follows graph,
    and of the start activities and end activities in the log (possibly inferred from the DFG)

    Parameters
    ------------
    dfg
        Directly-Follows graph
    start_activities
        Start activities
    end_activities
        End activities
    parameters
        Parameters of the algorithm including:
            activity key -> name of the attribute that contains the activity

    Returns
    -------
    net : :class:`pm4py.entities.petri.petrinet.PetriNet`
        A Petri net describing the event log that is provided as an input
    initial marking : :class:`pm4py.models.net.Marking`
        marking object representing the initial marking
    final marking : :class:`pm4py.models.net.Marking`
        marking object representing the final marking, not guaranteed that it is actually reachable!
    """
    if parameters is None:
        parameters = {}

    activity_key = exec_utils.get_param_value(
        Parameters.ACTIVITY_KEY, parameters,
        pm_util.xes_constants.DEFAULT_NAME_KEY)

    if start_activities is None:
        start_activities = dfg_utils.infer_start_activities(dfg)

    if end_activities is None:
        end_activities = dfg_utils.infer_end_activities(dfg)

    labels = set()
    for el in dfg:
        labels.add(el[0])
        labels.add(el[1])
    for a in start_activities:
        labels.add(a)
    for a in end_activities:
        labels.add(a)
    labels = list(labels)

    alpha_abstraction = alpha_classic_abstraction.ClassicAlphaAbstraction(
        start_activities, end_activities, dfg, activity_key=activity_key)
    pairs = list(
        map(
            lambda p: ({p[0]}, {p[1]}),
            filter(
                lambda p: __initial_filter(alpha_abstraction.parallel_relation,
                                           p),
                alpha_abstraction.causal_relation)))
    for i in range(0, len(pairs)):
        t1 = pairs[i]
        for j in range(i, len(pairs)):
            t2 = pairs[j]
            if t1 != t2:
                if t1[0].issubset(t2[0]) or t1[1].issubset(t2[1]):
                    if not (__check_is_unrelated(
                            alpha_abstraction.parallel_relation,
                            alpha_abstraction.causal_relation, t1[0], t2[0])
                            or __check_is_unrelated(
                                alpha_abstraction.parallel_relation,
                                alpha_abstraction.causal_relation, t1[1],
                                t2[1])):
                        new_alpha_pair = (t1[0] | t2[0], t1[1] | t2[1])
                        if new_alpha_pair not in pairs:
                            pairs.append((t1[0] | t2[0], t1[1] | t2[1]))
    internal_places = filter(lambda p: __pair_maximizer(pairs, p), pairs)
    net = PetriNet('alpha_classic_net_' + str(time.time()))
    label_transition_dict = {}

    for i in range(0, len(labels)):
        label_transition_dict[labels[i]] = PetriNet.Transition(
            labels[i], labels[i])
        net.transitions.add(label_transition_dict[labels[i]])

    src = __add_source(net, alpha_abstraction.start_activities,
                       label_transition_dict)
    sink = __add_sink(net, alpha_abstraction.end_activities,
                      label_transition_dict)

    for pair in internal_places:
        place = PetriNet.Place(str(pair))
        net.places.add(place)
        for in_arc in pair[0]:
            add_arc_from_to(label_transition_dict[in_arc], place, net)
        for out_arc in pair[1]:
            add_arc_from_to(place, label_transition_dict[out_arc], net)
    return net, Marking({src: 1}), Marking({sink: 1})
Exemplo n.º 29
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
Exemplo n.º 30
0
def processing(log: EventLog, causal: Tuple[str, str], follows: Tuple[str,
                                                                      str]):
    """
    Applying the Alpha Miner with the new relations

    Parameters
    -------------
    log
        Filtered log
    causal
        Pairs that have a causal relation (->)
    follows
        Pairs that have a follow relation (>)

    Returns
    -------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    """
    # create list of all events
    labels = set()
    start_activities = set()
    end_activities = set()
    for trace in log:
        start_activities.add(trace.__getitem__(0))
        end_activities.add(trace.__getitem__(len(trace) - 1))
        for events in trace:
            labels.add(events)
    labels = list(labels)
    pairs = []

    for key, element in causal.items():
        for item in element:
            if get_sharp_relation(follows, key, key):
                if get_sharp_relation(follows, item, item):
                    pairs.append(({key}, {item}))

    # combining pairs
    for i in range(0, len(pairs)):
        t1 = pairs[i]
        for j in range(i, len(pairs)):
            t2 = pairs[j]
            if t1 != t2:
                if t1[0].issubset(t2[0]) or t1[1].issubset(t2[1]):
                    if get_sharp_relations_for_sets(
                            follows, t1[0],
                            t2[0]) and get_sharp_relations_for_sets(
                                follows, t1[1], t2[1]):
                        new_alpha_pair = (t1[0] | t2[0], t1[1] | t2[1])
                        if new_alpha_pair not in pairs:
                            pairs.append((t1[0] | t2[0], t1[1] | t2[1]))
    # maximize pairs
    cleaned_pairs = list(filter(lambda p: __pair_maximizer(pairs, p), pairs))
    # create transitions
    net = PetriNet('alpha_plus_net_' + str(time.time()))
    label_transition_dict = {}
    for label in labels:
        if label != 'artificial_start' and label != 'artificial_end':
            label_transition_dict[label] = PetriNet.Transition(label, label)
            net.transitions.add(label_transition_dict[label])
        else:
            label_transition_dict[label] = PetriNet.Transition(label, None)
            net.transitions.add(label_transition_dict[label])
    # and source and sink
    src = add_source(net, start_activities, label_transition_dict)
    sink = add_sink(net, end_activities, label_transition_dict)
    # create places
    for pair in cleaned_pairs:
        place = PetriNet.Place(str(pair))
        net.places.add(place)
        for in_arc in pair[0]:
            add_arc_from_to(label_transition_dict[in_arc], place, net)
        for out_arc in pair[1]:
            add_arc_from_to(place, label_transition_dict[out_arc], net)

    return net, Marking({src: 1}), Marking({sink: 1}), cleaned_pairs