Closed weikengchen closed 3 years ago
It turns out that I cannot assign a reviewer here. So, let me here cc Pratyush for a review. @Pratyush
We may, in the future, has an improvement plan for outline_lcs
, since the resulting saving is not as large as expected.
Thanks for the PR! Given that there was a subtle bug in the logic here, would it be possible to add some comments documenting the algorithm?
No problem. On the way!
The documentation has been added. Please take a look :)
For the new_witness
, yes, good point, let me use new_witness
instead.
For the new constraint via enforce_constraint
, it has a problem---our code is modifying the lc_map but enforce_constraint
would also push to it, causing a conflict (that our code may overwrite the change). But let me take a more careful look to see I can still use enforce_constraint
in a black-box way if I save the lc_map
earlier.
For the new_constraint
issue, maybe we can extract the common logic into a separate method that is called in both places?
Yes. But I feel that probably I can call new_constraint
directly if I do self.lc_map = outlined_lcs;
earlier, since these new constraints all use outlined LCs (so no more processing is needed).
I use new_constraint
directly, so the code is now slightly simplified.
I didn't use new_witness
for a specific reason:
new_witness
somehow has to be in the for
loop of self.lc_map
. Moving it out could lead to potential missing assignments.new_witness
takes &mut self
as input, but this is forbidden (since self
is currently used for iteration).new_witness
to use &mut self
, I need to clone self.lc_map
, but the memory usage might be too high.Thus, given that the logic of new_witness
is simple, I just write the same code again.
Note: I need to test the upstream Marlin for this PR to see if it is working. So don't merge now!
Hmm in that case we should document that this is the same logic as new_witness
.
Also, speaking of memory requirements, we should "garbage-collect" the LCs that are inlined/put in new variables, like we do in inline_all_lcs
Got it. Let me have some tries.
Thanks for fixing this bug!
More review is welcome. Let me merge the suggestions!
I updated the suggestions. Currently testing with Marlin.
@ValarDragon can do a final pass over the new comments that try to explain the loop.
The upstream test passes, and it is ready to merge if no other issues pop up.
(ps I need someone who has write access.)
Doing a final review pass, and then I'll merge!
Thanks for the review. I will resolve the comments soon and also merge the logic of the two functions for fewer repetitions.
(I might have some delays due to sending the Mac for fixing---my "e" key is now an "ee" key.)
Response to this:
In a future PR, I think we should be able to improve the efficiency by changing new_lc_map to being just a map of the differences (SymbolicLC -> Var). (Instead of making a copy of all the LC's)
Indeed almost all lcs would be rewritten due to inlining (all symbolic LCs are replaced by linear combinations of input/witness variables).
The implementation has been refactored in that the common elements between inline_all_lcs
and outline_lcs
are extracted.
@Pratyush @ValarDragon You may want to give a fresh reading to see if the logic flows right.
Note: The PR is not ready for merging, as I need to test it on Groth16 and Marlin.
And also, should we change outline_lcs
to outline_all_lcs
?
A bug has been fixed. It now passes on Groth16 and Marlin.
Opinions on changing outline_lcs
to outline_all_lcs
? This is a good chance to decide (since it has not been used anywhere else).
I think outline_lcs
is better, as we're not outlining all the LCs, only those that are large, no?
That makes sense!
This function is presumably not an external facing API right?
The external facing api should probably be "reduce_matrix_density"
Indeed it will be externally facing, in that Marlin calls outline_lcs instead of inline_all_lcs before converting the constraint system into a matrix.
Technically, outline_lcs is also mostly inlining.
I see. I think we should make this function private, and make the external facing function reduce_matrix_arity
(or reduce_constraint_density
or something), which will then call this function. In the future, other matrix arity optimizations may make it in there.
I would call it reduce_constraint_weight
since Ale uses weight
in our paper on recursive Marlin.
Ok. The final change passes the CI.
I hereby need one person with write access to merge this PR.
In that case, should we provide a higher level API to inline_all_lcs too?
perhaps a single “finalize” method that takes in a rename OptimizationMode enum and then internally calls inline_lcs or outline_lcs? (This can be a separate PR)
After careful debugging, it appears that the current implementation of
outline_lcs
has two serious problems:It does not correctly create additional constraints. All the additional constraints should be
LC * 1 = V
where V is the new witness variable. In the end, all of them areV * 1 = V
.It does not increase the count of
num_linear_combinations
correctly. So that in Marlin, when the next step wants to pad the matrices to be square, the new linear combinations go to the wrong linear combination entry, causing the outer check to fail.This PR fixes these two problems and will close this issue in Marlin: https://github.com/arkworks-rs/marlin/issues/56