Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LogUp-GKR evaluator #18

Open
wants to merge 4 commits into
base: next
Choose a base branch
from
Open

LogUp-GKR evaluator #18

wants to merge 4 commits into from

Conversation

Al-Kindi-0
Copy link
Owner

Incomplete implementation of the proposal here

Notes:

  1. Sum-check is simplified, we now only have 1 sum-check for degree 3 multivariates and another one for arbitrary degree multivariates specific to the input layer.
  2. The arbitrary degree sum-check has been optimized to avoid an expensive evaluation at one. This should result in approximately 25% improvement for degree 5 multivariates.
  3. The current proposal for the evaluator does not address the need to have the multi-linears of the main-trace column contributing to the LogUp relation. These are needed in order to run the sum-check for the input layer. On the other hand, if we have these multi-linears then some of the methods in the evaluator need to change.
  4. The treatment of the s-column is still missing and removing the old way of treating the Lagrange column is not full done.

Copy link
Collaborator

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This is not a full review - I just looked at the math crate-related changes and left some comments.

Overall, I think we should try to implement this in phases. For example, the first PR in Winterfell could be just for introducing new functions/modules into the math crate. When we do that, we take the time to implement most things in near-final form (e.g., removing un-needed allocations, potentially parallelizing the most critical things etc.)

math/src/polynom/univariate.rs Show resolved Hide resolved
math/src/polynom/univariate.rs Show resolved Hide resolved
math/src/polynom/univariate.rs Show resolved Hide resolved
Comment on lines +73 to +76
/// This means that we can compute the evaluations of q at 1, ..., n - 1 using the evaluations
/// of p and thus reduce by 1 the size of the interpolation problem.
/// Once the coefficient of q are recovered, the c0 coefficient is appended to these and this
/// is precisely the coefficient representation of the original polynomial q.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does q refer to here?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q is defined in the two bulletpoints just above, it is just the polynomial resulting from factoring x.

Comment on lines +81 to +90
// construct the vector of interpolation points 1, ..., n
let n_minus_1 = self.partial_evaluations.len();
let mut points = vec![E::BaseField::ZERO; n_minus_1];

// construct their inverses. These will be needed for computing the evaluations
// of the q polynomial as well as for doing the interpolation on q
points
.iter_mut()
.enumerate()
.for_each(|(i, node)| *node = E::BaseField::from(i as u32 + 1));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just constructing a vector with values 1, 2, 3, 4 ... - right? If so, we could do this as something like this to avoid first allocating and zeroing out the vector and then filling it in with values:

let points = (1..n_minus_1).iter().map(E::BaseField::from).collect::<Vec<_>>();

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Comment on lines +141 to +145
/// ```ignore
/// EQ: {0 , 1}^ν ⛌ {0 , 1}^ν ⇾ {0 , 1}
/// ((x_0, ..., x_{ν - 1}), (y_0, ..., y_{ν - 1})) ↦ \prod_{i = 0}^{ν - 1} (x_i * y_i + (1 - x_i)
/// * (1 - y_i))
/// ```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These, and other formulas, we should explicitly write as formals (i.e., using $$ in comments) so that they are displayed nicely in the docs.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added but not sure if it is the right way to do it. Do you have some documentation to help?

math/src/polynom/multi_linear.rs Show resolved Hide resolved
Comment on lines +214 to +216
/// Computes the evaluations of the Lagrange basis polynomials over the interpolating
/// set {0 , 1}^ν at (r_0, ..., r_{ν - 1}) i.e., the Lagrange kernel at (r_0, ..., r_{ν - 1}).
fn compute_lagrange_basis_evals_at<E: FieldElement>(query: &[E]) -> Vec<E> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't thought about this too much, but I'm curious if there is a way to parallelize this function.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought about it a bit but couldn't come up with something clever. This would actually be a very important function to parallelize so we should give it more thought in my opinion. Will think more about it.

Comment on lines +22 to +31
/// Constructs a [`MultiLinearPoly`] from its evaluations over the boolean hyper-cube {0 , 1}^ν.
pub fn from_evaluations(evaluations: Vec<E>) -> Result<Self, MultiLinearPolyError> {
if !evaluations.len().is_power_of_two() {
return Err(MultiLinearPolyError::EvaluationsNotPowerOfTwo);
}
Ok(Self {
num_variables: (evaluations.len().ilog2()) as usize,
evaluations,
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is OK to panic here is the number of evaluations is not a power of two. This way, we also won't need the MultiLinearPolyError enum.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

Comment on lines +69 to +80
/// Computes f(r_0, y_1, ..., y_{ν - 1}) using the linear interpolation formula
/// (1 - r_0) * f(0, y_1, ..., y_{ν - 1}) + r_0 * f(1, y_1, ..., y_{ν - 1}) and assigns
/// the resulting multi-linear, defined over a domain of half the size, to `self`.
pub fn bind_least_significant_variable(&mut self, round_challenge: E) {
let mut result = vec![E::ZERO; 1 << (self.num_variables() - 1)];
for (i, res) in result.iter_mut().enumerate() {
*res = self.evaluations[i << 1]
+ round_challenge * (self.evaluations[(i << 1) + 1] - self.evaluations[i << 1]);
}
*self = Self::from_evaluations(result)
.expect("should not fail given that it is a multi-linear");
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this function a little confusing. I think what we are doing is reducing the number of variables by 1 and as the result, halving the number of evaluations - right?

If so, we should probably just return a new MultiLinearPoly from here. For example, the signature could be:

pub fn bind_least_significant_variable(self, variable_value: E) -> Self

Another thing, it seems to me that we don't actually need to allocate the result vector. Instead, we may be able to update the self.evaluations vector in place and then just truncate its length. Or am I missing something?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the two suggestions compatible? I went with the second one and removed the need for result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants