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('utf-8')).hexdigest(), 16) for t in net.transitions))) net.lvis_labels = lvis_labels net.t_tuple = t_tuple return (net, im, fm)
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
def test_52(self): # creating an empty Petri net from pm4py.objects.petri.petrinet import PetriNet, Marking net = PetriNet("new_petri_net") # creating source, p_1 and sink place source = PetriNet.Place("source") sink = PetriNet.Place("sink") p_1 = PetriNet.Place("p_1") # add the places to the Petri Net net.places.add(source) net.places.add(sink) net.places.add(p_1) # Create transitions t_1 = PetriNet.Transition("name_1", "label_1") t_2 = PetriNet.Transition("name_2", "label_2") # Add the transitions to the Petri Net net.transitions.add(t_1) net.transitions.add(t_2) # Add arcs from pm4py.objects.petri import utils utils.add_arc_from_to(source, t_1, net) utils.add_arc_from_to(t_1, p_1, net) utils.add_arc_from_to(p_1, t_2, net) utils.add_arc_from_to(t_2, sink, net) # Adding tokens initial_marking = Marking() initial_marking[source] = 1 final_marking = Marking() final_marking[sink] = 1 from pm4py.objects.petri.exporter import exporter as pnml_exporter pnml_exporter.apply(net, initial_marking, "createdPetriNet1.pnml", final_marking=final_marking) from pm4py.visualization.petrinet import visualizer as pn_visualizer gviz = pn_visualizer.apply(net, initial_marking, final_marking) from pm4py.visualization.petrinet import visualizer as pn_visualizer parameters = {pn_visualizer.Variants.WO_DECORATION.value.Parameters.FORMAT: "svg"} gviz = pn_visualizer.apply(net, initial_marking, final_marking, parameters=parameters) from pm4py.visualization.petrinet import visualizer as pn_visualizer parameters = {pn_visualizer.Variants.WO_DECORATION.value.Parameters.FORMAT: "svg"} gviz = pn_visualizer.apply(net, initial_marking, final_marking, parameters=parameters) pn_visualizer.save(gviz, "alpha.svg") os.remove("createdPetriNet1.pnml") os.remove("alpha.svg")
def __copy_into(source_net, target_net, upper, skip): t_map = {} p_map = {} for t in source_net.transitions: name = (t.name, skip) if upper else (skip, t.name) label = (t.label, skip) if upper else (skip, t.label) t_map[t] = PetriNet.Transition(name, label) if properties.TRACE_NET_TRANS_INDEX in t.properties: # 16/02/2021: copy the index property from the transition of the trace net t_map[t].properties[ properties.TRACE_NET_TRANS_INDEX] = t.properties[ properties.TRACE_NET_TRANS_INDEX] target_net.transitions.add(t_map[t]) for p in source_net.places: name = (p.name, skip) if upper else (skip, p.name) p_map[p] = PetriNet.Place(name) if properties.TRACE_NET_PLACE_INDEX in p.properties: # 16/02/2021: copy the index property from the place of the trace net p_map[p].properties[ properties.TRACE_NET_PLACE_INDEX] = p.properties[ properties.TRACE_NET_PLACE_INDEX] target_net.places.add(p_map[p]) for t in source_net.transitions: for a in t.in_arcs: add_arc_from_to(p_map[a.source], t_map[t], target_net) for a in t.out_arcs: add_arc_from_to(t_map[t], p_map[a.target], target_net) return t_map, p_map
def make_petrinet_from_automaton(auto): ''' Make petri net from automaton based on state-based region theory :param auto: automaton :return: derived petri net ''' min_region_set, di, ger = minimal_region_set(auto) id = 0 net = PetriNet('new_net') trans_set = set() for trans in auto.transitions: if trans.name not in trans_set: t = PetriNet.Transition(trans.name, trans.name) net.transitions.add(t) trans_set.add(trans.name) for min_region in di.items(): place = PetriNet.Place(id) net.places.add(place) for trans in min_region[1][0]: for transs in net.transitions: if trans == transs.name: petri_utils.add_arc_from_to(transs, place, net) for trans in min_region[1][1]: for transs in net.transitions: if trans == transs.name: petri_utils.add_arc_from_to(place, transs, net) id += 1 im = discover_initial_marking(net) fm = discover_final_marking(net) return net, im, fm
def to(net0, im0, fm0): net = PetriNet("") im = Marking() fm = Marking() dp = {} dt = {} i = 0 while i < len(net0[0]): p = PetriNet.Place(str(net0[0][i])) net.places.add(p) dp[i] = p i = i + 1 i = 0 while i < len(net0[1]): t = PetriNet.Transition("t%d" % (i), net0[1][i][0]) net.transitions.add(t) dt[i] = t i = i + 1 i = 0 while i < len(net0[1]): for p in net0[1][i][1]: petri_utils.utils.add_arc_from_to(dp[p], dt[i], net) for p in net0[1][i][2]: petri_utils.utils.add_arc_from_to(dt[i], dp[p], net) i = i + 1 for p in im0: im[dp[p]] = im0[p] for p in fm0: fm[dp[p]] = fm0[p] return net, im, fm
def petrinetcreator(self, places, transitions, arcs): net = PetriNet("new_petri_net") source = PetriNet.Place("source") sink = PetriNet.Place("sink") for i in range(1, places + 1): p = PetriNet.Place("p_" + str(i)) net.places.add(p) net.places.add(source) net.places.add(sink) for i in range(1, transitions + 1): t = PetriNet.Transition("name_" + str(i), "label_" + str(i)) net.transitions.add(t) for i in range(1, len(arcs + 1)): arc = arcs[i].split() utils.add_arc_from_to(arc[0], arc[1], net) initial_marking = Marking() initial_marking[source] = 1 final_marking = Marking() final_marking[sink] = 1 return net
def construct_trace_net(trace, trace_name_key=xes_util.DEFAULT_NAME_KEY, activity_key=xes_util.DEFAULT_NAME_KEY): """ Creates a trace net, i.e. a trace in Petri net form. Parameters ---------- trace: :class:`list` input trace, assumed to be a list of events trace_name_key: :class:`str` key of the attribute that defines the name of the trace activity_key: :class:`str` key of the attribute of the events that defines the activity name Returns ------- tuple: :class:`tuple` of the net, initial marking and the final marking """ net = PetriNet('trace net of %s' % trace.attributes[trace_name_key] if trace_name_key in trace.attributes else ' ') place_map = {0: PetriNet.Place('p_0')} net.places.add(place_map[0]) for i in range(0, len(trace)): t = PetriNet.Transition('t_' + trace[i][activity_key] + '_' + str(i), trace[i][activity_key]) net.transitions.add(t) place_map[i + 1] = PetriNet.Place('p_' + str(i + 1)) net.places.add(place_map[i + 1]) add_arc_from_to(place_map[i], t, net) add_arc_from_to(t, place_map[i + 1], net) return net, Marking({place_map[0]: 1}), Marking({place_map[len(trace)]: 1})
def add_transition(net, name=None, label=None): name = name if name is not None else 't_' + str(len( net.transitions)) + '_' + str(time.time()) + str( random.randint(0, 10000)) t = PetriNet.Transition(name=name, label=label) net.transitions.add(t) return t
def add_wait_net(net, wait_label): ''' Words don't have the same length. To compare them we add a "wait" transition at the end of the model and the traces. :return: ''' wait_transition = PetriNet.Transition(wait_label, wait_label) net.transitions.add(wait_transition) return wait_transition
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) 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
def test_figure415(self): net = PetriNet("figure_4_15") p_1 = PetriNet.Place("p_1") p_2 = PetriNet.Place("p_2") p_3 = PetriNet.Place("p_3") p_4 = PetriNet.Place("p_4") p_5 = PetriNet.Place("p_5") p_6 = PetriNet.Place("p_6") p_7 = PetriNet.Place("p_7") net.places.add(p_1) net.places.add(p_2) net.places.add(p_3) net.places.add(p_4) net.places.add(p_5) net.places.add(p_6) net.places.add(p_7) t_1 = PetriNet.Transition("t_1", "t_1") t_2 = PetriNet.Transition("t_2", "t_2") t_3 = PetriNet.Transition("t_3", "t_3") t_4 = PetriNet.Transition("t_4", "t_4") t_5 = PetriNet.Transition("t_5", "t_5") t_6 = PetriNet.Transition("t_6", "t_6") net.transitions.add(t_1) net.transitions.add(t_2) net.transitions.add(t_3) net.transitions.add(t_4) net.transitions.add(t_5) net.transitions.add(t_6) utils.add_arc_from_to(p_1, t_1, net) utils.add_arc_from_to(t_1, p_3, net) utils.add_arc_from_to(t_1, p_2, net) utils.add_arc_from_to(t_1, p_5, net) utils.add_arc_from_to(p_5, t_2, net) utils.add_arc_from_to(p_5, t_5, net) utils.add_arc_from_to(p_3, t_2, net) utils.add_arc_from_to(p_3, t_4, net) utils.add_arc_from_to(t_2, p_6, net) utils.add_arc_from_to(t_2, p_4, net) utils.add_arc_from_to(t_5, p_5, net) utils.add_arc_from_to(t_5, p_3, net) utils.add_arc_from_to(p_2, t_2, net) utils.add_arc_from_to(t_3, p_2, net) utils.add_arc_from_to(t_3, p_3, net) utils.add_arc_from_to(t_3, p_4, net) utils.add_arc_from_to(p_6, t_5, net) utils.add_arc_from_to(p_6, t_6, net) utils.add_arc_from_to(p_6, t_3, net) utils.add_arc_from_to(t_4, p_6, net) utils.add_arc_from_to(t_4, p_5, net) utils.add_arc_from_to(p_4, t_3, net) utils.add_arc_from_to(p_4, t_6, net) utils.add_arc_from_to(p_4, t_4, net) utils.add_arc_from_to(t_6, p_7, net) initial_marking = Marking() initial_marking[p_1] = 1 final_marking = Marking() final_marking[p_7] = 1 self.assertTrue(woflan.apply(net, initial_marking, final_marking))
def __addWaitTransitions(self, pn, mf): ''' This function add 2 type of wait transitions : - log moves - model moves Those transitions cost. :param pn (Petrinet) :param mf (Marking) ''' # creates the transitions with labels WAIT_LABEL_TRACE for log moves # and WAIT_LABEL_MODEL for model moves self.__wait_transition_trace = PetriNet.Transition( WAIT_LABEL_TRACE, WAIT_LABEL_TRACE) self.__wait_transition_model = PetriNet.Transition( WAIT_LABEL_MODEL, WAIT_LABEL_MODEL) final_places = [p for p in pn.places if p in mf] # WAIT_LABEL_MODEL is added in the Petrinet at the end of the # TODO I'm not sure here #petri.utils.add_arc_from_to(self.__wait_transition_model, final_places[0], pn) #petri.utils.add_arc_from_to(final_places[0],self.__wait_transition_model, pn) # add both transitions but notice that WAIT_LABEL_TRACE will be forbidden for the centroids self.__transitions.append(self.__wait_transition_trace) self.__transitions.append(self.__wait_transition_model)
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 utils.add_arc_from_to(sink, t_1, s_c_net) 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
def postprocessing(net, initial_marking, final_marking, A, B, pairs, loop_one_list): """ 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)) 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
def map_to_PN(auto, region_set): ''' Make Petri net from automaton :param auto: automaton to change into petri net :return: petri net ''' net = PetriNet("New Net") trans_set = set() for trans in auto.transitions: if trans.name not in trans_set: t = PetriNet.Transition(trans.name, trans.name) net.transitions.add(t) trans_set.add(trans.name) #add transitions to petri net petri_trans_dict = transition_dict(net) id = 0 for region in region_set: exit_set = set() enter_set = set() place = PetriNet.Place(id) #add places to petri net net.places.add(place) for event, value in is_region(auto, region)[1].items(): if value == 100: # exit exit_set.add(event) elif value == 1000: # enter enter_set.add(event) for t in exit_set: petri_utils.add_arc_from_to(place, petri_trans_dict[t], net) for tt in enter_set: petri_utils.add_arc_from_to(petri_trans_dict[tt], place, net) id += 1 #add final place (optional) # final_place = PetriNet.Place(id) # net.places.add(final_place) # for trans in net.transitions: # if len(trans.out_arcs) < 1: # petri_utils.add_arc_from_to(trans, final_place, net) im = discover_initial_marking(net) fm = discover_final_marking(net) return net, im, fm
def log_to_Pn(traces_xes,size_of_run): traces = project_traces(traces_xes) petri_of_traces=PetriNet() init, end=PetriNet.Place("init"),PetriNet.Place("end") [petri_of_traces.places.add(place) for place in [init, end]] prec=init for t in traces: prec=init for a in range (0,min(size_of_run,len(t))): transition=PetriNet.Transition(t[a]+str(a), t[a]) petri_of_traces.transitions.add(transition) place_suiv=end if a in [size_of_run-1,len(t)-1] else PetriNet.Place(t[a]+str(a)) add_arc_from_to(transition, place_suiv, petri_of_traces) add_arc_from_to(prec, transition, petri_of_traces) prec=place_suiv m0=Marking().__add__({init:1}) mf=Marking().__add__({end:1}) return petri_of_traces,m0,mf
def get_strongly_connected_subnets(net): """ Get the strongly connected components subnets in the Petri net Parameters ------------- net Petri net Returns ------------- strongly_connected_transitions List of strongly connected transitions of the Petri net """ import networkx as nx graph, inv_dictionary = create_networkx_directed_graph(net) sccg = list(nx.strongly_connected_components(graph)) strongly_connected_subnets = [] for sg in list(sccg): if len(sg) > 1: subnet = PetriNet() imarking = Marking() fmarking = Marking() corr = {} for node in sg: if node in inv_dictionary: if type(inv_dictionary[node]) is PetriNet.Transition: prev_trans = inv_dictionary[node] new_trans = PetriNet.Transition( prev_trans.name, prev_trans.label) corr[node] = new_trans subnet.transitions.add(new_trans) if type(inv_dictionary[node]) is PetriNet.Place: prev_place = inv_dictionary[node] new_place = PetriNet.Place(prev_place.name) corr[node] = new_place subnet.places.add(new_place) for edge in graph.edges: if edge[0] in sg and edge[1] in sg: add_arc_from_to(corr[edge[0]], corr[edge[1]], subnet) strongly_connected_subnets.append([subnet, imarking, fmarking]) return strongly_connected_subnets
def __add_wait_net(self): ''' Words don't have the same length. To compare them we add a "wait" transition at the end of the model and the traces. :return: ''' wait_transition = PetriNet.Transition(WAIT_TRANSITION, WAIT_TRANSITION) for place in self.__pn.places: if len(place.out_arcs) == 0: arcIn = PetriNet.Arc(place, wait_transition) arcOut = PetriNet.Arc(wait_transition, place) self.__pn.arcs.add(arcIn) self.__pn.arcs.add(arcOut) wait_transition.in_arcs.add(arcIn) wait_transition.out_arcs.add(arcOut) place.out_arcs.add(arcIn) place.in_arcs.add(arcOut) self.__pn.transitions.add(wait_transition) return wait_transition
def add_wait_net_end(pn, wait_label): ''' Words don't have the same length. To compare them we add a "wait" transition at the end of the model and the traces. :return: ''' wait_transition = PetriNet.Transition(wait_label, wait_label) for place in pn.places: if len(place.out_arcs) == 0: arcIn = PetriNet.Arc(place, wait_transition) arcOut = PetriNet.Arc(wait_transition, place) pn.arcs.add(arcIn) pn.arcs.add(arcOut) wait_transition.in_arcs.add(arcIn) wait_transition.out_arcs.add(arcOut) place.out_arcs.add(arcIn) place.in_arcs.add(arcOut) pn.transitions.add(wait_transition) return wait_transition
def create_PetriNet(n): # label_set[0] = 'a',...,label_set[26]=z label_set = dict(enumerate(string.ascii_lowercase)) if n >= 26: print("N is >= 26 but there are only 26 unique letters.") # create new petrinet net = PetriNet("PN") place_list = [] # create start and end place start = PetriNet.Place("start") end = PetriNet.Place("end") net.places.add(start) net.places.add(end) place_list.insert(0, start) place_list.insert(n + 1, end) # create the rest of n-2 places (n+1 places are needed for a length n trace) for i in range(n - 1): p = PetriNet.Place(f"p{i}") net.places.add(p) place_list.insert(i + 1, p) transitions_list = [] # create n transitions for i in range(n): t = PetriNet.Transition(f"t{i}", label_set[i]) net.transitions.add(t) transitions_list.insert(i, t) for i, t in enumerate(transitions_list): utils.add_arc_from_to(place_list[i], t, net) utils.add_arc_from_to(t, place_list[i + 1], net) # defining initial and final marking im = Marking() im[start] = 1 fm = Marking() fm[end] = 1 return net, im
def construct_trace_net_cost_aware(trace, costs, trace_name_key=xes_util.DEFAULT_NAME_KEY, activity_key=xes_util.DEFAULT_NAME_KEY): """ Creates a trace net, i.e. a trace in Petri net form mapping specific costs to transitions. Parameters ---------- trace: :class:`list` input trace, assumed to be a list of events costs: :class:`list` list of costs, length should be equal to the length of the input trace trace_name_key: :class:`str` key of the attribute that defines the name of the trace activity_key: :class:`str` key of the attribute of the events that defines the activity name Returns ------- tuple: :class:`tuple` of the net, initial marking, final marking and map of costs """ net = PetriNet('trace net of %s' % trace.attributes[trace_name_key] if trace_name_key in trace.attributes else ' ') place_map = {0: PetriNet.Place('p_0')} net.places.add(place_map[0]) cost_map = dict() for i in range(0, len(trace)): t = PetriNet.Transition('t_' + trace[i][activity_key] + '_' + str(i), trace[i][activity_key]) # 16/02/2021: set the trace index as property of the transition of the trace net t.properties[properties.TRACE_NET_TRANS_INDEX] = i cost_map[t] = costs[i] net.transitions.add(t) place_map[i + 1] = PetriNet.Place('p_' + str(i + 1)) # 16/02/2021: set the place index as property of the place of the trace net place_map[i + 1].properties[properties.TRACE_NET_PLACE_INDEX] = i + 1 net.places.add(place_map[i + 1]) add_arc_from_to(place_map[i], t, net) add_arc_from_to(t, place_map[i + 1], net) return net, Marking({place_map[0]: 1}), Marking({place_map[len(trace)]: 1}), cost_map
def get_initial_marking(net, max_no_comb=4): """ Get the initial marking from a Petri net (observing which nodes are without input connection, if several nodes exist, then a source place is created artificially) Parameters ------------- net Petri net Returns ------------- net Petri net initial_marking Initial marking of the Petri net """ places = set(net.places) places_wo_input = [] for place in places: if len(place.in_arcs) == 0: places_wo_input.append(place) places_wo_input = list(places_wo_input) initial_marking = Marking() if len(places_wo_input) > 1: source = PetriNet.Place('petri_source') net.places.add(source) for i in range(len(places_wo_input)): htrans = PetriNet.Transition("itrans_" + str(i), None) net.transitions.add(htrans) utils.add_arc_from_to(source, htrans, net) utils.add_arc_from_to(htrans, places_wo_input[i], net) initial_marking[source] = 1 elif len(places_wo_input) == 1: places_wo_input = list(places_wo_input) initial_marking[places_wo_input[0]] = 1 return net, initial_marking
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
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) 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) 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
def get_final_marking(net, max_no_comb=4): """ Get the final marking from a Petri net (observing which nodes are without output connection, if several nodes exist, then a sink place is created artificially) Parameters ------------- net Petri net Returns ------------- net Petri net final_marking Final marking of the Petri net """ places = set(net.places) places_wo_output = [] for place in places: if len(place.out_arcs) == 0: places_wo_output.append(place) places_wo_output = list(places_wo_output) final_marking = Marking() if len(places_wo_output) > 1: sink = PetriNet.Place('petri_sink') net.places.add(sink) for i in range(len(places_wo_output)): htrans = PetriNet.Transition("ftrans_" + str(i), None) net.transitions.add(htrans) utils.add_arc_from_to(htrans, sink, net) utils.add_arc_from_to(places_wo_output[i], htrans, net) final_marking[sink] = 1 elif len(places_wo_output) == 1: places_wo_output = list(places_wo_output) final_marking[places_wo_output[0]] = 1 return net, final_marking
def test_mcg(self): net = PetriNet("mcg") p_1 = PetriNet.Place("p_1") p_2 = PetriNet.Place("p_2") p_3 = PetriNet.Place("p_3") p_4 = PetriNet.Place("p_4") p_5 = PetriNet.Place("p_5") net.places.add(p_1) net.places.add(p_2) net.places.add(p_3) net.places.add(p_4) net.places.add(p_5) t_1 = PetriNet.Transition("t_1", "t_1") t_2 = PetriNet.Transition("t_2", "t_2") t_3 = PetriNet.Transition("t_3", "t_3") t_4 = PetriNet.Transition("t_4", "t_4") t_5 = PetriNet.Transition("t_5", "t_5") t_6 = PetriNet.Transition("t_6", "t_6") net.transitions.add(t_1) net.transitions.add(t_2) net.transitions.add(t_3) net.transitions.add(t_4) net.transitions.add(t_5) net.transitions.add(t_6) utils.add_arc_from_to(p_1, t_1, net) utils.add_arc_from_to(t_1, p_2, net) utils.add_arc_from_to(p_2, t_3, net) utils.add_arc_from_to(t_3, p_3, net, weight=2) utils.add_arc_from_to(p_3, t_4, net) utils.add_arc_from_to(t_4, p_2, net) utils.add_arc_from_to(p_1, t_2, net) utils.add_arc_from_to(t_2, p_4, net) utils.add_arc_from_to(p_4, t_5, net) utils.add_arc_from_to(t_5, p_5, net, weight=2) utils.add_arc_from_to(p_5, t_6, net) utils.add_arc_from_to(t_6, p_4, net) initial_marking = Marking() initial_marking[p_1] = 1 mcg = minimal_coverability_graph.apply(net, initial_marking)
def apply(dfg, parameters=None): """ Applies the DFG mining on a given object (if it is a Pandas dataframe or a log_skeleton, the DFG is calculated) Parameters ------------- dfg Object (DFG) (if it is a Pandas dataframe or a log_skeleton, 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
def get_transition(counts, label): """ Create a transitions with the specified label in the Petri net """ counts.inc_no_visible() return PetriNet.Transition(str(uuid.uuid4()), label)
def 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) utils.add_arc_from_to(p_1, t_1, net) utils.add_arc_from_to(t_1, p_6, net) utils.add_arc_from_to(t_1, p_4, net) utils.add_arc_from_to(p_4, t_4, net) utils.add_arc_from_to(p_4, t_5, net) utils.add_arc_from_to(t_2, p_6, net) utils.add_arc_from_to(t_2, p_4, net) utils.add_arc_from_to(t_4, p_3, net) utils.add_arc_from_to(t_4, p_5, net) utils.add_arc_from_to(t_5, p_7, net) utils.add_arc_from_to(t_7, p_4, net) utils.add_arc_from_to(p_3, t_2, net) utils.add_arc_from_to(p_3, t_3, net) utils.add_arc_from_to(p_5, t_2, net) utils.add_arc_from_to(p_5, t_3, net) utils.add_arc_from_to(p_5, t_4, net) utils.add_arc_from_to(p_7, t_6, net) utils.add_arc_from_to(p_8, t_7, net) utils.add_arc_from_to(p_8, t_8, net) utils.add_arc_from_to(t_3, p_2, net) utils.add_arc_from_to(p_6, t_6, net) utils.add_arc_from_to(t_6, p_5, net) 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}))