1
2use std::collections::{HashMap, HashSet};
3use std::hash::Hash;
4
5#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
23pub enum AlgebraicResult<V> {
24 #[default]
26 None,
27 Identity(u64),
31 Element(V),
33}
34
35pub const SELF_IDENT: u64 = 0x1;
37
38pub const COUNTER_IDENT: u64 = 0x2;
40
41impl<V> AlgebraicResult<V> {
42 #[inline]
44 pub fn is_none(&self) -> bool {
45 matches!(self, AlgebraicResult::None)
46 }
47 #[inline]
49 pub fn is_identity(&self) -> bool {
50 matches!(self, AlgebraicResult::Identity(_))
51 }
52 #[inline]
54 pub fn is_element(&self) -> bool {
55 matches!(self, AlgebraicResult::Element(_))
56 }
57 #[inline]
59 pub fn identity_mask(&self) -> Option<u64> {
60 match self {
61 Self::None => None,
62 Self::Identity(mask) => Some(*mask),
63 Self::Element(_) => None,
64 }
65 }
66 #[inline]
71 pub fn invert_identity(self) -> Self {
72 match self {
73 Self::None => AlgebraicResult::None,
74 Self::Identity(mask) => {
75 let new_mask = ((mask & SELF_IDENT) << 1) | ((mask & COUNTER_IDENT) >> 1);
76 AlgebraicResult::Identity(new_mask)
77 },
78 Self::Element(v) => AlgebraicResult::Element(v),
79 }
80 }
81 #[inline]
84 pub fn map<U, F>(self, f: F) -> AlgebraicResult<U>
85 where F: FnOnce(V) -> U,
86 {
87 match self {
88 Self::None => AlgebraicResult::None,
89 Self::Identity(mask) => AlgebraicResult::Identity(mask),
90 Self::Element(v) => AlgebraicResult::Element(f(v)),
91 }
92 }
93 #[inline]
95 pub fn as_ref(&self) -> AlgebraicResult<&V> {
96 match *self {
97 Self::Element(ref v) => AlgebraicResult::Element(v),
98 Self::None => AlgebraicResult::None,
99 Self::Identity(mask) => AlgebraicResult::Identity(mask),
100 }
101 }
102 #[inline]
107 pub fn map_into_option<IdentF>(self, ident_f: IdentF) -> Option<V>
108 where IdentF: FnOnce(usize) -> Option<V>
109 {
110 match self {
111 Self::Element(v) => Some(v),
112 Self::None => None,
113 Self::Identity(mask) => ident_f(mask.trailing_zeros() as usize),
114 }
115 }
116 #[inline]
119 pub fn into_option<I: AsRef<[VRef]>, VRef: std::borrow::Borrow<V>>(self, idents: I) -> Option<V>
120 where V: Clone
121 {
122 match self {
123 Self::Element(v) => Some(v),
124 Self::None => None,
125 Self::Identity(mask) => {
126 let idents = idents.as_ref();
127 Some(idents[mask.trailing_zeros() as usize].borrow().clone())
128 },
129 }
130 }
131
132 #[inline]
135 pub fn unwrap<I: AsRef<[VRef]>, VRef: std::borrow::Borrow<V>>(self, idents: I) -> V
136 where V: Clone
137 {
138 match self {
139 Self::Element(v) => v,
140 Self::None => panic!(),
141 Self::Identity(mask) => {
142 let idents = idents.as_ref();
143 idents[mask.trailing_zeros() as usize].borrow().clone()
144 },
145 }
146 }
147 #[inline]
151 pub fn unwrap_or_else<IdentF, NoneF>(self, ident_f: IdentF, none_f: NoneF) -> V
152 where
153 IdentF: FnOnce(usize) -> V,
154 NoneF: FnOnce() -> V
155 {
156 match self {
157 Self::Element(v) => v,
158 Self::None => none_f(),
159 Self::Identity(mask) => ident_f(mask.trailing_zeros() as usize),
160 }
161 }
162 #[inline]
164 pub fn unwrap_or<I: AsRef<[VRef]>, VRef: std::borrow::Borrow<V>>(self, idents: I, none: V) -> V
165 where V: Clone
166 {
167 match self {
168 Self::Element(v) => v,
169 Self::None => none,
170 Self::Identity(mask) => {
171 let idents = idents.as_ref();
172 idents[mask.trailing_zeros() as usize].borrow().clone()
173 },
174 }
175 }
176 #[inline]
216 pub fn merge<BV, U, MergeF, AIdent, BIdent>(self, b: AlgebraicResult<BV>, self_idents: AIdent, b_idents: BIdent, merge_f: MergeF) -> AlgebraicResult<U>
217 where
218 MergeF: FnOnce(Option<V>, Option<BV>) -> AlgebraicResult<U>,
219 AIdent: FnOnce(usize) -> Option<V>,
220 BIdent: FnOnce(usize) -> Option<BV>,
221 {
222 match self {
223 Self::None => {
224 match b {
225 AlgebraicResult::None => AlgebraicResult::None,
226 AlgebraicResult::Element(b_v) => merge_f(None, Some(b_v)),
227 AlgebraicResult::Identity(b_mask) => {
228 let self_ident = self_idents(0);
229 if self_ident.is_none() {
230 AlgebraicResult::Identity(b_mask)
231 } else {
232 let b_v = b_idents(b_mask.trailing_zeros() as usize);
233 merge_f(None, b_v)
234 }
235 },
236 }
237 },
238 Self::Identity(self_mask) => {
239 match b {
240 AlgebraicResult::None => {
241 let b_ident = b_idents(0);
242 if b_ident.is_none() {
243 AlgebraicResult::Identity(self_mask)
244 } else {
245 let self_v = self_idents(self_mask.trailing_zeros() as usize);
246 merge_f(self_v, None)
247 }
248 },
249 AlgebraicResult::Element(b_v) => {
250 let self_v = self_idents(self_mask.trailing_zeros() as usize);
251 merge_f(self_v, Some(b_v))
252 },
253 AlgebraicResult::Identity(b_mask) => {
254 let combined_mask = self_mask & b_mask;
255 if combined_mask > 0 {
256 AlgebraicResult::Identity(combined_mask)
257 } else {
258 let self_v = self_idents(self_mask.trailing_zeros() as usize);
259 let b_v = b_idents(b_mask.trailing_zeros() as usize);
260 merge_f(self_v, b_v)
261 }
262 }
263 }
264 },
265 Self::Element(self_v) => {
266 match b {
267 AlgebraicResult::None => merge_f(Some(self_v), None),
268 AlgebraicResult::Element(b_v) => merge_f(Some(self_v), Some(b_v)),
269 AlgebraicResult::Identity(b_mask) => {
270 let b_v = b_idents(b_mask.trailing_zeros() as usize);
271 merge_f(Some(self_v), b_v)
272 }
273 }
274 }
275 }
276 }
277 #[inline]
279 pub fn from_status<F>(status: AlgebraicStatus, element_f: F) -> Self
280 where F: FnOnce() -> V
281 {
282 match status {
283 AlgebraicStatus::None => Self::None,
284 AlgebraicStatus::Identity => Self::Identity(SELF_IDENT),
285 AlgebraicStatus::Element => Self::Element(element_f())
286 }
287 }
288 #[inline]
290 pub fn status(&self) -> AlgebraicStatus {
291 match self {
292 AlgebraicResult::None => AlgebraicStatus::None,
293 AlgebraicResult::Element(_) => AlgebraicStatus::Element,
294 AlgebraicResult::Identity(mask) => {
295 if mask & SELF_IDENT > 0 {
296 AlgebraicStatus::Identity
297 } else {
298 AlgebraicStatus::Element
299 }
300 }
301 }
302 }
303}
304
305impl<V> AlgebraicResult<Option<V>> {
306 #[inline]
309 pub fn flatten(self) -> AlgebraicResult<V> {
310 match self {
311 Self::Element(v) => {
312 match v {
313 Some(v) => AlgebraicResult::Element(v),
314 None => AlgebraicResult::None
315 }
316 },
317 Self::None => AlgebraicResult::None,
318 Self::Identity(mask) => AlgebraicResult::Identity(mask),
319 }
320 }
321}
322
323#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
339pub enum AlgebraicStatus {
340 #[default]
342 Element,
343 Identity,
345 None,
347}
348
349impl AlgebraicStatus {
350 #[inline]
352 pub fn is_none(&self) -> bool {
353 matches!(self, Self::None)
354 }
355 #[inline]
357 pub fn is_identity(&self) -> bool {
358 matches!(self, Self::Identity)
359 }
360 #[inline]
362 pub fn is_element(&self) -> bool {
363 matches!(self, Self::Element)
364 }
365 #[inline]
374 pub fn merge(self, b: Self, self_none: bool, b_none: bool) -> AlgebraicStatus {
375 match self {
376 Self::None => match b {
377 Self::None => Self::None,
378 Self::Element => Self::Element,
379 Self::Identity => if self_none {
380 Self::Identity
381 } else {
382 Self::Element
383 },
384 },
385 Self::Identity => match b {
386 Self::Element => Self::Element,
387 Self::Identity => Self::Identity,
388 Self::None => if b_none {
389 Self::Identity
390 } else {
391 Self::Element
392 },
393 },
394 Self::Element => Self::Element
395 }
396 }
397}
398
399impl<V> From<FatAlgebraicResult<V>> for AlgebraicResult<V> {
400 #[inline]
401 fn from(src: FatAlgebraicResult<V>) -> Self {
402 if src.identity_mask > 0 {
403 AlgebraicResult::Identity(src.identity_mask)
404 } else {
405 match src.element {
406 Some(element) => AlgebraicResult::Element(element),
407 None => AlgebraicResult::None
408 }
409 }
410 }
411}
412
413#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
415pub(crate) struct FatAlgebraicResult<V> {
416 pub identity_mask: u64,
418 pub element: Option<V>,
421}
422
423impl<V> FatAlgebraicResult<V> {
424 #[inline(always)]
425 pub(crate) const fn new(identity_mask: u64, element: Option<V>) -> Self {
426 Self {identity_mask, element}
427 }
428 #[inline]
431 pub(crate) fn from_binary_op_result(result: AlgebraicResult<V>, a: &V, b: &V) -> Self
432 where V: Clone
433 {
434 match result {
435 AlgebraicResult::None => FatAlgebraicResult::none(),
436 AlgebraicResult::Element(v) => FatAlgebraicResult::element(v),
437 AlgebraicResult::Identity(mask) => {
438 debug_assert!(mask <= (SELF_IDENT | COUNTER_IDENT));
439 if mask & SELF_IDENT > 0 {
440 FatAlgebraicResult::new(mask, Some(a.clone()))
441 } else {
442 debug_assert_eq!(mask, COUNTER_IDENT);
443 FatAlgebraicResult::new(mask, Some(b.clone()))
444 }
445 }
446 }
447 }
448 #[inline]
450 pub fn map<U, F>(self, f: F) -> FatAlgebraicResult<U>
451 where F: FnOnce(V) -> U,
452 {
453 FatAlgebraicResult::<U> {
454 identity_mask: self.identity_mask,
455 element: self.element.map(f)
456 }
457 }
458 #[inline(always)]
460 pub(crate) const fn none() -> Self {
461 Self {identity_mask: 0, element: None}
462 }
463 #[inline(always)]
465 pub(crate) fn element(e: V) -> Self {
466 Self {identity_mask: 0, element: Some(e)}
467 }
468 pub fn join(self, arg: &V, arg_idx: usize) -> Self where V: Lattice + Clone {
509 match self.element {
510 None => {
511 Self::new(self.identity_mask | 1 << arg_idx, Some(arg.clone()))
512 },
513 Some(self_element) => match self_element.pjoin(&arg) {
514 AlgebraicResult::None => Self::none(),
515 AlgebraicResult::Element(e) => Self::element(e),
516 AlgebraicResult::Identity(mask) => {
517 if mask & SELF_IDENT > 0 {
518 let new_mask = self.identity_mask | ((mask & COUNTER_IDENT) << (arg_idx-1));
519 Self::new(new_mask, Some(self_element))
520 } else {
521 debug_assert!(mask & COUNTER_IDENT > 0);
522 let new_mask = (mask & COUNTER_IDENT) << (arg_idx-1);
523 Self::new(new_mask, Some(arg.clone()))
524 }
525 }
526 }
527 }
528 }
529}
530
531pub trait Lattice {
533 const IDEMPOTENT: bool = true;
545
546 fn pjoin(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
549
550 fn join_into(&mut self, other: Self) -> AlgebraicStatus where Self: Sized {
553 let result = self.pjoin(&other);
554 in_place_default_impl(result, self, other, |_s| {}, |e| e)
558 }
559
560 fn pmeet(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
562
563 fn join_all<S: AsRef<Self>, Args: AsRef<[S]>>(xs: Args) -> AlgebraicResult<Self> where Self: Sized + Clone {
568 let mut iter = xs.as_ref().into_iter().enumerate();
569 let mut result = match iter.next() {
570 None => return AlgebraicResult::None,
571 Some((_, first)) => FatAlgebraicResult::new(SELF_IDENT, Some(first.as_ref().clone())),
572 };
573 for (i, next) in iter {
574 result = result.join(next.as_ref(), i);
575 }
576 result.into()
577 }
578}
579
580fn in_place_default_impl<SelfT, OtherT, ConvertF, DefaultF>(result: AlgebraicResult<SelfT>, self_ref: &mut SelfT, other: OtherT, default_f: DefaultF, convert_f: ConvertF) -> AlgebraicStatus
582 where
583 DefaultF: FnOnce(&mut SelfT),
584 ConvertF: Fn(OtherT) -> SelfT
585{
586 match result {
587 AlgebraicResult::None => {
588 default_f(self_ref);
589 AlgebraicStatus::None
590 },
591 AlgebraicResult::Element(v) => {
592 *self_ref = v;
593 AlgebraicStatus::Element
594 },
595 AlgebraicResult::Identity(mask) => {
596 if mask & SELF_IDENT > 0 {
597 AlgebraicStatus::Identity
598 } else {
599 *self_ref = convert_f(other);
600 AlgebraicStatus::Element
601 }
602 },
603 }
604}
605
606pub trait LatticeRef {
609 type T;
610 fn pjoin(&self, other: &Self) -> AlgebraicResult<Self::T>;
611 fn pmeet(&self, other: &Self) -> AlgebraicResult<Self::T>;
612}
613
614pub trait DistributiveLattice {
616 const IDEMPOTENT: bool = true;
626
627 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
629
630 }
632
633pub trait DistributiveLatticeRef {
635 type T;
637
638 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self::T>;
641}
642
643pub(crate) trait Quantale {
653 fn prestrict(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
655}
656
657pub(crate) trait HeteroLattice<OtherT> {
660 fn pjoin(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
661 fn join_into(&mut self, other: OtherT) -> AlgebraicStatus where Self: Sized {
662 let result = self.pjoin(&other);
663 in_place_default_impl(result, self, other, |_s| {}, |e| Self::convert(e))
665 }
666 fn pmeet(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
667 fn convert(other: OtherT) -> Self;
669}
670
671pub(crate) trait HeteroDistributiveLattice<OtherT> {
674 fn psubtract(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
675}
676
677pub(crate) trait HeteroQuantale<OtherT> {
679 fn prestrict(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
680}
681
682impl<V: Lattice + Clone> Lattice for Option<V> {
690 fn pjoin(&self, other: &Option<V>) -> AlgebraicResult<Self> {
691 match self {
692 None => match other {
693 None => { AlgebraicResult::None }
694 Some(_) => { AlgebraicResult::Identity(COUNTER_IDENT) }
695 },
696 Some(l) => match other {
697 None => { AlgebraicResult::Identity(SELF_IDENT) }
698 Some(r) => { l.pjoin(r).map(|result| Some(result)) }
699 }
700 }
701 }
702 fn join_into(&mut self, other: Self) -> AlgebraicStatus {
703 match self {
704 None => { match other {
705 None => AlgebraicStatus::None,
706 Some(r) => {
707 *self = Some(r);
708 AlgebraicStatus::Element
709 }
710 } }
711 Some(l) => match other {
712 None => AlgebraicStatus::Identity,
713 Some(r) => {
714 l.join_into(r)
715 }
716 }
717 }
718 }
719 fn pmeet(&self, other: &Option<V>) -> AlgebraicResult<Option<V>> {
720 match self {
721 None => { AlgebraicResult::None }
722 Some(l) => {
723 match other {
724 None => { AlgebraicResult::None }
725 Some(r) => l.pmeet(r).map(|result| Some(result))
726 }
727 }
728 }
729 }
730}
731
732impl<V: DistributiveLattice + Clone> DistributiveLattice for Option<V> {
733 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> {
734 match self {
735 None => { AlgebraicResult::None }
736 Some(s) => {
737 match other {
738 None => { AlgebraicResult::Identity(SELF_IDENT) }
739 Some(o) => { s.psubtract(o).map(|v| Some(v)) }
740 }
741 }
742 }
743 }
744}
745
746#[test]
747fn option_subtract_test() {
748 assert_eq!(Some(()).psubtract(&Some(())), AlgebraicResult::None);
749 assert_eq!(Some(()).psubtract(&None), AlgebraicResult::Identity(SELF_IDENT));
750 assert_eq!(Some(Some(())).psubtract(&Some(Some(()))), AlgebraicResult::None);
751 assert_eq!(Some(Some(())).psubtract(&None), AlgebraicResult::Identity(SELF_IDENT));
752 assert_eq!(Some(Some(())).psubtract(&Some(None)), AlgebraicResult::Identity(SELF_IDENT));
753 assert_eq!(Some(Some(Some(()))).psubtract(&Some(Some(None))), AlgebraicResult::Identity(SELF_IDENT));
754 assert_eq!(Some(Some(Some(()))).psubtract(&Some(Some(Some(())))), AlgebraicResult::None);
755}
756
757impl<V: Lattice + Clone> LatticeRef for Option<&V> {
761 type T = Option<V>;
762 fn pjoin(&self, other: &Self) -> AlgebraicResult<Self::T> {
763 match self {
764 None => { match other {
765 None => { AlgebraicResult::None }
766 Some(_) => { AlgebraicResult::Identity(COUNTER_IDENT) }
767 } }
768 Some(l) => match other {
769 None => { AlgebraicResult::Identity(SELF_IDENT) }
770 Some(r) => { l.pjoin(r).map(|result| Some(result)) }
771 }
772 }
773 }
774 fn pmeet(&self, other: &Option<&V>) -> AlgebraicResult<Option<V>> {
775 match self {
776 None => { AlgebraicResult::None }
777 Some(l) => {
778 match other {
779 None => { AlgebraicResult::None }
780 Some(r) => l.pmeet(r).map(|result| Some(result))
781 }
782 }
783 }
784 }
785}
786
787impl<V: DistributiveLattice + Clone> DistributiveLatticeRef for Option<&V> {
788 type T = Option<V>;
789 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self::T> {
790 match self {
791 None => { AlgebraicResult::None }
792 Some(s) => {
793 match other {
794 None => { AlgebraicResult::Identity(SELF_IDENT) }
795 Some(o) => { s.psubtract(o).map(|v| Some(v)) }
796 }
797 }
798 }
799 }
800}
801
802impl <V: Lattice> Lattice for Box<V> {
806 fn pjoin(&self, other: &Self) -> AlgebraicResult<Self> {
807 self.as_ref().pjoin(other.as_ref()).map(|result| Box::new(result))
808 }
809 fn pmeet(&self, other: &Self) -> AlgebraicResult<Self> {
810 self.as_ref().pmeet(other.as_ref()).map(|result| Box::new(result))
811 }
812}
813
814impl<V: DistributiveLattice> DistributiveLattice for Box<V> {
815 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> {
816 self.as_ref().psubtract(other.as_ref()).map(|result| Box::new(result))
817 }
818}
819
820impl <V: Lattice> LatticeRef for &V {
824 type T = V;
825 fn pjoin(&self, other: &Self) -> AlgebraicResult<Self::T> {
826 (**self).pjoin(other)
827 }
828 fn pmeet(&self, other: &Self) -> AlgebraicResult<Self::T> {
829 (**self).pmeet(other)
830 }
831}
832
833impl<V: DistributiveLattice> DistributiveLatticeRef for &V {
834 type T = V;
835 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self::T> {
836 (**self).psubtract(other)
837 }
838}
839
840impl DistributiveLattice for () {
844 fn psubtract(&self, _other: &Self) -> AlgebraicResult<Self> where Self: Sized {
845 AlgebraicResult::None
846 }
847}
848
849impl Lattice for () {
850 fn pjoin(&self, _other: &Self) -> AlgebraicResult<Self> { AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT) }
851 fn pmeet(&self, _other: &Self) -> AlgebraicResult<Self> { AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT) }
852}
853
854impl Lattice for usize {
856 fn pjoin(&self, _other: &usize) -> AlgebraicResult<usize> { AlgebraicResult::Identity(SELF_IDENT) }
857 fn pmeet(&self, _other: &usize) -> AlgebraicResult<usize> { AlgebraicResult::Identity(SELF_IDENT) }
858}
859
860impl Lattice for u64 {
862 fn pjoin(&self, _other: &u64) -> AlgebraicResult<u64> { AlgebraicResult::Identity(SELF_IDENT) }
863 fn pmeet(&self, _other: &u64) -> AlgebraicResult<u64> { AlgebraicResult::Identity(SELF_IDENT) }
864}
865
866impl DistributiveLattice for u64 {
868 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized {
869 if self == other { AlgebraicResult::None }
870 else { AlgebraicResult::Element(*self) }
871 }
872}
873
874impl Lattice for u32 {
876 fn pjoin(&self, _other: &u32) -> AlgebraicResult<u32> { AlgebraicResult::Identity(SELF_IDENT) }
877 fn pmeet(&self, _other: &u32) -> AlgebraicResult<u32> { AlgebraicResult::Identity(SELF_IDENT) }
878}
879
880impl Lattice for u16 {
882 fn pjoin(&self, _other: &u16) -> AlgebraicResult<u16> { AlgebraicResult::Identity(SELF_IDENT) }
883 fn pmeet(&self, _other: &u16) -> AlgebraicResult<u16> { AlgebraicResult::Identity(SELF_IDENT) }
884}
885
886impl DistributiveLattice for u16 {
888 fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> {
889 if self == other { AlgebraicResult::None }
890 else { AlgebraicResult::Element(*self) }
891 }
892}
893
894impl Lattice for u8 {
896 fn pjoin(&self, _other: &u8) -> AlgebraicResult<u8> { AlgebraicResult::Identity(SELF_IDENT) }
897 fn pmeet(&self, _other: &u8) -> AlgebraicResult<u8> { AlgebraicResult::Identity(SELF_IDENT) }
898}
899
900impl DistributiveLattice for bool {
906 fn psubtract(&self, other: &bool) -> AlgebraicResult<Self> {
907 if *self == *other {
908 AlgebraicResult::None
909 } else {
910 AlgebraicResult::Identity(SELF_IDENT)
911 }
912 }
913}
914
915impl Lattice for bool {
916 fn pjoin(&self, other: &bool) -> AlgebraicResult<bool> {
917 if !*self && *other {
918 AlgebraicResult::Identity(COUNTER_IDENT) } else {
920 AlgebraicResult::Identity(SELF_IDENT)
921 }
922 }
923 fn pmeet(&self, other: &bool) -> AlgebraicResult<bool> {
924 if *self && !*other {
925 AlgebraicResult::Identity(COUNTER_IDENT) } else {
927 AlgebraicResult::Identity(SELF_IDENT)
928 }
929 }
930}
931
932pub trait SetLattice {
943 type K: Clone + Eq;
945
946 type V: Clone;
948
949 type Iter<'a>: Iterator<Item=(&'a Self::K, &'a Self::V)> where Self: 'a, Self::V: 'a, Self::K: 'a;
951
952 fn with_capacity(capacity: usize) -> Self;
954
955 fn len(&self) -> usize;
957
958 fn is_empty(&self) -> bool;
960
961 fn contains_key(&self, key: &Self::K) -> bool;
963
964 fn insert(&mut self, key: Self::K, val: Self::V);
966
967 fn remove(&mut self, key: &Self::K);
969
970 fn get(&self, key: &Self::K) -> Option<&Self::V>;
972
973 fn replace(&mut self, key: &Self::K, val: Self::V);
975
976 fn iter<'a>(&'a self) -> Self::Iter<'a>;
978
979 fn shrink_to_fit(&mut self);
981}
982
983#[macro_export]
985macro_rules! set_lattice {
986 ( $type_ident:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ) => {
987 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::ring::Lattice for $type_ident $(< $( $lt ),+ >)? where Self: $crate::ring::SetLattice, <Self as $crate::ring::SetLattice>::V: $crate::ring::Lattice {
988 fn pjoin(&self, other: &Self) -> $crate::ring::AlgebraicResult<Self> {
989 let self_len = $crate::ring::SetLattice::len(self);
990 let other_len = $crate::ring::SetLattice::len(other);
991 let mut result = <Self as $crate::ring::SetLattice>::with_capacity(self_len.max(other_len));
992 let mut is_ident = self_len >= other_len;
993 let mut is_counter_ident = self_len <= other_len;
994 for (key, self_val) in $crate::ring::SetLattice::iter(self) {
995 if let Some(other_val) = $crate::ring::SetLattice::get(other, key) {
996 let inner_result = self_val.pjoin(other_val);
998 $crate::ring::set_lattice_update_ident_flags_with_result(
999 &mut result, inner_result, key, self_val, other_val, &mut is_ident, &mut is_counter_ident
1000 );
1001 } else {
1002 $crate::ring::SetLattice::insert(&mut result, key.clone(), self_val.clone());
1004 is_counter_ident = false;
1005 }
1006 }
1007 for (key, value) in SetLattice::iter(other) {
1008 if !$crate::ring::SetLattice::contains_key(self, key) {
1009 $crate::ring::SetLattice::insert(&mut result, key.clone(), value.clone());
1011 is_ident = false;
1012 }
1013 }
1014 $crate::ring::set_lattice_integrate_into_result(result, is_ident, is_counter_ident, self_len, other_len)
1015 }
1016 fn pmeet(&self, other: &Self) -> $crate::ring::AlgebraicResult<Self> {
1017 let mut result = <Self as $crate::ring::SetLattice>::with_capacity(0);
1018 let mut is_ident = true;
1019 let mut is_counter_ident = true;
1020 let (smaller, larger, switch) = if $crate::ring::SetLattice::len(self) < $crate::ring::SetLattice::len(other) {
1021 (self, other, false)
1022 } else {
1023 (other, self, true)
1024 };
1025 for (key, self_val) in $crate::ring::SetLattice::iter(smaller) {
1026 if let Some(other_val) = $crate::ring::SetLattice::get(larger, key) {
1027 let inner_result = self_val.pmeet(other_val);
1028 $crate::ring::set_lattice_update_ident_flags_with_result(
1029 &mut result, inner_result, key, self_val, other_val, &mut is_ident, &mut is_counter_ident
1030 );
1031 } else {
1032 is_ident = false;
1033 }
1034 }
1035 if switch {
1036 core::mem::swap(&mut is_ident, &mut is_counter_ident);
1037 }
1038 $crate::ring::set_lattice_integrate_into_result(result, is_ident, is_counter_ident, self.len(), other.len())
1039 }
1040 }
1041 }
1042}
1043
1044#[inline]
1046#[doc(hidden)]
1047pub fn set_lattice_update_ident_flags_with_result<S: SetLattice>(
1048 result_set: &mut S,
1049 result: AlgebraicResult<S::V>,
1050 key: &S::K,
1051 self_val: &S::V,
1052 other_val: &S::V,
1053 is_ident: &mut bool,
1054 is_counter_ident: &mut bool
1055) {
1056 match result {
1057 AlgebraicResult::None => {
1058 *is_ident = false;
1059 *is_counter_ident = false;
1060 },
1061 AlgebraicResult::Element(new_val) => {
1062 *is_ident = false;
1063 *is_counter_ident = false;
1064 result_set.insert(key.clone(), new_val);
1065 },
1066 AlgebraicResult::Identity(mask) => {
1067 if mask & SELF_IDENT > 0 {
1068 result_set.insert(key.clone(), self_val.clone());
1069 } else {
1070 *is_ident = false;
1071 }
1072 if mask & COUNTER_IDENT > 0 {
1073 if mask & SELF_IDENT == 0 {
1074 result_set.insert(key.clone(), other_val.clone());
1075 }
1076 } else {
1077 *is_counter_ident = false;
1078 }
1079 }
1080 }
1081}
1082
1083#[inline]
1085#[doc(hidden)]
1086pub fn set_lattice_integrate_into_result<S: SetLattice>(
1087 result_set: S,
1088 is_ident: bool,
1089 is_counter_ident: bool,
1090 self_set_len: usize,
1091 other_set_len: usize,
1092) -> AlgebraicResult<S> {
1093 let result_len = result_set.len();
1094 if result_len == 0 {
1095 AlgebraicResult::None
1096 } else {
1097 let mut ident_mask = 0;
1098 if is_ident && self_set_len == result_len {
1099 ident_mask |= SELF_IDENT;
1100 }
1101 if is_counter_ident && other_set_len == result_len {
1102 ident_mask |= COUNTER_IDENT;
1103 }
1104 if ident_mask > 0 {
1105 AlgebraicResult::Identity(ident_mask)
1106 } else {
1107 AlgebraicResult::Element(result_set)
1108 }
1109 }
1110}
1111
1112#[macro_export]
1114macro_rules! set_dist_lattice {
1115 ( $type_ident:ident $(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)? ) => {
1116 impl $(< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $crate::ring::DistributiveLattice for $type_ident $(< $( $lt ),+ >)? where Self: $crate::ring::SetLattice + Clone, <Self as $crate::ring::SetLattice>::V: $crate::ring::DistributiveLattice {
1117 fn psubtract(&self, other: &Self) -> $crate::ring::AlgebraicResult<Self> {
1118 let mut is_ident = true;
1119 let mut result = self.clone();
1120 if $crate::ring::SetLattice::len(self) > $crate::ring::SetLattice::len(other) {
1122 for (key, other_val) in $crate::ring::SetLattice::iter(other) {
1123 if let Some(self_val) = $crate::ring::SetLattice::get(self, key) {
1124 set_lattice_subtract_element(&mut result, key, self_val, other_val, &mut is_ident)
1125 }
1126 }
1127 } else {
1128 for (key, self_val) in $crate::ring::SetLattice::iter(self) {
1129 if let Some(other_val) = $crate::ring::SetLattice::get(other, key) {
1130 set_lattice_subtract_element(&mut result, key, self_val, other_val, &mut is_ident)
1131 }
1132 }
1133 }
1134 if $crate::ring::SetLattice::len(&result) == 0 {
1135 $crate::ring::AlgebraicResult::None
1136 } else if is_ident {
1137 $crate::ring::AlgebraicResult::Identity(SELF_IDENT)
1138 } else {
1139 $crate::ring::SetLattice::shrink_to_fit(&mut result);
1140 $crate::ring::AlgebraicResult::Element(result)
1141 }
1142 }
1143 }
1144 }
1145}
1146
1147#[inline]
1149fn set_lattice_subtract_element<S: SetLattice>(
1150 result_set: &mut S,
1151 key: &S::K,
1152 self_val: &S::V,
1153 other_val: &S::V,
1154 is_ident: &mut bool,
1155) where S::V: DistributiveLattice {
1156 match self_val.psubtract(other_val) {
1157 AlgebraicResult::Element(new_val) => {
1158 SetLattice::replace(result_set, key, new_val);
1159 *is_ident = false;
1160 },
1161 AlgebraicResult::Identity(mask) => {
1162 debug_assert_eq!(mask, SELF_IDENT);
1163 },
1164 AlgebraicResult::None => {
1165 SetLattice::remove(result_set, key);
1166 *is_ident = false;
1167 }
1168 }
1169}
1170
1171impl<K: Clone + Eq + Hash, V: Clone + Lattice> SetLattice for HashMap<K, V> {
1172 type K = K;
1173 type V = V;
1174 type Iter<'a> = std::collections::hash_map::Iter<'a, K, V> where K: 'a, V: 'a;
1175 fn with_capacity(capacity: usize) -> Self { Self::with_capacity(capacity) }
1176 fn len(&self) -> usize { self.len() }
1177 fn is_empty(&self) -> bool { self.is_empty() }
1178 fn contains_key(&self, key: &Self::K) -> bool { self.contains_key(key) }
1179 fn insert(&mut self, key: Self::K, val: Self::V) { self.insert(key, val); }
1180 fn get(&self, key: &Self::K) -> Option<&Self::V> { self.get(key) }
1181 fn replace(&mut self, key: &Self::K, val: Self::V) { *self.get_mut(key).unwrap() = val }
1182 fn remove(&mut self, key: &Self::K) { self.remove(key); }
1183 fn iter<'a>(&'a self) -> Self::Iter<'a> { self.iter() }
1184 fn shrink_to_fit(&mut self) { self.shrink_to_fit(); }
1185}
1186
1187set_lattice!(HashMap<K, V>);
1188set_dist_lattice!(HashMap<K, V>);
1189
1190impl<K: Clone + Eq + Hash> SetLattice for HashSet<K> {
1191 type K = K;
1192 type V = ();
1193 type Iter<'a> = HashSetIterWrapper<'a, K> where K: 'a;
1194 fn with_capacity(capacity: usize) -> Self { Self::with_capacity(capacity) }
1195 fn len(&self) -> usize { self.len() }
1196 fn is_empty(&self) -> bool { self.is_empty() }
1197 fn contains_key(&self, key: &Self::K) -> bool { self.contains(key) }
1198 fn insert(&mut self, key: Self::K, _val: Self::V) { self.insert(key); }
1199 fn get(&self, key: &Self::K) -> Option<&Self::V> { self.get(key).map(|_| &()) }
1200 fn replace(&mut self, key: &Self::K, _val: Self::V) { debug_assert!(self.contains(key)); }
1201 fn remove(&mut self, key: &Self::K) { self.remove(key); }
1202 fn iter<'a>(&'a self) -> Self::Iter<'a> { HashSetIterWrapper(self.iter()) }
1203 fn shrink_to_fit(&mut self) { self.shrink_to_fit(); }
1204}
1205
1206pub struct HashSetIterWrapper<'a, K> (std::collections::hash_set::Iter<'a, K>);
1207
1208impl<'a, K> Iterator for HashSetIterWrapper<'a, K> {
1209 type Item = (&'a K, &'a());
1210 fn next(&mut self) -> Option<(&'a K, &'a())> {
1211 self.0.next().map(|key| (key, &()))
1212 }
1213}
1214
1215set_lattice!(HashSet<K>);
1216set_dist_lattice!(HashSet<K>);
1217
1218#[cfg(test)]
1219mod tests {
1220 use super::{AlgebraicResult, SetLattice, COUNTER_IDENT, SELF_IDENT};
1221 use crate::ring::{DistributiveLattice, Lattice};
1222 use std::collections::{HashMap, HashSet};
1223 use std::fmt::Debug;
1224
1225 type NestedSetMap = HashMap<u8, HashSet<u16>>;
1226
1227 fn assert_binary_result<T>(
1228 result: AlgebraicResult<T>,
1229 self_value: &T,
1230 counter_value: &T,
1231 expected: &T,
1232 allow_counter_identity: bool,
1233 context: &str,
1234 ) where
1235 T: Clone + Default + Eq + Debug,
1236 {
1237 match &result {
1238 AlgebraicResult::None => {
1239 assert_eq!(expected, &T::default(), "{context}: None result");
1240 }
1241 AlgebraicResult::Identity(mask) => {
1242 assert_ne!(*mask, 0, "{context}: zero identity mask");
1243 assert_eq!(
1244 *mask & !(SELF_IDENT | COUNTER_IDENT),
1245 0,
1246 "{context}: identity mask sets an out-of-arity bit"
1247 );
1248 if !allow_counter_identity {
1249 assert_eq!(
1250 *mask & COUNTER_IDENT,
1251 0,
1252 "{context}: non-commutative operation returned counter identity"
1253 );
1254 }
1255 if *mask & SELF_IDENT != 0 {
1256 assert_eq!(self_value, expected, "{context}: self identity mismatch");
1257 }
1258 if *mask & COUNTER_IDENT != 0 {
1259 assert_eq!(
1260 counter_value, expected,
1261 "{context}: counter identity mismatch"
1262 );
1263 }
1264 }
1265 AlgebraicResult::Element(_) => {}
1266 }
1267
1268 let actual = result.unwrap_or([self_value, counter_value], T::default());
1269 assert_eq!(actual, *expected, "{context}: materialized result");
1270 }
1271
1272 fn normalize_nested_map(map: &NestedSetMap) -> NestedSetMap {
1273 map.iter()
1274 .filter(|(_, values)| !values.is_empty())
1275 .map(|(key, values)| (*key, values.clone()))
1276 .collect()
1277 }
1278
1279 fn assert_nested_result(
1280 result: AlgebraicResult<NestedSetMap>,
1281 self_value: &NestedSetMap,
1282 counter_value: &NestedSetMap,
1283 expected: &NestedSetMap,
1284 allow_counter_identity: bool,
1285 context: &str,
1286 ) {
1287 match &result {
1288 AlgebraicResult::None => {
1289 assert!(expected.is_empty(), "{context}: None result");
1290 }
1291 AlgebraicResult::Identity(mask) => {
1292 assert_ne!(*mask, 0, "{context}: zero identity mask");
1293 assert_eq!(
1294 *mask & !(SELF_IDENT | COUNTER_IDENT),
1295 0,
1296 "{context}: identity mask sets an out-of-arity bit"
1297 );
1298 if !allow_counter_identity {
1299 assert_eq!(
1300 *mask & COUNTER_IDENT,
1301 0,
1302 "{context}: non-commutative operation returned counter identity"
1303 );
1304 }
1305 if *mask & SELF_IDENT != 0 {
1306 assert_eq!(
1307 normalize_nested_map(self_value),
1308 *expected,
1309 "{context}: self identity mismatch"
1310 );
1311 }
1312 if *mask & COUNTER_IDENT != 0 {
1313 assert_eq!(
1314 normalize_nested_map(counter_value),
1315 *expected,
1316 "{context}: counter identity mismatch"
1317 );
1318 }
1319 }
1320 AlgebraicResult::Element(_) => {}
1321 }
1322
1323 let actual = result.unwrap_or([self_value, counter_value], NestedSetMap::new());
1324 assert_eq!(
1325 normalize_nested_map(&actual),
1326 *expected,
1327 "{context}: materialized result"
1328 );
1329 }
1330
1331 fn mixed(seed: u64) -> u64 {
1332 let mut x = seed.wrapping_add(0x9e37_79b9_7f4a_7c15);
1333 x = (x ^ (x >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
1334 x = (x ^ (x >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
1335 x ^ (x >> 31)
1336 }
1337
1338 fn generated_set(seed: u64, salt: u64) -> HashSet<u16> {
1339 let mut set = HashSet::new();
1340 for value in 0..48 {
1341 if mixed(seed ^ salt ^ ((value as u64) << 32)) % 5 < 2 {
1342 set.insert(value);
1343 }
1344 }
1345 set
1346 }
1347
1348 fn generated_nested_map(seed: u64, salt: u64) -> NestedSetMap {
1349 let mut map = NestedSetMap::new();
1350 for key in 0..8 {
1351 let key_seed = mixed(seed ^ salt ^ ((key as u64) << 24));
1352 if key_seed % 4 == 0 {
1353 continue;
1354 }
1355
1356 let mut values = HashSet::new();
1357 for value in 0..16 {
1358 if mixed(key_seed ^ ((value as u64) << 32)) % 5 < 2 {
1359 values.insert(value);
1360 }
1361 }
1362 if key_seed % 31 == 0 {
1363 values.clear();
1364 }
1365 map.insert(key, values);
1366 }
1367 map
1368 }
1369
1370 fn nested_join(a: &NestedSetMap, b: &NestedSetMap) -> NestedSetMap {
1371 let mut result = normalize_nested_map(a);
1372 for (key, values) in b {
1373 if values.is_empty() {
1374 continue;
1375 }
1376 result
1377 .entry(*key)
1378 .or_default()
1379 .extend(values.iter().copied());
1380 }
1381 result
1382 }
1383
1384 fn nested_meet(a: &NestedSetMap, b: &NestedSetMap) -> NestedSetMap {
1385 let mut result = NestedSetMap::new();
1386 for (key, a_values) in a {
1387 let Some(b_values) = b.get(key) else {
1388 continue;
1389 };
1390 let values = a_values
1391 .intersection(b_values)
1392 .copied()
1393 .collect::<HashSet<_>>();
1394 if !values.is_empty() {
1395 result.insert(*key, values);
1396 }
1397 }
1398 result
1399 }
1400
1401 fn nested_subtract(a: &NestedSetMap, b: &NestedSetMap) -> NestedSetMap {
1402 let mut result = NestedSetMap::new();
1403 for (key, a_values) in a {
1404 let values = if let Some(b_values) = b.get(key) {
1405 a_values.difference(b_values).copied().collect()
1406 } else {
1407 a_values.clone()
1408 };
1409 if !values.is_empty() {
1410 result.insert(*key, values);
1411 }
1412 }
1413 result
1414 }
1415
1416 #[test]
1417 fn set_lattice_join_test1() {
1418 let mut a = HashSet::new();
1419 let mut b = HashSet::new();
1420
1421 let joined_result = a.pjoin(&b);
1423 assert_eq!(joined_result, AlgebraicResult::None);
1424
1425 a.insert("A");
1427 b.insert("B");
1428 let joined_result = a.pjoin(&b);
1429 assert!(joined_result.is_element());
1430 let joined = joined_result.unwrap([&a, &b]);
1431 assert_eq!(joined.len(), 2);
1432 assert!(joined.get("A").is_some());
1433 assert!(joined.get("B").is_some());
1434
1435 a.insert("C");
1437 let joined_result = a.pjoin(&b);
1438 assert!(joined_result.is_element());
1439 let joined = joined_result.unwrap([&a, &b]);
1440 assert_eq!(joined.len(), 3);
1441
1442 b.insert("D");
1444 b.insert("F");
1445 b.insert("H");
1446 let joined_result = a.pjoin(&b);
1447 assert!(joined_result.is_element());
1448 let joined = joined_result.unwrap([&a, &b]);
1449 assert_eq!(joined.len(), 6);
1450
1451 let joined_result = joined.pjoin(&b);
1453 assert_eq!(joined_result, AlgebraicResult::Identity(SELF_IDENT));
1454
1455 let joined_result = b.pjoin(&joined);
1457 assert_eq!(joined_result, AlgebraicResult::Identity(COUNTER_IDENT));
1458
1459 let joined_result = joined.pjoin(&joined);
1461 assert_eq!(joined_result, AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT));
1462 }
1463
1464 #[test]
1465 fn set_lattice_meet_test1() {
1466 let mut a = HashSet::new();
1467 let mut b = HashSet::new();
1468
1469 a.insert("A");
1471 b.insert("B");
1472 let meet_result = a.pmeet(&b);
1473 assert_eq!(meet_result, AlgebraicResult::None);
1474
1475 a.insert("A");
1477 a.insert("C");
1478 b.insert("B");
1479 b.insert("C");
1480 let meet_result = a.pmeet(&b);
1481 assert!(meet_result.is_element());
1482 let meet = meet_result.unwrap([&a, &b]);
1483 assert_eq!(meet.len(), 1);
1484 assert!(meet.get("A").is_none());
1485 assert!(meet.get("B").is_none());
1486 assert!(meet.get("C").is_some());
1487
1488 a.insert("D");
1490 let meet_result = a.pmeet(&b);
1491 assert!(meet_result.is_element());
1492 let meet = meet_result.unwrap([&a, &b]);
1493 assert_eq!(meet.len(), 1);
1494
1495 b.insert("D");
1497 b.insert("E");
1498 b.insert("F");
1499 let meet_result = a.pmeet(&b);
1500 assert!(meet_result.is_element());
1501 let meet = meet_result.unwrap([&a, &b]);
1502 assert_eq!(meet.len(), 2);
1503
1504 let meet_result = meet.pmeet(&b);
1506 assert_eq!(meet_result, AlgebraicResult::Identity(SELF_IDENT));
1507
1508 let meet_result = b.pmeet(&meet);
1510 assert_eq!(meet_result, AlgebraicResult::Identity(COUNTER_IDENT));
1511
1512 let meet_result = meet.pmeet(&meet);
1514 assert_eq!(meet_result, AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT));
1515 }
1516
1517 #[test]
1518 fn seeded_hash_set_operations_match_set_oracle() {
1519 #[cfg(miri)]
1520 const SEEDS: u64 = 1;
1521 #[cfg(not(miri))]
1522 const SEEDS: u64 = 256;
1523
1524 for seed in 0..SEEDS {
1525 let a = generated_set(seed, 0x243f_6a88_85a3_08d3);
1526 let b = generated_set(seed, 0x1319_8a2e_0370_7344);
1527
1528 let expected_join = a.union(&b).copied().collect::<HashSet<_>>();
1529 assert_binary_result(
1530 a.pjoin(&b),
1531 &a,
1532 &b,
1533 &expected_join,
1534 true,
1535 &format!("HashSet join seed {seed}"),
1536 );
1537 let mut join_in_place = a.clone();
1538 join_in_place.join_into(b.clone());
1539 assert_eq!(
1540 join_in_place, expected_join,
1541 "HashSet join_into seed {seed}"
1542 );
1543
1544 let expected_meet = a.intersection(&b).copied().collect::<HashSet<_>>();
1545 assert_binary_result(
1546 a.pmeet(&b),
1547 &a,
1548 &b,
1549 &expected_meet,
1550 true,
1551 &format!("HashSet meet seed {seed}"),
1552 );
1553 let expected_subtract = a.difference(&b).copied().collect::<HashSet<_>>();
1554 assert_binary_result(
1555 a.psubtract(&b),
1556 &a,
1557 &b,
1558 &expected_subtract,
1559 false,
1560 &format!("HashSet subtract seed {seed}"),
1561 );
1562 }
1563 }
1564
1565 #[test]
1566 fn seeded_hash_map_operations_match_nested_set_oracle() {
1567 #[cfg(miri)]
1568 const SEEDS: u64 = 1;
1569 #[cfg(not(miri))]
1570 const SEEDS: u64 = 256;
1571
1572 for seed in 0..SEEDS {
1573 let a = generated_nested_map(seed, 0x243f_6a88_85a3_08d3);
1574 let b = generated_nested_map(seed, 0x1319_8a2e_0370_7344);
1575 let c = generated_nested_map(seed, 0xa409_3822_299f_31d0);
1576
1577 let expected_join = nested_join(&a, &b);
1578 assert_nested_result(
1579 a.pjoin(&b),
1580 &a,
1581 &b,
1582 &expected_join,
1583 true,
1584 &format!("HashMap join seed {seed}"),
1585 );
1586 let mut join_in_place = a.clone();
1587 join_in_place.join_into(b.clone());
1588 assert_eq!(
1589 normalize_nested_map(&join_in_place),
1590 expected_join,
1591 "HashMap join_into seed {seed}"
1592 );
1593
1594 let expected_meet = nested_meet(&a, &b);
1595 assert_nested_result(
1596 a.pmeet(&b),
1597 &a,
1598 &b,
1599 &expected_meet,
1600 true,
1601 &format!("HashMap meet seed {seed}"),
1602 );
1603 let expected_subtract = nested_subtract(&a, &b);
1604 assert_nested_result(
1605 a.psubtract(&b),
1606 &a,
1607 &b,
1608 &expected_subtract,
1609 false,
1610 &format!("HashMap subtract seed {seed}"),
1611 );
1612
1613 let ab_join = a.pjoin(&b).unwrap_or([&a, &b], NestedSetMap::new());
1614 let expected_chain = nested_subtract(&nested_join(&a, &b), &c);
1615 assert_nested_result(
1616 ab_join.psubtract(&c),
1617 &ab_join,
1618 &c,
1619 &expected_chain,
1620 false,
1621 &format!("HashMap chained join/subtract seed {seed}"),
1622 );
1623 }
1624 }
1625
1626 #[derive(Clone, Debug)]
1628 struct Map<'a>(HashMap::<&'a str, HashMap<&'a str, ()>>);impl<'a> SetLattice for Map<'a> {
1630 type K = &'a str;
1631 type V = HashMap<&'a str, ()>; type Iter<'it> = std::collections::hash_map::Iter<'it, Self::K, Self::V> where Self: 'it, Self::K: 'it, Self::V: 'it;
1633 fn with_capacity(capacity: usize) -> Self { Map(HashMap::with_capacity(capacity)) }
1634 fn len(&self) -> usize { self.0.len() }
1635 fn is_empty(&self) -> bool { self.0.is_empty() }
1636 fn contains_key(&self, key: &Self::K) -> bool { self.0.contains_key(key) }
1637 fn insert(&mut self, key: Self::K, val: Self::V) { self.0.insert(key, val); }
1638 fn get(&self, key: &Self::K) -> Option<&Self::V> { self.0.get(key) }
1639 fn replace(&mut self, key: &Self::K, val: Self::V) { self.0.replace(key, val) }
1640 fn remove(&mut self, key: &Self::K) { self.0.remove(key); }
1641 fn iter<'it>(&'it self) -> Self::Iter<'it> { self.0.iter() }
1642 fn shrink_to_fit(&mut self) { self.0.shrink_to_fit(); }
1643 }
1644 set_lattice!(Map<'a>);
1645
1646 #[test]
1647 fn set_lattice_join_test2() {
1652 let mut a = Map::with_capacity(1);
1653 let mut b = Map::with_capacity(1);
1654
1655 let mut inner_map_1 = HashMap::with_capacity(1);
1657 inner_map_1.insert("1", ());
1658 a.0.insert("A", inner_map_1.clone());
1659 b.0.insert("B", inner_map_1);
1660 a.0.insert("C", HashMap::new());
1661 b.0.insert("C", HashMap::new());
1662 let joined_result = a.pjoin(&b);
1663 assert!(joined_result.is_element());
1664 let joined = joined_result.unwrap([&a, &b]);
1665 assert_eq!(joined.len(), 2);
1666 assert!(joined.get(&"A").is_some());
1667 assert!(joined.get(&"B").is_some());
1668 assert!(joined.get(&"C").is_none()); a.0.remove("C");
1670 b.0.remove("C");
1671
1672 let mut inner_map_2 = HashMap::with_capacity(1);
1674 inner_map_2.insert("2", ());
1675 b.0.remove("B");
1676 b.0.insert("A", inner_map_2);
1677 let joined_result = a.pjoin(&b);
1678 assert!(joined_result.is_element());
1679 let joined = joined_result.unwrap([&a, &b]);
1680 assert_eq!(joined.len(), 1);
1681 let joined_inner = joined.get(&"A").unwrap();
1682 assert_eq!(joined_inner.len(), 2);
1683 assert!(joined_inner.get(&"1").is_some());
1684 assert!(joined_inner.get(&"2").is_some());
1685
1686 let joined_result = joined.pjoin(&a);
1688 assert_eq!(joined_result.identity_mask().unwrap(), SELF_IDENT);
1689 let joined_result = b.pjoin(&joined);
1690 assert_eq!(joined_result.identity_mask().unwrap(), COUNTER_IDENT);
1691 }
1692
1693 #[test]
1694 fn set_lattice_meet_test2() {
1696 let mut a = Map::with_capacity(1);
1697 let mut b = Map::with_capacity(1);
1698
1699 let mut inner_map_a = HashMap::new();
1700 inner_map_a.insert("a", ());
1701 let mut inner_map_b = HashMap::new();
1702 inner_map_b.insert("b", ());
1703 let mut inner_map_c = HashMap::new();
1704 inner_map_c.insert("c", ());
1705
1706 a.0.insert("A", inner_map_a.clone());
1708 a.0.insert("C", inner_map_c.clone());
1709 b.0.insert("B", inner_map_b.clone());
1710 b.0.insert("C", inner_map_c.clone());
1711 let meet_result = a.pmeet(&b);
1712 assert!(meet_result.is_element());
1713 let meet = meet_result.unwrap([&a, &b]);
1714 assert_eq!(meet.len(), 1);
1715 assert!(meet.get(&"A").is_none());
1716 assert!(meet.get(&"B").is_none());
1717 assert!(meet.get(&"C").is_some());
1718
1719 let mut inner_map_1 = HashMap::with_capacity(1);
1721 inner_map_1.insert("1", ());
1722 a.0.insert("A", inner_map_1);
1723 let mut inner_map_2 = HashMap::with_capacity(1);
1724 inner_map_2.insert("2", ());
1725 b.0.remove("B");
1726 b.0.remove("C");
1727 b.0.insert("A", inner_map_2.clone());
1728 let meet_result = a.pmeet(&b);
1729 assert!(meet_result.is_none());
1730
1731 inner_map_2.insert("1", ());
1733 b.0.insert("A", inner_map_2);
1734 let meet_result = a.pmeet(&b);
1735 assert!(meet_result.is_element());
1736 let meet = meet_result.unwrap([&a, &b]);
1737 assert_eq!(meet.len(), 1);
1738 let meet_inner = meet.get(&"A").unwrap();
1739 assert_eq!(meet_inner.len(), 1);
1740 assert!(meet_inner.get(&"1").is_some());
1741 assert!(meet_inner.get(&"2").is_none());
1742
1743 let meet_result = meet.pmeet(&a);
1745 assert_eq!(meet_result.identity_mask().unwrap(), SELF_IDENT);
1746 let meet_result = b.pmeet(&meet);
1747 assert_eq!(meet_result.identity_mask().unwrap(), COUNTER_IDENT);
1748 }
1749}
1750