1
//! Authors: Maurice Laveaux and Sjef van Loo
2

            
3
use std::marker::PhantomData;
4

            
5
use merc_collections::ByteCompressedVec;
6
use merc_collections::bytevec;
7

            
8
use crate::PG;
9
use crate::VertexIndex;
10

            
11
/// Stores the predecessors for a given parity game.
12
pub struct Predecessors<'a> {
13
    /// A flat list of all predecessors in the game.
14
    edges_from: ByteCompressedVec<VertexIndex>,
15

            
16
    /// A mapping from the vertex to the `edges_from` that stores its
17
    /// predecessors.
18
    vertex_to_predecessors: ByteCompressedVec<usize>,
19

            
20
    /// Marker to tie the lifetime of the predecessors to the game.
21
    _marker: PhantomData<&'a ()>,
22
}
23

            
24
impl<'a> Predecessors<'a> {
25
    /// Creates the predecessors structure for the given parity game.
26
1101
    pub fn new(game: &'a impl PG) -> Self {
27
1101
        let mut edges_from = bytevec![VertexIndex::new(0); game.num_of_edges()];
28
1101
        let mut state2incoming = bytevec![0; game.num_of_vertices()];
29

            
30
        // Count the number of incoming transitions for each state
31
3379
        for state_index in game.iter_vertices() {
32
4532
            for to in game.outgoing_edges(state_index) {
33
4532
                state2incoming.update(to.value(), |start| *start += 1);
34
            }
35
        }
36

            
37
        // Compute the start offsets (prefix sum)
38
3379
        state2incoming.fold(0, |offset, start| {
39
3379
            let new_offset = offset + *start;
40
3379
            *start = offset;
41
3379
            new_offset
42
3379
        });
43

            
44
        // Place the transitions
45
3379
        for state_index in game.iter_vertices() {
46
4532
            for to in game.outgoing_edges(state_index) {
47
4532
                state2incoming.update(to.value(), |start| {
48
4532
                    edges_from.set(*start, state_index);
49
4532
                    *start += 1;
50
4532
                });
51
            }
52
        }
53

            
54
3379
        state2incoming.fold(0, |previous, start| {
55
3379
            let result = *start;
56
3379
            *start = previous;
57
3379
            result
58
3379
        });
59

            
60
        // Add sentinel state
61
1101
        state2incoming.push(edges_from.len());
62

            
63
1101
        Self {
64
1101
            edges_from,
65
1101
            vertex_to_predecessors: state2incoming,
66
1101
            _marker: PhantomData,
67
1101
        }
68
1101
    }
69

            
70
    /// Returns an iterator over the predecessors the given vertex.
71
6253
    pub fn predecessors(&self, state_index: VertexIndex) -> impl Iterator<Item = VertexIndex> + '_ {
72
6253
        let start = self.vertex_to_predecessors.index(state_index.value());
73
6253
        let end = self.vertex_to_predecessors.index(state_index.value() + 1);
74
8733
        (start..end).map(move |i| self.edges_from.index(i))
75
6253
    }
76
}