Пример #1
0
def apply(tree, parameters=None):
    '''
    Only supports loops with 2 children!
    :param tree:
    :return:
    '''
    net = obj.PetriNet(name=str(tree))
    if len(tree.children) == 0:
        pn_util.add_transition(net, label=tree.label, name=str(id(tree)))
    else:
        sub_nets = list()
        for c in tree.children:
            sub_net, ini, fin = apply(c)
            sub_nets.append(sub_net)
        pn_util.merge(net, sub_nets)
        switch = {
            pt_opt.SEQUENCE: construct_sequence_pattern,
            pt_opt.XOR: construct_xor_pattern,
            pt_opt.PARALLEL: construct_and_pattern,
            pt_opt.LOOP: construct_loop_pattern
        }
        net, ini, fin = switch[tree.operator](net, sub_nets)
    if tree.parent is None:
        p_ini = pn_util.add_place(net)
        p_fin = pn_util.add_place(net)
        pn_util.add_arc_from_to(p_ini, _get_src_transition(net), net)
        pn_util.add_arc_from_to(_get_sink_transition(net), p_fin, net)
        return net, obj.Marking({p_ini: 1}), obj.Marking({p_fin: 1})
    return net, obj.Marking(), obj.Marking()
Пример #2
0
def apply_fst_rule(net):
    """
    Apply the Fusion of Series Transitions (FST) rule

    Parameters
    --------------
    net
        Reset Inhibitor net
    """
    cont = True
    while cont:
        cont = False
        for p, t, u in itertools.product(net.places, net.transitions, net.transitions):
            if (len(list(p.in_arcs)) == 1 and list(p.in_arcs)[0].source == t) and \
                    (len(list(p.out_arcs)) == 1 and list(p.out_arcs)[0].target == u) and \
                    (len(list(u.in_arcs)) == 1 and list(u.in_arcs)[0].source == p) and \
                    (len(post_set(t).intersection(post_set(u))) == 0) and \
                    (set().union(*[post_set(place, properties.INHIBITOR_ARC) for place in post_set(u)]) == post_set(p,
                                                                                                                      properties.INHIBITOR_ARC)) and \
                    (set().union(*[post_set(place, properties.RESET_ARC) for place in post_set(u)]) == post_set(p,
                                                                                                                  properties.RESET_ARC)) and \
                    (len(pre_set(u, properties.RESET_ARC)) == 0 and len(pre_set(u, properties.INHIBITOR_ARC)) == 0):
                if u.label == None:
                    remove_place(net, p)
                    for target in post_set(u):
                        add_arc_from_to(t, target, net)
                    remove_transition(net, u)
                    cont = True
                    break

    return net
Пример #3
0
def construct_xor_pattern(net, sub_nets):
    p_s = pn_util.add_place(net)
    p_o = pn_util.add_place(net)
    for n in sub_nets:
        pn_util.add_arc_from_to(p_s, _get_src_transition(n), net)
        pn_util.add_arc_from_to(_get_sink_transition(n), p_o, net)
    return _add_src_sink_transitions(net, p_s, p_o)
Пример #4
0
def reduce_single_exit_transitions(net):
    """
    Reduces the number of the single exit transitions in the Petri net

    Parameters
    --------------
    net
        Petri net
    """
    cont = True
    while cont:
        cont = False
        single_exit_transitions = [t for t in net.transitions if t.label is None and len(t.out_arcs) == 1]
        for i in range(len(single_exit_transitions)):
            t = single_exit_transitions[i]
            target_place = list(t.out_arcs)[0].target
            source_places = [a.source for a in t.in_arcs]
            if len(target_place.in_arcs) == 1 and len(target_place.out_arcs) == 1:
                target_transition = list(target_place.out_arcs)[0].target
                remove_transition(net, t)
                remove_place(net, target_place)
                for p in source_places:
                    add_arc_from_to(p, target_transition, net)
                cont = True
                break
    return net
Пример #5
0
def __copy_into(source_net, target_net, upper, skip):
    t_map = {}
    p_map = {}
    for t in source_net.transitions:
        name = (t.name, skip) if upper else (skip, t.name)
        label = (t.label, skip) if upper else (skip, t.label)
        t_map[t] = PetriNet.Transition(name, label)
        if properties.TRACE_NET_TRANS_INDEX in t.properties:
            # 16/02/2021: copy the index property from the transition of the trace net
            t_map[t].properties[
                properties.TRACE_NET_TRANS_INDEX] = t.properties[
                    properties.TRACE_NET_TRANS_INDEX]
        target_net.transitions.add(t_map[t])

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

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

    return t_map, p_map
Пример #6
0
def add_sink(net, end_activities, label_transition_dict):
    """
    Adding sink pe
    """
    end = PetriNet.Place('end')
    net.places.add(end)
    for e in end_activities:
        add_arc_from_to(label_transition_dict[e], end, net)
    return end
Пример #7
0
def add_source(net, start_activities, label_transition_dict):
    """
    Adding source pe
    """
    source = PetriNet.Place('start')
    net.places.add(source)
    for s in start_activities:
        add_arc_from_to(source, label_transition_dict[s], net)
    return source
def construct_xor_pattern(net, sub_nets):
    p_s = pn_util.add_place(net)
    p_o = pn_util.add_place(net)
    for n in sub_nets:
        #settings.src_dict[tuple(n.transitions)] = _get_src_transition(n)
        #settings.sink_dict[tuple(n.transitions)] = _get_sink_transition(n)
        settings.src_dict[_get_src_transition(n)] = n.transitions
        settings.sink_dict[_get_sink_transition(n)] = n.transitions
        pn_util.add_arc_from_to(p_s, _get_src_transition(n), net)
        pn_util.add_arc_from_to(_get_sink_transition(n), p_o, net)
    return _add_src_sink_transitions(net, p_s, p_o)
Пример #9
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
Пример #10
0
def binary_concurrency_detection(net):
    c1 = None
    c2 = None
    for t1, t2 in itertools.product(net.transitions, net.transitions):
        if concurrent_requirement(t1, t2):
            c1 = t1
            c2 = t2
            break
    if c1 is not None and c2 is not None:
        t = generate_new_binary_transition(c1, c2,
                                           pt_operator.Operator.PARALLEL, net)
        net.transitions.add(t)
        # reduce
        for a in c1.in_arcs:
            pn_util.add_arc_from_to(a.source, t, net)
        for a in c1.out_arcs:
            pn_util.add_arc_from_to(t, a.target, net)
        for a in c2.in_arcs:
            pn_util.add_arc_from_to(a.source, t, net)
        for a in c2.out_arcs:
            pn_util.add_arc_from_to(t, a.target, net)
        pn_util.remove_transition(net, c1)
        pn_util.remove_transition(net, c2)
        return net
    return None
Пример #11
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
Пример #12
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
Пример #13
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
Пример #14
0
def construct_loop_pattern(net, sub_nets):
    assert (len(sub_nets) == 2)
    p_s = pn_util.add_place(net)
    p_t = pn_util.add_place(net)
    pn_util.add_arc_from_to(p_s, _get_src_transition(sub_nets[0]), net)
    pn_util.add_arc_from_to(p_t, _get_src_transition(sub_nets[1]), net)
    pn_util.add_arc_from_to(_get_sink_transition(sub_nets[0]), p_t, net)
    pn_util.add_arc_from_to(_get_sink_transition(sub_nets[1]), p_s, net)
    net, ini, fin = _add_src_sink_transitions(net, p_s, p_t)
    return net, obj.Marking(), obj.Marking()
Пример #15
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
def construct_sequence_pattern(net, sub_nets):
    places = [None] * (len(sub_nets) + 1)
    for i in range(len(sub_nets) + 1):
        places[i] = pn_util.add_place(net)
    for i in range(len(sub_nets)):
        pn_util.add_arc_from_to(places[i], _get_src_transition(sub_nets[i]), net)
        pn_util.add_arc_from_to(_get_sink_transition(sub_nets[i]), places[i + 1], net)
    src = pn_util.add_transition(net)
    pn_util.add_arc_from_to(src, places[0], net)
    sink = pn_util.add_transition(net)
    pn_util.add_arc_from_to(places[len(places) - 1], sink, net)
    return net, obj.Marking(), obj.Marking()
Пример #17
0
def apply_a_rule(net):
    """
    Apply the Abstraction (A) rule

    Parameters
    --------------
    net
        Reset Inhibitor net
    """
    cont = True
    while cont:
        cont = False
        for Q, U in itertools.product(power_set(net.places, 1), power_set(net.transitions, 1)):
            for s, t in itertools.product([s for s in net.places if s not in Q],
                                          [t for t in net.transitions if (t not in U) and (t.label == None)]):
                if ((pre_set(t) == {s}) and \
                    (post_set(s) == {t}) and \
                    (pre_set(s) == set(U)) and \
                    (post_set(t) == set(Q)) and \
                    (len(set(itertools.product(pre_set(s), post_set(t))).intersection(
                        set([(arc.source, arc.target) for arc in net.arcs if
                             get_arc_type(arc) is None])))) == 0) and \
                        (len(pre_set(t, properties.RESET_ARC)) == 0) and \
                        (len(pre_set(t, properties.INHIBITOR_ARC)) == 0):

                    # check conditions on Q
                    condition = True
                    for q in Q:
                        if not ((post_set(s, properties.RESET_ARC) == post_set(q, properties.RESET_ARC)) and \
                                (post_set(s, properties.INHIBITOR_ARC) == post_set(q, properties.INHIBITOR_ARC))):
                            condition = False
                            break
                    # Q is a valid candidate
                    if condition:
                        for u in U:
                            for q in Q:
                                add_arc_from_to(u, q, net)
                        remove_place(net, s)
                        remove_transition(net, t)
                        cont = True
                        break
    return net
Пример #18
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
Пример #19
0
 def __deepcopy__(self, memodict={}):
     from pm4py.objects.petri_net.utils.petri_utils import add_arc_from_to
     this_copy = PetriNet(self.name)
     memodict[id(self)] = this_copy
     for place in self.places:
         place_copy = PetriNet.Place(place.name,
                                     properties=place.properties)
         this_copy.places.add(place_copy)
         memodict[id(place)] = place_copy
     for trans in self.transitions:
         trans_copy = PetriNet.Transition(trans.name,
                                          trans.label,
                                          properties=trans.properties)
         this_copy.transitions.add(trans_copy)
         memodict[id(trans)] = trans_copy
     for arc in self.arcs:
         add_arc_from_to(memodict[id(arc.source)],
                         memodict[id(arc.target)],
                         this_copy,
                         weight=arc.weight)
     return this_copy
Пример #20
0
def binary_sequence_detection(net):
    c1 = None
    c2 = None
    for t1, t2 in itertools.product(net.transitions, net.transitions):
        if sequence_requirement(t1, t2):
            c1 = t1
            c2 = t2
            break
    if c1 is not None and c2 is not None:
        t = generate_new_binary_transition(c1, c2,
                                           pt_operator.Operator.SEQUENCE, net)
        net.transitions.add(t)
        for a in c1.in_arcs:
            pn_util.add_arc_from_to(a.source, t, net)
        for a in c2.out_arcs:
            pn_util.add_arc_from_to(t, a.target, net)
        for p in pn_util.post_set(c1):
            pn_util.remove_place(net, p)
        pn_util.remove_transition(net, c1)
        pn_util.remove_transition(net, c2)
        return net
    return None
Пример #21
0
def construct_and_pattern(net, sub_nets):
    p_s = [None] * len(sub_nets)
    p_t = [None] * len(sub_nets)
    for i in range(len(sub_nets)):
        p_s[i] = pn_util.add_place(net)
        p_t[i] = pn_util.add_place(net)
        pn_util.add_arc_from_to(p_s[i], _get_src_transition(sub_nets[i]), net)
        pn_util.add_arc_from_to(_get_sink_transition(sub_nets[i]), p_t[i], net)
    src = pn_util.add_transition(net)
    for p in p_s:
        pn_util.add_arc_from_to(src, p, net)
    sink = pn_util.add_transition(net)
    for p in p_t:
        pn_util.add_arc_from_to(p, sink, net)
    return net, obj.Marking(), obj.Marking()
Пример #22
0
def apply_fsp_rule(net, im=None, fm=None):
    """
    Apply the Fusion of Series Places (FSP) rule

    Parameters
    --------------
    net
        Reset Inhibitor net
    """
    if im is None:
        im = {}
    if fm is None:
        fm = {}
    cont = True
    while cont:
        cont = False
        for p, q, t in itertools.product(net.places, net.places, net.transitions):
            if t.label == None:  # only silent transitions may be removed either way
                if (len(t.in_arcs) == 1 and list(t.in_arcs)[0].source == p) and \
                        (len(t.out_arcs) == 1 and list(t.out_arcs)[0].target == q) and \
                        (len(post_set(p)) == 1 and list(post_set(p))[0] == t) and \
                        (len(pre_set(p).intersection(pre_set(q))) == 0) and \
                        (post_set(p, properties.RESET_ARC) == post_set(q, properties.RESET_ARC)) and \
                        (post_set(p, properties.INHIBITOR_ARC) == post_set(q, properties.INHIBITOR_ARC)) and \
                        (len(pre_set(t, properties.RESET_ARC)) == 0 and len(
                            pre_set(t, properties.INHIBITOR_ARC)) == 0):
                    # remove place p and transition t
                    remove_transition(net, t)
                    for source in pre_set(p):
                        add_arc_from_to(source, q, net)
                    remove_place(net, p)
                    if p in im:
                        del im[p]
                        im[q] = 1
                    cont = True
                    break

    return net, im, fm
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
Пример #24
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
Пример #25
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)
Пример #26
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})
Пример #27
0
def _add_src_sink_transitions(net, p_s, p_t):
    src = pn_util.add_transition(net)
    pn_util.add_arc_from_to(src, p_s, net)
    sink = pn_util.add_transition(net)
    pn_util.add_arc_from_to(p_t, sink, net)
    return net, obj.Marking(), obj.Marking()
Пример #28
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
Пример #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
Пример #30
0
 def test_figure42(self):
     net = PetriNet("figure_4_2")
     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")
     p_8 = PetriNet.Place("p_8")
     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)
     net.places.add(p_8)
     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")
     t_7 = PetriNet.Transition("t_7", "t_7")
     t_8 = PetriNet.Transition("t_8", "t_8")
     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)
     net.transitions.add(t_7)
     net.transitions.add(t_8)
     petri_utils.add_arc_from_to(p_1, t_1, net)
     petri_utils.add_arc_from_to(t_1, p_6, net)
     petri_utils.add_arc_from_to(t_1, p_4, net)
     petri_utils.add_arc_from_to(p_4, t_4, net)
     petri_utils.add_arc_from_to(p_4, t_5, 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_4, p_3, net)
     petri_utils.add_arc_from_to(t_4, p_5, net)
     petri_utils.add_arc_from_to(t_5, p_7, net)
     petri_utils.add_arc_from_to(t_7, p_4, net)
     petri_utils.add_arc_from_to(p_3, t_2, net)
     petri_utils.add_arc_from_to(p_3, t_3, net)
     petri_utils.add_arc_from_to(p_5, t_2, net)
     petri_utils.add_arc_from_to(p_5, t_3, net)
     petri_utils.add_arc_from_to(p_5, t_4, net)
     petri_utils.add_arc_from_to(p_7, t_6, net)
     petri_utils.add_arc_from_to(p_8, t_7, net)
     petri_utils.add_arc_from_to(p_8, t_8, net)
     petri_utils.add_arc_from_to(t_3, p_2, net)
     petri_utils.add_arc_from_to(p_6, t_6, net)
     petri_utils.add_arc_from_to(t_6, p_5, net)
     petri_utils.add_arc_from_to(t_8, p_8, net)
     initial_marking = Marking()
     initial_marking[p_1] = 1
     final_marking = Marking()
     final_marking[p_2] = 1
     self.assertFalse(woflan.apply(net, initial_marking, final_marking, parameters={"print_diagnostics": False}))