Skip to main content

pathmap/
ring.rs

1
2use std::collections::{HashMap, HashSet};
3use std::hash::Hash;
4
5/// The result of an algebraic operation on elements in a partial lattice
6///
7/// NOTE: For some operations, it is conceptually valid for both `Identity` and `None` results to be
8/// simultaneously appropriate, for example `None.pmeet(Some)`. In these situations, `None` should take precedence
9/// over `Identity`, but either of the results can be considered correct so your code must behave correctly in
10/// either case.
11///
12/// NOTE 2: The following conditions for the Identity bitmask must be respected or the implementation may panic or
13/// produce logically invalid results.
14/// - The bit mask must be non-zero
15/// - Bits beyond the number of operation arguments must not be set.  e.g. an arity-2 operation may only set bit 0
16///     and bit 1, but never any additional bits.
17/// - Setting two or more bits simultaneously asserts the arguments are identities of each other, so this must be
18///     true in fact.
19/// - The inverse of the above does not hold.  E.g. if multiple bits are not set, it may **not** be assumed that 
20///     the arguments are not identities of each other.
21/// - Non-commutative operations, such as [DistributiveLattice::psubtract], must never set bits beyond bit 0 ([SELF_IDENT])
22#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
23pub enum AlgebraicResult<V> {
24    /// A result indicating the input values perfectly annhilate and the output should be removed and discarded
25    #[default]
26    None,
27    /// A result indicating the output element is identical to the input element(s) identified by the bit mask
28    ///
29    /// NOTE: The constants [SELF_IDENT] and [COUNTER_IDENT] can be used as conveniences when specifying the bitmask.
30    Identity(u64),
31    /// A new result element
32    Element(V),
33}
34
35/// A bitmask value to `or` into the [AlgebraicResult::Identity] argument to specify the result is the identity of `self`
36pub const SELF_IDENT: u64 = 0x1;
37
38/// A bitmask value to `or` into the [AlgebraicResult::Identity] argument to specify the result is the identity of `other`
39pub const COUNTER_IDENT: u64 = 0x2;
40
41impl<V> AlgebraicResult<V> {
42    /// Returns `true` is `self` is [AlgebraicResult::None], otherwise returns `false`
43    #[inline]
44    pub fn is_none(&self) -> bool {
45        matches!(self, AlgebraicResult::None)
46    }
47    /// Returns `true` is `self` is [AlgebraicResult::Identity], otherwise returns `false`
48    #[inline]
49    pub fn is_identity(&self) -> bool {
50        matches!(self, AlgebraicResult::Identity(_))
51    }
52    /// Returns `true` is `self` is [AlgebraicResult::Element], otherwise returns `false`
53    #[inline]
54    pub fn is_element(&self) -> bool {
55        matches!(self, AlgebraicResult::Element(_))
56    }
57    /// Returns the identity mask from a [AlgebraicResult::Identity], otherwise returns `None`
58    #[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    /// Swaps the mask bits in an [AlgebraicResult::Identity] result, for an arity-2 operation, such that
67    /// the [SELF_IDENT] bit becomes the [COUNTER_IDENT] bit, and vise-versa
68    ///
69    /// Removes identity mask bits higher than 2
70    #[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    /// Maps a `AlgebraicResult<V>` to `AlgebraicResult<U>` by applying a function to a contained value, if
82    /// self is `AlgebraicResult::Element(V)`.  Otherwise returns the value of `self`
83    #[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    /// Converts from `&AlgebraicResult<V>` to `AlgebraicResult<&V>`
94    #[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    /// Returns an option containing the `Element` value, substituting the result of the `ident_f` closure
103    /// if `self` is [Identity](AlgebraicResult::Identity)
104    ///
105    /// The index of the first identity argument is passed to the closure.  E.g. `0` for self, etc.
106    #[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    /// Returns an option containing the `Element` value, substituting the result from the corresponding
117    /// index in the `idents` table if `self` is [Identity](AlgebraicResult::Identity)
118    #[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    /// Returns the contained `Element` value or an identity value from the `idents` table.  Panics if `self`
133    /// is [AlgebraicResult::None]
134    #[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    /// Returns the contained `Element` value or runs one of the provided closures
148    ///
149    /// This is the most straightforward way to turn a partial lattice result into a complete lattice element
150    #[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    /// Returns the contained `Element` value or one of the provided default values
163    #[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    /// Merges two `AlgebraicResult`s into a combined `AlgebraicResult<U>`.  This method is useful to compose a
177    /// result for an operation on whole type arguments, from the results of separate operations on each field
178    /// of the arguments.
179    ///
180    /// NOTE: Take care when implementing the `meet` operation across heterogeneous items (e.g. abstracted sets),
181    /// because one set may be a superset of the other.  simply merging the `AlgebraicResult`s from individual
182    /// `meet` operations on the overlapping elements will lead to a false `Identity` result for one of the sets.
183    ///
184    /// ```
185    /// use pathmap::ring::{Lattice, AlgebraicResult};
186    /// 
187    /// struct Composed {
188    ///     field0: bool,
189    ///     field1: bool,
190    /// }
191    ///
192    /// fn pjoin(a: &Composed, b: &Composed) -> AlgebraicResult<Composed> {
193    ///     let result0 = a.field0.pjoin(&b.field0);
194    ///     let result1 = a.field1.pjoin(&b.field1);
195    ///     result0.merge(result1, |which_arg| {
196    ///         match which_arg {
197    ///             0 => Some(a.field0),
198    ///             1 => Some(b.field0),
199    ///             _ => unreachable!()
200    ///         }
201    ///     }, |which_arg| {
202    ///         match which_arg {
203    ///             0 => Some(a.field1),
204    ///             1 => Some(b.field1),
205    ///             _ => unreachable!()
206    ///         }
207    ///     }, |field0, field1| {
208    ///         AlgebraicResult::Element(Composed{
209    ///             field0: field0.unwrap(),
210    ///             field1: field1.unwrap()
211    ///         })
212    ///     })
213    /// }
214    /// ```
215    #[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    /// Creates a new `AlgebraicResult` from an [AlgebraicStatus], and a method to create the element value
278    #[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    /// Returns an [AlgebraicStatus] associated with the `AlgebraicResult`
289    #[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    /// Flattens a nested `Option<V>` inside an `AlgebraicResult<V>`, converting `AlgebraicResult::Element(None)`
307    /// into `AlgebraicResult::None`
308    #[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/// Status result that is returned from an in-place algebraic operation (a method that takes `&mut self`)
324///
325/// NOTE: `AlgebraicStatus` values are ordered, with `Element` being the lowest value and `None` being the
326/// highest.  Higher values make stronger guarantees about the results of the operation, but a lower values
327/// are still correct and your code must behave appropriately.
328///
329/// For example, for example `Empty.join(Empty)` would result in Empty, but also leave the original value
330/// unmodified, therefore both `Identity` and `None` are conceptually valid in that case.
331///
332/// In general, `AlgebraicStatus` return values are a valid signal for loop termination, but should not be
333/// strictly relied upon for other kinds of branching.  For example, `Element` might be returned by
334/// [ZipperWriting::join](crate::zipper::ZipperWriting::join) instead of `Identity` if the internal representation was changed by the method,
335/// however the next call to `join` ought to return `Identity` if nothing new is added.
336///
337/// This type mirrors [AlgebraicResult]
338#[derive(Clone, Copy, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
339pub enum AlgebraicStatus {
340    /// A result indicating `self` contains the operation's output
341    #[default]
342    Element,
343    /// A result indicating `self` was unmodified by the operation
344    Identity,
345    /// A result indicating `self` was completely annhilated and is now empty
346    None,
347}
348
349impl AlgebraicStatus {
350    /// Returns `true` if the status is [AlgebraicStatus::None], otherwise returns `false`
351    #[inline]
352    pub fn is_none(&self) -> bool {
353        matches!(self, Self::None)
354    }
355    /// Returns `true` if the status is [AlgebraicStatus::Identity], otherwise returns `false`
356    #[inline]
357    pub fn is_identity(&self) -> bool {
358        matches!(self, Self::Identity)
359    }
360    /// Returns `true` if the status is [AlgebraicStatus::Element], otherwise returns `false`
361    #[inline]
362    pub fn is_element(&self) -> bool {
363        matches!(self, Self::Element)
364    }
365    /// Merges two `AlgebraicStatus` values into one.  Useful when composing the status from operations on individual fields
366    ///
367    /// The `self_none` and `b_none` args indicate whether the `self` and `b` args, respectively, correspond to `None`
368    /// values prior to the operation.  Pass `true` if the existing values were already `none` or `false` if they
369    /// were made `None` by the operation.  For operations that cannot convert a non-`None` value to `None`,
370    /// (such as join) it is safe to pass (`true`, `true`) regardless of the actual original values.
371    ///
372    /// See [AlgebraicResult::merge].
373    #[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/// Internal result type that can be down-converted to an [AlgebraicResult], but carries additional information
414#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
415pub(crate) struct FatAlgebraicResult<V> {
416    /// An identity mask that maps to the [AlgebraicResult::Identity] value, or 0 if the result is not an identity
417    pub identity_mask: u64,
418    /// Carries the element value, irrespective of the identity information.  It is the discretion of the code using
419    /// this struct as to whether or not to populate this field in the case of an identity result
420    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    /// Converts an [AlgebraicResult] into a `FatAlgebraicResult`, assuming the source `result` was the
429    /// output of a binary operation (two arguments).
430    #[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    /// Maps a `FatAlgebraicResult<V>` to `FatAlgebraicResult<U>` by applying a function to a contained value
449    #[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    /// The result of an operation between non-none arguments that results in None
459    #[inline(always)]
460    pub(crate) const fn none() -> Self {
461        Self {identity_mask: 0, element: None}
462    }
463    /// The result of an operation that generated a brand new result
464    #[inline(always)]
465    pub(crate) fn element(e: V) -> Self {
466        Self {identity_mask: 0, element: Some(e)}
467    }
468    //GOAT, currently unused although implemented and working
469    // /// Merges two `FatAlgebraicResult<V>`s into an `AlgebraicResult<U>`.  See [AlgebraicResult::merge]
470    // #[inline]
471    // pub fn merge_and_convert<U, F>(self, other: Self, merge_f: F) -> AlgebraicResult<U>
472    //     where F: FnOnce(Option<V>, Option<V>) -> AlgebraicResult<U>,
473    // {
474    //     if self.element.is_none() && other.element.is_none() {
475    //         return AlgebraicResult::None
476    //     }
477    //     let combined_mask = self.identity_mask & other.identity_mask;
478    //     if combined_mask > 0 {
479    //         return AlgebraicResult::Identity(combined_mask)
480    //     }
481    //     merge_f(self.element, other.element)
482    // }
483    //GOAT, currently unused, but fully implemented and working
484    // /// Intersects arg with the contents of self, and sets the arg_idx bit in the case of an identity result
485    // pub fn meet(self, arg: &V, arg_idx: usize) -> Self where V: Lattice + Clone {
486    //     match self.element {
487    //         None => {
488    //             debug_assert_eq!(self.identity_mask, 0);
489    //             Self::new(self.identity_mask, None)
490    //         },
491    //         Some(self_element) => match self_element.pmeet(arg) {
492    //             AlgebraicResult::None => Self::none(),
493    //             AlgebraicResult::Element(e) => Self::element(e),
494    //             AlgebraicResult::Identity(mask) => {
495    //                 if mask & SELF_IDENT > 0 {
496    //                     let new_mask = self.identity_mask | ((mask & COUNTER_IDENT) << (arg_idx-1));
497    //                     Self::new(new_mask, Some(self_element))
498    //                 } else {
499    //                     debug_assert!(mask & COUNTER_IDENT > 0);
500    //                     let new_mask = (mask & COUNTER_IDENT) << (arg_idx-1);
501    //                     Self::new(new_mask, Some(arg.clone()))
502    //                 }
503    //             }
504    //         }
505    //     }
506    // }
507    /// Unions arg with the contents of self, and sets the arg_idx bit in the case of an identity result
508    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
531/// Implements basic algebraic behavior (union & intersection) for a type
532pub trait Lattice {
533    /// Indicates whether the lattice operations are idempotent for the purpose of
534    /// evaluating algebraic operations on shared subtries.
535    ///
536    /// If `IDEMPOTENT = true` the implementor is asserting that:
537    /// `pjoin(self) -> AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT)`,
538    /// `join_into(self) -> AlgebraicStatus::Identity`,
539    /// `pmeet(self) -> AlgebraicResult::Identity(SELF_IDENT | COUNTER_IDENT)`,
540    ///
541    /// WARNING! This constant is currently informational only.  The node-level and zipper
542    /// algebra implementations do not yet consult it, so changing it has no effect
543    /// on their behavior.  It is planned for gating implementation shortcuts in the future
544    const IDEMPOTENT: bool = true;
545
546    /// Implements the union operation between two instances of a type in a partial lattice, resulting in
547    /// the creation of a new result instance
548    fn pjoin(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
549
550    /// Implements the union operation between two instances of a type, consuming the `other` input operand,
551    /// and modifying `self` to become the joined type
552    fn join_into(&mut self, other: Self) -> AlgebraicStatus where Self: Sized {
553        let result = self.pjoin(&other);
554        //NOTE: pedantically, the `default_f` ought to assign the `&mut s` to `Self::bottom()`, however there is
555        // no way for a join to get to an empty result except by starting with an empty result, so leaving the
556        // arg alone is functionally the same.
557        in_place_default_impl(result, self, other, |_s| {}, |e| e)
558    }
559
560    /// Implements the intersection operation between two instances of a type in a partial lattice
561    fn pmeet(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
562
563    //GOAT, we want a meet_into, that has the same semantics as join_into, e.g. mutating in-place.  I
564    // don't think there is any benefit to consuming `other`, however, so we can still take `other: &Self`
565
566    //GOAT, this should be temporarily deprecated until we work out the correct function prototype
567    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
580/// Internal function to implement the default behavior of `join_into`, `meet_into`, etc. in terms of `pjoin`, `pmeet`, etc.
581fn 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
606/// Implements algebraic behavior on a reference to a [Lattice] type, such as a smart pointer that can't
607/// hold ownership
608pub 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
614/// Implements subtract behavior for a type
615pub trait DistributiveLattice {
616    /// Indicates whether the subtraction operation is idempotent for the purpose of
617    /// evaluating algebraic operations on shared subtries.
618    ///
619    /// If `IDEMPOTENT = true` the implementor is asserting that:
620    /// `psubtract(self) -> AlgebraicResult::None`,
621    ///
622    /// WARNING! This constant is currently informational only.  The node-level and zipper
623    /// algebra implementations do not yet consult it, so changing it has no effect
624    /// on their behavior.  It is planned for gating implementation shortcuts in the future
625    const IDEMPOTENT: bool = true;
626
627    /// Implements the partial subtract operation
628    fn psubtract(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
629
630    //GOAT, We want a psubtract_from (subtract_into??) that operates on a `&mut self`
631}
632
633/// Implements subtract behavior on a reference to a [DistributiveLattice] type
634pub trait DistributiveLatticeRef {
635    /// The type that is referenced
636    type T;
637
638    /// Implements the partial subtract operation on the referenced values, resulting in the potential
639    /// creation of a new value
640    fn psubtract(&self, other: &Self) -> AlgebraicResult<Self::T>;
641}
642
643// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
644// Private traits
645// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
646
647/// Used to implement restrict operation.  TODO, come up with a better math-explanation about how this
648/// is a quantale
649///
650/// Currently this trait isn't exposed because it's unclear what we degrees of felxibility really want
651/// from restrict, and what performance we are willing to trade to get them
652pub(crate) trait Quantale {
653    /// TODO: Document this (currently internal-only)
654    fn prestrict(&self, other: &Self) -> AlgebraicResult<Self> where Self: Sized;
655}
656
657/// An internal mirror of the [Lattice] trait, where the `self` and `other` types don't need to be
658/// exactly the same type, in order to permit blanket implementations
659pub(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        //NOTE: See comment on [Lattice::join_into] default impl, regarding using `Self::bottom` for `default_f`
664        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 join_all(xs: &[&Self]) -> Self where Self: Sized; //HeteroLattice will entirely disappear with the policy refactor, so it's not worth worying about this anymore
668    fn convert(other: OtherT) -> Self;
669}
670
671/// An internal mirror of the [DistributiveLattice] trait, where the `self` and `other` types
672/// don't need to be exactly the same type, to facilitate blanket impls
673pub(crate) trait HeteroDistributiveLattice<OtherT> {
674    fn psubtract(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
675}
676
677/// Internal mirror for [Quantale] See discussion on [HeteroLattice].
678pub(crate) trait HeteroQuantale<OtherT> {
679    fn prestrict(&self, other: &OtherT) -> AlgebraicResult<Self> where Self: Sized;
680}
681
682// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
683// impls on primitive & std types
684// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
685
686// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
687// =-*   `Option<V>`                                                                                  *-=
688
689impl<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
757// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
758// =-*   `Option<&V>`                                                                                 *-=
759
760impl<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
802// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
803// =-*   `Box<V>`                                                                                     *-=
804
805impl <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
820// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
821// =-*   `&V`                                                                                         *-=
822
823impl <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
840// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
841// =-*  `()`, aka unit                                                                                *-=
842
843impl 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
854//GOAT trash
855impl 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
860//GOAT trash
861impl 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
866//GOAT trash
867impl 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
874//GOAT trash
875impl 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
880//GOAT trash
881impl 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
886//GOAT trash
887impl 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
894//GOAT trash
895impl 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
900// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
901// =-*   `bool`                                                                                       *-=
902// NOTE: There is a default impl for `bool` and not for other primitives because there are fewer states,
903// and therefore fewer meanings for a `bool`.
904
905impl 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) //result is true
919        } 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) //result is false
926        } else {
927            AlgebraicResult::Identity(SELF_IDENT)
928        }
929    }
930}
931
932// =-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-==-**-=
933// =-*   `SetLattice<K>`, including `HashMap<K, V>`, `HashSet<K>`, etc.                               *-=
934
935/// Implemented on an unordered set type, (e.g. [HashMap], [HashSet], etc.) to get automatic implementations
936/// of the [Lattice] and [DistributiveLattice] traits on the set type with the [set_lattice](crate::set_lattice) and
937/// [set_dist_lattice](crate::set_dist_lattice) macros
938///
939/// BEWARE: The `Lattice` and `DistributiveLattice` impls that are derived from the `SetLattice` impl treat
940/// an empty set as equivalent to a nonexistent set.  Therefore, if your arguments contain empty sets, those
941/// sets may or may not be collapsed.  Your code must be aware of this.
942pub trait SetLattice {
943    /// A key type that uniquely identifies an element within the set
944    type K: Clone + Eq;
945
946    /// A payload value type that can be associated with a key in the set
947    type V: Clone;
948
949    /// An [Iterator] type over the contents of the set
950    type Iter<'a>: Iterator<Item=(&'a Self::K, &'a Self::V)> where Self: 'a, Self::V: 'a, Self::K: 'a;
951
952    /// Returns a new empty set with the specified capacity preallocated
953    fn with_capacity(capacity: usize) -> Self;
954
955    /// Returns the number of items in the set
956    fn len(&self) -> usize;
957
958    /// Returns `true` is the set is empty (`len() == 0`), otherwise returns `false`
959    fn is_empty(&self) -> bool;
960
961    /// Returns `true` if the set contains the key, otherwise `false`
962    fn contains_key(&self, key: &Self::K) -> bool;
963
964    /// Inserts a new (key, value) pair, replacing the item at `key` if it already existed
965    fn insert(&mut self, key: Self::K, val: Self::V);
966
967    /// Removes the element at `key` from the set
968    fn remove(&mut self, key: &Self::K);
969
970    /// Returns a reference to the element in the set, or None if the element is not contained within the set
971    fn get(&self, key: &Self::K) -> Option<&Self::V>;
972
973    /// Replaces the element at `key` with the new value `val`.  Will never be called for a non-existent key
974    fn replace(&mut self, key: &Self::K, val: Self::V);
975
976    /// Return a `Self::Iter` in order to iterate the set
977    fn iter<'a>(&'a self) -> Self::Iter<'a>;
978
979    /// An opportunity to free unused space in the set container, if appropriate
980    fn shrink_to_fit(&mut self);
981}
982
983/// A macro to emit the [Lattice] implementation for a type that implements [SetLattice]
984#[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                        // A key in both sets
997                        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                        // A key in self, but not in other
1003                        $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                        // A key in other, but not in self
1010                        $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/// Internal function to integrate an `AlgebraicResult` from an element in a set into the set's own overall result
1045#[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/// Internal function to make an `AlgebraicResult` from a new result set and flags
1084#[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/// A macro to emit the [DistributiveLattice] implementation for a type that implements [SetLattice]
1113#[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                //Two code paths, so that we only iterate over the smaller set
1121                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/// Internal function to subtract set elements and integrate the results
1148#[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)); /* a noop since we can assume the key already exists */ }
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        //Test None result
1422        let joined_result = a.pjoin(&b);
1423        assert_eq!(joined_result, AlgebraicResult::None);
1424
1425        //Straightforward join
1426        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        //Make "self" contain more entries
1436        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        //Make "other" contain more entries
1443        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        //Test identity with self arg
1452        let joined_result = joined.pjoin(&b);
1453        assert_eq!(joined_result, AlgebraicResult::Identity(SELF_IDENT));
1454
1455        //Test identity with other arg
1456        let joined_result = b.pjoin(&joined);
1457        assert_eq!(joined_result, AlgebraicResult::Identity(COUNTER_IDENT));
1458
1459        //Test mutual identity
1460        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        //Test disjoint result
1470        a.insert("A");
1471        b.insert("B");
1472        let meet_result = a.pmeet(&b);
1473        assert_eq!(meet_result, AlgebraicResult::None);
1474
1475        //Straightforward meet
1476        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        //Make "self" contain more entries
1489        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        //Make "other" contain more entries
1496        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        //Test identity with self arg
1505        let meet_result = meet.pmeet(&b);
1506        assert_eq!(meet_result, AlgebraicResult::Identity(SELF_IDENT));
1507
1508        //Test identity with other arg
1509        let meet_result = b.pmeet(&meet);
1510        assert_eq!(meet_result, AlgebraicResult::Identity(COUNTER_IDENT));
1511
1512        //Test mutual identity
1513        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    /// Used in [set_lattice_join_test2] and [set_lattice_meet_test2]
1627    #[derive(Clone, Debug)]
1628    struct Map<'a>(HashMap::<&'a str, HashMap<&'a str, ()>>);// TODO, should be struct Map<'a>(HashMap::<&'a str, Map<'a>>); see comment above about chalk
1629    impl<'a> SetLattice for Map<'a> {
1630        type K = &'a str;
1631        type V = HashMap<&'a str, ()>; //Option<Box<Map<'a>>>; TODO, see comment above about chalk
1632        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    /// Tests a HashMap containing more HashMaps
1648    //TODO: When the [chalk trait solver](https://github.com/rust-lang/chalk) lands in stable rust, it would be nice
1649    // to promote this test to sample code and implement an arbitrarily deep recursive structure.  But currently
1650    // that's not worth the complexity due to limits in the stable rust trait sovler.
1651    fn set_lattice_join_test2() {
1652        let mut a = Map::with_capacity(1);
1653        let mut b = Map::with_capacity(1);
1654
1655        // Top level join
1656        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()); //Empty sub-sets should not be merged
1669        a.0.remove("C");
1670        b.0.remove("C");
1671
1672        // Two level join, results should be Element even though the key existed in both args, because the values joined
1673        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        // Redoing the join should yield Identity
1687        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    /// Tests a HashMap containing more HashMaps.  See comments on [set_lattice_join_test2]
1695    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        // One level meet
1707        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        // Two level meet, results should be None even though the key existed in both args, because the inner values don't overlap
1720        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        // Two level meet, now should return Element, because the values have some overlap
1732        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        // Redoing the meet should yield Identity
1744        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//GOAT, do an impl of SetLattice for Vec as an indexed set
1751
1752
1753//GOAT, LatticeCounter and LatticeBitfield should be traits.
1754// BitfieldLattice should be implemented on bool
1755// Make monad types that can implement these traits on all prim types
1756// Make a "convertable_to" trait across all prim types
1757
1758// GOAT, TEST TODO:  A fuzz test for some of the algebraic operations (join, meet, subtract) across all
1759// different path configurations and operation orderings.
1760
1761// Envisioned Implementation:
1762// 1. Create `set_a` of N values (e.g. integers 0..100) and assign a pseudorandom path to each element
1763// 2. Create `set_b` of M values and assign a different pseudorandom path to each element
1764// 3. Compose pseudorandom subsets of `set_a` and `set_b` and put them into HashSets
1765// 4. Put corresponding concatenated paths (Cartesian product) into PathMaps.
1766// 5. Select an operation to perform, and do the same operation to both the HashSets contining simple
1767// indices and to the PathMaps.  And validate the results match
1768// 6. Loop back to 3, continuing to choose additional operations to perform.
1769
1770// The reason behind the cartesian product (concatenated paths) is because the chances of getting overlap
1771// beyond the first couple bytes of a random path are very slim.  The Cartesian product appraoch
1772// means we are likely to get large common prefixes followed by splits deep in the trie, which will
1773// exercise the code more thoroughly.