Skip to content

Commit

Permalink
remove evaluate from MultilinearExtension
Browse files Browse the repository at this point in the history
remove
  • Loading branch information
mmagician committed Oct 23, 2023
1 parent 0ab3d75 commit 14eb52a
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 82 deletions.
9 changes: 2 additions & 7 deletions poly/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,7 @@ let g: DenseMultilinearExtension<Fq> = DenseMultilinearExtension::from_evaluatio
);
// when evaluated at any point within the Boolean hypercube, f and g should be equal
let point_within_hypercube = &vec![Fq::from(0), Fq::from(1), Fq::from(1)];
assert_eq!(
f.evaluate(&point_within_hypercube),
MultilinearExtension::evaluate(&g, &point_within_hypercube).unwrap()
);
assert_eq!(f.evaluate(&point_within_hypercube), g.evaluate(&point_within_hypercube));

// We can also define a MLE g'(x_0, x_1, x_2) by providing the list of non-zero evaluations:
let g_prime: SparseMultilinearExtension<Fq> = SparseMultilinearExtension::from_evaluations(
Expand All @@ -138,9 +135,7 @@ let g_prime: SparseMultilinearExtension<Fq> = SparseMultilinearExtension::from_e
);
// at any random point (X0, X1, X2), g == g' with negligible probability, unless they are the same function
let random_point = &vec![Fq::from(123), Fq::from(456), Fq::from(789)];
assert_eq!(
MultilinearExtension::evaluate(&g_prime, &random_point).unwrap(), MultilinearExtension::evaluate(&g, &random_point).unwrap()
);
assert_eq!(g_prime.evaluate(&random_point), g.evaluate(&random_point));

```

Expand Down
4 changes: 2 additions & 2 deletions poly/benches/dense_multilinear.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
extern crate criterion;

use ark_ff::Field;
use ark_poly::{DenseMultilinearExtension, MultilinearExtension};
use ark_poly::{DenseMultilinearExtension, MultilinearExtension, Polynomial};
use ark_std::{ops::Range, test_rng};
use ark_test_curves::bls12_381;
use criterion::{black_box, BenchmarkId, Criterion};
Expand Down Expand Up @@ -40,7 +40,7 @@ fn evaluation_op_bench<F: Field>(c: &mut Criterion) {
group.bench_with_input(BenchmarkId::from_parameter(nv), &nv, |b, &nv| {
let poly = DenseMultilinearExtension::<F>::rand(nv, &mut rng);
let point: Vec<_> = (0..nv).map(|_| F::rand(&mut rng)).collect();
b.iter(|| black_box(poly.evaluate(&point).unwrap()))
b.iter(|| black_box(poly.evaluate(&point)))
});
}
group.finish();
Expand Down
69 changes: 31 additions & 38 deletions poly/src/evaluations/multivariate/multilinear/dense.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,32 +89,6 @@ impl<F: Field> MultilinearExtension<F> for DenseMultilinearExtension<F> {
self.num_vars
}

/// Evaluate the dense MLE at the given point
/// # Example
/// ```
/// use ark_test_curves::bls12_381::Fr;
/// # use ark_poly::{MultilinearExtension, DenseMultilinearExtension};
/// # use ark_ff::One;
///
/// // The two-variate polynomial x_0 + 3 * x_0 * x_1 + 2 evaluates to [2, 3, 2, 6]
/// // in the two-dimensional hypercube with points [00, 10, 01, 11]
/// let mle = DenseMultilinearExtension::from_evaluations_vec(
/// 2, vec![2, 3, 2, 6].iter().map(|x| Fr::from(*x as u64)).collect()
/// );
///
/// // By the uniqueness of MLEs, `mle` is precisely the above polynomial, which
/// // takes the value 54 at the point (1, 17)
/// let eval = mle.evaluate(&[Fr::one(), Fr::from(17)]).unwrap();
/// assert_eq!(eval, Fr::from(54));
/// ```
fn evaluate(&self, point: &[F]) -> Option<F> {
if point.len() == self.num_vars {
Some(self.fix_variables(point)[0])
} else {
None
}
}

fn rand<R: Rng>(num_vars: usize, rng: &mut R) -> Self {
Self::from_evaluations_vec(
num_vars,
Expand Down Expand Up @@ -317,14 +291,33 @@ impl<F: Field> Polynomial<F> for DenseMultilinearExtension<F> {
1
}

/// Evaluate the dense MLE at the given point
/// # Example
/// ```
/// use ark_test_curves::bls12_381::Fr;
/// # use ark_poly::{MultilinearExtension, DenseMultilinearExtension, Polynomial};
/// # use ark_ff::One;
///
/// // The two-variate polynomial x_0 + 3 * x_0 * x_1 + 2 evaluates to [2, 3, 2, 6]
/// // in the two-dimensional hypercube with points [00, 10, 01, 11]
/// let mle = DenseMultilinearExtension::from_evaluations_vec(
/// 2, vec![2, 3, 2, 6].iter().map(|x| Fr::from(*x as u64)).collect()
/// );
///
/// // By the uniqueness of MLEs, `mle` is precisely the above polynomial, which
/// // takes the value 54 at the point (1, 17)
/// let eval = mle.evaluate(&[Fr::one(), Fr::from(17)].into());
/// assert_eq!(eval, Fr::from(54));
/// ```
fn evaluate(&self, point: &Self::Point) -> F {
MultilinearExtension::<F>::evaluate(self, point).unwrap()
assert!(point.len() == self.num_vars);
self.fix_variables(&point)[0]
}
}

#[cfg(test)]
mod tests {
use crate::{DenseMultilinearExtension, MultilinearExtension};
use crate::{DenseMultilinearExtension, MultilinearExtension, Polynomial};
use ark_ff::{Field, Zero};
use ark_std::{ops::Neg, test_rng, vec::Vec, UniformRand};
use ark_test_curves::bls12_381::Fr;
Expand Down Expand Up @@ -355,7 +348,7 @@ mod tests {
let point: Vec<_> = (0..10).map(|_| Fr::rand(&mut rng)).collect();
assert_eq!(
evaluate_data_array(&poly.evaluations, &point),
poly.evaluate(&point).unwrap()
poly.evaluate(&point)
)
}
}
Expand Down Expand Up @@ -405,32 +398,32 @@ mod tests {
let point: Vec<_> = (0..NV).map(|_| Fr::rand(&mut rng)).collect();
let poly1 = DenseMultilinearExtension::rand(NV, &mut rng);
let poly2 = DenseMultilinearExtension::rand(NV, &mut rng);
let v1 = poly1.evaluate(&point).unwrap();
let v2 = poly2.evaluate(&point).unwrap();
let v1 = poly1.evaluate(&point);
let v2 = poly2.evaluate(&point);
// test add
assert_eq!((&poly1 + &poly2).evaluate(&point).unwrap(), v1 + v2);
assert_eq!((&poly1 + &poly2).evaluate(&point), v1 + v2);
// test sub
assert_eq!((&poly1 - &poly2).evaluate(&point).unwrap(), v1 - v2);
assert_eq!((&poly1 - &poly2).evaluate(&point), v1 - v2);
// test negate
assert_eq!(poly1.clone().neg().evaluate(&point).unwrap(), -v1);
assert_eq!(poly1.clone().neg().evaluate(&point), -v1);
// test add assign
{
let mut poly1 = poly1.clone();
poly1 += &poly2;
assert_eq!(poly1.evaluate(&point).unwrap(), v1 + v2)
assert_eq!(poly1.evaluate(&point), v1 + v2)
}
// test sub assign
{
let mut poly1 = poly1.clone();
poly1 -= &poly2;
assert_eq!(poly1.evaluate(&point).unwrap(), v1 - v2)
assert_eq!(poly1.evaluate(&point), v1 - v2)
}
// test add assign with scalar
{
let mut poly1 = poly1.clone();
let scalar = Fr::rand(&mut rng);
poly1 += (scalar, &poly2);
assert_eq!(poly1.evaluate(&point).unwrap(), v1 + scalar * v2)
assert_eq!(poly1.evaluate(&point), v1 + scalar * v2)
}
// test additive identity
{
Expand All @@ -443,7 +436,7 @@ mod tests {
let mut zero = DenseMultilinearExtension::zero();
let scalar = Fr::rand(&mut rng);
zero += (scalar, &poly1);
assert_eq!(zero.evaluate(&point).unwrap(), scalar * v1);
assert_eq!(zero.evaluate(&point), scalar * v1);
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions poly/src/evaluations/multivariate/multilinear/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@ pub trait MultilinearExtension<F: Field>:
/// Returns the number of variables in `self`
fn num_vars(&self) -> usize;

/// Evaluates `self` at the given the vector `point` in slice.
/// If the number of variables does not match, return `None`.
fn evaluate(&self, point: &[F]) -> Option<F>;

/// Outputs an `l`-variate multilinear extension where value of evaluations
/// are sampled uniformly at random.
fn rand<R: Rng>(num_vars: usize, rng: &mut R) -> Self;
Expand Down
53 changes: 22 additions & 31 deletions poly/src/evaluations/multivariate/multilinear/sparse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,6 @@ impl<F: Field> MultilinearExtension<F> for SparseMultilinearExtension<F> {
self.num_vars
}

fn evaluate(&self, point: &[F]) -> Option<F> {
if point.len() == self.num_vars {
Some(self.fix_variables(point)[0])
} else {
None
}
}

/// Outputs an `l`-variate multilinear extension where value of evaluations
/// are sampled uniformly at random. The number of nonzero entries is
/// `sqrt(2^num_vars)` and indices of those nonzero entries are distributed
Expand Down Expand Up @@ -235,7 +227,8 @@ impl<F: Field> Polynomial<F> for SparseMultilinearExtension<F> {
}

fn evaluate(&self, point: &Self::Point) -> F {
MultilinearExtension::<F>::evaluate(self, point).unwrap()
assert!(point.len() == self.num_vars);
self.fix_variables(point)[0]
}
}

Expand Down Expand Up @@ -411,7 +404,8 @@ fn hashmap_to_treemap<F: Field>(map: &HashMap<usize, F>) -> BTreeMap<usize, F> {
#[cfg(test)]
mod tests {
use crate::{
evaluations::multivariate::multilinear::MultilinearExtension, SparseMultilinearExtension,
evaluations::multivariate::multilinear::MultilinearExtension, Polynomial,
SparseMultilinearExtension,
};
use ark_ff::{One, Zero};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
Expand Down Expand Up @@ -465,25 +459,22 @@ mod tests {
let mut rng = test_rng();
let ev1 = Fr::rand(&mut rng);
let poly1 = SparseMultilinearExtension::from_evaluations(0, &vec![(0, ev1)]);
assert_eq!(poly1.evaluate(&[]).unwrap(), ev1);
assert_eq!(poly1.evaluate(&[].into()), ev1);

// test single-variate polynomial
let ev2 = vec![Fr::rand(&mut rng), Fr::rand(&mut rng)];
let poly2 =
SparseMultilinearExtension::from_evaluations(1, &vec![(0, ev2[0]), (1, ev2[1])]);

let x = Fr::rand(&mut rng);
assert_eq!(
poly2.evaluate(&[x]).unwrap(),
x * ev2[1] + (Fr::one() - x) * ev2[0]
);
assert_eq!(poly2.evaluate(&[x].into()), x * ev2[1] + (Fr::one() - x) * ev2[0]);

// test single-variate polynomial with one entry missing
let ev3 = Fr::rand(&mut rng);
let poly2 = SparseMultilinearExtension::from_evaluations(1, &vec![(1, ev3)]);

let x = Fr::rand(&mut rng);
assert_eq!(poly2.evaluate(&[x]).unwrap(), x * ev3);
assert_eq!(poly2.evaluate(&[x].into()), x * ev3);
}

#[test]
Expand Down Expand Up @@ -512,32 +503,32 @@ mod tests {
let point: Vec<_> = (0..NV).map(|_| Fr::rand(&mut rng)).collect();
let poly1 = SparseMultilinearExtension::rand(NV, &mut rng);
let poly2 = SparseMultilinearExtension::rand(NV, &mut rng);
let v1 = poly1.evaluate(&point).unwrap();
let v2 = poly2.evaluate(&point).unwrap();
let v1 = poly1.evaluate(&point);
let v2 = poly2.evaluate(&point);
// test add
assert_eq!((&poly1 + &poly2).evaluate(&point).unwrap(), v1 + v2);
assert_eq!((&poly1 + &poly2).evaluate(&point), v1 + v2);
// test sub
assert_eq!((&poly1 - &poly2).evaluate(&point).unwrap(), v1 - v2);
assert_eq!((&poly1 - &poly2).evaluate(&point), v1 - v2);
// test negate
assert_eq!(poly1.clone().neg().evaluate(&point).unwrap(), -v1);
assert_eq!(poly1.clone().neg().evaluate(&point), -v1);
// test add assign
{
let mut poly1 = poly1.clone();
poly1 += &poly2;
assert_eq!(poly1.evaluate(&point).unwrap(), v1 + v2)
assert_eq!(poly1.evaluate(&point), v1 + v2)
}
// test sub assign
{
let mut poly1 = poly1.clone();
poly1 -= &poly2;
assert_eq!(poly1.evaluate(&point).unwrap(), v1 - v2)
assert_eq!(poly1.evaluate(&point), v1 - v2)
}
// test add assign with scalar
{
let mut poly1 = poly1.clone();
let scalar = Fr::rand(&mut rng);
poly1 += (scalar, &poly2);
assert_eq!(poly1.evaluate(&point).unwrap(), v1 + scalar * v2)
assert_eq!(poly1.evaluate(&point), v1 + scalar * v2)
}
// test additive identity
{
Expand All @@ -550,7 +541,7 @@ mod tests {
let mut zero = SparseMultilinearExtension::zero();
let scalar = Fr::rand(&mut rng);
zero += (scalar, &poly1);
assert_eq!(zero.evaluate(&point).unwrap(), scalar * v1);
assert_eq!(zero.evaluate(&point), scalar * v1);
}
}
}
Expand All @@ -563,29 +554,29 @@ mod tests {
let mut poly = SparseMultilinearExtension::rand(10, &mut rng);
let mut point: Vec<_> = (0..10).map(|_| Fr::rand(&mut rng)).collect();

let expected = poly.evaluate(&point).unwrap();
let expected = poly.evaluate(&point);

poly = poly.relabel(2, 2, 1); // should have no effect
assert_eq!(expected, poly.evaluate(&point).unwrap());
assert_eq!(expected, poly.evaluate(&point));

poly = poly.relabel(3, 4, 1); // should switch 3 and 4
point.swap(3, 4);
assert_eq!(expected, poly.evaluate(&point).unwrap());
assert_eq!(expected, poly.evaluate(&point));

poly = poly.relabel(7, 5, 1);
point.swap(7, 5);
assert_eq!(expected, poly.evaluate(&point).unwrap());
assert_eq!(expected, poly.evaluate(&point));

poly = poly.relabel(2, 5, 3);
point.swap(2, 5);
point.swap(3, 6);
point.swap(4, 7);
assert_eq!(expected, poly.evaluate(&point).unwrap());
assert_eq!(expected, poly.evaluate(&point));

poly = poly.relabel(7, 0, 2);
point.swap(0, 7);
point.swap(1, 8);
assert_eq!(expected, poly.evaluate(&point).unwrap());
assert_eq!(expected, poly.evaluate(&point));
}
}

Expand Down

0 comments on commit 14eb52a

Please sign in to comment.