petri_net_simulation/
edit.rs

1use std::ops::Deref;
2
3use pns::{Pid, Tid};
4
5use super::{maximum_fire_count, maximum_unfire_count, PetriNetInfo};
6
7/// A wrapper type for net which only supports safe edits.
8pub struct EditNet<'a> {
9    net: &'a mut PetriNetInfo,
10}
11
12impl Deref for EditNet<'_> {
13    type Target = PetriNetInfo;
14    fn deref(&self) -> &PetriNetInfo {
15        self.net
16    }
17}
18
19impl<'a> EditNet<'a> {
20    pub(crate) fn new(net: &'a mut PetriNetInfo) -> Self {
21        Self { net }
22    }
23}
24
25impl EditNet<'_> {
26    /// Add a new place to the petri net and get the index and refresh states.
27    #[inline]
28    pub fn add_place(&mut self) -> Pid {
29        self.net.add_place()
30    }
31
32    /// Add a new transition to the petri net and get the index and refresh states.
33    #[inline]
34    pub fn add_transition(&mut self) -> Tid {
35        self.net.add_transition()
36    }
37
38    /// Add a new transition to the petri net, connct it to the specified places and get the index and refresh states.
39    #[inline]
40    pub fn add_connected_transition(&mut self, in_pids: &[Pid], out_pids: &[Pid]) -> Tid {
41        self.net.add_connected_transition(in_pids, out_pids)
42    }
43
44    /// Remove a place at index `pid` from petri net and refresh states.
45    #[inline]
46    pub fn remove_place(&mut self, pid: Pid) {
47        self.net.remove_place(pid)
48    }
49
50    /// Make a connection in to the transition with index `tid` from place with index `pid` and refresh states.
51    /// Result represents success.
52    #[inline]
53    pub fn connect_place_to_transition(&mut self, pid: Pid, tid: Tid) -> bool {
54        let minimal_count = maximum_fire_count(self.net, tid);
55
56        let count = self.net.initial_token_count(pid);
57        let Some(minimal_count) = minimal_count else {
58            return false;
59        };
60        if count < minimal_count {
61            return false;
62        }
63
64        self.net.connect_place_to_transition(pid, tid)
65    }
66
67    /// Make a connection out from the transition with index `tid` to place with index `pid` and refresh states.
68    /// Result represents success.
69    #[inline]
70    pub fn connect_transition_to_place(&mut self, tid: Tid, pid: Pid) -> bool {
71        let minimal_count = maximum_unfire_count(self.net, tid);
72
73        let count = self.net.initial_token_count(pid);
74        let Some(minimal_count) = minimal_count else {
75            return false;
76        };
77        if count < minimal_count {
78            return false;
79        }
80
81        self.net.connect_transition_to_place(tid, pid)
82    }
83
84    /// Duplicate the transition and get the index of the clone and refresh states.
85    #[inline]
86    pub fn duplicate_transition(&mut self, tid: Tid) -> Tid {
87        self.net.duplicate_transition(tid)
88    }
89
90    /// Duplicate the place and get the index of the clone and refresh states.
91    #[inline]
92    pub fn duplicate_place(&mut self, pid: Pid) -> Pid {
93        self.net.duplicate_place(pid)
94    }
95
96    /// Increase the initial token count in place indexed by `pid` and refresh states.
97    #[inline]
98    pub fn add_initial_tokens(&mut self, pid: Pid, count: usize) -> usize {
99        self.net.add_initial_tokens(pid, count)
100    }
101}