use bincode::{Decode, Encode};
use itertools::Itertools;
use std::hash::Hash;
use crate::auxiliar::deposit;
use crate::auxiliar::CountUnique;
pub trait GenericValue: Eq + Default + Clone + Ord {}
impl<Output: Eq + Default + Clone + Ord> GenericValue for Output {}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FValue<Output: GenericValue> {
repr: Vec<Output>,
}
impl<Output: GenericValue + Encode> Encode for FValue<Output> {
fn encode<E: bincode::enc::Encoder>(
&self,
encoder: &mut E,
) -> Result<(), bincode::error::EncodeError> {
self.repr.encode(encoder)
}
}
impl<Output: GenericValue + Decode<()>> Decode<()> for FValue<Output> {
fn decode<D: bincode::de::Decoder<Context = ()>>(
decoder: &mut D,
) -> Result<Self, bincode::error::DecodeError> {
Vec::decode(decoder).map(FValue::new)
}
}
fn is_valid_size(n: usize) -> bool {
n > 0 && n.is_power_of_two()
}
impl<Output: GenericValue> FValue<Output> {
pub fn new(repr: Vec<Output>) -> Self {
if !is_valid_size(repr.len()) {
panic!("Invalid size");
}
FValue { repr }
}
pub fn repr(&self) -> &Vec<Output> {
&self.repr
}
}
impl<Output: Send + Sync + Hash + GenericValue> FValue<Output> {
pub fn n_vars(&self) -> usize {
self.repr.len().ilog2() as usize
}
pub fn get(&self, i: usize) -> Option<&Output> {
self.repr.get(i)
}
pub fn fixed(&self, var: usize, value: bool) -> Self {
let it = crate::auxiliar::binary_numbers(self.n_vars(), var, value as usize);
let mut new_repr = vec![];
it.for_each(|x| {
let bit = self.repr.get(x).cloned().unwrap_or_default();
new_repr.push(bit.clone());
});
FValue::new(new_repr)
}
pub fn multiple_fixed(&self, mut vars: Vec<(usize, bool)>) -> Self {
let mut new_repr = self.clone();
vars.sort_by_key(|a| a.0);
for (i, (var, value)) in vars.iter().enumerate() {
new_repr = new_repr.fixed(*var - i, *value);
}
new_repr
}
pub fn list_forms_by_fixed(&self, var: usize) -> Vec<Self> {
vec![self.fixed(var, false), self.fixed(var, true)]
}
pub fn count_forms_by_multiple_fixed(&self, vars: &[usize]) -> usize {
let mut fixed_positions = vars.to_vec();
fixed_positions.sort();
let free_positions = (0..self.repr().len().ilog2() as usize)
.filter(|i| !fixed_positions.contains(i))
.collect::<Vec<_>>();
let (fixed, free) = (fixed_positions.len(), free_positions.len());
let free_deposits: Vec<_> = (0..(1 << free))
.map(|w| deposit(w, &free_positions))
.collect();
(0..(1 << fixed))
.map(|v| {
let fixed_part = deposit(v, &fixed_positions);
let repr = free_deposits
.iter()
.map(|&free_part| {
let index = fixed_part | free_part;
self.repr.get(index).cloned().unwrap_or_default()
})
.collect::<Vec<Output>>();
FValue::new(repr)
})
.count_unique()
}
pub fn table(&self, vars: &[usize]) -> Vec<Vec<Output>> {
let mut fixed_positions = vars.to_vec();
fixed_positions.sort();
let free_positions = (0..self.repr().len().ilog2() as usize)
.filter(|i| !fixed_positions.contains(i))
.collect::<Vec<_>>();
let (fixed, free) = (fixed_positions.len(), free_positions.len());
let free_deposits: Vec<_> = (0..(1 << free))
.map(|w| deposit(w, &free_positions))
.collect();
(0..(1 << fixed))
.map(|v| {
let fixed_part = deposit(v, &fixed_positions);
free_deposits
.iter()
.map(|&free_part| {
let index = fixed_part | free_part;
self.repr.get(index).cloned().unwrap_or_default()
})
.collect::<Vec<Output>>()
})
.collect()
}
pub fn set_entropy(&self, vars: &[usize]) -> f32 {
let mut fixed_positions = vars.to_vec();
fixed_positions.sort();
let free_positions = (0..self.repr().len().ilog2() as usize)
.filter(|i| !fixed_positions.contains(i))
.collect::<Vec<_>>();
let (fixed, free) = (fixed_positions.len(), free_positions.len());
let free_deposits: Vec<_> = (0..(1 << free))
.map(|w| deposit(w, &free_positions))
.collect();
let map = (0..(1 << fixed))
.map(|v| {
let fixed_part = deposit(v, &fixed_positions);
let repr = free_deposits
.iter()
.map(|&free_part| {
let index = fixed_part | free_part;
self.repr.get(index).cloned().unwrap_or_default()
})
.collect::<Vec<Output>>();
FValue::new(repr)
})
.counts();
let k2 = 1 << fixed;
let sigmas = map
.values()
.map(|&x| x as f32 / k2 as f32)
.collect::<Vec<f32>>();
-sigmas.iter().map(|x| x * x.log2()).sum::<f32>()
}
pub fn information(&self, vars: &[usize]) -> usize {
self.count_forms_by_multiple_fixed(vars)
}
pub async fn async_information(&self, vars: &[usize]) -> usize {
self.count_forms_by_multiple_fixed(vars)
}
pub fn negate_var(&self, i: usize) -> Self {
let mut repr: Vec<Output> = vec![Output::default(); self.repr.len()];
let n = self.n_vars();
for j in 0..self.repr.len() {
repr[j ^ (1 << (n - 1 - i))] = self.repr[j].clone();
}
FValue::new(repr)
}
pub fn permutate_var(&self, i: usize, j: usize) -> Self {
let n_vars = self.n_vars();
let repr: Vec<Output> = (0..self.repr.len())
.map(|k| {
let bit_i = (k >> (n_vars - 1 - i)) & 1;
let bit_j = (k >> (n_vars - 1 - j)) & 1;
let mut k_prima = k & !(1 << (n_vars - 1 - i)) & !(1 << (n_vars - 1 - j));
k_prima |= bit_j << (n_vars - 1 - i);
k_prima |= bit_i << (n_vars - 1 - j);
self.repr[k_prima].clone()
})
.collect();
FValue::new(repr)
}
}
impl FValue<bool> {
pub fn negate(&self) -> Self {
let repr: Vec<bool> = self.repr.iter().map(|x| !x).collect();
FValue::new(repr)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_encode_and_decode() {
let n = 5;
let f1 = FValue::<bool>::primality(n);
let raw = bincode::encode_to_vec(&f1, bincode::config::standard()).unwrap();
let (f2, _): (FValue<bool>, _) =
bincode::decode_from_slice(&raw, bincode::config::standard()).unwrap();
for i in 0..1 << n {
assert_eq!(f1.get(i), f2.get(i));
}
}
}