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 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 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 test_marking_equality(): net = PetriNet() p0 = PetriNet.Place('p0') p1 = PetriNet.Place('p1') net.places.update([p0, p1]) m0 = Marking([p0]) m1 = Marking([p0]) assert m0 == m1
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 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 __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 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
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 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 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 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 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 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 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 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 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 __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 apply(bpmn_graph, parameters=None): """ Converts a BPMN graph to an accepting Petri net Parameters -------------- bpmn_graph BPMN graph parameters Parameters of the algorithm Returns -------------- net Petri net im Initial marking fm Final marking """ if parameters is None: parameters = {} import networkx as nx from pm4py.objects.bpmn.bpmn_graph import BPMN use_id = exec_utils.get_param_value(Parameters.USE_ID, parameters, False) net = PetriNet("") source_place = PetriNet.Place("source") net.places.add(source_place) sink_place = PetriNet.Place("sink") net.places.add(sink_place) im = Marking() fm = Marking() im[source_place] = 1 fm[sink_place] = 1 # keep this correspondence for adding invisible transitions for OR-gateways inclusive_gateway_exit = set() inclusive_gateway_entry = set() flow_place = {} source_count = {} target_count = {} for flow in bpmn_graph.get_flows(): source = flow.get_source() target = flow.get_target() place = PetriNet.Place(str(flow.get_id())) net.places.add(place) flow_place[flow] = place if source not in source_count: source_count[source] = 0 if target not in target_count: target_count[target] = 0 source_count[source] = source_count[source] + 1 target_count[target] = target_count[target] + 1 for flow in bpmn_graph.get_flows(): source = flow.get_source() target = flow.get_target() place = PetriNet.Place(str(flow.get_id())) if isinstance(source, BPMN.InclusiveGateway) and source_count[source] > 1: inclusive_gateway_exit.add(place.name) elif isinstance(target, BPMN.InclusiveGateway) and target_count[target] > 1: inclusive_gateway_entry.add(place.name) # remove possible places that are both in inclusive_gateway_exit and inclusive_gateway_entry, # because we do not need to add invisibles in this situation incl_gat_set_inters = inclusive_gateway_entry.intersection( inclusive_gateway_exit) inclusive_gateway_exit = inclusive_gateway_exit.difference( incl_gat_set_inters) inclusive_gateway_entry = inclusive_gateway_entry.difference( incl_gat_set_inters) nodes_entering = {} nodes_exiting = {} for node in bpmn_graph.get_nodes(): entry_place = PetriNet.Place("ent_" + str(node.get_id())) net.places.add(entry_place) exiting_place = PetriNet.Place("exi_" + str(node.get_id())) net.places.add(exiting_place) if use_id: label = str(node.get_id()) else: label = str(node.get_name()) if isinstance(node, BPMN.Task) else None if not label: label = None transition = PetriNet.Transition(name=str(node.get_id()), label=label) net.transitions.add(transition) add_arc_from_to(entry_place, transition, net) add_arc_from_to(transition, exiting_place, net) if isinstance(node, BPMN.ParallelGateway) or isinstance( node, BPMN.InclusiveGateway): if source_count[node] > 1: exiting_object = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(exiting_object) add_arc_from_to(exiting_place, exiting_object, net) else: exiting_object = exiting_place if target_count[node] > 1: entering_object = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(entering_object) add_arc_from_to(entering_object, entry_place, net) else: entering_object = entry_place nodes_entering[node] = entering_object nodes_exiting[node] = exiting_object else: nodes_entering[node] = entry_place nodes_exiting[node] = exiting_place if isinstance(node, BPMN.StartEvent): start_transition = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(start_transition) add_arc_from_to(source_place, start_transition, net) add_arc_from_to(start_transition, entry_place, net) elif isinstance(node, BPMN.EndEvent): end_transition = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(end_transition) add_arc_from_to(exiting_place, end_transition, net) add_arc_from_to(end_transition, sink_place, net) for flow in bpmn_graph.get_flows(): source_object = nodes_exiting[flow.get_source()] target_object = nodes_entering[flow.get_target()] if isinstance(source_object, PetriNet.Place): inv1 = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(inv1) add_arc_from_to(source_object, inv1, net) source_object = inv1 if isinstance(target_object, PetriNet.Place): inv2 = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(inv2) add_arc_from_to(inv2, target_object, net) target_object = inv2 add_arc_from_to(source_object, flow_place[flow], net) add_arc_from_to(flow_place[flow], target_object, net) if inclusive_gateway_exit and inclusive_gateway_entry: # do the following steps if there are inclusive gateways: # - calculate the shortest paths # - add an invisible transition between couples of corresponding places # this ensures soundness and the correct translation of the BPMN inv_places = {x.name: x for x in net.places} digraph = build_digraph_from_petri_net(net) all_shortest_paths = dict(nx.all_pairs_dijkstra(digraph)) keys = list(all_shortest_paths.keys()) for pl1 in inclusive_gateway_exit: if pl1 in keys: output_places = sorted( [(x, len(y)) for x, y in all_shortest_paths[pl1][1].items() if x in inclusive_gateway_entry], key=lambda x: x[1]) if output_places: inv_trans = PetriNet.Transition(str(uuid.uuid4()), None) net.transitions.add(inv_trans) add_arc_from_to(inv_places[pl1], inv_trans, net) add_arc_from_to(inv_trans, inv_places[output_places[0][0]], net) reduction.apply_simple_reduction(net) return net, im, fm
def import_net(input_file_path, parameters=None): """ Import a Petri net from a PNML file Parameters ---------- input_file_path Input file path parameters Other parameters of the algorithm """ if parameters is None: parameters = {} parser = etree.XMLParser(remove_comments=True) tree = objectify.parse(input_file_path, parser=parser) root = tree.getroot() 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_name = child.get("id") trans_label = trans_name trans_visible = True random_variable = None for child2 in child: if child2.tag.endswith("name"): for child3 in child2: if child3.text: if trans_label == trans_name: trans_label = 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) if not trans_visible: trans_label = None #if "INVISIBLE" in trans_label: # trans_label = None trans_dict[trans_name] = PetriNet.Transition( trans_name, trans_label) net.transitions.add(trans_dict[trans_name]) if random_variable is not None: trans_dict[trans_name].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_name].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
def add_place(net, name=None): name = name if name is not None else 'p_' + str(len( net.places)) + '_' + str(time.time()) + str(random.randint(0, 10000)) p = PetriNet.Place(name=name) net.places.add(p) return p
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
def get_new_place(counts): """ Create a new place in the Petri net """ counts.inc_places() return PetriNet.Place('p_' + str(counts.num_places))
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}))
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
from pm4py.objects.petri.petrinet import PetriNet, Marking net = PetriNet("new_petri_net") start = PetriNet.Place("start") end = PetriNet.Place("end") p_1 = PetriNet.Place("({'Activity A'}, {'Activity C', 'Activity D'})") p_2 = PetriNet.Place("({'Activity C','Activity E'}, {'Activity B'})") p_3 = PetriNet.Place("({'Activity D','Activity H'}, {'Activity F'})") p_4 = PetriNet.Place("({'Activity F'}, {'Activity G', 'Activity E'})") p_5 = PetriNet.Place("({'Activity G'}, {'Activity I'})") p_6 = PetriNet.Place("({'Activity G'}, {'Activity J'})") p_7 = PetriNet.Place("({'Activity I','Activity J'}, {'Activity H'})") # add the places to the Petri Net net.places.add(start) net.places.add(end) 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("Activity A", "Activity A") t_2 = PetriNet.Transition("Activity B", "Activity B") t_3 = PetriNet.Transition("Activity C", "Activity C") t_4 = PetriNet.Transition("Activity D", "Activity D") t_5 = PetriNet.Transition("Activity E", "Activity E") t_6 = PetriNet.Transition("Activity F", "Activity F") t_7 = PetriNet.Transition("Activity G", "Activity G")