1use std::{
2 collections::{ HashMap, BTreeMap, hash_map, }, vec,
3};
4use core::fmt::Debug;
5
6use hashed_type_def::{ HashedTypeDef, add_hash_fnv1a, };
7use crate::types::{ u128slx, f64slx, SlxInto, IntoSlx, };
11
12
13#[cfg(feature = "serde")] use serde::{Serialize as SerdeSerialize, Deserialize as SerdeDeserialize};
14#[cfg(feature = "rkyv")] use rkyv::{Archive, Serialize as RkyvSerialize, Deserialize as RkyvDeserialize};
15use rand::prelude::*;
32
33use crate::{
34 traits::{ Lattice, ComplementedLattice, IterableLattice, LatticeWithLeaves },
35 structs::SafeElement,
36};
37
38const DEFAULT_MAX_ITER_LEN : usize = 1024;
39
40#[derive(Clone, Debug, HashedTypeDef)]
41#[cfg_attr(feature = "rkyv", derive(Archive,RkyvSerialize,RkyvDeserialize))]
42pub struct Powerset {
44 max_iter_len: u128slx,
45 top: SafeElement<u128slx>,
46 bottom: SafeElement<u128slx>,
47 tags: BTreeMap<u128slx,String,>,
48 untags: HashMap<String,u128slx,>,
49 leaves: Vec<u128slx>,
50 weighted_leaves: HashMap<u128slx,f64slx>,
51 bottom_to_top: Option<Vec<u128slx>>,
52}
53
54#[cfg(feature = "serde")] mod serding {
56 use super::{
60 Powerset as SerdingPowerset, SerdeSerialize, SerdeDeserialize, SlxInto,
61 };
62 #[derive(SerdeSerialize,SerdeDeserialize)]
63 pub struct Powerset {
64 nb_leaves: usize, max_iter_len: usize,
65 }
66 impl<'de> SerdeDeserialize<'de> for SerdingPowerset {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where D: serde::Deserializer<'de> {
69 let Powerset { nb_leaves, max_iter_len } = Powerset::deserialize(deserializer)?;
70 match SerdingPowerset::new(nb_leaves, max_iter_len) {
71 Ok(p) => Ok(p),
72 Err(_) => Ok(Self::empty()),
73 }
74 }
75 }
76 impl SerdeSerialize for SerdingPowerset {
77 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
78 where S: serde::Serializer {
79 let SerdingPowerset { max_iter_len, leaves, .. } = self;
80 let nb_leaves = leaves.len();
81 let max_iter_len = (*max_iter_len).unslx() as usize;
82 let powerset = Powerset { nb_leaves, max_iter_len };
83 powerset.serialize(serializer)
84 }
85 }
86}
87
88impl Powerset {
89 pub fn new(nb_leaves: usize, max_iter_len: usize,) -> Result<Powerset,String> {
95 let leaves_names = (0..nb_leaves).map(|u| format!("U{u}")).collect::<Vec<_>>();
96 Self::new_with_label(&leaves_names, max_iter_len)
97 }
98 pub fn new_with_label(leaves_names: &[String], max_iter_len: usize,) -> Result<Powerset,String> {
105 let nb_leaves = leaves_names.len();
106 let s = std::mem::size_of::<u128>() << 3; let top = match nb_leaves { m if m > s => Err(format!("Number of leaves cannot excess {s}")), m if m == s => Ok(u128::MAX.slx()),
110 m => Ok(((1u128 << m)-1u128).slx()),
111 };
112 top.map(|top| {
113 let leaves: Vec<u128slx> = (0..nb_leaves).map(|rank|(1u128 << rank).slx()).collect::<Vec<_>>();
114 let (tags,untags) = leaves_names.iter().enumerate()
115 .map(|(rank,label)| ((leaves[rank],label.clone()),(label.clone(),leaves[rank])))
116 .unzip::<_,_,BTreeMap<_,_>,HashMap<_,_>>();
117 let unif: f64slx = (nb_leaves as f64).recip().slx();
118 let weighted_leaves = leaves.iter().map(|k| (*k,unif)).collect::<HashMap<_,_>>();
119 let mut sorted_tags = tags.iter().map(
120 |(u,s)| ((*u).unslx(),s)
121 ).collect::<Vec<_>>(); sorted_tags.sort_by_key(|(k,_)| *k);
122 let mut sorted_leaves = weighted_leaves.iter().map(
123 |(u,w)| ((*u).unslx(),(*w).unslx())
124 ).collect::<Vec<_>>(); sorted_leaves.sort_by_key(|(k,_)| *k);
125 let lattice_hash = {
126 let mut lattice_hash = Powerset::TYPE_HASH_NATIVE;
127 lattice_hash = add_hash_fnv1a(&nb_leaves.to_le_bytes(), lattice_hash);
128 for (u,s) in &sorted_tags {
129 lattice_hash = add_hash_fnv1a(&(*u).to_le_bytes(), lattice_hash);
130 lattice_hash = add_hash_fnv1a(s.as_bytes(), lattice_hash);
131 }
132 for (u,w) in &sorted_leaves {
133 lattice_hash = add_hash_fnv1a(&(*u).to_le_bytes(), lattice_hash);
134 lattice_hash = add_hash_fnv1a(&(*w).to_le_bytes(), lattice_hash);
135 }
136 lattice_hash.slx()
137 };
138 let max_iter_len = (max_iter_len as u128).slx();
139 let bottom = SafeElement { code: 0u128.slx(), lattice_hash, };
140 let top = SafeElement { code: top, lattice_hash, };
141 Powerset { bottom, top, leaves, weighted_leaves, tags, untags, max_iter_len, bottom_to_top: None, }
142 })
143 }
144
145 #[cfg(feature = "serde")]
146 fn empty() -> Powerset {
148 let zero = 0u128.slx();
149 let top = SafeElement{ code: zero, lattice_hash: zero };
150 let bottom = top;
151 Powerset {
152 max_iter_len: zero, top, bottom, tags: BTreeMap::new(), untags: HashMap::new(),
153 leaves: Vec::new(), weighted_leaves: HashMap::new(), bottom_to_top: None,
154 }
155 }
156
157 fn build_double_sequence_up(&self) -> Vec<Vec<u128slx>> {
159 let mut double_sequence = vec![vec![0u128.slx()]];
161 for (n,(leaf,_)) in self.weighted_leaves.iter().enumerate() {
162 let mut next_ds = Vec::with_capacity(n+1);
163 next_ds.push(vec![0u128.slx()]);
164 for k in 0..n {
165 next_ds.push(double_sequence[k+1].iter().copied().chain(
166 double_sequence[k].iter().copied().map(|u| u | *leaf)
167 ).collect());
168 }
169 next_ds.push(vec![double_sequence[n][0] | *leaf]);
170 double_sequence = next_ds;
171 }
172 double_sequence
173 }
174
175 pub fn set_iterators(mut self) -> Self {
179 if self.top.code < self.max_iter_len && self.bottom_to_top.is_none() {
180 self.bottom_to_top = Some(
181 self.build_double_sequence_up().into_iter().flat_map(|v|v).collect()
182 );
183 } self
184 }
185}
186
187impl Lattice for Powerset {
188 type Item = u128slx;
189
190 fn rand_lattice<R: Rng>(rng: &mut R) -> Self {
191 let nb_leaves = rng.gen_range(1..=(std::mem::size_of::<u128>() << 3));
192 Self::new(nb_leaves,DEFAULT_MAX_ITER_LEN).expect("unexpected: None returned")
193 }
194
195 fn rand_element<R: Rng>(&self, rng: &mut R) -> SafeElement<Self::Item> {
196 let SafeElement { code: top, lattice_hash } = self.top;
197 let top = top.unslx();
198 let element = rng.gen_range(0..=top).slx();
199 SafeElement { code: element, lattice_hash }
200 }
201
202 fn ref_lattice_hash(&self) -> &u128slx { &self.bottom.lattice_hash }
203
204 fn contains(&self, element: &Self::Item) -> bool { element <= &self.top.code }
205
206 fn ref_bottom(&self) -> &SafeElement<Self::Item> { &self.bottom }
207
208 fn ref_top(&self) -> &SafeElement<Self::Item> { &self.top }
209
210 unsafe fn unsafe_meet(&self, element_left: &Self::Item, element_right: &Self::Item) -> Self::Item {
211 *element_left & *element_right
212 }
213
214 unsafe fn unsafe_join(&self, element_left: &Self::Item, element_right: &Self::Item) -> Self::Item {
215 *element_left | *element_right
216 }
217
218 fn from_str(&self, s: &str) -> Result<SafeElement<Self::Item>,String> {
219 let tokens = s.split('|')
220 .map(|s| s.split_whitespace().fold(String::new(),|acc,u| {
221 if acc.is_empty() { u.to_string() } else { format!("{acc} {u}") }
222 }));
223 let SafeElement { code: mut element, lattice_hash } = self.bottom;
224 for token in tokens {
225 match (&token == "\u{22A5}",&token == "\u{22A4}") {
226 (true, true) => panic!("unexpected error: \u{22A5} == \u{22A4}"),
227 (true, false) => (), (false, true) => element = self.top.code, (false, false) => match self.untags.get(&token) {
230 Some(l) => element |= *l,
231 None => return Err(format!("leaf {token} is unknown")),
232 },
233 }
234 }
235 Ok(SafeElement { code: element, lattice_hash })
236 }
237
238 fn to_string(&self, element: &SafeElement<Self::Item>) -> Result<String,String> {
239 let SafeElement { code: element, lattice_hash } = element;
240 let element = *element;
241 if lattice_hash == &self.bottom.lattice_hash {
242 match (element == self.bottom.code,element == self.top.code) {
243 (true, true) => panic!("unexpected error: \u{22A5} == \u{22A4}"),
244 (true, false) => Ok("\u{22A5}".to_string()),
245 (false, true) => Ok("\u{22A4}".to_string()),
246 (false, false) => {
247 Ok(self.tags.iter().filter(|(l,_)| { let l = **l; (element & l) == l } )
248 .fold(String::new(), |acc,(_,s)| {
249 if acc.is_empty() { s.to_string() } else { format!("{acc} | {s}") }
250 }))
251 },
252 }
253 } else { Err("lattice does not contain element".to_string()) }
254 }
255}
256
257impl ComplementedLattice for Powerset {
258 unsafe fn unsafe_not(&self, element: &Self::Item) -> Self::Item { self.top.code ^ *element }
259}
260
261impl IterableLattice for Powerset {
262 type IntoIterUp = vec::IntoIter<u128slx>;
263
264 type IntoIterDown = vec::IntoIter<u128slx>;
265
266 unsafe fn unsafe_bottom_to_top(&self) -> Result<Self::IntoIterUp,String> {
267 match &self.bottom_to_top {
268 Some(btt) => Ok(btt.clone().into_iter()),
269 None => Err("Iterator is not set or is exceeding allowed size".to_string()),
270 }
271 }
272
273 unsafe fn unsafe_top_to_bottom(&self) -> Result<Self::IntoIterDown,String> {
274 match &self.bottom_to_top {
275 Some(btt) => Ok(btt.iter().copied().rev().collect::<Vec<_>>().into_iter()),
276 None => Err("Iterator is not set or is exceeding allowed size".to_string()),
277 }
278 }
279
280}
281
282impl LatticeWithLeaves for Powerset {
283 type IntoIterLeaves = hash_map::IntoIter<Self::Item, f64slx>;
284
285 unsafe fn unsafe_leaves(&self) -> Result<Self::IntoIterLeaves,String> {
286 let len_slx: u128slx = (self.weighted_leaves.len() as u128).slx();
287 if len_slx >= self.max_iter_len {
288 Err("Iterator is exceeding allowed size".to_string())
289 } else {
290 Ok(self.weighted_leaves.clone().into_iter())
291 }
292 }
293
294 unsafe fn unsafe_leaf(&self, u: usize) -> Result<&Self::Item,String> {
295 match self.leaves.get(u) {
296 Some(x) => Ok(x),
297 None => Err(format!("Leaf of index {u} is not found within lattice")),
298 }
299 }
300
301 unsafe fn unsafe_weighted_leaf(&self, u: usize) -> Result<(&Self::Item,&f64slx),String> {
302 let leaf = self.unsafe_leaf(u)?;
303 Ok((leaf,&self.weighted_leaves[leaf]))
304 }
305}