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
/// A trait for providing the predecessors of a parity game.
12
pub trait Pred {
13
    /// Returns an iterator over the predecessors the given vertex.
14
    fn predecessors(&self, vertex_index: VertexIndex) -> impl Iterator<Item = VertexIndex> + '_;
15
}
16

            
17
impl<T: Pred + ?Sized> Pred for &T {
18
4190
    fn predecessors(&self, vertex_index: VertexIndex) -> impl Iterator<Item = VertexIndex> + '_ {
19
4190
        (*self).predecessors(vertex_index)
20
4190
    }
21
}
22

            
23
/// Stores the predecessors for a given parity game, implements [Pred].
24
pub struct Predecessors<'a> {
25
    /// A flat list of all predecessors in the game.
26
    edges_from: ByteCompressedVec<VertexIndex>,
27

            
28
    /// A mapping from the vertex to the `edges_from` that stores its
29
    /// predecessors.
30
    vertex_to_predecessors: ByteCompressedVec<usize>,
31

            
32
    /// Marker to tie the lifetime of the predecessors to the game.
33
    _marker: PhantomData<&'a ()>,
34
}
35

            
36
impl<'a> Predecessors<'a> {
37
    /// Creates the predecessors structure for the given parity game.
38
2946
    pub fn new<G: PG>(game: &'a G) -> Self {
39
2946
        let mut edges_from = bytevec![VertexIndex::new(0); game.num_of_edges()];
40
2946
        let mut vertex_to_predecessors = bytevec![0; game.num_of_vertices()];
41

            
42
        // Count the number of incoming transitions for each vertex
43
139118
        for vertex_index in game.iter_vertices() {
44
176221
            for edge in game.outgoing_edges(vertex_index) {
45
176221
                vertex_to_predecessors.update(edge.to().value(), |start| *start += 1);
46
            }
47
        }
48

            
49
        // Compute the start offsets (prefix sum)
50
143205
        vertex_to_predecessors.fold(0, |offset, start| {
51
143205
            let new_offset = offset + *start;
52
143205
            *start = offset;
53
143205
            new_offset
54
143205
        });
55

            
56
        // Place the transitions
57
139118
        for vertex_index in game.iter_vertices() {
58
176221
            for edge in game.outgoing_edges(vertex_index) {
59
176221
                vertex_to_predecessors.update(edge.to().value(), |start| {
60
176221
                    edges_from.set(*start, vertex_index);
61
176221
                    *start += 1;
62
176221
                });
63
            }
64
        }
65

            
66
2946
        let mut offset = 0usize;
67
143205
        vertex_to_predecessors.fold(0, |previous, start| {
68
143205
            let result = *start;
69
143205
            *start = previous;
70
143205
            offset = result;
71
143205
            result
72
143205
        });
73

            
74
2946
        vertex_to_predecessors.push(offset);
75

            
76
2946
        Self {
77
2946
            edges_from,
78
2946
            vertex_to_predecessors,
79
2946
            _marker: PhantomData,
80
2946
        }
81
2946
    }
82
}
83

            
84
impl Pred for Predecessors<'_> {
85
224304
    fn predecessors(&self, vertex_index: VertexIndex) -> impl Iterator<Item = VertexIndex> + '_ {
86
224304
        let start = self.vertex_to_predecessors.index(vertex_index.value());
87
224304
        let end = self.vertex_to_predecessors.index(vertex_index.value() + 1);
88
311369
        (start..end).map(move |i| self.edges_from.index(i))
89
224304
    }
90
}
91

            
92
#[cfg(test)]
93
mod tests {
94
    use bitvec::bitvec;
95
    use bitvec::order::Lsb0;
96
    use itertools::Itertools;
97
    use merc_utilities::random_test;
98

            
99
    use crate::PG;
100
    use crate::Pred;
101
    use crate::Predecessors;
102
    use crate::PrioSubgame;
103
    use crate::Priority;
104
    use crate::Subgame;
105
    use crate::random_parity_game;
106

            
107
    #[test]
108
    #[cfg_attr(miri, ignore)] // Test is too slow under miri
109
1
    fn test_random_predecessors() {
110
100
        random_test(100, |rng| {
111
100
            let game = random_parity_game(rng, true, 50, 10, 5);
112
100
            check_predecessors(game);
113
100
        })
114
1
    }
115

            
116
    #[test]
117
    #[cfg_attr(miri, ignore)] // Test is too slow under miri
118
1
    fn test_random_predecessors_subgame() {
119
100
        random_test(100, |rng| {
120
100
            let pg = random_parity_game(rng, true, 50, 10, 5);
121
100
            let game = PrioSubgame::new(&pg, Priority::new(0));
122

            
123
100
            check_predecessors(game);
124
100
        })
125
1
    }
126

            
127
    #[test]
128
    #[cfg_attr(miri, ignore)] // Test is too slow under miri
129
1
    fn test_random_pred_trait_subgame() {
130
100
        random_test(100, |rng| {
131
100
            let pg = random_parity_game(rng, true, 50, 10, 5);
132

            
133
100
            let mut restricted = bitvec![usize, Lsb0; 0; pg.num_of_vertices()];
134
5000
            for vertex in pg.iter_vertices() {
135
5000
                if pg.priority(vertex) <= Priority::new(2) {
136
2144
                    restricted.set(vertex.value(), true);
137
2856
                }
138
            }
139

            
140
100
            let predecessors = Predecessors::new(&pg);
141
100
            let subgame = Subgame::new(&pg, restricted, predecessors);
142

            
143
100
            check_pred_trait(&subgame);
144
100
        })
145
1
    }
146

            
147
    /// Checks that the predecessors computed by the `Predecessors` structure
148
    /// match the expected predecessors computed by iterating over all vertices
149
    /// and their outgoing edges.
150
200
    fn check_predecessors<G: PG>(game: G) {
151
200
        let predecessors = Predecessors::new(&game);
152
5913
        for vertex in game.iter_vertices() {
153
            // Compute the expected predecessors by iterating over all vertices and their outgoing edges.
154
5913
            let expected_predecessors: Vec<_> = game
155
5913
                .iter_vertices()
156
542776
                .filter(|&v| game.outgoing_edges(v).any(|e| e.to() == vertex))
157
5913
                .collect();
158
5913
            let actual_predecessors: Vec<_> = predecessors.predecessors(vertex).collect();
159

            
160
5913
            assert_eq!(
161
5913
                expected_predecessors.into_iter().sorted().collect::<Vec<_>>(),
162
5913
                actual_predecessors.into_iter().sorted().collect::<Vec<_>>(),
163
                "Predecessors of vertex {} do not match",
164
                vertex.value()
165
            );
166
        }
167
200
    }
168

            
169
    /// Checks that the `Pred` trait implementation for a game matches
170
    /// predecessors computed from outgoing edges.
171
100
    fn check_pred_trait<G: PG + Pred>(game: &G) {
172
2144
        for vertex in game.iter_vertices() {
173
2144
            let expected_predecessors: Vec<_> = game
174
2144
                .iter_vertices()
175
50047
                .filter(|&v| game.outgoing_edges(v).any(|e| e.to() == vertex))
176
2144
                .collect();
177
2144
            let actual_predecessors: Vec<_> = game.predecessors(vertex).collect();
178

            
179
2144
            assert_eq!(
180
2144
                expected_predecessors.into_iter().sorted().collect::<Vec<_>>(),
181
2144
                actual_predecessors.into_iter().sorted().collect::<Vec<_>>(),
182
                "Predecessors of vertex {} do not match",
183
                vertex.value()
184
            );
185
        }
186
100
    }
187
}