Skip to content

Commit

Permalink
Merge pull request #32 from codeWhizperer/gkr
Browse files Browse the repository at this point in the history
update
  • Loading branch information
codeWhizperer authored Sep 16, 2024
2 parents 7cbcbe4 + e669725 commit b3939e1
Show file tree
Hide file tree
Showing 11 changed files with 505 additions and 339 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{
"cSpell.words": [
"coeff",
"composedsumcheck",
"datastructure",
"multilinear"
"multilinear",
"univariant"
]
}
1 change: 1 addition & 0 deletions gkr/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use polynomial::{
use sum_check::multi_composedsumcheck::MultiComposedSumcheckVerifier;
use sum_check::multi_composedsumcheck::{ComposedSumcheckProof, MultiComposedSumcheckProver};
use transcript::transcription::Transcript;
//look into this.
pub fn label_to_binary_to_decimal(a: usize, b: usize, c: usize) -> usize {
let a_shifted = a << 4;
let b_shifted = b << 2;
Expand Down
2 changes: 1 addition & 1 deletion polynomial/src/interface.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ UnivariatePolynomial};
use crate::univariate_polynomial::univariate::UnivariatePolynomial;
use ark_ff::PrimeField;

pub trait UnivariatePolynomialTrait<F: PrimeField> {
Expand Down
3 changes: 1 addition & 2 deletions polynomial/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
pub mod univariate_polynomial;
pub mod multilinear;
pub mod composed;
pub use univariate_polynomial::UnivariatePolynomial;
pub use multilinear::coefficient_form::{MultilinearMonomial, MultilinearPolynomial};
pub mod interface;
pub mod util;
pub mod util;
24 changes: 24 additions & 0 deletions polynomial/src/univariate_polynomial/interface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use ark_ff::PrimeField;
pub trait PolynomialInterface<F: PrimeField> {
type Point;

/// Return the total degree of the polynomial
fn degree(&self) -> usize;

/// Evaluates `self` at the given `point` in `Self::Point`.
fn evaluate(&self, point: &Self::Point) -> F;

/// Checks if the polynomial is zero
fn is_zero(&self) -> bool;
}

pub trait UnivariantPolynomialInterface<F: PrimeField>: PolynomialInterface<F> {
/// This function returs an array of co-efficents of this polynomial
fn coefficients(&self) -> &[F];
/// This function createsa new polynomial from a list of coefficients slice
fn from_coefficients_slice(coeffs: &[F]) -> Self;
/// This function creates a new polynomial from a list of coefficients vector
fn from_coefficients_vec(coeffs: Vec<F>) -> Self;
/// This function is used to create a new univariate polynomial using an interpolation
fn interpolate(point_ys: Vec<F>, domain: Vec<F>) -> Self;
}
334 changes: 3 additions & 331 deletions polynomial/src/univariate_polynomial/mod.rs
Original file line number Diff line number Diff line change
@@ -1,331 +1,3 @@
use crate::interface::UnivariatePolynomialTrait;
use crate::util::lagrange_basis;
use ark_ff::{PrimeField, BigInteger};
use std::{
fmt::{Display, Formatter, Result},
ops::{Add, Mul},
};

#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
pub struct UnivariateMonomial<F: PrimeField> {
pub coeff: F,
pub pow: F,
}
#[derive(Clone, PartialEq, Eq, Hash, Default, Debug)]
pub struct UnivariatePolynomial<F: PrimeField> {
pub monomial: Vec<UnivariateMonomial<F>>,
}

impl<F: PrimeField> UnivariatePolynomialTrait<F> for UnivariatePolynomial<F> {
fn new(data: Vec<F>) -> Self {
let mut monomial: Vec<UnivariateMonomial<F>> = Vec::new();

for n in (0..data.len()).step_by(2) {
if n < data.len() - 1 {
let monomial_value: UnivariateMonomial<F> =
UnivariateMonomial { coeff: data[n], pow: data[n + 1] };
monomial.push(monomial_value);
} else if n == data.len() - 1 {
let monomial_value: UnivariateMonomial<F> =
UnivariateMonomial { coeff: data[n], pow: F::zero() };
monomial.push(monomial_value);
}
}

UnivariatePolynomial { monomial }
}

fn zero() -> Self {
Self { monomial: vec![] }
}
fn evaluate(&self, point: F) -> F {
let mut point_evaluation: F = F::from(0_u8);
for n in self.monomial.iter() {
let coefficient = n.coeff;
let n_pow: <F as PrimeField>::BigInt = n.pow.into();
let power = point.pow(&n_pow);

let evaluation = coefficient * power;
point_evaluation += evaluation;
}

point_evaluation
}

fn interpolate(points: &[(F, F)]) -> UnivariatePolynomial<F> {
let mut result: Vec<F> = vec![F::zero(); points.len()];

for (i, &(_, y_i)) in points.iter().enumerate() {
let l_i: Vec<F> = lagrange_basis(points, i);
let l_i: Vec<F> = l_i.into_iter().map(|coeff| coeff * y_i).collect();

for (k, &coeff) in l_i.iter().enumerate() {
result[k] += coeff;
}
}

let monomial: Vec<UnivariateMonomial<F>> = result
.into_iter()
.enumerate()
.filter(|&(_, coeff)| coeff != F::zero())
.map(|(pow, coeff)| UnivariateMonomial { coeff, pow: F::from(pow as u64) })
.collect();

UnivariatePolynomial { monomial }
}

fn degree(&self) -> F {
let mut highest_degree: F = F::from(0_u8);
for m in self.monomial.iter() {
if m.pow > highest_degree {
highest_degree = m.pow;
}
}

highest_degree.try_into().unwrap()
}

fn to_bytes(&self) -> Vec<u8> {
let mut bytes = Vec::new();
for p in self.monomial.iter() {
bytes.extend_from_slice(&p.coeff.into_bigint().to_bytes_be());
bytes.extend_from_slice(&p.pow.into_bigint().to_bytes_be());
}
bytes
}

}

impl<F: PrimeField> Mul for UnivariatePolynomial<F> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
let mut result_monomial: Vec<UnivariateMonomial<F>> = Vec::new();

for lhs_mn in &self.monomial {
for rhs_mn in &rhs.monomial {
let new_coeff = lhs_mn.coeff * rhs_mn.coeff;
let new_pow = lhs_mn.pow + rhs_mn.pow;

let mut found_like_terms = false;
for res_mn in &mut result_monomial {
if res_mn.pow == new_pow {
res_mn.coeff += new_coeff;
found_like_terms = true;
break;
}
}

if !found_like_terms {
result_monomial.push(UnivariateMonomial { coeff: new_coeff, pow: new_pow });
}
}
}

UnivariatePolynomial { monomial: result_monomial }
}
}

impl<F: PrimeField> Add for UnivariatePolynomial<F> {
type Output = Self;

fn add(self, rhs: Self) -> Self::Output {
let mut result_monomials = Vec::new();
let mut lhs_iter = self.monomial.into_iter();
let mut rhs_iter = rhs.monomial.into_iter();
let mut lhs_mn = lhs_iter.next();
let mut rhs_mn = rhs_iter.next();

while lhs_mn.is_some() || rhs_mn.is_some() {
match (lhs_mn.clone(), rhs_mn.clone()) {
(Some(l), Some(r)) => {
if l.pow == r.pow {
result_monomials
.push(UnivariateMonomial { coeff: l.coeff + r.coeff, pow: l.pow });
lhs_mn = lhs_iter.next();
rhs_mn = rhs_iter.next();
} else if l.pow < r.pow {
result_monomials.push(l);
lhs_mn = lhs_iter.next();
} else {
result_monomials.push(r);
rhs_mn = rhs_iter.next();
}
},
(Some(l), None) => {
result_monomials.push(l);
lhs_mn = lhs_iter.next();
},
(None, Some(r)) => {
result_monomials.push(r);
rhs_mn = rhs_iter.next();
},
(None, None) => break,
}
}

UnivariatePolynomial { monomial: result_monomials }
}
}

impl<F: PrimeField> Display for UnivariatePolynomial<F> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
for (index, mn) in self.monomial.iter().enumerate() {
if index == 0 {
write!(f, "{}", mn.coeff)?;
} else {
if mn.pow == F::from(0_u8) || mn.coeff == F::from(0_u8) {
write!(f, " + {}", mn.coeff)?;
} else if mn.pow == F::from(1_u8) {
write!(f, " + {}x", mn.coeff)?;
} else {
write!(f, " + {}x^{}", mn.coeff, mn.pow)?;
}
}
}
Ok(())
}
}

mod tests {
use super::*;
use ark_ff::MontConfig;
use ark_ff::{Fp64, MontBackend};

#[derive(MontConfig)]
#[modulus = "17"]
#[generator = "3"]
struct FqConfig;
type Fq = Fp64<MontBackend<FqConfig, 1>>;

#[test]
fn test_polynomial_evaluation() {
let data = vec![
Fq::from(5_u8),
Fq::from(0_u8),
Fq::from(2_u8),
Fq::from(1_u8),
Fq::from(4_u8),
Fq::from(6_u8),
];
let polynomial = UnivariatePolynomial::new(data);
let evaluation = polynomial.evaluate(Fq::from(2_u8));

assert_eq!(evaluation, Fq::from(10_u8));
}

#[test]
fn test_polynomial_addition() {
let data = vec![Fq::from(5_u8), Fq::from(0_u8)];
let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)];


let polynomial1 = UnivariatePolynomial::new(data);
let polynomial2 = UnivariatePolynomial::new(data2);

assert_eq!(
polynomial1 + polynomial2,
UnivariatePolynomial::new(vec![
Fq::from(5_u8),
Fq::from(0_u8),
Fq::from(2_u8),
Fq::from(1_u8),
])
);

let data3 = vec![Fq::from(5_u8), Fq::from(0_u8), Fq::from(5_u8), Fq::from(2_u8)];
let data4 = vec![Fq::from(2_u8), Fq::from(1_u8), Fq::from(2_u8), Fq::from(2_u8)];
let polynomial1 = UnivariatePolynomial::new(data3);
let polynomial2 = UnivariatePolynomial::new(data4);

assert_eq!(
polynomial1 + polynomial2,
UnivariatePolynomial::new(vec![
Fq::from(5_u8),
Fq::from(0_u8),
Fq::from(2_u8),
Fq::from(1_u8),
Fq::from(7_u8),
Fq::from(2_u8),
])
);
}

#[test]
fn test_polynomial_multiplication() {
let data = vec![Fq::from(5_u8), Fq::from(0_u8)];
let data2 = vec![Fq::from(2_u8), Fq::from(1_u8)];

let polynomial1 = UnivariatePolynomial::new(data);
let polynomial2 = UnivariatePolynomial::new(data2);

assert_eq!(
polynomial1 + polynomial2,
UnivariatePolynomial::new(vec![
Fq::from(5_u8),
Fq::from(0_u8),
Fq::from(2_u8),
Fq::from(1_u8),
])
);

let data3 = vec![
Fq::from(5_u8),
Fq::from(0_u8),
Fq::from(2_u8),
Fq::from(1_u8),
Fq::from(4_u8),
Fq::from(6_u8),
];
let data4 =
vec![Fq::from(4), Fq::from(0), Fq::from(3), Fq::from(2), Fq::from(4), Fq::from(5)];

let polynomial3 = UnivariatePolynomial::new(data3);
let polynomial4 = UnivariatePolynomial::new(data4);

assert_eq!(
polynomial3 * polynomial4,
UnivariatePolynomial::new(vec![
Fq::from(3_u8),
Fq::from(0_u8),
Fq::from(15_u8),
Fq::from(2_u8),
Fq::from(3_u8),
Fq::from(5_u8),
Fq::from(8_u8),
Fq::from(1_u8),
Fq::from(6_u8),
Fq::from(3_u8),
Fq::from(7_u8),
Fq::from(6_u8),
Fq::from(12_u8),
Fq::from(8_u8),
Fq::from(16_u8),
Fq::from(11_u8),
])
);
}

#[test]
fn test_polynomial_interpolate() {
let interpolation = UnivariatePolynomial::interpolate(&[
(Fq::from(1), Fq::from(2)),
(Fq::from(2), Fq::from(3)),
(Fq::from(4), Fq::from(11)),
]);

let interpolation_check = UnivariatePolynomial::new(vec![
Fq::from(3_u8),
Fq::from(0_u8),
Fq::from(15_u8),
Fq::from(1_u8),
Fq::from(1_u8),
Fq::from(2_u8),
]);
assert_eq!(interpolation, interpolation_check);

// to test the evaluation of the polynomial
let evaluation = interpolation.evaluate(Fq::from(2_u8));
assert_eq!(evaluation, Fq::from(3_u8));
}

}
pub mod univariate;
pub mod univariant_coefficient;
pub mod interface;
Loading

0 comments on commit b3939e1

Please sign in to comment.