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

            
4
use crate::Player;
5
use crate::VertexIndex;
6
use crate::PG;
7

            
8
/// Keeps track of a strategy for a player in a parity game.
9
///
10
/// # Details
11
///
12
/// A strategy is a partial function from vertices owned by a player to one of
13
/// their successors.
14
pub struct Strategy {
15
    mapping: HashMap<VertexIndex, VertexIndex>,
16
}
17

            
18
impl Strategy {
19
    /// Creates a new, empty strategy.
20
7506
    pub fn new() -> Self {
21
7506
        Self {
22
7506
            mapping: HashMap::new(),
23
7506
        }
24
7506
    }
25

            
26
    /// Adds a mapping from `from` to `to` in the strategy.
27
1394
    pub fn set(&mut self, from: VertexIndex, to: VertexIndex) {
28
1394
        self.mapping.insert(from, to);
29
1394
    }
30

            
31
    /// Gets the target vertex for the given source vertex, if it is defined.
32
    pub fn get(&self, from: VertexIndex) -> Option<&VertexIndex> {
33
        self.mapping.get(&from)
34
    }
35

            
36
    /// Combines two strategies, preferring mappings from the second strategy.
37
2110
    pub fn combine(mut self, extension: Strategy) -> Strategy {
38
        // Add all mappings from the extension strategy to the base strategy
39
2110
        for (&from, &to) in extension.iter() {
40
556
            self.set(from, to);
41
556
        }
42
2110
        self
43
2110
    }
44

            
45
    /// Returns an iterator over all (from, to) pairs in the strategy.
46
2110
    pub fn iter(&self) -> impl Iterator<Item = (&VertexIndex, &VertexIndex)> {
47
2110
        self.mapping.iter()
48
2110
    }
49

            
50
    /// Checks that the strategy is only defined for the vertices owned by the
51
    /// given player.
52
    pub fn check_consistent(&self, pg: &impl PG, player: Player) {
53
        for vertex in pg.iter_vertices() {
54
            if self.get(vertex).is_some() && pg.owner(vertex) != player {
55
                panic!(
56
                    "Strategy is defined for vertex {:?} owned by {:?}, \
57
                        but should only be defined for vertices owned by {:?}",
58
                    vertex,
59
                    pg.owner(vertex),
60
                    player
61
                );
62
            }
63
        }
64
    }
65
}
66

            
67
impl Default for Strategy {
68
    fn default() -> Self {
69
        Self::new()
70
    }
71
}
72

            
73
impl fmt::Debug for Strategy {
74
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75
        writeln!(f, "Strategy {{")?;
76
        for (from, to) in &self.mapping {
77
            writeln!(f, "  v{} -> v{}", from, to)?;
78
        }
79
        writeln!(f, "}}")
80
    }
81
}