Source code for pm4py.objects.petri_net.utils.reachability_graph

'''
    PM4Py – A Process Mining Library for Python
Copyright (C) 2024 Process Intelligence Solutions UG (haftungsbeschränkt)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see this software project's root or
visit <https://www.gnu.org/licenses/>.

Website: https://processintelligence.solutions
Contact: info@processintelligence.solutions
'''
import re

from pm4py.objects import petri_net
from pm4py.objects.transition_system.obj import TransitionSystem
from pm4py.objects.petri_net.utils import align_utils
from pm4py.objects.transition_system import obj as ts
from pm4py.objects.transition_system import utils
from pm4py.util import exec_utils
from enum import Enum
import time


[docs] class Parameters(Enum): MAX_ELAB_TIME = "max_elab_time" PETRI_SEMANTICS = "petri_semantics"
[docs] def staterep(name): """ Creates a string representation for a state of a transition system. Necessary because graphviz does not support symbols simulation than alphanimerics and '_'. TODO: find a better representation. Parameters ---------- name: the name of a state Returns ------- Version of the name filtered of non-alphanumerical characters (except '_'). """ return re.sub(r"\W+", "", name)
[docs] def marking_flow_petri( net, im, return_eventually_enabled=False, parameters=None ): """ Construct the marking flow of a Petri net Parameters ----------------- net Petri net im Initial marking return_eventually_enabled Return the eventually enabled (visible) transitions """ if parameters is None: parameters = {} # set a maximum execution time of 1 day (it can be changed by providing # the parameter) max_exec_time = exec_utils.get_param_value( Parameters.MAX_ELAB_TIME, parameters, 86400 ) semantics = exec_utils.get_param_value( Parameters.PETRI_SEMANTICS, parameters, petri_net.semantics.ClassicSemantics(), ) start_time = time.time() incoming_transitions = {im: set()} outgoing_transitions = {} eventually_enabled = {} active = [im] while active: if (time.time() - start_time) >= max_exec_time: # interrupt the execution return ( incoming_transitions, outgoing_transitions, eventually_enabled, ) m = active.pop() enabled_transitions = semantics.enabled_transitions(net, m) if return_eventually_enabled: eventually_enabled[m] = ( align_utils.get_visible_transitions_eventually_enabled_by_marking( net, m)) outgoing_transitions[m] = {} for t in enabled_transitions: nm = semantics.weak_execute(t, net, m) outgoing_transitions[m][t] = nm if nm not in incoming_transitions: incoming_transitions[nm] = set() if nm not in active: active.append(nm) incoming_transitions[nm].add(t) return incoming_transitions, outgoing_transitions, eventually_enabled
[docs] def construct_reachability_graph_from_flow( incoming_transitions, outgoing_transitions, use_trans_name=False, parameters=None, ): """ Construct the reachability graph from the marking flow Parameters ---------------- incoming_transitions Incoming transitions outgoing_transitions Outgoing transitions use_trans_name Use the transition name Returns ---------------- re_gr Transition system that represents the reachability graph of the input Petri net. """ if parameters is None: parameters = {} re_gr = ts.TransitionSystem() map_states = {} for s in incoming_transitions: map_states[s] = ts.TransitionSystem.State(staterep(repr(s))) re_gr.states.add(map_states[s]) for s1 in outgoing_transitions: for t in outgoing_transitions[s1]: s2 = outgoing_transitions[s1][t] if use_trans_name: utils.add_arc_from_to( t.name, map_states[s1], map_states[s2], re_gr ) else: utils.add_arc_from_to( repr(t), map_states[s1], map_states[s2], re_gr ) return re_gr
[docs] def construct_reachability_graph( net, initial_marking, use_trans_name=False, parameters=None ) -> TransitionSystem: """ Creates a reachability graph of a certain Petri net. DO NOT ATTEMPT WITH AN UNBOUNDED PETRI NET, EVER. Parameters ---------- net: Petri net initial_marking: initial marking of the Petri net. Returns ------- re_gr: Transition system that represents the reachability graph of the input Petri net. """ incoming_transitions, outgoing_transitions, eventually_enabled = ( marking_flow_petri(net, initial_marking, parameters=parameters) ) return construct_reachability_graph_from_flow( incoming_transitions, outgoing_transitions, use_trans_name=use_trans_name, parameters=parameters, )