1
//! The labelled transition system (LTS) trait and associated types.
2

            
3
use std::fmt;
4
use std::hash::Hash;
5

            
6
use merc_utilities::TagIndex;
7

            
8
use crate::LabelledTransitionSystem;
9

            
10
/// A unique type for the labels.
11
pub struct LabelTag;
12

            
13
/// A unique type for the states.
14
pub struct StateTag;
15

            
16
/// The index type for a label.
17
pub type LabelIndex = TagIndex<usize, LabelTag>;
18

            
19
/// The index for a state.
20
pub type StateIndex = TagIndex<usize, StateTag>;
21

            
22
/// The trait for labelled transition systems.
23
///
24
/// Uses (strong) indices to refer to states and labels. The state indices are
25
/// represented as `StateIndex`, and the label indices as `LabelIndex`. The
26
/// labels themselves are given by type `Label`.
27
pub trait LTS
28
where
29
    Self: Sized,
30
{
31
    /// The associated type for transition labels.
32
    type Label: TransitionLabel;
33

            
34
    /// Returns the index of the initial state
35
    fn initial_state_index(&self) -> StateIndex;
36

            
37
    /// Returns the set of outgoing transitions for the given state.
38
    fn outgoing_transitions(&self, state_index: StateIndex) -> impl Iterator<Item = Transition> + '_;
39

            
40
    /// Iterate over all state_index in the labelled transition system
41
    fn iter_states(&self) -> impl Iterator<Item = StateIndex> + '_ ;
42

            
43
    /// Returns the number of states.
44
    fn num_of_states(&self) -> usize;
45

            
46
    /// Returns the number of labels.
47
    fn num_of_labels(&self) -> usize;
48

            
49
    /// Returns the number of transitions.
50
    fn num_of_transitions(&self) -> usize;
51

            
52
    /// Returns the list of labels.
53
    fn labels(&self) -> &[Self::Label];
54

            
55
    /// Returns true iff the given label index is a hidden label.
56
    fn is_hidden_label(&self, label_index: LabelIndex) -> bool;
57

            
58
    /// Consumes the current LTS and merges it with another one, returning the
59
    /// disjoint merged LTS and the initial state of the other LTS in the merged
60
    /// LTS.
61
    ///
62
    /// TODO: Can this be generalised to returning `Self`?
63
    fn merge_disjoint<L: LTS<Label = Self::Label>>(
64
        self,
65
        other: &L,
66
    ) -> (LabelledTransitionSystem<Self::Label>, StateIndex);
67
}
68

            
69
/// A common trait for all transition labels. For various algorithms on LTSs we
70
/// require that  they are orderable, comparable, and hashable. So we require that here
71
/// instead of specifying these bounds on usage.
72
pub trait TransitionLabel: Ord + Hash + Eq + Clone + fmt::Display + fmt::Debug {
73
    /// Returns the tau label for this transition label type.
74
    fn tau_label() -> Self;
75

            
76
    /// Returns true iff this label is the tau label.
77
    fn is_tau_label(&self) -> bool {
78
        self == &Self::tau_label()
79
    }
80

            
81
    /// Returns true iff this label matches the given string label.
82
    fn matches_label(&self, label: &str) -> bool;
83

            
84
    /// Used for generating labels for the random LTSs
85
    fn from_index(i: usize) -> Self;
86
}
87

            
88
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
89
pub struct Transition {
90
    pub label: LabelIndex,
91
    pub to: StateIndex,
92
}
93

            
94
impl Transition {
95
    /// Constructs a new transition.
96
335441
    pub fn new(label: LabelIndex, to: StateIndex) -> Self {
97
335441
        Self { label, to }
98
335441
    }
99
}