Esempio n. 1
0
def remove_initial_hidden_if_possible(net, im):
    """
    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
Esempio n. 2
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
Esempio n. 3
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
Esempio n. 4
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
Esempio n. 5
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
Esempio 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
Esempio n. 7
0
def remove_final_hidden_if_possible(net, fm):
    """
    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
Esempio n. 8
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
Esempio n. 9
0
def remove_unconnected_transitions(net):
    """
    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
Esempio n. 10
0
def reduce_petri_net(net):
    transes = set([x for x in net.transitions if x.label is None])
    places = list(net.places)
    i = 0
    while i < len(places):
        place = places[i]
        source_transes = set([x.source for x in place.in_arcs])
        target_transes = set([x.target for x in place.out_arcs])
        if len(source_transes) == 1 and len(target_transes) == 1:
            if source_transes.issubset(transes) and target_transes.issubset(
                    transes):
                source_trans = list(source_transes)[0]
                target_trans = list(target_transes)[0]
                if len(target_trans.out_arcs) == 1:
                    target_place = list(target_trans.out_arcs)[0].target
                    add_arc_from_to(source_trans, target_place, net)
                    remove_place(net, place)
                    remove_transition(net, target_trans)
                    places = list(net.places)
                    continue
                    # print(source_trans, target_trans, target_place)
        i = i + 1

    return net
Esempio n. 11
0
def reduce1(net):
    """
    Reduction rule (1) to simplify the Petri net

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

    Returns
    ------------
    net
        Simplified Petri net
    """
    something_changed = True
    while something_changed:
        something_changed = False
        transitions = list(net.transitions)
        for trans in transitions:
            source_places = [arc.source for arc in trans.in_arcs]
            target_places = [arc.target for arc in trans.out_arcs]
            target_transes = [
                arc.target for place in target_places for arc in place.out_arcs
            ]
            if len(source_places) == 1 and len(target_places) == 1 and len(
                    target_transes) == 1:
                source_place = source_places[0]
                target_place = target_places[0]
                target_trans = target_transes[0]
                #target_places2 = [arc.target for arc in target_trans.out_arcs]
                if len(target_place.in_arcs) == 1 and len(
                        target_trans.in_arcs) == 1 and len(
                            target_trans.out_arcs) == 1:
                    if trans.label is None:
                        net = remove_transition(net, trans)
                        net = remove_place(net, target_place)
                        add_arc_from_to(source_place, target_trans, net)
                        something_changed = True
                        continue
    return net
Esempio n. 12
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
Esempio n. 13
0
def project(net0, im0, fm0, allowed_transitions):
    """
    Project a Petri Net on a set of transitions provided by the user

    Parameters
    -------------
    net0
        Petri net
    im0
        Initial marking
    fm0
        Final marking
    allowed_transitions
        Sets of allowed transitions

    Returns
    -------------
    net
        Projected net
    im
        Projected initial marking
    fm
        Projected final marking
    """
    [net, im1, fm1] = deepcopy([net0, im0, fm0])

    # keep only visible transitions that have a label in allowed_transitions
    trans_list = list(net.transitions)
    for trans in trans_list:
        if trans.label is not None and trans.name not in allowed_transitions:
            net = utils.remove_transition(net, trans)

    # create a fictious Petri net
    old_net = PetriNet("")
    # remove unconnected elements until a 'stable' platform is reached
    n_it = 0
    while not (len(old_net.places) == len(net.places) and len(old_net.transitions) == len(net.transitions) and len(
            old_net.arcs) == len(net.arcs)):
        n_it = n_it + 1
        old_net = deepcopy(net)
        trans_list = list(net.transitions)
        for trans in trans_list:
            # remove invisible transitions that have no input or output arcs
            if trans.label is None and (
                    len(trans.in_arcs) == 0 or len(trans.out_arcs) == 0) and trans.name not in allowed_transitions:
                net = utils.remove_transition(net, trans)
                continue

        places_list = list(net.places)

        for place in places_list:
            # remove places that have no input or output arcs
            if len(place.in_arcs) == 0 and (not place in im1 or len(place.out_arcs) == 0):
                net = utils.remove_place(net, place)
                continue

        # now the goal is to remove further places, but being carefully to not remove something structurally relevant

        for place in places_list:
            all_inputs = [arc.source for arc in place.in_arcs]
            hid_input = [trans for trans in all_inputs if trans.label is None and trans.name not in allowed_transitions]
            all_outputs = [arc.target for arc in place.out_arcs]
            hid_output = [trans for trans in all_outputs if
                          trans.label is None and trans.name not in allowed_transitions]

            if len(hid_input) == len(all_inputs) and len(hid_output) == len(all_outputs):
                net = utils.remove_place(net, place)
                continue

    im = Marking()
    fm = Marking()

    for place in im1:
        if place in net.places:
            im[place] = im1[place]

    for place in fm1:
        if place in net.places:
            fm[place] = fm1[place]

    return net, im, fm