1use std::cmp::Ordering::{self, *};
4use std::collections::{BTreeMap, HashMap};
5use std::fmt::Debug;
6use std::marker::PhantomData;
7
8use cc_traits::{Collection, GetKeyValue, Iter, MapInsert, SimpleCollectionRef};
9
10use crate::cc_traits::{GetMut, Keyed, Map, MapIter, SimpleKeyedRef};
11use crate::collections::{ArrayMap, MapMapValues, OptionMap, SingletonMap, VecMap};
12use crate::{Atomize, DeepReveal, IsBot, IsTop, LatticeBimorphism, LatticeFrom, LatticeOrd, Merge};
13
14#[repr(transparent)]
19#[derive(Copy, Clone, Debug, Default)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct MapUnion<Map>(Map);
22impl<Map> MapUnion<Map> {
23 pub fn new(val: Map) -> Self {
25 Self(val)
26 }
27
28 pub fn new_from(val: impl Into<Map>) -> Self {
30 Self::new(val.into())
31 }
32
33 pub fn as_reveal_ref(&self) -> &Map {
35 &self.0
36 }
37
38 pub fn as_reveal_mut(&mut self) -> &mut Map {
40 &mut self.0
41 }
42
43 pub fn into_reveal(self) -> Map {
45 self.0
46 }
47}
48
49impl<Map, Val> DeepReveal for MapUnion<Map>
50where
51 Map: Keyed<Item = Val> + MapMapValues<Val>,
52 Val: DeepReveal,
53{
54 type Revealed = Map::MapValue<Val::Revealed>;
55
56 fn deep_reveal(self) -> Self::Revealed {
57 self.0.map_values(DeepReveal::deep_reveal)
58 }
59}
60
61impl<MapSelf, MapOther, K, ValSelf, ValOther> Merge<MapUnion<MapOther>> for MapUnion<MapSelf>
62where
63 MapSelf: Keyed<Key = K, Item = ValSelf>
64 + Extend<(K, ValSelf)>
65 + for<'a> GetMut<&'a K, Item = ValSelf>,
66 MapOther: IntoIterator<Item = (K, ValOther)>,
67 ValSelf: Merge<ValOther> + LatticeFrom<ValOther>,
68 ValOther: IsBot,
69{
70 fn merge(&mut self, other: MapUnion<MapOther>) -> bool {
71 let mut changed = false;
72 let iter: Vec<_> = other
77 .0
78 .into_iter()
79 .filter(|(_k_other, val_other)| !val_other.is_bot())
80 .filter_map(|(k_other, val_other)| {
81 match self.0.get_mut(&k_other) {
82 Some(mut val_self) => {
84 changed |= val_self.merge(val_other);
85 None
86 }
87 None => {
89 changed = true;
90 Some((k_other, ValSelf::lattice_from(val_other)))
91 }
92 }
93 })
94 .collect();
95 self.0.extend(iter);
96 changed
97 }
98}
99
100impl<MapSelf, MapOther, K, ValSelf, ValOther> LatticeFrom<MapUnion<MapOther>> for MapUnion<MapSelf>
101where
102 MapSelf: Keyed<Key = K, Item = ValSelf> + FromIterator<(K, ValSelf)>,
103 MapOther: IntoIterator<Item = (K, ValOther)>,
104 ValSelf: LatticeFrom<ValOther>,
105{
106 fn lattice_from(other: MapUnion<MapOther>) -> Self {
107 Self(
108 other
109 .0
110 .into_iter()
111 .map(|(k_other, val_other)| (k_other, LatticeFrom::lattice_from(val_other)))
112 .collect(),
113 )
114 }
115}
116
117impl<MapSelf, MapOther, K, ValSelf, ValOther> PartialOrd<MapUnion<MapOther>> for MapUnion<MapSelf>
118where
119 MapSelf: Map<K, ValSelf, Key = K, Item = ValSelf> + MapIter + SimpleKeyedRef,
120 MapOther: Map<K, ValOther, Key = K, Item = ValOther> + MapIter + SimpleKeyedRef,
121 ValSelf: PartialOrd<ValOther> + IsBot,
122 ValOther: IsBot,
123{
124 fn partial_cmp(&self, other: &MapUnion<MapOther>) -> Option<Ordering> {
125 let mut self_any_greater = false;
126 let mut other_any_greater = false;
127 let self_keys = self
128 .0
129 .iter()
130 .filter(|(_k, v)| !v.is_bot())
131 .map(|(k, _v)| <MapSelf as SimpleKeyedRef>::into_ref(k));
132 let other_keys = other
133 .0
134 .iter()
135 .filter(|(_k, v)| !v.is_bot())
136 .map(|(k, _v)| <MapOther as SimpleKeyedRef>::into_ref(k));
137 for k in self_keys.chain(other_keys) {
138 match (self.0.get(k), other.0.get(k)) {
139 (Some(self_value), Some(other_value)) => {
140 match self_value.partial_cmp(&*other_value)? {
141 Less => {
142 other_any_greater = true;
143 }
144 Greater => {
145 self_any_greater = true;
146 }
147 Equal => {}
148 }
149 }
150 (Some(_), None) => {
151 self_any_greater = true;
152 }
153 (None, Some(_)) => {
154 other_any_greater = true;
155 }
156 (None, None) => unreachable!(),
157 }
158 if self_any_greater && other_any_greater {
159 return None;
160 }
161 }
162 match (self_any_greater, other_any_greater) {
163 (true, false) => Some(Greater),
164 (false, true) => Some(Less),
165 (false, false) => Some(Equal),
166 (true, true) => unreachable!(),
168 }
169 }
170}
171impl<MapSelf, MapOther> LatticeOrd<MapUnion<MapOther>> for MapUnion<MapSelf> where
172 Self: PartialOrd<MapUnion<MapOther>>
173{
174}
175
176impl<MapSelf, MapOther, K, ValSelf, ValOther> PartialEq<MapUnion<MapOther>> for MapUnion<MapSelf>
177where
178 MapSelf: Map<K, ValSelf, Key = K, Item = ValSelf> + MapIter + SimpleKeyedRef,
179 MapOther: Map<K, ValOther, Key = K, Item = ValOther> + MapIter + SimpleKeyedRef,
180 ValSelf: PartialEq<ValOther> + IsBot,
181 ValOther: IsBot,
182{
183 fn eq(&self, other: &MapUnion<MapOther>) -> bool {
184 let self_keys = self
185 .0
186 .iter()
187 .filter(|(_k, v)| !v.is_bot())
188 .map(|(k, _v)| <MapSelf as SimpleKeyedRef>::into_ref(k));
189 let other_keys = other
190 .0
191 .iter()
192 .filter(|(_k, v)| !v.is_bot())
193 .map(|(k, _v)| <MapOther as SimpleKeyedRef>::into_ref(k));
194 for k in self_keys.chain(other_keys) {
195 match (self.0.get(k), other.0.get(k)) {
196 (Some(self_value), Some(other_value)) => {
197 if *self_value != *other_value {
198 return false;
199 }
200 }
201 (None, None) => unreachable!(),
202 _ => {
203 return false;
204 }
205 }
206 }
207
208 true
209 }
210}
211impl<MapSelf> Eq for MapUnion<MapSelf> where Self: PartialEq {}
212
213impl<Map> IsBot for MapUnion<Map>
214where
215 Map: Iter,
216 Map::Item: IsBot,
217{
218 fn is_bot(&self) -> bool {
219 self.0.iter().all(|v| v.is_bot())
220 }
221}
222
223impl<Map> IsTop for MapUnion<Map> {
224 fn is_top(&self) -> bool {
225 false
226 }
227}
228
229impl<Map, K, Val> Atomize for MapUnion<Map>
230where
231 Map: 'static
232 + IntoIterator<Item = (K, Val)>
233 + Keyed<Key = K, Item = Val>
234 + Extend<(K, Val)>
235 + for<'a> GetMut<&'a K, Item = Val>,
236 K: 'static + Clone,
237 Val: 'static + Atomize + LatticeFrom<<Val as Atomize>::Atom>,
238{
239 type Atom = MapUnionSingletonMap<K, Val::Atom>;
240
241 type AtomIter = Box<dyn Iterator<Item = Self::Atom>>;
243
244 fn atomize(self) -> Self::AtomIter {
245 Box::new(self.0.into_iter().flat_map(|(k, val)| {
246 val.atomize()
247 .map(move |v| MapUnionSingletonMap::new_from((k.clone(), v)))
248 }))
249 }
250}
251
252pub type MapUnionHashMap<K, Val> = MapUnion<HashMap<K, Val>>;
254
255pub type MapUnionBTreeMap<K, Val> = MapUnion<BTreeMap<K, Val>>;
257
258pub type MapUnionVec<K, Val> = MapUnion<VecMap<K, Val>>;
260
261pub type MapUnionArrayMap<K, Val, const N: usize> = MapUnion<ArrayMap<K, Val, N>>;
263
264pub type MapUnionSingletonMap<K, Val> = MapUnion<SingletonMap<K, Val>>;
266
267pub type MapUnionOptionMap<K, Val> = MapUnion<OptionMap<K, Val>>;
269
270pub struct KeyedBimorphism<MapOut, Bimorphism> {
274 bimorphism: Bimorphism,
275 _phantom: PhantomData<fn() -> MapOut>,
276}
277impl<MapOut, Bimorphism> KeyedBimorphism<MapOut, Bimorphism> {
278 pub fn new(bimorphism: Bimorphism) -> Self {
280 Self {
281 bimorphism,
282 _phantom: PhantomData,
283 }
284 }
285}
286impl<MapA, MapB, MapOut, ValFunc> LatticeBimorphism<MapUnion<MapA>, MapUnion<MapB>>
287 for KeyedBimorphism<MapOut, ValFunc>
288where
289 ValFunc: LatticeBimorphism<MapA::Item, MapB::Item>,
290 MapA: MapIter + SimpleKeyedRef + SimpleCollectionRef,
291 MapB: for<'a> GetKeyValue<&'a MapA::Key, Key = MapA::Key> + SimpleCollectionRef,
292 MapA::Key: Clone + Eq,
293 MapA::Item: Clone,
294 MapB::Item: Clone,
295 MapOut: Default + MapInsert<MapA::Key> + Collection<Item = ValFunc::Output>,
296{
297 type Output = MapUnion<MapOut>;
298
299 fn call(&mut self, lat_a: MapUnion<MapA>, lat_b: MapUnion<MapB>) -> Self::Output {
300 let mut output = MapUnion::<MapOut>::default();
301 for (key, val_a) in lat_a.as_reveal_ref().iter() {
302 let key = <MapA as SimpleKeyedRef>::into_ref(key);
303 let Some((_key, val_b)) = lat_b.as_reveal_ref().get_key_value(key) else {
304 continue;
305 };
306 let val_a = <MapA as SimpleCollectionRef>::into_ref(val_a).clone();
307 let val_b = <MapB as SimpleCollectionRef>::into_ref(val_b).clone();
308
309 let val_out = LatticeBimorphism::call(&mut self.bimorphism, val_a, val_b);
310 <MapOut as MapInsert<_>>::insert(output.as_reveal_mut(), key.clone(), val_out);
311 }
312 output
313 }
314}
315
316#[cfg(test)]
317mod test {
318 use std::collections::HashSet;
319
320 use super::*;
321 use crate::collections::SingletonSet;
322 use crate::set_union::{CartesianProductBimorphism, SetUnionHashSet, SetUnionSingletonSet};
323 use crate::test::{cartesian_power, check_all, check_atomize_each, check_lattice_bimorphism};
324
325 #[test]
326 fn test_map_union() {
327 let mut my_map_a = <MapUnionHashMap<&str, SetUnionHashSet<u64>>>::default();
328 let my_map_b = <MapUnionSingletonMap<&str, SetUnionSingletonSet<u64>>>::new(SingletonMap(
329 "hello",
330 SetUnionSingletonSet::new(SingletonSet(100)),
331 ));
332 let my_map_c =
333 MapUnionSingletonMap::new_from(("hello", SetUnionHashSet::new_from([100, 200])));
334 my_map_a.merge(my_map_b);
335 my_map_a.merge(my_map_c);
336 }
337
338 #[test]
339 fn consistency_atomize() {
340 let mut test_vec = Vec::new();
341
342 test_vec.push(MapUnionHashMap::default());
344 for key in [0, 1] {
346 for value in [vec![], vec![0], vec![1], vec![0, 1]] {
347 test_vec.push(MapUnionHashMap::new(HashMap::from_iter([(
348 key,
349 SetUnionHashSet::new(HashSet::from_iter(value)),
350 )])));
351 }
352 }
353 for [val_a, val_b] in cartesian_power(&[vec![], vec![0], vec![1], vec![0, 1]]) {
355 test_vec.push(MapUnionHashMap::new(HashMap::from_iter([
356 (0, SetUnionHashSet::new(HashSet::from_iter(val_a.clone()))),
357 (1, SetUnionHashSet::new(HashSet::from_iter(val_b.clone()))),
358 ])));
359 }
360
361 check_all(&test_vec);
362 check_atomize_each(&test_vec);
363 }
364
365 #[test]
367 fn test_collapes_bot() {
368 let map_empty = <MapUnionHashMap<&str, SetUnionHashSet<u64>>>::default();
369 let map_a_bot = <MapUnionSingletonMap<&str, SetUnionHashSet<u64>>>::new(SingletonMap(
370 "a",
371 Default::default(),
372 ));
373 let map_b_bot = <MapUnionSingletonMap<&str, SetUnionHashSet<u64>>>::new(SingletonMap(
374 "b",
375 Default::default(),
376 ));
377
378 assert_eq!(map_empty, map_a_bot);
379 assert_eq!(map_empty, map_b_bot);
380 assert_eq!(map_a_bot, map_b_bot);
381 }
382
383 #[test]
384 fn test_join_aka_keyed_cartesian_product() {
385 let items_a = &[
386 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["bar"]))]),
387 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["baz"]))]),
388 MapUnionHashMap::new_from([("hello", SetUnionHashSet::new_from(["world"]))]),
389 ];
390 let items_b = &[
391 MapUnionHashMap::new_from([("foo", SetUnionHashSet::new_from(["bang"]))]),
392 MapUnionHashMap::new_from([(
393 "hello",
394 SetUnionHashSet::new_from(["goodbye", "farewell"]),
395 )]),
396 ];
397
398 check_lattice_bimorphism(
399 KeyedBimorphism::<HashMap<_, _>, _>::new(
400 CartesianProductBimorphism::<HashSet<_>>::default(),
401 ),
402 items_a,
403 items_a,
404 );
405 check_lattice_bimorphism(
406 KeyedBimorphism::<HashMap<_, _>, _>::new(
407 CartesianProductBimorphism::<HashSet<_>>::default(),
408 ),
409 items_a,
410 items_b,
411 );
412 check_lattice_bimorphism(
413 KeyedBimorphism::<HashMap<_, _>, _>::new(
414 CartesianProductBimorphism::<HashSet<_>>::default(),
415 ),
416 items_b,
417 items_a,
418 );
419 check_lattice_bimorphism(
420 KeyedBimorphism::<HashMap<_, _>, _>::new(
421 CartesianProductBimorphism::<HashSet<_>>::default(),
422 ),
423 items_b,
424 items_b,
425 );
426
427 check_lattice_bimorphism(
428 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
429 CartesianProductBimorphism::<HashSet<_>>::default(),
430 ),
431 items_a,
432 items_a,
433 );
434 check_lattice_bimorphism(
435 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
436 CartesianProductBimorphism::<HashSet<_>>::default(),
437 ),
438 items_a,
439 items_b,
440 );
441 check_lattice_bimorphism(
442 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
443 CartesianProductBimorphism::<HashSet<_>>::default(),
444 ),
445 items_b,
446 items_a,
447 );
448 check_lattice_bimorphism(
449 KeyedBimorphism::<BTreeMap<_, _>, _>::new(
450 CartesianProductBimorphism::<HashSet<_>>::default(),
451 ),
452 items_b,
453 items_b,
454 );
455 }
456}