Skip to content

Commit c8861ba

Browse files
committed
Add permutivity checks
1 parent 8ac9b83 commit c8861ba

File tree

1 file changed

+97
-0
lines changed

1 file changed

+97
-0
lines changed

src/lib.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,40 @@ pub trait BooleanFunctionImpl: Debug {
617617
.count()
618618
}
619619

620+
/// Checks if the Boolean function is left-permutive.
621+
///
622+
/// A Boolean function is left-permutive if changing the left-most input bit always changes the output.
623+
fn is_left_permutive(&self) -> bool {
624+
let num_variables = self.variables_count();
625+
let max_input_value = self.get_max_input_value();
626+
let left_most_bit_mask = 1 << (num_variables - 1);
627+
(0..=max_input_value >> 1)
628+
.into_iter()
629+
.all(|x| {
630+
self.compute_cellular_automata_rule(x) != self.compute_cellular_automata_rule(x | left_most_bit_mask)
631+
})
632+
}
633+
634+
/// Checks if the Boolean function is right-permutive.
635+
///
636+
/// A Boolean function is right-permutive if changing the right-most input bit always changes the output.
637+
fn is_right_permutive(&self) -> bool {
638+
let max_input_value = self.get_max_input_value();
639+
let right_most_bit_mask = 1;
640+
(0..=max_input_value >> 1)
641+
.into_iter()
642+
.all(|x| {
643+
self.compute_cellular_automata_rule(x << 1) != self.compute_cellular_automata_rule((x << 1) | right_most_bit_mask)
644+
})
645+
}
646+
647+
/// Checks if the Boolean function is bipermutive.
648+
///
649+
/// A Boolean function is bipermutive if it is both left-permutive and right-permutive.
650+
fn is_bipermutive(&self) -> bool {
651+
self.is_left_permutive() && self.is_right_permutive()
652+
}
653+
620654
/// Returns a 1-local neighbor of the Boolean function, at a specific position
621655
///
622656
/// A 1-local neighbor of a Boolean function $f$ at position $i$ is a Boolean function $f_i$ such that:
@@ -2632,4 +2666,67 @@ mod tests {
26322666
let boolean_function = BooleanFunction::from_anf_polynomial(&anf);
26332667
assert_eq!(boolean_function.printable_hex_truth_table(), "7fffffffffffffffffffffffffffffff80000000000000000000000000000000");
26342668
}
2669+
2670+
#[test]
2671+
fn test_is_left_permutive() {
2672+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0 + x1 + x2", 3).unwrap());
2673+
assert!(boolean_function.is_left_permutive());
2674+
2675+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0*x1 + x0 + x1 + x2", 3).unwrap());
2676+
assert!(boolean_function.is_left_permutive());
2677+
2678+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x2*x1 + x0 + x1 + x2", 3).unwrap());
2679+
assert!(!boolean_function.is_left_permutive());
2680+
2681+
let boolean_function = BooleanFunction::from_hex_string_truth_table("ff").unwrap();
2682+
assert!(!boolean_function.is_left_permutive());
2683+
2684+
let boolean_function = BooleanFunction::from_hex_string_truth_table("00").unwrap();
2685+
assert!(!boolean_function.is_left_permutive());
2686+
2687+
let boolean_function = BooleanFunction::from_hex_string_truth_table("0f").unwrap();
2688+
assert!(boolean_function.is_left_permutive());
2689+
}
2690+
2691+
#[test]
2692+
fn test_is_right_permutive() {
2693+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0 + x1 + x2", 3).unwrap());
2694+
assert!(boolean_function.is_right_permutive());
2695+
2696+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0*x1 + x0 + x1 + x2", 3).unwrap());
2697+
assert!(!boolean_function.is_right_permutive());
2698+
2699+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x2*x1 + x0 + x1 + x2", 3).unwrap());
2700+
assert!(boolean_function.is_right_permutive());
2701+
2702+
let boolean_function = BooleanFunction::from_hex_string_truth_table("ff").unwrap();
2703+
assert!(!boolean_function.is_right_permutive());
2704+
2705+
let boolean_function = BooleanFunction::from_hex_string_truth_table("00").unwrap();
2706+
assert!(!boolean_function.is_right_permutive());
2707+
2708+
let boolean_function = BooleanFunction::from_hex_string_truth_table("0f").unwrap();
2709+
assert!(!boolean_function.is_right_permutive());
2710+
}
2711+
2712+
#[test]
2713+
fn test_is_bipermutive() {
2714+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0 + x1 + x2", 3).unwrap());
2715+
assert!(boolean_function.is_bipermutive());
2716+
2717+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x0*x1 + x0 + x1 + x2", 3).unwrap());
2718+
assert!(!boolean_function.is_bipermutive());
2719+
2720+
let boolean_function = BooleanFunction::from_anf_polynomial(&AnfPolynomial::from_str("x2*x1 + x0 + x1 + x2", 3).unwrap());
2721+
assert!(!boolean_function.is_bipermutive());
2722+
2723+
let boolean_function = BooleanFunction::from_hex_string_truth_table("ff").unwrap();
2724+
assert!(!boolean_function.is_bipermutive());
2725+
2726+
let boolean_function = BooleanFunction::from_hex_string_truth_table("00").unwrap();
2727+
assert!(!boolean_function.is_bipermutive());
2728+
2729+
let boolean_function = BooleanFunction::from_hex_string_truth_table("0f").unwrap();
2730+
assert!(!boolean_function.is_bipermutive());
2731+
}
26352732
}

0 commit comments

Comments
 (0)