//! This module implements the permutation check protocol. use ark_ff::PrimeField; use ark_poly::DenseMultilinearExtension; use crate::PolyIOPErrors; /// Compute `prod(0,x) := prod(0, x1, …, xn)` which is the MLE over the /// evaluations of the following polynomial on the boolean hypercube {0,1}^n: /// /// (w(x) + \beta s_id(x) + \gamma)/(w(x) + \beta s_perm(x) + \gamma) /// /// where /// - beta and gamma are challenges /// - w(x), s_id(x), s_perm(x) are mle-s #[allow(dead_code)] // TODO: remove fn compute_prod_0( beta: &F, gamma: &F, w: &DenseMultilinearExtension, s_id: &DenseMultilinearExtension, s_perm: &DenseMultilinearExtension, ) -> Result, PolyIOPErrors> { let num_vars = w.num_vars; if num_vars != s_id.num_vars || num_vars != s_perm.num_vars { return Err(PolyIOPErrors::InvalidParameters( "num of variables do not match".to_string(), )); } let eval: Vec = w .iter() .zip(s_id.iter().zip(s_perm.iter())) .map(|(wi, (s_id_i, s_perm_i))| { let tmp = *wi + *gamma; (tmp + *beta * *s_id_i) / (tmp + *beta * *s_perm_i) }) .collect(); let res = DenseMultilinearExtension::from_evaluations_vec(num_vars, eval); Ok(res) } #[cfg(test)] mod test { use super::*; use crate::utils::bit_decompose; use ark_bls12_381::Fr; use ark_ff::UniformRand; use ark_poly::MultilinearExtension; use ark_std::test_rng; #[test] fn test_compute_prod_0() -> Result<(), PolyIOPErrors> { let mut rng = test_rng(); for num_vars in 2..6 { let w_vec: Vec = (0..(1 << num_vars)).map(|_| Fr::rand(&mut rng)).collect(); let w = DenseMultilinearExtension::from_evaluations_vec(num_vars, w_vec); let s_id_vec: Vec = (0..(1 << num_vars)).map(|_| Fr::rand(&mut rng)).collect(); let s_id = DenseMultilinearExtension::from_evaluations_vec(num_vars, s_id_vec); let s_perm_vec: Vec = (0..(1 << num_vars)).map(|_| Fr::rand(&mut rng)).collect(); let s_perm = DenseMultilinearExtension::from_evaluations_vec(num_vars, s_perm_vec); let beta = Fr::rand(&mut rng); let gamma = Fr::rand(&mut rng); for i in 0..1 << num_vars { let r: Vec = bit_decompose(i, num_vars) .iter() .map(|&x| Fr::from(x)) .collect(); let prod_0 = compute_prod_0(&beta, &gamma, &w, &s_id, &s_perm)?; let eval = prod_0.evaluate(&r).unwrap(); let w_eval = w.evaluate(&r).unwrap(); let s_id_eval = s_id.evaluate(&r).unwrap(); let s_perm_eval = s_perm.evaluate(&r).unwrap(); let eval_rec = (w_eval + beta * s_id_eval + gamma) / (w_eval + beta * s_perm_eval + gamma); assert_eq!(eval, eval_rec); } } Ok(()) } }