Exemple #1
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)
Exemple #2
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
Exemple #3
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")
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
Exemple #5
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})
Exemple #6
0
def add_transition(net: PetriNet,
                   name=None,
                   label=None) -> PetriNet.Transition:
    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
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
Exemple #8
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}))
Exemple #9
0
def postprocessing(net: PetriNet, initial_marking: Marking,
                   final_marking: Marking, A, B, pairs,
                   loop_one_list) -> Tuple[PetriNet, Marking, Marking]:
    """
    Adding the filtered transitions to the Petri net

    Parameters
    ------------
    loop_list
        List of looped activities
    classical_alpha_result
        Result after applying the classic alpha algorithm to the filtered log
    A
        See Paper for definition
    B
        See Paper for definition

    Returns
    ------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    """
    label_transition_dict = {}
    for label in loop_one_list:
        label_transition_dict[label] = PetriNet.Transition(label, label)
        net.transitions.add(label_transition_dict[label])

    # F L1L
    # Key is specific loop element
    for key, value in A.items():
        if key in B:
            A_without_B = value - B[key]
            B_without_A = B[key] - value
            pair = (A_without_B, B_without_A)
            for pair_try in pairs:
                in_part = pair_try[0]
                out_part = pair_try[1]
                if pair[0].issubset(in_part) and pair[1].issubset(out_part):
                    pair_try_place = PetriNet.Place(str(pair_try))
                    net.places.add(pair_try_place)
                    add_arc_from_to(label_transition_dict[key], pair_try_place,
                                    net)
                    add_arc_from_to(pair_try_place, label_transition_dict[key],
                                    net)
    return net, initial_marking, final_marking
Exemple #10
0
def short_circuit_petri_net(net, print_diagnostics=False):
    """
    Fist, sink and source place are identified. Then, a transition from source to sink is added to short-circuited
    the given petri net. If there is no unique source and sink place, an error gets returned
    :param net: Petri net that is going to be short circuited
    :return:
    """
    s_c_net = copy.deepcopy(net)
    no_source_places = 0
    no_sink_places = 0
    sink = None
    source = None
    for place in s_c_net.places:
        if len(place.in_arcs) == 0:
            source = place
            no_source_places += 1
        if len(place.out_arcs) == 0:
            sink = place
            no_sink_places += 1
    if (sink is not None) and (
            source
            is not None) and no_source_places == 1 and no_sink_places == 1:
        # If there is one unique source and sink place, short circuit Petri Net is constructed
        t_1 = PetriNet.Transition("short_circuited_transition",
                                  "short_circuited_transition")
        s_c_net.transitions.add(t_1)
        # add arcs in short-circuited net
        petri_utils.add_arc_from_to(sink, t_1, s_c_net)
        petri_utils.add_arc_from_to(t_1, source, s_c_net)
        return s_c_net
    else:
        if sink is None:
            if print_diagnostics:
                print("There is no sink place.")
            return None
        elif source is None:
            if print_diagnostics:
                print("There is no source place.")
            return None
        elif no_source_places > 1:
            if print_diagnostics:
                print("There is more than one source place.")
            return None
        elif no_sink_places > 1:
            if print_diagnostics:
                print("There is more than one sink place.")
            return None
Exemple #11
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
Exemple #12
0
def _short_circuit_petri_net(net):
    """
    Creates a short circuited Petri net,
    whether an unique source place and sink place are there,
    by connecting the sink with the source

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

    Returns
    ---------------
    boolean
        Boolean value
    """
    s_c_net = copy.deepcopy(net)
    no_source_places = 0
    no_sink_places = 0
    sink = None
    source = None
    for place in s_c_net.places:
        if len(place.in_arcs) == 0:
            source = place
            no_source_places += 1
        if len(place.out_arcs) == 0:
            sink = place
            no_sink_places += 1
    if (sink is not None) and (
            source
            is not None) and no_source_places == 1 and no_sink_places == 1:
        # If there is one unique source and sink place, short circuit Petri Net is constructed
        t_1 = PetriNet.Transition("short_circuited_transition",
                                  "short_circuited_transition")
        s_c_net.transitions.add(t_1)
        # add arcs in short-circuited net
        pn_utils.add_arc_from_to(sink, t_1, s_c_net)
        pn_utils.add_arc_from_to(t_1, source, s_c_net)
        return s_c_net
    else:
        return None
Exemple #13
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)
def apply(dfg: Dict[Tuple[str, str], int],
          parameters: Optional[Dict[Any, Any]] = 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:
        - Parameters.START_ACTIVITIES: the start activities of the DFG
        - Parameters.END_ACTIVITIES: the end activities of the DFG

    Returns
    -------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    """
    if parameters is None:
        parameters = {}

    start_activities = exec_utils.get_param_value(
        Parameters.START_ACTIVITIES, parameters,
        {x: 1
         for x in dfg_utils.infer_start_activities(dfg)})
    end_activities = exec_utils.get_param_value(
        Parameters.END_ACTIVITIES, parameters,
        {x: 1
         for x in dfg_utils.infer_end_activities(dfg)})
    artificial_start_activity = exec_utils.get_param_value(
        Parameters.PARAM_ARTIFICIAL_START_ACTIVITY, parameters,
        constants.DEFAULT_ARTIFICIAL_START_ACTIVITY)
    artificial_end_activity = exec_utils.get_param_value(
        Parameters.PARAM_ARTIFICIAL_END_ACTIVITY, parameters,
        constants.DEFAULT_ARTIFICIAL_END_ACTIVITY)

    enriched_dfg = copy(dfg)
    for act in start_activities:
        enriched_dfg[(artificial_start_activity, act)] = start_activities[act]
    for act in end_activities:
        enriched_dfg[(act, artificial_end_activity)] = end_activities[act]
    activities = set(x[1] for x in enriched_dfg).union(
        set(x[0] for x in enriched_dfg))
    net = PetriNet("")
    im = Marking()
    fm = Marking()
    left_places = {}
    transes = {}
    right_places = {}
    for act in activities:
        pl1 = PetriNet.Place("source_" + act)
        pl2 = PetriNet.Place("sink_" + act)
        trans = PetriNet.Transition("trans_" + act, act)
        if act in [artificial_start_activity, artificial_end_activity]:
            trans.label = None
        net.places.add(pl1)
        net.places.add(pl2)
        net.transitions.add(trans)
        petri_utils.add_arc_from_to(pl1, trans, net)
        petri_utils.add_arc_from_to(trans, pl2, net)
        left_places[act] = pl1
        right_places[act] = pl2
        transes[act] = trans
    for arc in enriched_dfg:
        hidden = PetriNet.Transition(arc[0] + "_" + arc[1], None)
        net.transitions.add(hidden)
        petri_utils.add_arc_from_to(right_places[arc[0]], hidden, net)
        petri_utils.add_arc_from_to(hidden, left_places[arc[1]], net)
    im[left_places[artificial_start_activity]] = 1
    fm[right_places[artificial_end_activity]] = 1

    return net, im, fm
def discover_sound_petrinet(rules_dict, net):
    """
    Discover Intermediate Petri net which preserves soundness between XOR branches.
    
    Parameter: 
        rules (dict) : Discovered rules with the association rule metrics values
        net (PetriNet): Generated Petri net of the log
    
    Return:
        net (PetriNet): Intermediate Petri net of the log
    """
    for pair in rules_dict:
        trans_exist = 0
        #if the place already exists, We do not need to add new places, just use existing ones
        tau_t = PetriNet.Transition(f"tau_{pair[0]}{pair[1]}", None)
        for trans in net.transitions:
            if str(trans) == str(tau_t):
                trans_exist = 1
                break
        if (trans_exist == 0):
            net.transitions.add(tau_t)
            s_place = f"ps_{pair[0]}"
            t_place = f"pt_{pair[1]}"
            source_found = 0
            target_found = 0
            for place in net.places:
                if place.name == s_place:
                    source_found = 1

                    p_utils.add_arc_from_to(place, tau_t, net)

                elif place.name == t_place:
                    target_found = 1
                    p_utils.add_arc_from_to(tau_t, place, net)

                if (source_found and target_found):
                    break

            ## Handle Source Side
            # Adding new place after source
            if (not source_found):
                source = PetriNet.Place(s_place)
                net.places.add(source)
                p_utils.add_arc_from_to(source, tau_t, net)
                all_src = pair[0][1:-1].split(", ")
                #print("Sinc Dict", settings.sink_dict)
                for k, v in settings.sink_dict.items():
                    if all(item in list(map(str, settings.sink_dict[k]))
                           for item in list(all_src)):
                        #if all(elem in str(list(k)) for elem in str(pair[0])):
                        for t in net.transitions:
                            if str(t) == str(k):
                                #print("Added arc for source", t)

                                p_utils.add_arc_from_to(t, source, net)
                                break

            if (not target_found):
                target = PetriNet.Place(t_place)
                net.places.add(target)
                p_utils.add_arc_from_to(tau_t, target, net)
                all_tgt = pair[1][1:-1].split(", ")
                #print("sOURCE Dict", settings.src_dict)
                for k, v in settings.src_dict.items():
                    if all(item in list(map(str, settings.src_dict[k]))
                           for item in list(all_tgt)):
                        #if all(elem in str(list(k)) for elem in str(pair[1])):
                        for t in net.transitions:
                            if str(t) == str(k):
                                #print("Added arc for target", t)
                                p_utils.add_arc_from_to(target, t, net)
                                break

    return net
Exemple #16
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
def repair_unsound_model(net, rules_dict, support, confidence, lift):
    """
    Repairing a bordered Petri net generated from Process tree to include long-term dependencies in it and
    create a precise Petri net. Soundness parameter is not given.
    
    Parameter: 
        net (PetriNet): Generated Petri net of the log
        rules (dict) : Discovered rules with the association rule metrics values
        support (str): Threshold value for support
        confidence (str) : Threshold value for confidence 
        lift (str): Threshold value for confidence 
    
    Return:
        net (PetriNet): Repaired Petri net of the log
        rules (dict) : Added rules to the net with their association rule metrics values
    """
    rules = {}
    # p_net, im, fm = discover_petri_net(settings.PROCESS_TREE)
    for pair, value in rules_dict.items():
        if str(value[2]) > lift and str(value[0]) > support and str(
                value[1]) > confidence and value[2] > 1.001:
            rules[pair] = value
            trans_exist = 0
            #if the place already exists, We do not need to add new places, just use existing ones
            tau_t = PetriNet.Transition(f"tau_{pair[0]}{pair[1]}", None)
            for trans in net.transitions:
                if str(trans) == str(tau_t):
                    trans_exist = 1
                    break
            if (trans_exist == 0):
                net.transitions.add(tau_t)
                s_place = f"ps_{pair[0]}"
                t_place = f"pt_{pair[1]}"
                source_found = 0
                target_found = 0
                for place in net.places:
                    if place.name == s_place:
                        source_found = 1

                        p_utils.add_arc_from_to(place, tau_t, net)

                    elif place.name == t_place:
                        target_found = 1
                        p_utils.add_arc_from_to(tau_t, place, net)

                    if (source_found and target_found):
                        break

                ## Handle Source Side
                # Adding new place after source
                if (not source_found):
                    source = PetriNet.Place(s_place)
                    net.places.add(source)
                    p_utils.add_arc_from_to(source, tau_t, net)
                    all_src = pair[0][1:-1].split(", ")
                    #print("Sinc Dict", settings.sink_dict)
                    for k, v in settings.sink_dict.items():
                        #if all(elem in str(list(k)) for elem in str(pair[0])):
                        if all(item in list(map(str, settings.sink_dict[k]))
                               for item in list(all_src)):
                            for t in net.transitions:
                                if str(t) == str(k):
                                    p_utils.add_arc_from_to(t, source, net)
                                    break

                if (not target_found):
                    target = PetriNet.Place(t_place)
                    net.places.add(target)
                    p_utils.add_arc_from_to(tau_t, target, net)
                    all_tgt = pair[1][1:-1].split(", ")
                    for k, v in settings.src_dict.items():
                        if all(item in list(map(str, settings.src_dict[k]))
                               for item in list(all_tgt)):
                            #if all(elem in str(list(k)) for elem in str(pair[1])):
                            for t in net.transitions:
                                if str(t) == str(k):
                                    #print("Added arc for target", t)
                                    p_utils.add_arc_from_to(target, t, net)
                                    break

    return net, rules
Exemple #18
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
Exemple #19
0
def get_transition(counts, label):
    """
    Create a transitions with the specified label in the Petri net
    """
    counts.inc_no_visible()
    return PetriNet.Transition(str(uuid.uuid4()), label)
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
Exemple #21
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)
Exemple #22
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
Exemple #23
0
def generate_new_binary_transition(t1, t2, operator, net):
    t = PetriNet.Transition(TRANSITION_PREFIX + str(datetime.datetime.now()))
    t.label = str(operator) + '(' + generate_label_for_transition(
        t1) + ', ' + generate_label_for_transition(t2) + ')'
    return t
Exemple #24
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})
Exemple #25
0
    def construct_cost_aware(self, pn1, im1, fm1, pn2, im2, fm2, skip,
                             pn1_costs, pn2_costs, sync_costs):
        """
        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
        :param pn1_costs: dictionary mapping transitions of pn1 to corresponding costs
        :param pn2_costs: dictionary mapping transitions of pn2 to corresponding costs
        :param pn1_costs: dictionary mapping pairs of transitions in pn1 and pn2 to costs
        :param sync_costs: Costs of sync moves

        Returns
        -------
        :return: Synchronous product net and associated marking labels are of the form (a,>>)
        """
        sync_net = PetriNet('synchronous_product_net')
        t1_map, p1_map = copy_into(pn1, sync_net, True, skip)
        t2_map, p2_map = copy_into(pn2, sync_net, False, skip)
        costs = dict()
        lst_t_pn1 = []
        lst_t_pn2 = []
        for t in pn1.transitions:
            lst_t_pn1.append(t)
        for t in pn2.transitions:
            lst_t_pn2.append(t)
        lst_t_pn1.sort(key=lambda k: k.name)
        lst_t_pn2.sort(key=lambda k: k.name)

        for t1 in lst_t_pn1:
            costs[t1_map[t1]] = pn1_costs[t1]
        for t2 in lst_t_pn2:
            costs[t2_map[t2]] = pn2_costs[t2]
        for t1 in lst_t_pn1:
            for t2 in lst_t_pn2:
                if t1.label == t2.label:
                    sync = PetriNet.Transition((t1.name, t2.name),
                                               (t1.label, t2.label))
                    sync_net.transitions.add(sync)
                    costs[sync] = sync_costs[(t1, t2)]
                    # 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 = SyncMarking()
        sync_fm = SyncMarking()
        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, costs
Exemple #26
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
Exemple #27
0
    def transform_net(self, net0, initial_marking0, final_marking0, s_map, avg_time_starts):
        """
        Transform the source Petri net removing the initial and final marking, and connecting
        to each "initial" place a hidden timed transition mimicking the case start

        Parameters
        -------------
        net0
            Initial Petri net provided to the object
        initial_marking0
            Initial marking of the Petri net provided to the object
        final_marking0
            Final marking of the Petri net provided to the object
        s_map
            Stochastic map of transitions (EXPONENTIAL distribution since we assume a Markovian process)
        avg_time_starts
            Average time interlapsed between case starts

        Returns
        -------------
        net
            Petri net that will be simulated
        initial_marking
            Initial marking of the Petri net that will be simulated (empty)
        final_marking
            Final marking of the Petri net that will be simulated (empty)
        s_map
            Stochastic map of transitions enriched by new hidden case-generator transitions
        """
        # copy the Petri net object (assure that we do not change the original Petri net)
        [net1, initial_marking1, final_marking1] = copy([net0, initial_marking0, final_marking0])
        # on the copied Petri net, add a sucking transition for the final marking
        for index, place in enumerate(final_marking1):
            suck_transition = PetriNet.Transition("SUCK_TRANSITION" + str(index), None)
            net1.transitions.add(suck_transition)
            add_arc_from_to(place, suck_transition, net1)
            hidden_generator_distr = Exponential()
            hidden_generator_distr.scale = avg_time_starts
            s_map[suck_transition] = hidden_generator_distr
        # on the copied Petri net, remove both the place(s) in the initial marking and
        # the immediate transitions that are connected to it.
        target_places = []
        for place in initial_marking1:
            out_arcs = list(place.out_arcs)
            for target_arc in out_arcs:
                target_trans = target_arc.target
                if len(target_trans.in_arcs) == 1:
                    out_arcs_lev2 = list(target_trans.out_arcs)
                    for arc in out_arcs_lev2:
                        target_place = arc.target
                        target_places.append(target_place)
                    net1 = remove_transition(net1, target_trans)
            net1 = remove_place(net1, place)
        # add hidden case-generation transitions to the model.
        # all places that are left orphan by the previous operation are targeted.
        for index, place in enumerate(target_places):
            hidden_generator_trans = PetriNet.Transition("HIDDEN_GENERATOR_TRANS" + str(index), None)
            net1.transitions.add(hidden_generator_trans)
            add_arc_from_to(hidden_generator_trans, place, net1)
            hidden_generator_distr = Exponential()
            hidden_generator_distr.scale = avg_time_starts
            s_map[hidden_generator_trans] = hidden_generator_distr
        # the simulated Petri net is assumed to start from an empty initial and final marking
        initial_marking = Marking()
        final_marking = Marking()
        return net1, initial_marking, final_marking, s_map
Exemple #28
0
def get_new_hidden_trans(counts, type_trans="unknown"):
    """
    Create a new hidden transition in the Petri net
    """
    counts.inc_no_hidden()
    return PetriNet.Transition(type_trans + '_' + str(counts.num_hidden), None)
Exemple #29
0
def apply(bpmn_graph, parameters=None):
    """
    Converts a BPMN graph to an accepting Petri net

    Parameters
    --------------
    bpmn_graph
        BPMN graph
    parameters
        Parameters of the algorithm

    Returns
    --------------
    net
        Petri net
    im
        Initial marking
    fm
        Final marking
    """
    if parameters is None:
        parameters = {}

    import networkx as nx
    from pm4py.objects.bpmn.obj import BPMN

    use_id = exec_utils.get_param_value(Parameters.USE_ID, parameters, False)

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

    # keep this correspondence for adding invisible transitions for OR-gateways
    inclusive_gateway_exit = set()
    inclusive_gateway_entry = set()

    flow_place = {}
    source_count = {}
    target_count = {}
    for flow in bpmn_graph.get_flows():
        source = flow.get_source()
        target = flow.get_target()
        place = PetriNet.Place(str(flow.get_id()))
        net.places.add(place)
        flow_place[flow] = place
        if source not in source_count:
            source_count[source] = 0
        if target not in target_count:
            target_count[target] = 0
        source_count[source] = source_count[source] + 1
        target_count[target] = target_count[target] + 1

    for flow in bpmn_graph.get_flows():
        source = flow.get_source()
        target = flow.get_target()
        place = PetriNet.Place(str(flow.get_id()))
        if isinstance(source,
                      BPMN.InclusiveGateway) and source_count[source] > 1:
            inclusive_gateway_exit.add(place.name)
        elif isinstance(target,
                        BPMN.InclusiveGateway) and target_count[target] > 1:
            inclusive_gateway_entry.add(place.name)

    # remove possible places that are both in inclusive_gateway_exit and inclusive_gateway_entry,
    # because we do not need to add invisibles in this situation
    incl_gat_set_inters = inclusive_gateway_entry.intersection(
        inclusive_gateway_exit)
    inclusive_gateway_exit = inclusive_gateway_exit.difference(
        incl_gat_set_inters)
    inclusive_gateway_entry = inclusive_gateway_entry.difference(
        incl_gat_set_inters)

    nodes_entering = {}
    nodes_exiting = {}
    for node in bpmn_graph.get_nodes():
        entry_place = PetriNet.Place("ent_" + str(node.get_id()))
        net.places.add(entry_place)
        exiting_place = PetriNet.Place("exi_" + str(node.get_id()))
        net.places.add(exiting_place)
        if use_id:
            label = str(node.get_id())
        else:
            label = str(node.get_name()) if isinstance(node,
                                                       BPMN.Task) else None
            if not label:
                label = None
        transition = PetriNet.Transition(name=str(node.get_id()), label=label)
        net.transitions.add(transition)
        add_arc_from_to(entry_place, transition, net)
        add_arc_from_to(transition, exiting_place, net)

        if isinstance(node, BPMN.ParallelGateway) or isinstance(
                node, BPMN.InclusiveGateway):
            if source_count[node] > 1:
                exiting_object = PetriNet.Transition(str(uuid.uuid4()), None)
                net.transitions.add(exiting_object)
                add_arc_from_to(exiting_place, exiting_object, net)
            else:
                exiting_object = exiting_place

            if target_count[node] > 1:
                entering_object = PetriNet.Transition(str(uuid.uuid4()), None)
                net.transitions.add(entering_object)
                add_arc_from_to(entering_object, entry_place, net)
            else:
                entering_object = entry_place
            nodes_entering[node] = entering_object
            nodes_exiting[node] = exiting_object
        else:
            nodes_entering[node] = entry_place
            nodes_exiting[node] = exiting_place

        if isinstance(node, BPMN.StartEvent):
            start_transition = PetriNet.Transition(str(uuid.uuid4()), None)
            net.transitions.add(start_transition)
            add_arc_from_to(source_place, start_transition, net)
            add_arc_from_to(start_transition, entry_place, net)
        elif isinstance(node, BPMN.EndEvent):
            end_transition = PetriNet.Transition(str(uuid.uuid4()), None)
            net.transitions.add(end_transition)
            add_arc_from_to(exiting_place, end_transition, net)
            add_arc_from_to(end_transition, sink_place, net)

    for flow in bpmn_graph.get_flows():
        source_object = nodes_exiting[flow.get_source()]
        target_object = nodes_entering[flow.get_target()]

        if isinstance(source_object, PetriNet.Place):
            inv1 = PetriNet.Transition(str(uuid.uuid4()), None)
            net.transitions.add(inv1)
            add_arc_from_to(source_object, inv1, net)
            source_object = inv1

        if isinstance(target_object, PetriNet.Place):
            inv2 = PetriNet.Transition(str(uuid.uuid4()), None)
            net.transitions.add(inv2)
            add_arc_from_to(inv2, target_object, net)
            target_object = inv2

        add_arc_from_to(source_object, flow_place[flow], net)
        add_arc_from_to(flow_place[flow], target_object, net)

    if inclusive_gateway_exit and inclusive_gateway_entry:
        # do the following steps if there are inclusive gateways:
        # - calculate the shortest paths
        # - add an invisible transition between couples of corresponding places
        # this ensures soundness and the correct translation of the BPMN
        inv_places = {x.name: x for x in net.places}
        digraph = build_digraph_from_petri_net(net)
        all_shortest_paths = dict(nx.all_pairs_dijkstra(digraph))
        keys = list(all_shortest_paths.keys())

        for pl1 in inclusive_gateway_exit:
            if pl1 in keys:
                output_places = sorted(
                    [(x, len(y))
                     for x, y in all_shortest_paths[pl1][1].items()
                     if x in inclusive_gateway_entry],
                    key=lambda x: x[1])
                if output_places:
                    inv_trans = PetriNet.Transition(str(uuid.uuid4()), None)
                    net.transitions.add(inv_trans)
                    add_arc_from_to(inv_places[pl1], inv_trans, net)
                    add_arc_from_to(inv_trans, inv_places[output_places[0][0]],
                                    net)

    reduction.apply_simple_reduction(net)

    return net, im, fm