1use std::fmt::Display;
2
3use crate::{
4 BusinessProcessModelAndNotation,
5 element::BPMNElement,
6 stochastic_business_process_model_and_notation::StochasticBusinessProcessModelAndNotation,
7 traits::{
8 processable::Processable,
9 startable::{InitiationMode, Startable},
10 transitionable::Transitionable,
11 },
12};
13use anyhow::{Result, anyhow};
14use bitvec::bitvec;
15use ebi_activity_key::Activity;
16use ebi_arithmetic::Fraction;
17
18pub type TransitionIndex = usize;
19
20#[derive(Debug, PartialEq, Eq, Clone, Hash)]
21pub struct BPMNMarking {
22 pub(crate) element_index_2_sub_markings: Vec<BPMNSubMarking>,
23 pub(crate) root_marking: BPMNRootMarking,
24}
25
26#[derive(Debug, PartialEq, Eq, Clone, Hash)]
27pub struct BPMNRootMarking {
28 pub(crate) root_initial_choice_token: bool,
29 pub(crate) message_flow_2_tokens: Vec<u64>,
30}
31
32#[derive(Debug, PartialEq, Eq, Hash, Clone)]
33pub struct BPMNSubMarking {
34 pub(crate) sequence_flow_2_tokens: Vec<u64>,
35 pub(crate) initial_choice_token: bool,
36 pub(crate) element_index_2_tokens: Vec<u64>,
37 pub(crate) element_index_2_sub_markings: Vec<Vec<BPMNSubMarking>>,
38}
39
40impl Display for BPMNMarking {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 writeln!(f, "{}", stringify!(self))
43 }
44}
45
46impl BPMNSubMarking {
47 pub(crate) fn new_empty() -> Self {
48 Self {
49 sequence_flow_2_tokens: vec![],
50 initial_choice_token: false,
51 element_index_2_tokens: vec![],
52 element_index_2_sub_markings: vec![],
53 }
54 }
55}
56
57impl BusinessProcessModelAndNotation {
58 pub fn get_initial_marking(&self) -> Result<BPMNMarking> {
60 let mut initiation_mode = InitiationMode::ParallelElements(vec![]);
62 for element in &self.elements {
63 if let BPMNElement::Process(process) = element {
64 initiation_mode = initiation_mode + process.initiation_mode(self)?;
65 }
66 }
67
68 if initiation_mode.is_choice_between_start_events() {
69 let root_marking = BPMNRootMarking {
70 message_flow_2_tokens: vec![0; self.message_flows.len()],
71 root_initial_choice_token: true,
72 };
73
74 let mut element_index_2_sub_markings = Vec::with_capacity(self.elements.len());
75 for element in self.elements.iter() {
76 if let BPMNElement::Process(process) = element {
77 element_index_2_sub_markings.push(process.to_sub_marking(&initiation_mode)?);
78 } else {
79 element_index_2_sub_markings.push(BPMNSubMarking::new_empty());
80 }
81 }
82
83 Ok(BPMNMarking {
84 element_index_2_sub_markings,
85 root_marking,
86 })
87 } else {
88 todo!()
89 }
90 }
91
92 pub fn execute_transition(
93 &self,
94 marking: &mut BPMNMarking,
95 mut transition_index: TransitionIndex,
96 ) -> Result<()> {
97 let transition_index_debug = transition_index;
98 let BPMNMarking {
99 element_index_2_sub_markings,
100 root_marking,
101 } = marking;
102 for (element, sub_marking) in self
103 .elements
104 .iter()
105 .zip(element_index_2_sub_markings.iter_mut())
106 {
107 let number_of_transitions = element.number_of_transitions(sub_marking);
108 if transition_index < number_of_transitions {
109 return element.execute_transition(
110 transition_index,
111 root_marking,
112 sub_marking,
113 self,
114 self,
115 );
116 }
117 transition_index -= number_of_transitions;
118 }
119 Err(anyhow!(
120 "transition {} is not enabled, as it is unknown",
121 transition_index_debug
122 ))
123 }
124
125 pub fn is_final_marking(&self, marking: &BPMNMarking) -> Result<bool> {
126 Ok(self.get_enabled_transitions(marking)?.is_empty())
127 }
128
129 pub fn is_transition_silent(
130 &self,
131 transition_index: TransitionIndex,
132 marking: &BPMNMarking,
133 ) -> bool {
134 self.get_transition_activity(transition_index, marking)
135 .is_none()
136 }
137
138 pub fn get_transition_activity(
139 &self,
140 mut transition_index: TransitionIndex,
141 marking: &BPMNMarking,
142 ) -> Option<Activity> {
143 for (element, sub_marking) in self
144 .elements
145 .iter()
146 .zip(marking.element_index_2_sub_markings.iter())
147 {
148 let number_of_transitions = element.number_of_transitions(sub_marking);
149 if transition_index < number_of_transitions {
150 return element.transition_activity(transition_index, sub_marking);
151 }
152 transition_index -= number_of_transitions;
153 }
154 None
155 }
156
157 pub fn get_enabled_transitions(&self, marking: &BPMNMarking) -> Result<Vec<TransitionIndex>> {
158 let mut result = bitvec![0;0];
159 for (element, sub_marking) in self
160 .elements
161 .iter()
162 .zip(marking.element_index_2_sub_markings.iter())
163 {
164 result.extend(element.enabled_transitions(
165 &marking.root_marking,
166 sub_marking,
167 self,
168 self,
169 )?);
170 }
171
172 let mut result2 = Vec::new();
174 for index in result.iter_ones() {
175 result2.push(index);
176 }
177 Ok(result2)
178 }
179
180 pub fn number_of_transitions(&self, marking: &BPMNMarking) -> usize {
181 let mut result = 0;
182 for (element, sub_marking) in self
183 .elements
184 .iter()
185 .zip(marking.element_index_2_sub_markings.iter())
186 {
187 result += element.number_of_transitions(sub_marking);
188 }
189 result
190 }
191}
192
193impl StochasticBusinessProcessModelAndNotation {
194 pub fn get_initial_marking(&self) -> Result<BPMNMarking> {
196 self.bpmn.get_initial_marking()
197 }
198
199 pub fn execute_transition(
200 &self,
201 marking: &mut BPMNMarking,
202 transition_index: TransitionIndex,
203 ) -> Result<()> {
204 self.bpmn.execute_transition(marking, transition_index)
205 }
206
207 pub fn is_final_marking(&self, marking: &BPMNMarking) -> Result<bool> {
208 self.bpmn.is_final_marking(marking)
209 }
210
211 pub fn is_transition_silent(
212 &self,
213 transition_index: TransitionIndex,
214 marking: &BPMNMarking,
215 ) -> bool {
216 self.bpmn.is_transition_silent(transition_index, marking)
217 }
218
219 pub fn get_transition_activity(
220 &self,
221 transition_index: TransitionIndex,
222 marking: &BPMNMarking,
223 ) -> Option<Activity> {
224 self.bpmn.get_transition_activity(transition_index, marking)
225 }
226
227 pub fn get_enabled_transitions(&self, marking: &BPMNMarking) -> Result<Vec<TransitionIndex>> {
228 self.bpmn.get_enabled_transitions(marking)
229 }
230
231 pub fn number_of_transitions(&self, marking: &BPMNMarking) -> usize {
232 self.bpmn.number_of_transitions(marking)
233 }
234
235 pub fn get_transition_weight(
236 &self,
237 mut transition_index: TransitionIndex,
238 marking: &BPMNMarking,
239 ) -> Option<Fraction> {
240 for (element, sub_marking) in self
241 .bpmn
242 .elements
243 .iter()
244 .zip(marking.element_index_2_sub_markings.iter())
245 {
246 let number_of_transitions = element.number_of_transitions(sub_marking);
247 if transition_index < number_of_transitions {
248 return element.transition_weight(transition_index, sub_marking, &self.bpmn);
249 }
250 transition_index -= number_of_transitions;
251 }
252 None
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use ebi_arithmetic::{Fraction, One, f};
259
260 use crate::{
261 BusinessProcessModelAndNotation,
262 semantics::{BPMNMarking, BPMNRootMarking, BPMNSubMarking},
263 stochastic_business_process_model_and_notation::StochasticBusinessProcessModelAndNotation,
264 };
265 use std::fs::{self};
266
267 pub fn debug_transitions(bpmn: &BusinessProcessModelAndNotation, marking: &BPMNMarking) {
268 println!("transitions");
269 for transition_index in 0..bpmn.number_of_transitions(&marking) {
270 println!(
271 "\ttransition {} \t {}",
272 transition_index,
273 bpmn.transition_debug(transition_index, marking)
274 .unwrap_or("None".to_string())
275 );
276 }
277 }
278
279 #[test]
280 fn bpmn_semantics() {
281 let fin = fs::read_to_string("testfiles/model.bpmn").unwrap();
282 let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
283
284 let mut marking = bpmn.get_initial_marking().unwrap();
285 assert_eq!(bpmn.number_of_transitions(&marking), 13);
286 debug_transitions(&bpmn, &marking);
287
288 assert_eq!(
289 marking,
290 BPMNMarking {
291 root_marking: BPMNRootMarking {
292 root_initial_choice_token: true,
293 message_flow_2_tokens: vec![]
294 },
295 element_index_2_sub_markings: vec![BPMNSubMarking {
296 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
297 initial_choice_token: false,
298 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
299 element_index_2_sub_markings: vec![vec![]; 9],
300 }],
301 }
302 );
303 let enabled = bpmn.get_enabled_transitions(&marking).unwrap();
304 assert_eq!(enabled, [0]);
305
306 bpmn.execute_transition(&mut marking, 0).unwrap();
308 assert_eq!(
309 marking,
310 BPMNMarking {
311 root_marking: BPMNRootMarking {
312 root_initial_choice_token: false,
313 message_flow_2_tokens: vec![]
314 },
315 element_index_2_sub_markings: vec![BPMNSubMarking {
316 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
317 initial_choice_token: false,
318 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
319 element_index_2_sub_markings: vec![vec![]; 9],
320 }],
321 }
322 );
323 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
324
325 assert_eq!(
327 bpmn.activity_key
328 .deprocess_activity(&bpmn.get_transition_activity(1, &marking).unwrap()),
329 "Register claim\n(2min)"
330 );
331 bpmn.execute_transition(&mut marking, 1).unwrap();
332 assert_eq!(
333 marking,
334 BPMNMarking {
335 root_marking: BPMNRootMarking {
336 root_initial_choice_token: false,
337 message_flow_2_tokens: vec![]
338 },
339 element_index_2_sub_markings: vec![BPMNSubMarking {
340 sequence_flow_2_tokens: vec![1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
341 initial_choice_token: false,
342 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
343 element_index_2_sub_markings: vec![vec![]; 9],
344 }],
345 }
346 );
347 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 3]);
348
349 bpmn.is_transition_silent(3, &marking);
351 bpmn.execute_transition(&mut marking, 3).unwrap();
352 assert_eq!(
353 marking,
354 BPMNMarking {
355 root_marking: BPMNRootMarking {
356 root_initial_choice_token: false,
357 message_flow_2_tokens: vec![]
358 },
359 element_index_2_sub_markings: vec![BPMNSubMarking {
360 sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
361 initial_choice_token: false,
362 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
363 element_index_2_sub_markings: vec![vec![]; 9],
364 }],
365 }
366 );
367 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [5]);
368
369 assert_eq!(
371 bpmn.activity_key
372 .deprocess_activity(&bpmn.get_transition_activity(5, &marking).unwrap()),
373 "Check easy claim\n(5 min)"
374 );
375 bpmn.execute_transition(&mut marking, 5).unwrap();
376 assert_eq!(
377 marking,
378 BPMNMarking {
379 root_marking: BPMNRootMarking {
380 root_initial_choice_token: false,
381 message_flow_2_tokens: vec![]
382 },
383 element_index_2_sub_markings: vec![BPMNSubMarking {
384 sequence_flow_2_tokens: vec![0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
385 initial_choice_token: false,
386 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
387 element_index_2_sub_markings: vec![vec![]; 9],
388 }],
389 }
390 );
391 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [9, 10]);
392
393 bpmn.is_transition_silent(9, &marking);
395 bpmn.execute_transition(&mut marking, 9).unwrap();
396 assert_eq!(
397 marking,
398 BPMNMarking {
399 root_marking: BPMNRootMarking {
400 root_initial_choice_token: false,
401 message_flow_2_tokens: vec![]
402 },
403 element_index_2_sub_markings: vec![BPMNSubMarking {
404 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 1, 0, 0],
405 initial_choice_token: false,
406 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
407 element_index_2_sub_markings: vec![vec![]; 9],
408 }],
409 }
410 );
411 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [7]);
412
413 bpmn.is_transition_silent(7, &marking);
415 bpmn.execute_transition(&mut marking, 7).unwrap();
416 assert_eq!(
417 marking,
418 BPMNMarking {
419 root_marking: BPMNRootMarking {
420 root_initial_choice_token: false,
421 message_flow_2_tokens: vec![]
422 },
423 element_index_2_sub_markings: vec![BPMNSubMarking {
424 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
425 initial_choice_token: false,
426 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
427 element_index_2_sub_markings: vec![vec![]; 9],
428 }],
429 }
430 );
431 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [8]);
432 assert!(!bpmn.is_final_marking(&marking).unwrap());
433
434 bpmn.is_transition_silent(8, &marking);
436 bpmn.execute_transition(&mut marking, 8).unwrap();
437 assert_eq!(
438 marking,
439 BPMNMarking {
440 root_marking: BPMNRootMarking {
441 root_initial_choice_token: false,
442 message_flow_2_tokens: vec![]
443 },
444 element_index_2_sub_markings: vec![BPMNSubMarking {
445 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
446 initial_choice_token: false,
447 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0, 0],
448 element_index_2_sub_markings: vec![vec![]; 9],
449 }],
450 }
451 );
452 assert_eq!(
453 bpmn.get_enabled_transitions(&marking).unwrap(),
454 Vec::<usize>::new()
455 );
456 assert!(bpmn.is_final_marking(&marking).unwrap());
457 }
458
459 #[test]
460 fn bpmn_lanes_semantics() {
461 let fin = fs::read_to_string("testfiles/model-lanes.bpmn").unwrap();
462 let bpmn = fin.parse::<BusinessProcessModelAndNotation>().unwrap();
463
464 let mut marking = bpmn.get_initial_marking().unwrap();
465 debug_transitions(&bpmn, &marking);
466
467 assert_eq!(
468 marking,
469 BPMNMarking {
470 root_marking: BPMNRootMarking {
471 root_initial_choice_token: true,
472 message_flow_2_tokens: vec![0]
473 },
474 element_index_2_sub_markings: vec![
475 BPMNSubMarking::new_empty(),
476 BPMNSubMarking {
477 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
478 initial_choice_token: false,
479 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
480 element_index_2_sub_markings: vec![vec![]; 8],
481 }
482 ],
483 }
484 );
485 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1, 6]);
486
487 bpmn.is_transition_silent(1, &marking);
489 bpmn.execute_transition(&mut marking, 1).unwrap();
490 assert_eq!(
491 marking,
492 BPMNMarking {
493 root_marking: BPMNRootMarking {
494 root_initial_choice_token: false,
495 message_flow_2_tokens: vec![0]
496 },
497 element_index_2_sub_markings: vec![
498 BPMNSubMarking::new_empty(),
499 BPMNSubMarking {
500 sequence_flow_2_tokens: vec![1, 0, 0, 0, 0, 0, 0],
501 initial_choice_token: false,
502 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
503 element_index_2_sub_markings: vec![vec![]; 8],
504 }
505 ],
506 }
507 );
508 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0]);
509
510 bpmn.is_transition_silent(0, &marking);
512 bpmn.execute_transition(&mut marking, 0).unwrap();
513 assert_eq!(
514 marking,
515 BPMNMarking {
516 root_marking: BPMNRootMarking {
517 root_initial_choice_token: false,
518 message_flow_2_tokens: vec![0]
519 },
520 element_index_2_sub_markings: vec![
521 BPMNSubMarking::new_empty(),
522 BPMNSubMarking {
523 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
524 initial_choice_token: false,
525 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
526 element_index_2_sub_markings: vec![
527 vec![BPMNSubMarking {
528 sequence_flow_2_tokens: vec![0, 0],
529 initial_choice_token: true,
530 element_index_2_tokens: vec![0, 0, 0],
531 element_index_2_sub_markings: vec![vec![]; 3]
532 }],
533 vec![],
534 vec![],
535 vec![],
536 vec![],
537 vec![],
538 vec![],
539 vec![],
540 ],
541 }
542 ],
543 }
544 );
545 debug_transitions(&bpmn, &marking);
546 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2]);
547
548 bpmn.is_transition_silent(2, &marking);
550 bpmn.execute_transition(&mut marking, 2).unwrap();
551 assert_eq!(
552 marking,
553 BPMNMarking {
554 root_marking: BPMNRootMarking {
555 root_initial_choice_token: false,
556 message_flow_2_tokens: vec![0]
557 },
558 element_index_2_sub_markings: vec![
559 BPMNSubMarking::new_empty(),
560 BPMNSubMarking {
561 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
562 initial_choice_token: false,
563 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
564 element_index_2_sub_markings: vec![
565 vec![BPMNSubMarking {
566 sequence_flow_2_tokens: vec![1, 0],
567 initial_choice_token: false,
568 element_index_2_tokens: vec![0, 0, 0],
569 element_index_2_sub_markings: vec![vec![]; 3]
570 }],
571 vec![],
572 vec![],
573 vec![],
574 vec![],
575 vec![],
576 vec![],
577 vec![],
578 ],
579 }
580 ],
581 }
582 );
583 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [3]);
584
585 assert_eq!(
587 bpmn.activity_key
588 .deprocess_activity(&bpmn.get_transition_activity(3, &marking).unwrap()),
589 ""
590 );
591 assert!(!bpmn.is_transition_silent(3, &marking));
592 bpmn.execute_transition(&mut marking, 3).unwrap();
593 assert_eq!(
594 marking,
595 BPMNMarking {
596 root_marking: BPMNRootMarking {
597 root_initial_choice_token: false,
598 message_flow_2_tokens: vec![0]
599 },
600 element_index_2_sub_markings: vec![
601 BPMNSubMarking::new_empty(),
602 BPMNSubMarking {
603 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
604 initial_choice_token: false,
605 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
606 element_index_2_sub_markings: vec![
607 vec![BPMNSubMarking {
608 sequence_flow_2_tokens: vec![0, 1],
609 initial_choice_token: false,
610 element_index_2_tokens: vec![0, 0, 0],
611 element_index_2_sub_markings: vec![vec![]; 3]
612 }],
613 vec![],
614 vec![],
615 vec![],
616 vec![],
617 vec![],
618 vec![],
619 vec![],
620 ],
621 }
622 ],
623 }
624 );
625 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4]);
626
627 assert!(bpmn.is_transition_silent(4, &marking));
629 bpmn.execute_transition(&mut marking, 4).unwrap();
630 assert_eq!(
631 marking,
632 BPMNMarking {
633 root_marking: BPMNRootMarking {
634 root_initial_choice_token: false,
635 message_flow_2_tokens: vec![0]
636 },
637 element_index_2_sub_markings: vec![
638 BPMNSubMarking::new_empty(),
639 BPMNSubMarking {
640 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
641 initial_choice_token: false,
642 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
643 element_index_2_sub_markings: vec![
644 vec![BPMNSubMarking {
645 sequence_flow_2_tokens: vec![0, 0],
646 initial_choice_token: false,
647 element_index_2_tokens: vec![0, 0, 0],
648 element_index_2_sub_markings: vec![vec![]; 3]
649 }],
650 vec![],
651 vec![],
652 vec![],
653 vec![],
654 vec![],
655 vec![],
656 vec![],
657 ],
658 }
659 ],
660 }
661 );
662 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
663
664 assert!(bpmn.is_transition_silent(1, &marking));
666 bpmn.execute_transition(&mut marking, 1).unwrap();
667 assert_eq!(
668 marking,
669 BPMNMarking {
670 root_marking: BPMNRootMarking {
671 root_initial_choice_token: false,
672 message_flow_2_tokens: vec![0]
673 },
674 element_index_2_sub_markings: vec![
675 BPMNSubMarking::new_empty(),
676 BPMNSubMarking {
677 sequence_flow_2_tokens: vec![0, 0, 1, 1, 0, 0, 0],
678 initial_choice_token: false,
679 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
680 element_index_2_sub_markings: vec![
681 vec![],
682 vec![],
683 vec![],
684 vec![],
685 vec![],
686 vec![],
687 vec![],
688 vec![],
689 ],
690 }
691 ],
692 }
693 );
694 debug_transitions(&bpmn, &marking);
695 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 5]);
696
697 assert_eq!(
699 bpmn.activity_key
700 .deprocess_activity(&bpmn.get_transition_activity(5, &marking).unwrap()),
701 ""
702 );
703 bpmn.execute_transition(&mut marking, 5).unwrap();
704 assert_eq!(
705 marking,
706 BPMNMarking {
707 root_marking: BPMNRootMarking {
708 root_initial_choice_token: false,
709 message_flow_2_tokens: vec![0]
710 },
711 element_index_2_sub_markings: vec![
712 BPMNSubMarking::new_empty(),
713 BPMNSubMarking {
714 sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 1],
715 initial_choice_token: false,
716 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
717 element_index_2_sub_markings: vec![
718 vec![],
719 vec![],
720 vec![],
721 vec![],
722 vec![],
723 vec![],
724 vec![],
725 vec![],
726 ],
727 }
728 ],
729 }
730 );
731 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 8]);
732
733 assert!(bpmn.is_transition_silent(8, &marking));
735 bpmn.execute_transition(&mut marking, 8).unwrap();
736 assert_eq!(
737 marking,
738 BPMNMarking {
739 root_marking: BPMNRootMarking {
740 root_initial_choice_token: false,
741 message_flow_2_tokens: vec![0]
742 },
743 element_index_2_sub_markings: vec![
744 BPMNSubMarking::new_empty(),
745 BPMNSubMarking {
746 sequence_flow_2_tokens: vec![0, 0, 1, 0, 0, 0, 0],
747 initial_choice_token: false,
748 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
749 element_index_2_sub_markings: vec![
750 vec![],
751 vec![],
752 vec![],
753 vec![],
754 vec![],
755 vec![],
756 vec![],
757 vec![],
758 ],
759 }
760 ],
761 }
762 );
763 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2]);
764
765 assert_eq!(
767 bpmn.activity_key
768 .deprocess_activity(&bpmn.get_transition_activity(2, &marking).unwrap()),
769 "collapsed subprocess"
770 );
771 bpmn.execute_transition(&mut marking, 2).unwrap();
772 assert_eq!(
773 marking,
774 BPMNMarking {
775 root_marking: BPMNRootMarking {
776 root_initial_choice_token: false,
777 message_flow_2_tokens: vec![0]
778 },
779 element_index_2_sub_markings: vec![
780 BPMNSubMarking::new_empty(),
781 BPMNSubMarking {
782 sequence_flow_2_tokens: vec![0, 1, 0, 0, 0, 0, 0],
783 initial_choice_token: false,
784 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
785 element_index_2_sub_markings: vec![
786 vec![],
787 vec![],
788 vec![],
789 vec![],
790 vec![],
791 vec![],
792 vec![],
793 vec![],
794 ],
795 }
796 ],
797 }
798 );
799 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4]);
800
801 assert!(bpmn.is_transition_silent(4, &marking));
803 bpmn.execute_transition(&mut marking, 4).unwrap();
804 assert_eq!(
805 marking,
806 BPMNMarking {
807 root_marking: BPMNRootMarking {
808 root_initial_choice_token: false,
809 message_flow_2_tokens: vec![0]
810 },
811 element_index_2_sub_markings: vec![
812 BPMNSubMarking::new_empty(),
813 BPMNSubMarking {
814 sequence_flow_2_tokens: vec![0, 0, 0, 0, 0, 0, 0],
815 initial_choice_token: false,
816 element_index_2_tokens: vec![0, 0, 0, 0, 0, 0, 0, 0],
817 element_index_2_sub_markings: vec![
818 vec![],
819 vec![],
820 vec![],
821 vec![],
822 vec![],
823 vec![],
824 vec![],
825 vec![],
826 ],
827 }
828 ],
829 }
830 );
831
832 assert!(bpmn.is_final_marking(&marking).unwrap());
833 }
834
835 #[test]
836 fn bpmn_or_import() {
837 let fin = fs::read_to_string("testfiles/and-a-b-xor-c-or.sbpmn").unwrap();
838 let bpmn = fin
839 .parse::<StochasticBusinessProcessModelAndNotation>()
840 .unwrap();
841
842 let mut marking = bpmn.get_initial_marking().unwrap();
843 debug_transitions(&bpmn.bpmn, &marking);
844 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0]);
845 assert_eq!(
846 bpmn.get_transition_weight(0, &marking).unwrap(),
847 Fraction::one()
848 );
849
850 bpmn.execute_transition(&mut marking, 0).unwrap();
851 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [1]);
852 assert_eq!(
853 bpmn.get_transition_weight(1, &marking).unwrap(),
854 Fraction::one()
855 );
856
857 bpmn.execute_transition(&mut marking, 1).unwrap();
858 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [2, 3]);
859 assert_eq!(
860 bpmn.get_transition_weight(3, &marking).unwrap(),
861 Fraction::one()
862 );
863 assert_eq!(
864 bpmn.get_transition_weight(2, &marking).unwrap(),
865 Fraction::one()
866 );
867
868 bpmn.execute_transition(&mut marking, 2).unwrap();
869 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [3]);
870 assert_eq!(
871 bpmn.get_transition_weight(3, &marking).unwrap(),
872 Fraction::one()
873 );
874
875 bpmn.execute_transition(&mut marking, 3).unwrap();
876 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [4, 5]);
877 assert_eq!(bpmn.get_transition_weight(4, &marking).unwrap(), f!(1, 3));
878 assert_eq!(bpmn.get_transition_weight(5, &marking).unwrap(), f!(2, 3));
879
880 bpmn.execute_transition(&mut marking, 4).unwrap();
881 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [6, 7]);
882 assert_eq!(
883 bpmn.get_transition_weight(6, &marking).unwrap(),
884 Fraction::one()
885 );
886 assert_eq!(
887 bpmn.get_transition_weight(7, &marking).unwrap(),
888 Fraction::one()
889 );
890
891 bpmn.execute_transition(&mut marking, 6).unwrap();
892 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [7, 9]);
893 assert_eq!(
894 bpmn.get_transition_weight(7, &marking).unwrap(),
895 Fraction::one()
896 );
897 assert_eq!(
898 bpmn.get_transition_weight(9, &marking).unwrap(),
899 Fraction::one()
900 );
901
902 bpmn.execute_transition(&mut marking, 7).unwrap();
903 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [8, 9]);
904 assert_eq!(
905 bpmn.get_transition_weight(8, &marking).unwrap(),
906 Fraction::one()
907 );
908 assert_eq!(
909 bpmn.get_transition_weight(9, &marking).unwrap(),
910 Fraction::one()
911 );
912
913 bpmn.execute_transition(&mut marking, 8).unwrap();
914 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [9]);
915 assert_eq!(
916 bpmn.get_transition_weight(9, &marking).unwrap(),
917 Fraction::one()
918 );
919
920 bpmn.execute_transition(&mut marking, 9).unwrap();
921 assert_eq!(bpmn.get_enabled_transitions(&marking).unwrap(), [0; 0]);
922 assert!(bpmn.is_final_marking(&marking).unwrap());
923 }
924}