ebi_objects/conversions/
to_petri_net_markup_language.rs1use std::collections::HashMap;
2
3use anyhow::{Error, anyhow};
4use process_mining::{
5 PetriNet,
6 petri_net::petri_net_struct::{self, ArcType},
7};
8
9use crate::ebi_objects::{
10 deterministic_finite_automaton::DeterministicFiniteAutomaton,
11 directly_follows_graph::DirectlyFollowsGraph, directly_follows_model::DirectlyFollowsModel,
12 labelled_petri_net::LabelledPetriNet, petri_net_markup_language::PetriNetMarkupLanguage,
13 process_tree::ProcessTree,
14 stochastic_deterministic_finite_automaton::StochasticDeterministicFiniteAutomaton,
15 stochastic_directly_follows_model::StochasticDirectlyFollowsModel,
16 stochastic_labelled_petri_net::StochasticLabelledPetriNet,
17 stochastic_process_tree::StochasticProcessTree,
18};
19
20impl TryFrom<&LabelledPetriNet> for process_mining::PetriNet {
21 type Error = anyhow::Error;
22
23 fn try_from(lpn: &LabelledPetriNet) -> std::result::Result<Self, Self::Error> {
24 log::info!("Convert LPN into PNML.");
25
26 let mut result = PetriNet::new();
27
28 let mut place2new_place = HashMap::new();
30 {
31 for place in 0..lpn.get_number_of_places() {
32 let new_place = result.add_place(None);
33 place2new_place.insert(place, new_place);
34 }
35 }
36
37 for transition in 0..lpn.transition2input_places.len() {
39 let new_transition = result.add_transition(
40 match lpn.get_transition_label(transition) {
41 Some(activity) => {
42 Some(lpn.activity_key.get_activity_label(&activity).to_string())
43 }
44 None => None,
45 },
46 None,
47 );
48
49 {
51 let mut map = HashMap::new();
53 for (pos, place) in lpn.transition2input_places[transition].iter().enumerate() {
54 *map.entry(*place).or_insert(0) +=
55 u32::try_from(lpn.transition2input_places_cardinality[transition][pos])?;
56 }
57
58 for (place, weight) in map {
60 let new_place = place2new_place
61 .get(&place)
62 .ok_or(anyhow!("Non-existing place referenced."))?;
63 result.add_arc(
64 ArcType::place_to_transition(*new_place, new_transition),
65 Some(weight),
66 );
67 }
68 }
69
70 {
72 let mut map = HashMap::new();
74 for (pos, place) in lpn.transition2output_places[transition].iter().enumerate() {
75 *map.entry(*place).or_insert(0) +=
76 u32::try_from(lpn.transition2output_places_cardinality[transition][pos])?;
77 }
78
79 for (place, weight) in map {
81 let new_place = place2new_place
82 .get(&place)
83 .ok_or(anyhow!("Non-existing place referenced."))?;
84 result.add_arc(
85 ArcType::transition_to_place(new_transition, *new_place),
86 Some(weight),
88 );
89 }
90 }
91 }
92
93 let mut new_initial_marking = petri_net_struct::Marking::new();
95 for (place, cardinality) in lpn
96 .initial_marking
97 .get_place2token()
98 .into_iter()
99 .enumerate()
100 {
101 if cardinality > &0u64 {
102 let new_place = place2new_place
103 .get(&place)
104 .ok_or(anyhow!("Non-existing place referenced."))?;
105 new_initial_marking.insert(*new_place, *cardinality);
106 }
107 }
108 result.initial_marking = Some(new_initial_marking);
109
110 Ok(result)
111 }
112}
113
114macro_rules! from {
115 ($t:ident) => {
116 impl TryFrom<$t> for process_mining::PetriNet {
117 type Error = Error;
118
119 fn try_from(value: $t) -> Result<Self, Self::Error> {
120 let lpn: LabelledPetriNet = value.into();
121 (&lpn).try_into()
122 }
123 }
124
125 impl TryFrom<$t> for PetriNetMarkupLanguage {
126 type Error = Error;
127
128 fn try_from(value: $t) -> Result<Self, Self::Error> {
129 let lpn: LabelledPetriNet = value.into();
130 Ok(Self(lpn))
131 }
132 }
133 };
134}
135
136from!(StochasticLabelledPetriNet);
137from!(DeterministicFiniteAutomaton);
138from!(DirectlyFollowsModel);
139from!(DirectlyFollowsGraph);
140from!(StochasticDirectlyFollowsModel);
141from!(ProcessTree);
142from!(StochasticProcessTree);
143from!(StochasticDeterministicFiniteAutomaton);