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
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
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
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
def remove_unconnected_places(net, sources, targets): """ Remove unconnected places from the Petri net Parameters ----------- net Petri net Returns ----------- net Petri net """ places = set(net.places) for place in places: if not place in sources and not place in targets: if (len(place.in_arcs) == 0) or (len(place.out_arcs) == 0): #print("unconnected place: " + place.name) remove_place(net, place) return net
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
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
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
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
def apply(tree, parameters=None): """ Apply from Process Tree to Petri net Parameters ----------- tree Process tree parameters Parameters of the algorithm Returns ----------- net Petri net initial_marking Initial marking final_marking Final marking """ if parameters is None: parameters = {} del parameters counts = Counts() net = PetriNet('imdf_net_' + str(time.time())) initial_marking = Marking() final_marking = Marking() source = get_new_place(counts) source.name = "source" sink = get_new_place(counts) sink.name = "sink" net.places.add(source) net.places.add(sink) initial_marking[source] = 1 final_marking[sink] = 1 initial_mandatory = check_tau_mandatory_at_initial_marking(tree) final_mandatory = check_tau_mandatory_at_final_marking(tree) if initial_mandatory: initial_place = get_new_place(counts) net.places.add(initial_place) tau_initial = get_new_hidden_trans(counts, type_trans="tau") net.transitions.add(tau_initial) add_arc_from_to(source, tau_initial, net) add_arc_from_to(tau_initial, initial_place, net) else: initial_place = source if final_mandatory: final_place = get_new_place(counts) net.places.add(final_place) tau_final = get_new_hidden_trans(counts, type_trans="tau") net.transitions.add(tau_final) add_arc_from_to(final_place, tau_final, net) add_arc_from_to(tau_final, sink, net) else: final_place = sink net, counts, last_added_place = recursively_add_tree( tree, tree, net, initial_place, final_place, counts, 0) reduction.apply_simple_reduction(net) places = list(net.places) for place in places: if len(place.out_arcs) == 0 and not place in final_marking: remove_place(net, place) if len(place.in_arcs) == 0 and not place in initial_marking: remove_place(net, place) return net, initial_marking, final_marking