1
use std::collections::HashMap;
2
use std::fmt;
3
use std::hash::Hash;
4

            
5
use merc_collections::VecSet;
6

            
7
/// An antichain is a structure (<, S) such that < is a preorder on S, such that
8
/// for any s, t in S neither s < t nor t < s holds. In other words, all
9
/// elements of S are incomparable under the preorder <. This is dual to to
10
/// notion of a chain.
11
/// 
12
/// # Details
13
/// 
14
/// This implementation stores pairs (s, T) in S.
15
pub struct Antichain<K, V> {
16
    storage: HashMap<K, VecSet<VecSet<V>>>,
17

            
18
    /// The largest size of the antichain.
19
    max_antichain: usize,
20
    /// Number of times a pair was inserted into the antichain.
21
    antichain_misses: usize,
22
    /// Number of times antichain_insert was called.
23
    antichain_inserts: usize,
24
}
25

            
26
impl<K: Eq + Hash, V: Clone + Ord> Antichain<K, V> {
27
    /// Creates a new empty antichain.
28
1204
    pub fn new() -> Self {
29
1204
        Antichain {
30
1204
            storage: HashMap::new(),
31
1204
            max_antichain: 0,
32
1204
            antichain_misses: 0,
33
1204
            antichain_inserts: 0,
34
1204
        }
35
1204
    }
36

            
37
    /// Inserts the given (s, T) pair into the antichain and returns true iff it was
38
    /// not already present.
39
    /// 
40
    /// # Details
41
    /// 
42
    /// A pair (s, T) is `present` in `S` iff there exists a pair (s, T') in S such that T < T'.
43
10917
    pub fn insert(&mut self, key: K, value: VecSet<V>) -> bool {
44
10917
        let mut inserted = false;
45
10917
        self.storage
46
10917
            .entry(key)
47
10917
            .and_modify(|entry| {
48
4602
                let mut contains = false;
49
11899
                entry.retain(|inner_value| {
50
11899
                    if inner_value.is_subset(&value) {
51
                        // The new value is a superset of an existing entry
52
842
                        contains = true;
53
842
                        true
54
11057
                    } else if value.is_subset(inner_value) {
55
                        // Remove any entry that is a superset of the new value
56
398
                        false
57
                    } else {
58
                        // Leave incomparable entries unchanged
59
10659
                        true
60
                    }
61
11899
                });
62

            
63
4602
                if !contains {
64
3779
                    self.antichain_misses += 1; // Was not present
65
3779
                    entry.insert(value.clone());
66
3779
                    inserted = true;
67
3779
                }
68
4602
            })
69
10917
            .or_insert_with(|| {
70
6315
                self.antichain_misses += 1; // Was not present
71
6315
                inserted = true;
72
6315
                VecSet::singleton(value)
73
6315
            });
74

            
75
10917
        self.antichain_inserts += 1;
76
10917
        self.max_antichain = self.max_antichain.max(self.storage.len());
77

            
78
10917
        inserted
79
10917
    }
80

            
81
    /// Returns true iff the antichain is empty.
82
    pub fn is_empty(&self) -> bool {
83
        self.storage.is_empty()
84
    }
85

            
86
    /// Returns the size of the antichain.
87
    pub fn len(&self) -> usize {
88
        self.storage.len()
89
    }
90

            
91
    /// Clears the antichain.
92
    pub fn clear(&mut self) {
93
        self.storage.clear();
94
    }
95

            
96
    /// Returns the metrics of this antichain
97
    pub fn metrics(&self) -> (usize, usize, usize) {
98
        (self.max_antichain, self.antichain_misses, self.antichain_inserts)
99
    }
100
}
101

            
102
impl<K: Eq + Hash, V: Clone + Ord> Default for Antichain<K, V> {
103
    fn default() -> Self {
104
        Self::new()
105
    }
106
}
107

            
108
impl<K, V: fmt::Debug + Ord> Antichain<K, V> {
109
    /// Checks the internal consistency of the antichain invariant.
110
    #[cfg(test)]
111
100
    fn check_consistency(&self) {
112
994
        for (_key, values) in &self.storage {
113
4291
            for i in values.iter() {
114
21501
                for j in values.iter() {
115
21501
                    if i == j {
116
                        // Ignore identical entries
117
4291
                        continue;
118
17210
                    }
119

            
120
17210
                    assert!(
121
17210
                        !i.is_subset(j) && !j.is_subset(i),
122
                        "Antichain invariant violated: {:?} and {:?} are comparable.",
123
                        i,
124
                        j
125
                    );
126
                }
127
            }
128
        }
129
100
    }
130
}
131

            
132
impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Antichain<T, U> {
133
1
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134
1
        writeln!(f, "Antichain {{")?;
135
1
        for (key, values) in &self.storage {
136
1
            writeln!(f, "  {:?}: {:?}", key, values)?;
137
        }
138
1
        writeln!(f, "}}")
139
1
    }
140
}
141

            
142
#[cfg(test)]
143
mod tests {
144
    use merc_collections::vecset;
145
    use merc_utilities::random_test;
146
    use rand::RngExt;
147

            
148
    use crate::Antichain;
149

            
150
    #[test]
151
1
    fn test_antichain() {
152
1
        let mut antichain: Antichain<u32, u32> = Antichain::new();
153

            
154
1
        let inserted = antichain.insert(1, vecset![2, 3]);
155
1
        assert!(inserted);
156

            
157
1
        println!("{:?}", antichain);
158

            
159
1
        let inserted = antichain.insert(1, vecset![2, 3, 6]);
160
1
        assert!(
161
1
            !inserted,
162
            "The pair (1, {{2,3,6}}) should not be inserted in {:?}.",
163
            antichain
164
        );
165

            
166
1
        let inserted = antichain.insert(1, vecset![2]);
167
1
        assert!(
168
1
            inserted,
169
            "The pair (1, {{2}}) should overwrite (1, {{2, 3}}) in {:?}.",
170
            antichain
171
        );
172

            
173
1
        let inserted = antichain.insert(1, vecset![5, 6]);
174
1
        assert!(
175
1
            inserted,
176
            "The pair (1, {{5, 6}}) should be inserted since it is incomparable to existing pairs in {:?}.",
177
            antichain
178
        );
179
1
    }
180

            
181
    #[test]
182
1
    fn test_random_antichain() {
183
100
        random_test(100, |rng| {
184
100
            let mut antichain: Antichain<u32, u32> = Antichain::new();
185

            
186
            // Insert random pairs into the antichain.
187
100
            for _ in 0..50 {
188
5000
                let key = rng.random_range(0..10);
189
5000
                let set_size = rng.random_range(1..5);
190
5000
                let mut value = vecset![];
191

            
192
12427
                for _ in 0..set_size {
193
12427
                    value.insert(rng.random_range(0..20));
194
12427
                }
195

            
196
5000
                antichain.insert(key, value);
197
            }
198

            
199
100
            antichain.check_consistency();
200
100
        })
201
1
    }
202
}