use std::fmt::Display;
use crate::{
BusinessProcessModelAndNotation,
element::BPMNElement,
parser::parser_state::GlobalIndex,
stochastic_business_process_model_and_notation::StochasticBusinessProcessModelAndNotation,
traits::{
processable::Processable,
startable::{InitiationMode, Startable},
transitionable::Transitionable,
},
};
use anyhow::{Result, anyhow};
use bitvec::bitvec;
use ebi_activity_key::Activity;
use ebi_arithmetic::Fraction;
pub type TransitionIndex = usize;
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct BPMNMarking {
pub(crate) element_index_2_sub_markings: Vec<BPMNSubMarking>,
pub(crate) root_marking: BPMNRootMarking,
}
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct BPMNRootMarking {
pub(crate) root_initial_choice_token: bool,
pub(crate) message_flow_2_tokens: Vec<u64>,
}
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct BPMNSubMarking {
pub(crate) sequence_flow_2_tokens: Vec<u64>,
pub(crate) initial_choice_token: bool,
pub(crate) element_index_2_tokens: Vec<u64>,
pub(crate) element_index_2_sub_markings: Vec<Vec<BPMNSubMarking>>,
}
impl Display for BPMNMarking {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
writeln!(f, "{}", stringify!(self))
}
}
impl BPMNSubMarking {
pub(crate) fn new_empty() -> Self {
Self {
sequence_flow_2_tokens: vec![],
initial_choice_token: false,
element_index_2_tokens: vec![],
element_index_2_sub_markings: vec![],
}
}
}
impl BusinessProcessModelAndNotation {
pub fn get_initial_marking(&self) -> Result<Option<BPMNMarking>> {
if self.elements.is_empty() {
return Ok(None);
}
let mut initiation_mode = InitiationMode::ParallelElements(vec![]);
for element in &self.elements {
if let BPMNElement::Process(process) = element {
initiation_mode = initiation_mode + process.initiation_mode(self)?;
}
}
if initiation_mode.is_choice_between_start_events() {
let root_marking = BPMNRootMarking {
message_flow_2_tokens: vec![0; self.message_flows.len()],
root_initial_choice_token: true,
};
let mut element_index_2_sub_markings = Vec::with_capacity(self.elements.len());
for element in self.elements.iter() {
if let BPMNElement::Process(process) = element {
element_index_2_sub_markings.push(process.to_sub_marking(&initiation_mode)?);
} else {
element_index_2_sub_markings.push(BPMNSubMarking::new_empty());
}
}
Ok(Some(BPMNMarking {
element_index_2_sub_markings,
root_marking,
}))
} else {
todo!()
}
}
pub fn execute_transition(
&self,
marking: &mut BPMNMarking,
mut transition_index: TransitionIndex,
) -> Result<()> {
let transition_index_debug = transition_index;
let BPMNMarking {
element_index_2_sub_markings,
root_marking,
} = marking;
for (element, sub_marking) in self
.elements
.iter()
.zip(element_index_2_sub_markings.iter_mut())
{
let number_of_transitions = element.number_of_transitions(sub_marking);
if transition_index < number_of_transitions {
return element.execute_transition(
transition_index,
root_marking,
sub_marking,
self,
self,
);
}
transition_index -= number_of_transitions;
}
Err(anyhow!(
"transition {} is not enabled, as it is unknown",
transition_index_debug
))
}
pub fn is_final_marking(&self, marking: &BPMNMarking) -> Result<bool> {
Ok(self.get_enabled_transitions(marking)?.is_empty())
}
pub fn is_transition_silent(
&self,
transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> bool {
self.get_transition_activity(transition_index, marking)
.is_none()
}
pub fn get_transition_activity(
&self,
mut transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> Option<Activity> {
for (element, sub_marking) in self
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
let number_of_transitions = element.number_of_transitions(sub_marking);
if transition_index < number_of_transitions {
return element.transition_activity(transition_index, sub_marking);
}
transition_index -= number_of_transitions;
}
None
}
pub fn get_enabled_transitions(&self, marking: &BPMNMarking) -> Result<Vec<TransitionIndex>> {
let mut result = bitvec![0;0];
for (element, sub_marking) in self
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
result.extend(element.enabled_transitions(
&marking.root_marking,
sub_marking,
self,
self,
)?);
}
let mut result2 = Vec::new();
for index in result.iter_ones() {
result2.push(index);
}
Ok(result2)
}
pub fn number_of_transitions(&self, marking: &BPMNMarking) -> usize {
let mut result = 0;
for (element, sub_marking) in self
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
result += element.number_of_transitions(sub_marking);
}
result
}
pub fn transition_debug(
&self,
mut transition_index: usize,
marking: &BPMNMarking,
) -> Option<String> {
for (element, sub_marking) in self
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
let number_of_transitions = element.number_of_transitions(sub_marking);
if transition_index < number_of_transitions {
return element.transition_debug(transition_index, sub_marking, self);
}
transition_index -= number_of_transitions;
}
None
}
pub fn transition_2_marked_sequence_flows(
&self,
mut transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> Option<Vec<GlobalIndex>> {
for (element, sub_marking) in self
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
let number_of_transitions = element.number_of_transitions(sub_marking);
if transition_index < number_of_transitions {
return element.transition_2_marked_sequence_flows(
transition_index,
sub_marking,
self,
);
}
transition_index -= number_of_transitions;
}
None
}
}
impl StochasticBusinessProcessModelAndNotation {
pub fn get_initial_marking(&self) -> Result<Option<BPMNMarking>> {
self.bpmn.get_initial_marking()
}
pub fn execute_transition(
&self,
marking: &mut BPMNMarking,
transition_index: TransitionIndex,
) -> Result<()> {
self.bpmn.execute_transition(marking, transition_index)
}
pub fn is_final_marking(&self, marking: &BPMNMarking) -> Result<bool> {
self.bpmn.is_final_marking(marking)
}
pub fn is_transition_silent(
&self,
transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> bool {
self.bpmn.is_transition_silent(transition_index, marking)
}
pub fn get_transition_activity(
&self,
transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> Option<Activity> {
self.bpmn.get_transition_activity(transition_index, marking)
}
pub fn get_enabled_transitions(&self, marking: &BPMNMarking) -> Result<Vec<TransitionIndex>> {
self.bpmn.get_enabled_transitions(marking)
}
pub fn number_of_transitions(&self, marking: &BPMNMarking) -> usize {
self.bpmn.number_of_transitions(marking)
}
pub fn get_transition_weight(
&self,
mut transition_index: TransitionIndex,
marking: &BPMNMarking,
) -> Option<Fraction> {
for (element, sub_marking) in self
.bpmn
.elements
.iter()
.zip(marking.element_index_2_sub_markings.iter())
{
let number_of_transitions = element.number_of_transitions(sub_marking);
if transition_index < number_of_transitions {
return element.transition_weight(transition_index, sub_marking, &self.bpmn);
}
transition_index -= number_of_transitions;
}
None
}
}
#[cfg(test)]
pub(crate) mod tests {
use ebi_arithmetic::{Fraction, One, f};
use crate::{
BusinessProcessModelAndNotation,
semantics::{BPMNMarking, BPMNRootMarking, BPMNSubMarking},
stochastic_business_process_model_and_notation::StochasticBusinessProcessModelAndNotation,
};
use std::fs::{self};
pub fn debug_transitions(bpmn: &BusinessProcessModelAndNotation, marking: &BPMNMarking) {
println!("transitions");
for transition_index in 0..bpmn.number_of_transitions(&marking) {
println!(
"\ttransition {} \t {}",
transition_index,
bpmn.transition_debug(transition_index, marking)
.unwrap_or("None".to_string())
);
}
}
#[test]
fn bpmn_semantics() {
let fin = fs::read_to_string("testfiles/model.bpmn").unwrap();
let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
let mut marking = bpmn.get_initial_marking().unwrap().unwrap();
assert_eq!(bpmn.number_of_transitions(&marking), 13);
debug_transitions(&bpmn, &marking);
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: true,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
let enabled = bpmn.get_enabled_transitions(&marking).unwrap();
assert_eq!(enabled, [0]);
bpmn.execute_transition(&mut marking, 0).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
assert_eq!(
bpmn.activity_key
.deprocess_activity(&bpmn.get_transition_activity(1, &marking).unwrap()),
"Register claim\n(2min)"
);
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 3]);
bpmn.is_transition_silent(3, &marking);
bpmn.execute_transition(&mut marking, 3).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [5]);
assert_eq!(
bpmn.activity_key
.deprocess_activity(&bpmn.get_transition_activity(5, &marking).unwrap()),
"Check easy claim\n(5 min)"
);
bpmn.execute_transition(&mut marking, 5).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [9, 10]);
bpmn.is_transition_silent(9, &marking);
bpmn.execute_transition(&mut marking, 9).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [7]);
bpmn.is_transition_silent(7, &marking);
bpmn.execute_transition(&mut marking, 7).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [8]);
assert!(!bpmn.is_final_marking(&marking).unwrap());
bpmn.is_transition_silent(8, &marking);
bpmn.execute_transition(&mut marking, 8).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![]
},
element_index_2_sub_markings: vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 9],
}],
}
);
assert_eq!(
bpmn.get_enabled_transitions(&marking).unwrap(),
Vec::<usize>::new()
);
assert!(bpmn.is_final_marking(&marking).unwrap());
}
#[test]
fn bpmn_lanes_semantics() {
let fin = fs::read_to_string("testfiles/model-lanes.bpmn").unwrap();
let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
let mut marking = bpmn.get_initial_marking().unwrap().unwrap();
debug_transitions(&bpmn, &marking);
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: true,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 8],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1, 6]);
bpmn.is_transition_silent(1, &marking);
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![1, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 8],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0]);
bpmn.is_transition_silent(0, &marking);
bpmn.execute_transition(&mut marking, 0).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0],
initial_choice_token: true,
element_index_2_tokens: vec![0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 3]
}],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
debug_transitions(&bpmn, &marking);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2]);
bpmn.is_transition_silent(2, &marking);
bpmn.execute_transition(&mut marking, 2).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![1, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 3]
}],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [3]);
assert_eq!(
bpmn.activity_key
.deprocess_activity(&bpmn.get_transition_activity(3, &marking).unwrap()),
""
);
assert!(!bpmn.is_transition_silent(3, &marking));
bpmn.execute_transition(&mut marking, 3).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 1],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 3]
}],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4]);
assert!(bpmn.is_transition_silent(4, &marking));
bpmn.execute_transition(&mut marking, 4).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0],
element_index_2_sub_markings: vec![vec![]; 3]
}],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
assert!(bpmn.is_transition_silent(1, &marking));
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 1, 1, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
debug_transitions(&bpmn, &marking);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 5]);
assert_eq!(
bpmn.activity_key
.deprocess_activity(&bpmn.get_transition_activity(5, &marking).unwrap()),
""
);
bpmn.execute_transition(&mut marking, 5).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 1],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 8]);
assert!(bpmn.is_transition_silent(8, &marking));
bpmn.execute_transition(&mut marking, 8).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2]);
assert_eq!(
bpmn.activity_key
.deprocess_activity(&bpmn.get_transition_activity(2, &marking).unwrap()),
"collapsed subprocess"
);
bpmn.execute_transition(&mut marking, 2).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 1, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4]);
assert!(bpmn.is_transition_silent(4, &marking));
bpmn.execute_transition(&mut marking, 4).unwrap();
assert_eq!(
marking,
BPMNMarking {
root_marking: BPMNRootMarking {
root_initial_choice_token: false,
message_flow_2_tokens: vec![0]
},
element_index_2_sub_markings: vec![
BPMNSubMarking::new_empty(),
BPMNSubMarking {
sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
initial_choice_token: false,
element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
element_index_2_sub_markings: vec![
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
vec![],
],
}
],
}
);
assert!(bpmn.is_final_marking(&marking).unwrap());
}
#[test]
fn bpmn_or_import() {
let fin = fs::read_to_string("testfiles/and-a-b-xor-c-or.sbpmn").unwrap();
let bpmn = fin
.parse::<StochasticBusinessProcessModelAndNotation>()
.unwrap();
let mut marking = bpmn.get_initial_marking().unwrap().unwrap();
debug_transitions(&bpmn.bpmn, &marking);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0]);
assert_eq!(
bpmn.get_transition_weight(0, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 0).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
assert_eq!(
bpmn.get_transition_weight(1, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 3]);
assert_eq!(
bpmn.get_transition_weight(3, &marking).unwrap(),
Fraction::one()
);
assert_eq!(
bpmn.get_transition_weight(2, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 2).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [3]);
assert_eq!(
bpmn.get_transition_weight(3, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 3).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4, 5]);
assert_eq!(bpmn.get_transition_weight(4, &marking).unwrap(), f!(1, 3));
assert_eq!(bpmn.get_transition_weight(5, &marking).unwrap(), f!(2, 3));
bpmn.execute_transition(&mut marking, 4).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [6, 7]);
assert_eq!(
bpmn.get_transition_weight(6, &marking).unwrap(),
Fraction::one()
);
assert_eq!(
bpmn.get_transition_weight(7, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 6).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [7, 9]);
assert_eq!(
bpmn.get_transition_weight(7, &marking).unwrap(),
Fraction::one()
);
assert_eq!(
bpmn.get_transition_weight(9, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 7).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [8, 9]);
assert_eq!(
bpmn.get_transition_weight(8, &marking).unwrap(),
Fraction::one()
);
assert_eq!(
bpmn.get_transition_weight(9, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 8).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [9]);
assert_eq!(
bpmn.get_transition_weight(9, &marking).unwrap(),
Fraction::one()
);
bpmn.execute_transition(&mut marking, 9).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0; 0]);
assert!(bpmn.is_final_marking(&marking).unwrap());
}
#[test]
fn bpmn_eventbasedgateway() {
let fin = fs::read_to_string("testfiles/eventbasedgateway.bpmn").unwrap();
let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
let mut marking = bpmn.get_initial_marking().unwrap().unwrap();
debug_transitions(&bpmn, &marking);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![0]);
bpmn.execute_transition(&mut marking, 0).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![1]);
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(
bpmn.get_enabled_transitions(&marking).unwrap(),
vec![2, 6, 7]
);
bpmn.execute_transition(&mut marking, 6).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![3]);
bpmn.execute_transition(&mut marking, 3).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![0; 0]);
assert!(bpmn.is_final_marking(&marking).unwrap());
}
#[test]
fn admission() {
let fin = fs::read_to_string("testfiles/admission.bpmn").unwrap();
let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
let mut marking = bpmn.get_initial_marking().unwrap().unwrap();
debug_transitions(&bpmn, &marking);
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![0]);
bpmn.execute_transition(&mut marking, 0).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![1]);
bpmn.execute_transition(&mut marking, 1).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![3, 4]);
bpmn.execute_transition(&mut marking, 3).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![5]);
bpmn.execute_transition(&mut marking, 5).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![7]);
bpmn.execute_transition(&mut marking, 7).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![2]);
bpmn.execute_transition(&mut marking, 2).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![3, 4]);
bpmn.execute_transition(&mut marking, 4).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![8]);
bpmn.execute_transition(&mut marking, 8).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![6, 9]);
bpmn.execute_transition(&mut marking, 6).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![9, 11]);
bpmn.execute_transition(&mut marking, 9).unwrap();
assert_eq!(
bpmn.get_enabled_transitions(&marking).unwrap(),
vec![10, 11]
);
bpmn.execute_transition(&mut marking, 10).unwrap();
assert_eq!(
bpmn.get_enabled_transitions(&marking).unwrap(),
vec![11, 12]
);
bpmn.execute_transition(&mut marking, 11).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![12]);
bpmn.execute_transition(&mut marking, 12).unwrap();
assert_eq!(
bpmn.get_enabled_transitions(&marking).unwrap(),
vec![12, 13]
);
bpmn.execute_transition(&mut marking, 12).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![13]);
bpmn.execute_transition(&mut marking, 13).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![13]);
assert!(!bpmn.is_final_marking(&marking).unwrap());
bpmn.execute_transition(&mut marking, 13).unwrap();
assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), vec![0; 0]);
assert!(bpmn.is_final_marking(&marking).unwrap());
}
}