1
#![forbid(unsafe_code)]
2

            
3
use std::fmt;
4

            
5
use itertools::Itertools;
6

            
7
use log::trace;
8
use merc_lts::StateIndex;
9

            
10
use crate::BlockIndex;
11
use crate::Partition;
12

            
13
/// A partition that explicitly stores a list of blocks and their indexing into
14
/// the list of elements. Similar to [super::BlockPartition] but without taking
15
/// the stability of individual elements into account.
16
#[derive(Debug)]
17
pub struct SimpleBlockPartition {
18
    elements: Vec<StateIndex>,
19
    blocks: Vec<SimpleBlock>,
20
}
21

            
22
impl SimpleBlockPartition {
23
    /// Create an initial partition where all the states are in a single block
24
    /// 0. And all the elements in the block are marked.
25
101
    pub fn new(num_of_elements: usize) -> Self {
26
101
        debug_assert!(num_of_elements > 0, "Cannot partition the empty set");
27

            
28
101
        let blocks = vec![SimpleBlock::new(0, num_of_elements)];
29
101
        let elements = (0..num_of_elements).map(StateIndex::new).collect();
30

            
31
101
        Self { elements, blocks }
32
101
    }
33

            
34
    /// Marks the given block as stable
35
288
    pub fn mark_block_stable(&mut self, block_index: BlockIndex) {
36
288
        self.blocks[block_index].stable = true;
37
288
    }
38

            
39
    /// Return a reference to the given block.
40
528
    pub fn block(&self, block_index: BlockIndex) -> &SimpleBlock {
41
528
        &self.blocks[block_index]
42
528
    }
43

            
44
    /// Splits a block into two blocks according to the given predicate. If the
45
    /// predicate holds for all or none of the elements, no split occurs.
46
8449
    pub fn split_block(
47
8449
        &mut self,
48
8449
        block_index: BlockIndex,
49
8449
        predicate: impl Fn(StateIndex) -> bool,
50
8449
    ) -> Option<BlockIndex> {
51
        // Size of the new block.
52
8449
        let mut size = 0usize;
53

            
54
9910
        for state in self.blocks[block_index].begin..self.blocks[block_index].end {
55
9910
            if predicate(self.elements[state]) {
56
1457
                self.elements.swap(self.blocks[block_index].begin + size, state);
57
1457
                size += 1;
58
8453
            }
59
        }
60

            
61
        // The original block are now the first [begin, begin + size) elements
62
8449
        if size == 0 || size == self.blocks[block_index].len() {
63
            // No split occurred
64
8327
            return None;
65
122
        }
66

            
67
        // Create a new block for the remaining elements
68
122
        let new_block = SimpleBlock::new(self.blocks[block_index].begin + size, self.blocks[block_index].end);
69
122
        let last_block = self.blocks.len();
70
122
        self.blocks.push(new_block);
71

            
72
        // Update the original block
73
122
        self.blocks[block_index].end = self.blocks[block_index].begin + size;
74
122
        self.blocks[block_index].stable = false;
75

            
76
122
        trace!(
77
            "Split block {:?} into blocks {:?} and {:?}",
78
            block_index,
79
            block_index,
80
            BlockIndex::new(last_block)
81
        );
82
122
        Some(BlockIndex::new(last_block))
83
8449
    }
84

            
85
    /// Returns the number of blocks in the partition.
86
3675
    pub fn num_of_blocks(&self) -> usize {
87
3675
        self.blocks.len()
88
3675
    }
89

            
90
    /// Returns an iterator over the elements of a given block.
91
990
    pub fn iter_block(&self, block_index: BlockIndex) -> SimpleBlockIter<'_> {
92
990
        SimpleBlockIter {
93
990
            elements: &self.elements,
94
990
            index: self.blocks[block_index].begin,
95
990
            end: self.blocks[block_index].end,
96
990
        }
97
990
    }
98

            
99
    /// Returns an iterator over all blocks in the partition.
100
    pub fn iter(&self) -> impl Iterator<Item = &SimpleBlock> {
101
        self.blocks.iter()
102
    }
103

            
104
    /// Returns an iterator over all blocks in the partition.
105
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut SimpleBlock> {
106
        self.blocks.iter_mut()
107
    }
108
}
109

            
110
impl fmt::Display for SimpleBlockPartition {
111
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112
        let format = self
113
            .blocks
114
            .iter()
115
            .map(|block| format!("{{{}}}", block.iter(&self.elements).format(", ")))
116
            .format(", ");
117

            
118
        write!(f, "{{{}}}", format)
119
    }
120
}
121

            
122
impl Partition for SimpleBlockPartition {
123
1646
    fn block_number(&self, state_index: StateIndex) -> BlockIndex {
124
        // Note that this is O(n) in the number of blocks. This could be improved
125
        // by storing a mapping from state index to block index. However, this
126
        // is only used in the comparison functions, so it is not a big issue.
127
3592
        for (block_index, block) in self.blocks.iter().enumerate() {
128
3996
            for element in block.iter(&self.elements) {
129
3996
                if element == state_index {
130
1646
                    return BlockIndex::new(block_index);
131
2350
                }
132
            }
133
        }
134

            
135
        panic!("State index {:?} not found in partition {:?}", state_index, self);
136
1646
    }
137

            
138
706
    fn num_of_blocks(&self) -> usize {
139
706
        self.blocks.len()
140
706
    }
141

            
142
    fn len(&self) -> usize {
143
        self.elements.len()
144
    }
145
}
146

            
147
/// A [super::Block] that stores a subset of the elements in a partition, but
148
/// with individual stable elements.
149
///
150
/// # Details
151
///
152
/// It uses `start` and `end` to indicate a range start..end of elements in the
153
/// partition. The stable flag indicates whether the block is stable.
154
#[derive(Clone, Copy, Debug)]
155
pub struct SimpleBlock {
156
    begin: usize,
157
    end: usize,
158
    stable: bool,
159
}
160

            
161
impl SimpleBlock {
162
    /// Creates a new block that is not marked.
163
223
    pub fn new(begin: usize, end: usize) -> SimpleBlock {
164
223
        debug_assert!(begin < end, "The range of this block is incorrect");
165

            
166
223
        SimpleBlock {
167
223
            begin,
168
223
            end,
169
223
            stable: false,
170
223
        }
171
223
    }
172

            
173
    /// Returns an iterator over the elements in this block.
174
3592
    pub fn iter<'a>(&self, elements: &'a Vec<StateIndex>) -> SimpleBlockIter<'a> {
175
3592
        SimpleBlockIter {
176
3592
            elements,
177
3592
            index: self.begin,
178
3592
            end: self.end,
179
3592
        }
180
3592
    }
181

            
182
    /// Returns the number of elements in the block.
183
1091
    pub fn len(&self) -> usize {
184
1091
        self.assert_consistent();
185

            
186
1091
        self.end - self.begin
187
1091
    }
188

            
189
    /// Returns true iff the block is empty.
190
    pub fn is_empty(&self) -> bool {
191
        self.assert_consistent();
192

            
193
        self.begin == self.end
194
    }
195

            
196
    /// Returns true iff the block is stable.
197
525
    pub fn is_stable(&self) -> bool {
198
525
        self.stable
199
525
    }
200

            
201
    /// Marks the block as stable.
202
    pub fn mark_stable(&mut self) {
203
        self.stable = true
204
    }
205

            
206
    /// Returns true iff the block is consistent.
207
1091
    fn assert_consistent(self) {
208
1091
        debug_assert!(self.begin < self.end, "The range of block {self:?} is incorrect");
209
1091
    }
210
}
211

            
212
pub struct SimpleBlockIter<'a> {
213
    elements: &'a Vec<StateIndex>,
214
    index: usize,
215
    end: usize,
216
}
217

            
218
impl Iterator for SimpleBlockIter<'_> {
219
    type Item = StateIndex;
220

            
221
7864
    fn next(&mut self) -> Option<Self::Item> {
222
7864
        if self.index < self.end {
223
5376
            let element = self.elements[self.index];
224
5376
            self.index += 1;
225
5376
            Some(element)
226
        } else {
227
2488
            None
228
        }
229
7864
    }
230
}
231

            
232
#[cfg(test)]
233
mod tests {
234
    use super::*;
235

            
236
    #[test]
237
1
    fn test_simple_block_partition() {
238
1
        let mut partition = SimpleBlockPartition::new(10);
239

            
240
1
        assert_eq!(partition.num_of_blocks(), 1);
241

            
242
1
        let initial_block = BlockIndex::new(0);
243
1
        assert_eq!(partition.block(initial_block).len(), 10);
244

            
245
1
        let block_index = partition
246
10
            .split_block(BlockIndex::new(0), |state| *state < *StateIndex::new(5))
247
1
            .unwrap();
248

            
249
1
        assert_eq!(partition.num_of_blocks(), 2);
250
1
        assert_eq!(partition.block(initial_block).len(), 5);
251
1
        assert_eq!(partition.block(block_index).len(), 5);
252
1
    }
253
}