1
use merc_collections::BlockIndex;
2
use merc_collections::IndexedPartition;
3
use merc_lts::StateIndex;
4

            
5
/// A trait for partition refinement algorithms that expose the block number for
6
/// every state. Can be used to compute the quotient labelled transition system.
7
///
8
/// The invariants are that the union of all blocks is the original set, and
9
/// that each block contains distinct elements
10
pub trait Partition {
11
    /// Returns the block number for the given state.
12
    fn block_number(&self, state_index: StateIndex) -> BlockIndex;
13

            
14
    /// Returns the number of blocks in the partition.
15
    fn num_of_blocks(&self) -> usize;
16

            
17
    /// Returns the number of elements in the partition.
18
    fn len(&self) -> usize;
19

            
20
    /// Returns whether the partition is empty.
21
    fn is_empty(&self) -> bool {
22
        self.len() == 0
23
    }
24
}
25

            
26
impl Partition for IndexedPartition {
27
532076
    fn block_number(&self, state_index: StateIndex) -> BlockIndex {
28
532076
        self.partition()[state_index.value()]
29
532076
    }
30

            
31
20667
    fn num_of_blocks(&self) -> usize {
32
20667
        self.num_of_blocks()
33
20667
    }
34

            
35
756
    fn len(&self) -> usize {
36
756
        self.len()
37
756
    }
38
}
39

            
40
/// Combines two partitions into a new partition.
41
pub fn combine_partition(left: IndexedPartition, right: &impl Partition) -> IndexedPartition {
42
    let mut combined_partition = IndexedPartition::new(left.len());
43

            
44
    for (element_index, block) in left.partition().iter().enumerate() {
45
        let new_block = right.block_number(StateIndex::new(block.value()));
46

            
47
        combined_partition.set_block(element_index, new_block);
48
    }
49

            
50
    combined_partition
51
}