Exemplo n.º 1
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
Exemplo n.º 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
Exemplo n.º 3
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
Exemplo n.º 4
0
def apply_fpt_rule(net):
    """
    Apply the Fusion of Parallel Transitions (FPT) rule

    Parameters
    --------------
    net
        Reset Inhibitor net
    """
    cont = True
    while cont:
        cont = False
        for V in power_set([transition for transition in net.transitions if transition.label == None], 2):
            condition = True
            for x, y in itertools.product(V, V):
                if x != y:
                    if not ((pre_set(x) == pre_set(y)) and \
                            (post_set(x) == post_set(y)) and \
                            (pre_set(x, properties.RESET_ARC) == pre_set(y, properties.RESET_ARC)) and \
                            (pre_set(x, properties.INHIBITOR_ARC) == pre_set(y, properties.INHIBITOR_ARC))):
                        condition = False
                        break
            # V is a valid candidate
            if condition:
                # remove transitions except the first one
                for t in V[1:]:
                    remove_transition(net, t)
                cont = True
                break
    return net
Exemplo n.º 5
0
def remove_initial_hidden_if_possible(net: PetriNet, im: Marking):
    """
    Remove initial hidden transition if possible

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

    Returns
    ------------
    net
        Petri net
    im
        Possibly different initial marking
    """
    source = list(im.keys())[0]
    first_hidden = list(source.out_arcs)[0].target
    target_places_first_hidden = [x.target for x in first_hidden.out_arcs]
    if len(target_places_first_hidden) == 1:
        target_place_first_hidden = target_places_first_hidden[0]
        if len(target_place_first_hidden.in_arcs) == 1:
            new_im = Marking()
            new_im[target_place_first_hidden] = 1
            remove_place(net, source)
            remove_transition(net, first_hidden)
            return net, new_im
    return net, im
Exemplo n.º 6
0
def petri_reduction_treplay(net, parameters=None):
    """
    Apply petri_reduction on the Petrinet removing hidden transitions
    that are unused according to token-based replay

    Parameters
    -----------
    net
        Petri net
    parameters
        Parameters of the algorithm, including:
            aligned_traces -> Result of alignment according to token-based replay
    Returns
    -----------
    net
        Reduced Petri net
    """
    if parameters is None:
        parameters = {}

    aligned_traces = parameters["aligned_traces"]

    enabled_trans_in_at_least_one_trace = set()

    for trace in aligned_traces:
        for trans in trace["activated_transitions"]:
            enabled_trans_in_at_least_one_trace.add(trans)

    transitions = list(net.transitions)
    for trans in transitions:
        if trans.label is None:
            if trans not in enabled_trans_in_at_least_one_trace:
                net = remove_transition(net, trans)

    return net
Exemplo n.º 7
0
def clean_duplicate_transitions(net):
    """
    Clean duplicate transitions in a Petri net

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

    Returns
    ------------
    net
        Cleaned Petri net
    """
    transitions = list(net.transitions)
    already_visited_combo = set()
    for i in range(0, len(transitions)):
        trans = transitions[i]
        if trans.label is None:
            in_arcs = trans.in_arcs
            out_arcs = trans.out_arcs
            to_delete = False
            for in_arc in in_arcs:
                in_place = in_arc.source
                for out_arc in out_arcs:
                    out_place = out_arc.target
                    combo = in_place.name + " " + out_place.name
                    if combo in already_visited_combo:
                        to_delete = True
                        break
                    already_visited_combo.add(combo)
            if to_delete:
                net = remove_transition(net, trans)
    return net
Exemplo n.º 8
0
def remove_final_hidden_if_possible(net: PetriNet, fm: Marking):
    """
    Remove final hidden transition if possible

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

    Returns
    -------------
    net
        Petri net
    """
    sink = list(fm.keys())[0]
    last_hidden = list(sink.in_arcs)[0].source
    source_places_last_hidden = [x.source for x in last_hidden.in_arcs]
    removal_possible = len(source_places_last_hidden) == 1
    for place in source_places_last_hidden:
        if len(place.out_arcs) > 1:
            removal_possible = False
            break
        else:
            source_trans = set([x.source for x in place.in_arcs])
            for trans in source_trans:
                if len(trans.out_arcs) > 1:
                    removal_possible = False
                    break
    if removal_possible:
        all_sources = set()
        remove_transition(net, last_hidden)
        i = 0
        while i < len(source_places_last_hidden):
            place = source_places_last_hidden[i]
            source_trans = set([x.source for x in place.in_arcs])
            for trans in source_trans:
                if trans not in all_sources:
                    all_sources.add(trans)
                    add_arc_from_to(trans, sink, net)
            remove_place(net, place)
            i = i + 1
    return net
Exemplo n.º 9
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
Exemplo n.º 10
0
def apply_elt_rule(net):
    """
    Apply the Elimination of Self-Loop Transitions (ELT) rule

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

    return net
Exemplo n.º 11
0
def remove_unconnected_transitions(net: PetriNet):
    """
    Remove unconnected transitions if any

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

    Returns
    -------------
    net
        Petri net without unconnected transitions
    """
    transitions = list(net.transitions)
    i = 0
    while i < len(transitions):
        if len(transitions[i].in_arcs) == 0 and len(
                transitions[i].out_arcs) == 0:
            remove_transition(net, transitions[i])
        i = i + 1
    return net
Exemplo n.º 12
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
Exemplo n.º 13
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
Exemplo n.º 14
0
def remove_rendundant_invisible_transitions(net):
    """
    Remove redundant transitions from Petri net

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

    Returns
    -----------
    net
        Cleaned net
    """
    trans = [x for x in list(net.transitions) if not x.label]
    i = 0
    while i < len(trans):
        if trans[i] in net.transitions:
            preset_i = set(x.source for x in trans[i].in_arcs)
            postset_i = set(x.target for x in trans[i].out_arcs)
            j = 0
            while j < len(trans):
                if not j == i:
                    preset_j = set(x.source for x in trans[j].in_arcs)
                    postset_j = set(x.target for x in trans[j].out_arcs)
                    if len(preset_j) == len(
                            preset_i) and len(postset_j) < len(postset_i):
                        if len(preset_j.intersection(preset_i)) == len(
                                preset_j) and len(
                                    postset_j.intersection(postset_i)) == len(
                                        postset_j):
                            remove_transition(net, trans[j])
                            del trans[j]
                            continue
                j = j + 1
            i = i + 1
    return net
Exemplo n.º 15
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
Exemplo n.º 16
0
def repair_sound_Model(s_net, rules_dict, support, confidence, lift, sound=1):
    """
    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 a given requirement.
    
    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 
        sound (str) : Yes
    
    Return:
        net (PetriNet): Repaired Sound Petri net of the log
        rules (dict) : Added rules to the net with their association rule metrics values
    """
    rules = {}

    rules_dict = dict(sorted(rules_dict.items(), key=lambda item: item[1][2]))
    print("rules_dict", rules_dict)

    for pair, value in rules_dict.items():
        trans = None
        if value[2] < 1.001 or str(value[2]) < lift or str(
                value[0]) < support or str(value[1]) < confidence:
            tau_t = f"tau_{pair[0]}{pair[1]}"
            for t in s_net.transitions:
                s_place_valid = 0
                t_place_valid = 0
                if str(t) == str(tau_t):
                    trans = t
                    source_places = set([x.source for x in t.in_arcs])
                    for p in source_places:
                        s_place = f"ps_{pair[0]}"
                        if str(p) == s_place:
                            if sound == 'on' and len(p.out_arcs) > 1:
                                s_place_valid = 1
                            elif sound == None:
                                s_place_valid = -1
                                if len(p.out_arcs) == 1:
                                    p_utils.remove_place(s_net, p)

                        if sound == 'on' and len(p.out_arcs) == 1:
                            rules[pair] = value
                    target_places = set([x.target for x in t.out_arcs])
                    for p in target_places:
                        t_place = f"pt_{pair[1]}"
                        if str(p) == t_place:
                            if sound == 'on' and len(p.in_arcs) > 1:
                                t_place_valid = 1
                            elif sound == None:
                                t_place_valid = -1
                                if len(p.in_arcs) == 1:
                                    p_utils.remove_place(s_net, p)

                            if sound == 'on' and len(p.in_arcs) == 1:
                                rules[pair] = value
                    if s_place_valid == 1 and t_place_valid == 1:
                        s_net = p_utils.remove_transition(s_net, trans)
                        break
                    elif s_place_valid == -1 and t_place_valid == -1:
                        s_net = p_utils.remove_transition(s_net, trans)
                        break
        else:
            rules[pair] = value
    return s_net, rules