taco_threshold_automaton/
lib.rs

1//! A library to interact with threshold automata
2//!
3//! This crate contains the definitions of the types used to represent and
4//! interact with threshold automata. In particular, it contains the
5//! traits:
6//! - [`ThresholdAutomaton`]: common interface for all flavors of threshold
7//!   automata
8//! - [`RuleDefinition`]: common interface for rules in a threshold automaton
9//! - [`ActionDefinition`]: trait to represent different flavors of actions
10
11//! - [`VariableConstraint`]: different forms of constraints over variables
12//!
13//! The most general type implementing the interface is the
14//! [`general_threshold_automaton::GeneralThresholdAutomaton`] type. However,
15//! the type is more general than the theoretical definition of threshold
16//! automata, as it for example allows variable comparisons or resets.
17//!
18//! To the best of our knowledge, verification algorithms for threshold automata
19//! only exist for threshold automata that use linear integer arithmetic in
20//! their guards / thresholds. Therefore, when implementing a  new model
21//! checker, you will usually want to work with the
22//! [`lia_threshold_automaton::LIAThresholdAutomaton`] flavor of threshold
23//! automata.
24
25use std::fmt::Debug;
26use std::{fmt, hash::Hash};
27
28use expressions::{BooleanExpression, IntegerExpression, Location, Parameter, Variable};
29
30use crate::expressions::IsDeclared;
31
32pub mod expressions;
33pub mod general_threshold_automaton;
34pub mod lia_threshold_automaton;
35
36pub mod path;
37
38#[cfg(feature = "dot")]
39pub mod dot;
40
41/// Constraint over the number of processes in a certain location
42pub type LocationConstraint = BooleanExpression<Location>;
43
44/// Constraint over the valuation of parameters
45pub type ParameterConstraint = BooleanExpression<Parameter>;
46
47/// Constraint over the valuation of the shared variables
48pub type BooleanVarConstraint = BooleanExpression<Variable>;
49
50/// Common trait for different types of threshold automata
51///
52/// This trait is implemented by all types and flavors of threshold
53/// automata and provides a common interface for interacting with threshold
54/// automata.
55///
56/// This trait is for example implemented by
57/// [`general_threshold_automaton::GeneralThresholdAutomaton`]
58/// or [`lia_threshold_automaton::LIAThresholdAutomaton`].
59pub trait ThresholdAutomaton:
60    Debug + Clone + fmt::Display + IsDeclared<Parameter> + IsDeclared<Variable> + IsDeclared<Location>
61{
62    /// Type of the rules of the threshold automaton
63    type Rule: RuleDefinition;
64    /// Type of the initial variable conditions of the threshold automaton
65    type InitialVariableConstraintType: VariableConstraint;
66
67    /// Get the name of the threshold automaton
68    fn name(&self) -> &str;
69
70    /// Get the parameters of the threshold automaton
71    fn parameters(&self) -> impl Iterator<Item = &Parameter>;
72
73    /// Get the initial location constraints of the threshold automaton
74    fn initial_location_constraints(&self) -> impl Iterator<Item = &LocationConstraint>;
75
76    /// Get the initial variable constraints of the threshold automaton
77    fn initial_variable_constraints(
78        &self,
79    ) -> impl Iterator<Item = &Self::InitialVariableConstraintType>;
80
81    /// Get the resilience condition of the threshold automaton
82    fn resilience_conditions(&self) -> impl Iterator<Item = &BooleanExpression<Parameter>>;
83
84    /// Get the shared variables of the threshold automaton
85    fn variables(&self) -> impl Iterator<Item = &Variable>;
86
87    /// Get the locations of the threshold automaton
88    fn locations(&self) -> impl Iterator<Item = &Location>;
89
90    /// Check if a location can be initial by the location constraints of the
91    /// threshold automaton
92    ///
93    /// Returns true if the location can be an initial location of the threshold
94    fn can_be_initial_location(&self, location: &Location) -> bool;
95
96    /// Get the rules of the threshold automaton
97    fn rules(&self) -> impl Iterator<Item = &Self::Rule>;
98
99    /// Get incoming rules to a location
100    ///
101    /// Returns the rules that have the given location as target location.
102    /// This means that the location is the target of the transition.
103    fn incoming_rules(&self, location: &Location) -> impl Iterator<Item = &Self::Rule>;
104
105    /// Get outgoing rules for a location
106    ///
107    /// Returns the rules that have the given location as source location.
108    fn outgoing_rules(&self, location: &Location) -> impl Iterator<Item = &Self::Rule>;
109
110    /// Check whether the threshold automaton contains any decrements or resets
111    fn has_decrements_or_resets(&self) -> bool {
112        self.rules().any(|r| r.has_decrements() || r.has_resets())
113    }
114
115    /// Check whether the threshold automaton contains any decrements
116    fn has_decrements(&self) -> bool {
117        self.rules().any(|r| r.has_decrements())
118    }
119
120    /// Check whether the threshold automaton contains any resets
121    fn has_resets(&self) -> bool {
122        self.rules().any(|r| r.has_resets())
123    }
124}
125
126/// Trait implemented by all flavors of rules
127///
128/// Trait for common functionality of rules. This trait is implemented for
129/// the [`general_threshold_automaton::Rule`] type for
130/// [`general_threshold_automaton::GeneralThresholdAutomaton`] and
131/// [`lia_threshold_automaton::LIARule`] for
132/// [`lia_threshold_automaton::LIAThresholdAutomaton`].
133pub trait RuleDefinition: Clone + Debug + fmt::Display + PartialEq + Hash + Eq {
134    /// Type of the actions of the rule
135    type Action: ActionDefinition;
136    /// Type of the guard of the rule
137    type Guard: VariableConstraint;
138
139    /// Returns the id of the rule
140    ///
141    /// The id is a unique identifier assigned to the rule in the specification.
142    /// It is used to refer to the rule in the specification.
143    fn id(&self) -> u32;
144
145    /// Returns the source location of the rule
146    ///
147    /// The source location is the location from which the rule transitions
148    /// to the target location.
149    fn source(&self) -> &Location;
150
151    /// Returns the target location of the rule
152    ///
153    /// The target location is the location to which the rule transitions
154    /// from the source location.
155    fn target(&self) -> &Location;
156
157    /// Returns the guard of the rule
158    ///
159    /// The guard is a boolean expression over shared variables that must be
160    /// satisfied for the rule to be enabled.
161    fn guard(&self) -> &Self::Guard;
162
163    /// Returns the actions of the rule
164    ///
165    /// The actions are the updates to shared variables that are performed
166    /// when the rule is executed.
167    fn actions(&self) -> impl Iterator<Item = &Self::Action>;
168
169    /// Check whether the rule has a decrement action
170    fn has_decrements(&self) -> bool {
171        self.actions().any(|ac| ac.is_decrement())
172    }
173
174    /// Check whether the rule has a reset action
175    fn has_resets(&self) -> bool {
176        self.actions().any(|ac| ac.is_reset())
177    }
178}
179
180/// Trait implemented by all flavors of actions
181///
182/// This trait is for example implemented for the
183/// [`general_threshold_automaton::Action`] type.
184pub trait ActionDefinition: Clone + Debug + fmt::Display + PartialEq + Hash + Eq + Ord {
185    /// Returns the variable to be updated by the action
186    fn variable(&self) -> &Variable;
187
188    /// Check whether the action does not change any variables, i.e. is a noop
189    fn is_unchanged(&self) -> bool;
190
191    /// Check whether the action is a reset action
192    fn is_reset(&self) -> bool;
193
194    /// Check whether the action is an increment action
195    fn is_increment(&self) -> bool;
196
197    /// Check whether the action is a decrement action
198    fn is_decrement(&self) -> bool;
199}
200
201/// Trait implemented by all flavors of constraints over variables that can
202/// serve as Guards
203///
204/// This trait is for example implemented by [`BooleanExpression<Variable>`] or
205/// [`lia_threshold_automaton::LIAVariableConstraint`]
206pub trait VariableConstraint: Clone + Debug + fmt::Display + PartialEq + Ord {
207    /// Get the guard as a boolean expression over variables
208    fn as_boolean_expr(&self) -> BooleanExpression<Variable>;
209}
210
211/// Trait for threshold automata that can be modified
212///
213/// This trait is implemented by threshold automata that can be modified.
214/// for example, through preprocessing or other means. It provides methods to
215/// modify, remove or add components of the threshold automaton.
216///
217/// Note the resulting threshold automaton is not validated. It is up to the
218/// user to ensure that transformations result in a valid threshold automaton.
219/// Invalid threshold automata can lead to panics of other methods or functions.
220/// If a type does not implement this trait, you should modify a higher level
221/// representation.
222///
223/// Methods from this trait should not be used to construct a threshold
224/// automaton, but rather to modify an existing one. To build a threshold
225/// automaton, use the corresponding builder, e.g.,
226/// [`general_threshold_automaton::builder::GeneralThresholdAutomatonBuilder`].
227pub trait ModifiableThresholdAutomaton: ThresholdAutomaton {
228    /// Rename the threshold automaton
229    fn set_name(&mut self, new_name: String);
230
231    /// Add a new rule to the threshold automaton
232    ///
233    /// **Note**: The rule that is inserted is not validated. To build a threshold
234    /// automaton, you should use the corresponding builder, e.g.,
235    /// `GeneralThresholdAutomatonBuilder`.
236    fn add_rule(&mut self, rule: Self::Rule);
237
238    /// Add a new resilience condition to the threshold automaton
239    ///
240    /// **Note**: The resilience condition that is inserted is not validated. To
241    /// build a threshold automaton, you should use the corresponding builder,
242    ///  e.g., `GeneralThresholdAutomatonBuilder`.
243    fn add_resilience_conditions<C: IntoIterator<Item = BooleanExpression<Parameter>>>(
244        &mut self,
245        conditions: C,
246    );
247
248    /// Add a new initial location constraint to the threshold automaton
249    ///
250    /// **Note**: The initial location constraint that is inserted is not
251    /// validated. To build a threshold automaton, you should use the
252    /// corresponding builder, e.g., `GeneralThresholdAutomatonBuilder`.
253    fn add_initial_location_constraints<C: IntoIterator<Item = LocationConstraint>>(
254        &mut self,
255        constraints: C,
256    );
257
258    /// Add a new initial variable constraint to the threshold automaton
259    ///
260    /// **Note**: The initial variable constraint that is inserted is not
261    /// validated. To build a threshold automaton, you should use the
262    /// corresponding builder, e.g., `GeneralThresholdAutomatonBuilder`.
263    fn add_initial_variable_constraints<C: IntoIterator<Item = BooleanVarConstraint>>(
264        &mut self,
265        constraints: C,
266    );
267
268    /// Retains only the rules specified by the predicate.
269    ///
270    /// In other words, remove all rules r for which predicate(&r) returns false.
271    ///
272    /// **Note**: The method `predicate` can be called multiple times per rule.
273    fn retain_rules<F>(&mut self, predicate: F)
274    where
275        F: Fn(&Self::Rule) -> bool;
276
277    /// Apply a transformation to each rule
278    ///
279    /// This method is used to apply a transformation to each rule of the
280    /// threshold automaton. The transformation is applied in place, meaning
281    /// that the rule is modified directly.
282    ///
283    /// **Note**:
284    /// - The method `f` can be called multiple times per rule.
285    /// - The transformed rule is not validated
286    fn transform_rules<F>(&mut self, f: F)
287    where
288        F: FnMut(&mut Self::Rule);
289
290    /// Remove a location `location` from the threshold automaton, removes rules
291    /// referencing the location and replace every occurrence in initial
292    /// conditions with `subst`
293    ///
294    /// **Note**: The resulting location constraints are not validated
295    fn remove_location_and_replace_with(
296        &mut self,
297        location: &Location,
298        subst: IntegerExpression<Location>,
299    );
300
301    /// Remove a variable `variable` from the threshold automaton, replace every
302    /// occurrence in initial conditions or guards with `subst` and remove all
303    /// updates to `variable` from the rules
304    ///
305    /// **Note**: The resulting variable constraints and guards are not validated
306    fn remove_variable_and_replace_with(
307        &mut self,
308        variable: &Variable,
309        subst: IntegerExpression<Variable>,
310    );
311
312    /// Remove all location_constraints from the threshold automaton
313    /// Needed to specify initial configurations for coverability and
314    /// reachability through the CLI.
315    fn replace_initial_location_constraints<C: IntoIterator<Item = LocationConstraint>>(
316        &mut self,
317        constraints: C,
318    );
319
320    /// Remove all variable_constraints from the threshold automaton
321    /// Needed to specify initial configurations for coverability and
322    /// reachability through the CLI.
323    fn replace_initial_variable_constraints<C: IntoIterator<Item = BooleanVarConstraint>>(
324        &mut self,
325        constraints: C,
326    );
327}