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

Hybrid method for random access/conditional selection from 2^k values #119

Open
wants to merge 28 commits into
base: master
Choose a base branch
from

Conversation

mmagician
Copy link
Member

Description

Create O(sqrt(n)) instead of O(n) constraints as per https://github.com/mir-protocol/r1cs-workshop/blob/master/workshop.pdf.

By trying to make this as generic as possible, I had to add two extra methods on the trait, which for now are only implemented for FpVar for testing.
@arkworks-rs/maintainers do you see a way to NOT introduce these extra methods? I tried adding a trait bound for AllocVar to CondSelectGadget, but going down that rabbit hole hasn't worked so far.

Benches:

for k=7, 2^7=128 values

  1. Repeated-selection 5.1, O(n):
  • expecting2^(k-1) - 1 constraints
cond_select takes: 63 constraints, 347 non-zeros
  1. Hybrid method 5.3, O(sqrt(n)):
  • expect 2^m + 2^l - l - 2 constraints
  • m = k/2 = 3; l = 4; 2^3 + 2^4 - 4 - 2 = 18
cond_select takes: 18 constraints, 184 non-zeros

as expected.

closes: #118


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (master)
  • Linked to Github issue with discussion and accepted design OR have an explanation in the PR that describes this work.
  • Wrote unit tests
  • Updated relevant documentation in the code
  • Added a relevant changelog entry to the Pending section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer

Copy link
Member

@Pratyush Pratyush left a comment

Choose a reason for hiding this comment

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

Leaving an initial review for the time being, but if the selection methods are not generic, maybe we can add the methods to FpVar as inherent methods for the time being?

Comment on lines 992 to 998
fn allocate_to_lc(
var: Variable,
val: &Self,
cs: &ConstraintSystemRef<F>,
) -> Result<Self, SynthesisError> {
let v = val.value()?;
Ok(AllocatedFp::new(Some(v), var, cs.clone()).into())
Copy link
Member

Choose a reason for hiding this comment

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

Hm not sure what this method is doing; is it just a clone of the variable?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's a chance I'm doing something wrong here. The way I understand it is that I have an LC that corresponds to some Variable in the constraint system, and I need to fix it to some value. But I need to retrieve something of type Self (CondSelectGadget) that is equal to that LC, since the repeated_selection sub-routine (which used to be the main routine before this PR) operates on CondSelectGadget elements.

Perhaps the method name isn't great... what I thought of doing was, as mentioned in the PR description, adding a trait bound for AllocVar so that I could call AllocVar>::new_variable, but I'm not really sure of how to do this.

Comment on lines 983 to 989
fn add_lc(
val: &Self,
lc: &LinearCombination<F>,
) -> Result<LinearCombination<F>, SynthesisError> {
let root: LinearCombination<F> = LinearCombination::zero();
let v = val.value()?;
Ok(root + (v, lc))
Copy link
Member

Choose a reason for hiding this comment

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

Why doesn't it suffice to just use addition on FpVar?

Copy link
Member

Choose a reason for hiding this comment

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

Or, sum?

Copy link
Member Author

Choose a reason for hiding this comment

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

I simplified this slightly.

lc: LinearCombination<F>,
) -> Result<LinearCombination<F>, SynthesisError> {
let v = val.value()?;
Ok(lc * v)
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure what this method will look like for ECVar points.

@mmagician
Copy link
Member Author

The selection methods should be generic. I don't know yet how the implementation would look for EC points, where I can't just get a single underlying value F. Possibly I'll need to adapt the interface or generic impl.

@mmagician mmagician marked this pull request as ready for review May 9, 2023 01:52
@mmagician
Copy link
Member Author

mmagician commented May 9, 2023

@Pratyush I couldn't find an intuitive interface for abstracting away the repeated part of the logic, so in the end I've followed your suggestion and have default implementation use the repeated-selection method. My best attempt is here, but then even I quickly get lost in what the method is supposed to be doing 🤣 I've implemented the improved version for:

  • Boolean & AllocatedBool
  • FpVar & AllocatedFp
  • ProjectiveVar

I've benched some of the new ones too:
before:

FpVar_select takes: 63 constraints, 347 non-zeros
Boolean_select takes: 56 constraints, 260 non-zeros
SWProjective_select takes: 189 constraints, 945 non-zeros

after:

FpVar_select takes: 18 constraints, 184 non-zeros
Boolean_select takes: 22 constraints, 130 non-zeros
SWProjective_select takes: 54 constraints, 428 non-zeros

@mmagician
Copy link
Member Author

Also @dlubarov @bpfarmer in case you're interested in having a look at this implementation based on your workshop doc.

@Pratyush
Copy link
Member

@mmagician Do you have recommendations on how I should go about reviewing the PR?

@mmagician
Copy link
Member Author

@Pratyush I can share my circom reference impl with you and maybe we can go through this PR during the maintainers' call next week?

@Pratyush
Copy link
Member

Sure!

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.

Implement O(sqrt(n)) conditionally_select_power_of_two_vector method
2 participants