Source code for pm4py.objects.petri_net.saw_net.convert
'''
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
'''
from pm4py.objects.petri_net.saw_net.obj import StochasticArcWeightNet
from pm4py.objects.petri_net.stochastic.obj import StochasticPetriNet
from pm4py.objects.petri_net.saw_net.semantics import (
GlobalStochasticArcWeightNetSemantics as sawsem_global,
LocalStochasticArcWeightNetSemantics as sawsem_local,
)
from typing import Counter as TCounter, Tuple
from collections import deque
[docs]
def convert_saw_net_to_stochastic_net_global_semantics(
saw: StochasticArcWeightNet,
) -> StochasticPetriNet:
sn = StochasticPetriNet()
p_map = dict()
for p in saw.places:
p_new = StochasticPetriNet.Place(p.name, properties=p.properties)
sn.places.add(p_new)
p_map[p] = p_new
a_sums = dict()
for a in saw.arcs:
a_sums[a] = 0
for w, v in a.weight_distribution.items():
a_sums[a] = a_sums[a] + v
for t in saw.transitions:
bindings = sawsem_global.all_legal_bindings(saw, t)
for b in bindings:
transition_weight = t.weight
t_new = StochasticPetriNet.Transition(
"t" + str(len(sn.transitions)), t.label
)
sn.transitions.add(t_new)
for a, w in b:
a_new = (
StochasticPetriNet.Arc(t_new, p_map[a.target], w)
if a.source == t
else StochasticPetriNet.Arc(p_map[a.source], t_new, w)
)
if a.source == t:
t_new.out_arcs.add(a_new)
p_map[a.target].in_arcs.add(a_new)
else:
t_new.in_arcs.add(a_new)
p_map[a.source].out_arcs.add(a_new)
sn.arcs.add(a_new)
transition_weight = transition_weight * (
a.weight_distribution[w] / a_sums[a]
)
t_new.weight = transition_weight
return sn, p_map
[docs]
def convert_saw_net_to_stochastic_net_local_semantics(
saw: StochasticArcWeightNet,
marking: TCounter[StochasticArcWeightNet.Place],
) -> Tuple[StochasticPetriNet, TCounter[StochasticArcWeightNet.Place]]:
sn = StochasticPetriNet()
open = deque()
closed = set()
markings = dict()
markings[marking] = {
p: StochasticPetriNet.Place(p.name + "-" + str(marking))
for p in marking
if marking[p] > 0
}
for p in markings[marking]:
sn.places.add(markings[marking][p])
open.append(marking)
while len(open) > 0:
m = open.pop()
for t in saw.transitions:
if sawsem_local.is_enabled(saw, t, m):
for b in sawsem_local.all_enabled_bindings(saw, t, m):
m_out = sawsem_local.fire(saw, b, m)
if m_out not in markings:
markings[m_out] = {
p: StochasticPetriNet.Place(
p.name + "-" + str(m_out)
)
for p in m_out
if m_out[p] > 0
}
for p in markings[m_out]:
sn.places.add(markings[m_out][p])
t_new = StochasticPetriNet.Transition(
t.name + "-" + str(b),
t.label,
weight=t.weight
* sawsem_local.amortized_priority(b)
/ sum(
[
sawsem_local.amortized_priority(bb)
for bb in sawsem_local.all_enabled_bindings(
saw, t, m
)
]
),
)
sn.transitions.add(t_new)
plcs_in = markings[m]
plcs_out = markings[m_out]
for p in m:
if m[p] > 0:
a = StochasticPetriNet.Arc(plcs_in[p], t_new, m[p])
plcs_in[p].out_arcs.add(a)
t_new.in_arcs.add(a)
sn.arcs.add(a)
for p in m_out:
if m_out[p] > 0:
a = StochasticPetriNet.Arc(
t_new, plcs_out[p], m_out[p]
)
plcs_out[p].in_arcs.add(a)
t_new.out_arcs.add(a)
sn.arcs.add(a)
if m_out not in closed and m_out is not m:
open.append(m_out)
return sn, {markings[marking][p]: marking[p] for p in marking}