Skip to content

Commit 942f52f

Browse files
committed
Generate SmallBooleanFunction and BigBooleanFunction from ANF polynomial and string representation, bump new version
1 parent 91fb12a commit 942f52f

File tree

4 files changed

+144
-12
lines changed

4 files changed

+144
-12
lines changed

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "boolean_function"
33
description = "Mathematical analysis of Boolean functions"
4-
version = "0.0.5"
4+
version = "0.0.6"
55
edition = "2021"
66
rust-version = "1.56.0"
77
authors = ["Thomas Prévost"]
@@ -15,10 +15,10 @@ exclude = [".github/*", "examples"]
1515
num-traits = "0.2"
1616
num-integer = "0.1"
1717
num-bigint = "0.4"
18-
thiserror = "1.0"
18+
thiserror = "2.0"
1919
itertools = "0.13"
2020
fast-boolean-anf-transform = "0.0.3"
21-
gen-combinations = "0.1.0"
21+
gen-combinations = "0.1"
2222
enum_dispatch = "0.3"
2323
ouroboros = "0.18"
2424

src/big_boolean_function.rs

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{BooleanFunction, BooleanFunctionError, BooleanFunctionImpl, BooleanF
99
use itertools::{enumerate, Itertools};
1010
use num_bigint::BigUint;
1111
use num_integer::binomial;
12-
use num_traits::{One, Zero};
12+
use num_traits::{FromPrimitive, One, Zero};
1313
use std::ops::{BitXor, BitXorAssign, Not};
1414

1515
/// Struct representing a boolean function with a big truth table.
@@ -306,6 +306,41 @@ impl BigBooleanFunction {
306306

307307
Ok(BigCloseBalancedFunctionIterator::create(self, flippable_positions, bits_to_flip_count))
308308
}
309+
310+
/// Computes BigBooleanFunction from string ANF representation
311+
///
312+
/// The ANF string representation must be in exact form "`x0*x2*x3 + x2*x3 + x1 + 1`".
313+
///
314+
/// X's index starts at 0, meaning the maximum index is variable count - 1.
315+
///
316+
/// # Parameters:
317+
/// - `anf_polynomial`: The string representation of the ANF form
318+
/// - `num_variables`: Variable count of the polynomial
319+
///
320+
/// # Returns
321+
/// The BigBooleanFunction corresponding to the ANF string representation, or an error if the input string doesn't respect the format,
322+
/// and `unsafe_disable_safety_checks` feature is not activated.
323+
pub fn from_anf_polynomial_str_inner(anf_polynomial: &str, num_variables: usize) -> Result<Self, BooleanFunctionError> {
324+
Ok(Self::from_anf_polynomial_inner(
325+
&AnfPolynomial::from_str(anf_polynomial, num_variables)?
326+
))
327+
}
328+
329+
/// Computes BigBooleanFunction from ANF polynomial
330+
///
331+
/// # Parameters:
332+
/// - `anf_polynomial`: The polynomial in Algebraic Normal Form
333+
///
334+
/// # Returns
335+
/// The BigBooleanFunction corresponding to the ANF polynomial
336+
pub fn from_anf_polynomial_inner(anf_polynomial: &AnfPolynomial) -> Self {
337+
match anf_polynomial.to_boolean_function() {
338+
BooleanFunction::Small(small_bf) => BigBooleanFunction::from_truth_table(
339+
BigUint::from_u64(small_bf.get_truth_table_u64()).unwrap(), small_bf.variables_count()
340+
),
341+
BooleanFunction::Big(big_bf) => big_bf
342+
}
343+
}
309344
}
310345
impl BooleanFunctionImpl for BigBooleanFunction {
311346
#[inline]
@@ -335,7 +370,7 @@ impl BooleanFunctionImpl for BigBooleanFunction {
335370
}
336371

337372
fn derivative(&self, direction: u32) -> Result<BooleanFunction, BooleanFunctionError> {
338-
Ok((self.derivative_inner(direction)?).into())
373+
Ok(self.derivative_inner(direction)?.into())
339374
}
340375

341376
fn is_linear(&self) -> bool {
@@ -439,7 +474,7 @@ impl Not for BigBooleanFunction {
439474

440475
#[cfg(test)]
441476
mod tests {
442-
use crate::{BigBooleanFunction, BooleanFunctionImpl};
477+
use crate::{AnfPolynomial, BigBooleanFunction, BooleanFunctionError, BooleanFunctionImpl};
443478
use num_bigint::BigUint;
444479
use num_traits::{Num, One, Zero};
445480

@@ -974,4 +1009,32 @@ mod tests {
9741009
assert!(close_balanced_iterator.next().unwrap().is_balanced());
9751010
}
9761011
}
1012+
1013+
#[test]
1014+
fn test_from_anf_polynomial_str_inner() {
1015+
let rule_30_anf_str = "x0*x1 + x0 + x1 + x2";
1016+
let rule_30_function = BigBooleanFunction::from_anf_polynomial_str_inner(rule_30_anf_str, 3).unwrap();
1017+
assert_eq!(rule_30_function.printable_hex_truth_table(), "1e");
1018+
1019+
let anf_str = "x7*x6*x0*x1 + x0 + x1 + x2";
1020+
let boolean_function = BigBooleanFunction::from_anf_polynomial_str_inner(anf_str, 3);
1021+
assert!(boolean_function.is_err());
1022+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::AnfFormNVariableTooBigFactor(3, 7));
1023+
1024+
let anf_str = "x7*x6*x0*x1 + x0 + x1 + x2";
1025+
let boolean_function = BigBooleanFunction::from_anf_polynomial_str_inner(anf_str, 8).unwrap();
1026+
assert_eq!(boolean_function.printable_hex_truth_table(), "1e1e1e1e1e1e1e1e969696969696969696969696969696969696969696969696");
1027+
1028+
let anf_str = "x0*y1 + x0 + x1 + x2";
1029+
let boolean_function = BigBooleanFunction::from_anf_polynomial_str_inner(anf_str, 3);
1030+
assert!(boolean_function.is_err());
1031+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::ErrorParsingAnfString);
1032+
}
1033+
1034+
#[test]
1035+
fn test_from_anf_polynomial_inner() {
1036+
let anf = AnfPolynomial::from_str("x7*x6*x0*x1 + x0 + x1 + x2", 8).unwrap();
1037+
let boolean_function = BigBooleanFunction::from_anf_polynomial_inner(&anf);
1038+
assert_eq!(boolean_function.printable_hex_truth_table(), "1e1e1e1e1e1e1e1e969696969696969696969696969696969696969696969696");
1039+
}
9771040
}

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -954,8 +954,6 @@ impl BooleanFunction {
954954
}
955955
}
956956

957-
// TODO from ANF in Small and Big Boolean functions
958-
959957
#[cfg(test)]
960958
mod tests {
961959
use crate::BooleanFunctionError::InvalidWalshValuesCount;

src/small_boolean_function.rs

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use crate::anf_polynom::AnfPolynomial;
33
use crate::boolean_function_error::XOR_DIFFERENT_VAR_COUNT_PANIC_MSG;
44
use crate::iterator::{BooleanFunctionIterator, CloseBalancedFunctionIterator, SmallCloseBalancedFunctionIterator};
55
use crate::utils::left_kernel_boolean;
6-
#[cfg(not(feature = "unsafe_disable_safety_checks"))]
7-
use crate::BooleanFunctionError::TooBigTruthTableForVarCount;
8-
use crate::BooleanFunctionError::TooBigVariableCount;
6+
use crate::BooleanFunctionError::{TooBigTruthTableForVarCount, TooBigVariableCount};
97
use crate::{BooleanFunction, BooleanFunctionError, BooleanFunctionImpl, BooleanFunctionType};
108
use fast_boolean_anf_transform::fast_bool_anf_transform_unsigned;
119
use itertools::{enumerate, Itertools};
@@ -327,6 +325,44 @@ impl SmallBooleanFunction {
327325

328326
Ok(SmallCloseBalancedFunctionIterator::create(self, flippable_positions, bits_to_flip_count))
329327
}
328+
329+
/// Computes SmallBooleanFunction from string ANF representation
330+
///
331+
/// The ANF string representation must be in exact form "`x0*x2*x3 + x2*x3 + x1 + 1`".
332+
///
333+
/// X's index starts at 0, meaning the maximum index is variable count - 1.
334+
///
335+
/// # Parameters:
336+
/// - `anf_polynomial`: The string representation of the ANF form
337+
/// - `num_variables`: Variable count of the polynomial
338+
///
339+
/// # Returns
340+
/// The SmallBooleanFunction corresponding to the ANF string representation, or an error if:
341+
/// - the input string doesn't respect the format and `unsafe_disable_safety_checks` feature is not activated.
342+
/// - the polynomial variable count is greater than 6
343+
pub fn from_anf_polynomial_str_inner(anf_polynomial: &str, num_variables: usize) -> Result<Self, BooleanFunctionError> {
344+
#[cfg(not(feature = "unsafe_disable_safety_checks"))]
345+
if num_variables > 6 {
346+
return Err(TooBigTruthTableForVarCount);
347+
}
348+
Ok(Self::from_anf_polynomial_inner(
349+
&AnfPolynomial::from_str(anf_polynomial, num_variables)?
350+
)?)
351+
}
352+
353+
/// Computes SmallBooleanFunction from ANF polynomial
354+
///
355+
/// # Parameters:
356+
/// - `anf_polynomial`: The polynomial in Algebraic Normal Form
357+
///
358+
/// # Returns
359+
/// The SmallBooleanFunction corresponding to the ANF polynomial, or an error if polynomial variable count > 6
360+
pub fn from_anf_polynomial_inner(anf_polynomial: &AnfPolynomial) -> Result<Self, BooleanFunctionError> {
361+
match anf_polynomial.to_boolean_function() {
362+
BooleanFunction::Small(small_bf) => Ok(small_bf),
363+
BooleanFunction::Big(_) => Err(TooBigTruthTableForVarCount)
364+
}
365+
}
330366
}
331367

332368
impl BooleanFunctionImpl for SmallBooleanFunction {
@@ -461,7 +497,7 @@ impl Not for SmallBooleanFunction {
461497

462498
#[cfg(test)]
463499
mod tests {
464-
use crate::{BooleanFunctionImpl, SmallBooleanFunction};
500+
use crate::{AnfPolynomial, BooleanFunctionError, BooleanFunctionImpl, SmallBooleanFunction};
465501

466502
#[test]
467503
fn test_from_truth_table() {
@@ -862,4 +898,39 @@ mod tests {
862898
let mut close_balanced_iterator = bent_function.close_balanced_functions_iterator_inner().unwrap();
863899
assert!(close_balanced_iterator.all(|f| f.is_balanced()));
864900
}
901+
902+
#[test]
903+
fn test_from_anf_polynomial_str_inner() {
904+
let rule_30_anf_str = "x0*x1 + x0 + x1 + x2";
905+
let rule_30_function = SmallBooleanFunction::from_anf_polynomial_str_inner(rule_30_anf_str, 3).unwrap();
906+
assert_eq!(rule_30_function.printable_hex_truth_table(), "1e");
907+
assert_eq!(rule_30_function.get_truth_table_u64(), 30);
908+
909+
let rule_30_anf_str = "x0*x1 + x0 + x1 + x2";
910+
let boolean_function = SmallBooleanFunction::from_anf_polynomial_str_inner(rule_30_anf_str, 8);
911+
assert!(boolean_function.is_err());
912+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::TooBigTruthTableForVarCount);
913+
914+
let anf_str = "x0*x1*x3 + x0 + x1 + x2";
915+
let boolean_function = SmallBooleanFunction::from_anf_polynomial_str_inner(anf_str, 3);
916+
assert!(boolean_function.is_err());
917+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::AnfFormNVariableTooBigFactor(3, 3));
918+
919+
let anf_str = "x0*y1 + x0 + x1 + x2";
920+
let boolean_function = SmallBooleanFunction::from_anf_polynomial_str_inner(anf_str, 3);
921+
assert!(boolean_function.is_err());
922+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::ErrorParsingAnfString);
923+
}
924+
925+
#[test]
926+
fn test_from_anf_polynomial_inner() {
927+
let rule_30_anf = AnfPolynomial::from_str("x0*x1 + x0 + x1 + x2", 3).unwrap();
928+
let rule_30_function = SmallBooleanFunction::from_anf_polynomial_inner(&rule_30_anf).unwrap();
929+
assert_eq!(rule_30_function.get_truth_table_u64(), 30);
930+
931+
let rule_30_anf = AnfPolynomial::from_str("x0*x1 + x0 + x1 + x2", 7).unwrap();
932+
let boolean_function = SmallBooleanFunction::from_anf_polynomial_inner(&rule_30_anf);
933+
assert!(boolean_function.is_err());
934+
assert_eq!(boolean_function.unwrap_err(), BooleanFunctionError::TooBigTruthTableForVarCount);
935+
}
865936
}

0 commit comments

Comments
 (0)