1
use std::collections::VecDeque;
2
use std::fmt;
3

            
4
use merc_lts::LabelIndex;
5
use merc_utilities::TagIndex;
6

            
7
/// A unique type for vertices in the counterexample tree.
8
pub struct CounterTag {}
9

            
10
/// The index type for vertices in the counterexample tree.
11
pub type CounterIndex = TagIndex<usize, CounterTag>;
12

            
13
/// A generic trait for counterexample tree structures.
14
///
15
/// # Details
16
///
17
/// This is useful such that we can both provide a concrete implementation that
18
/// constructs a counterexample tree, but also a placeholder implementation that
19
/// does nothing when no counterexample is needed.
20
pub trait CounterExampleTree {
21
    type Index: Clone + Copy;
22

            
23
    /// Returns the index of the root of the counterexample tree.
24
    fn root_index(&self) -> Self::Index;
25

            
26
    /// Adds an edge to the counterexample tree.
27
    fn add_edge(&mut self, label: LabelIndex, to: Self::Index) -> Self::Index;
28
}
29

            
30
/// A class that can be used to store a counter example tree from which a
31
/// counter example trace can be extracted.
32
pub struct CounterExampleConstructor {
33
    /// The backward tree is stored in a deque.
34
    backward_tree: VecDeque<(LabelIndex, CounterIndex)>,
35
}
36

            
37
impl CounterExampleConstructor {
38
    /// Creates a new counterexample constructor.    
39
200
    pub fn new() -> Self {
40
200
        Self {
41
200
            // Add the root such that index 0 is the root.
42
200
            backward_tree: VecDeque::from([(LabelIndex::default(), TagIndex::default())]),
43
200
        }
44
200
    }
45

            
46
    /// Reconstructs the trace from the counterexample tree given the index
47
    /// of the leaf node.
48
178
    pub fn reconstruct_trace(&self, mut index: CounterIndex) -> Vec<LabelIndex> {
49
178
        let mut trace = Vec::new();
50

            
51
372
        while index != self.root_index() {
52
194
            let (label, parent) = &self.backward_tree[*index];
53
194
            trace.push(*label);
54
194
            index = *parent;
55
194
        }
56

            
57
178
        trace.reverse();
58
178
        trace
59
178
    }
60
}
61

            
62
impl fmt::Debug for CounterExampleConstructor {
63
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64
        f.debug_struct("CounterExampleConstructor")
65
            .field("backward_tree", &self.backward_tree)
66
            .finish()
67
    }
68
}
69

            
70
impl CounterExampleTree for CounterExampleConstructor {
71
    type Index = CounterIndex;
72

            
73
294
    fn add_edge(&mut self, label: LabelIndex, to: Self::Index) -> Self::Index {
74
294
        self.backward_tree.push_back((label, to));
75
294
        TagIndex::new(self.backward_tree.len() - 1)
76
294
    }
77

            
78
572
    fn root_index(&self) -> Self::Index {
79
572
        TagIndex::new(0)
80
572
    }
81
}
82

            
83
impl Default for CounterExampleConstructor {
84
    fn default() -> Self {
85
        Self::new()
86
    }
87
}
88

            
89
impl CounterExampleTree for () {
90
    type Index = ();
91

            
92
    fn add_edge(&mut self, _label: LabelIndex, _to: Self::Index) -> Self::Index {
93
        // Do nothing
94
    }
95

            
96
    fn root_index(&self) -> Self::Index {}
97
}