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

feat: Simplify relation containers #2619

Merged
merged 48 commits into from
Oct 11, 2023

Conversation

codygunton
Copy link
Contributor

@codygunton codygunton commented Oct 2, 2023

The main goal of this PR is to simplify the construction of the containers that we use to accumulate relation values (in sumcheck and, soon, in Protogalaxy folding).

Core changes

  • Expose a View alias for each of the primitives that needs one (Univariate, field and field_t).
  • Add nested container classes that can be instantiated from a std::array of sizes. Credit: https://stackoverflow.com/a/60440611
  • Remove AccumulatorsAndViews types, replacing each with simply an accumulator type with a intrinsic notion of view.

Other changes

  • Bring ECCVM more in line with the rest of the relation and circuit builder code.
  • Add a get_row function to avoid passing index values to some functions.
  • Use more explicit or more appropriate type names (e.g., RelationUnivariates becomes TupleOfTuplesOfUnivariates, ClaimedEvaluations becomes AllValues outside of sumcheck, where it is now used in the execution trace builders).
  • Replace some autos with useful template parameter names, still deducing the types.
  • Deduce more types, especially in accumulate functions where now it is possible, since we don't have an 'alias container type' grouping a type with a view.
  • Use a more idiomatic approach to identify non-linearly independent subrelations.
  • Get rid of special proxy functions to accumulate functions.
  • Compile time calculation of individual relation lengths, possible now that the subrelation lengths live in a std::array.
  • Relations (always fully static) are no longer instantiated anywhere.

@codygunton codygunton self-assigned this Oct 3, 2023
@codygunton codygunton marked this pull request as ready for review October 6, 2023 22:53
Copy link
Contributor

@ledwards2225 ledwards2225 left a comment

Choose a reason for hiding this comment

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

Looks great. Just a few comments/questions about naming

using RelationUnivariates = decltype(create_relation_univariates_container<FF, Relations>());
using RelationValues = decltype(create_relation_values_container<FF, Relations>());
using TupleOfTuplesOfUnivariates = decltype(create_relation_univariates_container<FF, Relations>());
using TupleOfTuplesOfValues = decltype(create_relation_values_container<FF, Relations>());
Copy link
Contributor

Choose a reason for hiding this comment

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

Tuple of array of values?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it should be this, thanks.

using RelationUnivariates = decltype(create_relation_univariates_container<FF, Relations>());
using RelationValues = decltype(create_relation_values_container<FF, Relations>());
using TupleOfTuplesOfUnivariates = decltype(create_relation_univariates_container<FF, Relations>());
using TupleOfTuplesOfValues = decltype(create_relation_values_container<FF, Relations>());
Copy link
Contributor

Choose a reason for hiding this comment

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

again

@@ -501,31 +502,26 @@ template <typename Flavor> class ECCVMCircuitBuilder {
.eccvm_set_permutation_delta = eccvm_set_permutation_delta,
};

auto rows = compute_full_polynomials();
const size_t num_rows = rows[0].size();
auto polynomials = finalize();
Copy link
Contributor

Choose a reason for hiding this comment

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

this seems a bit awkward - why is finalize better?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was trying to bring this in line with what's done in Ultra where finalize is called at the beginning of check_circuit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But I see your point and I see that the flow in ECCVM has diverge more than I had realized, so I'm renaming to compute_polynomials.


static constexpr std::array<bool, 2> SUBRELATION_LINEARLY_INDEPENDENT = { true, false };

template <typename AccumulatorTypes>
static Accumulator<AccumulatorTypes> convert_to_wnaf(const auto& s0, const auto& s1)
Copy link
Contributor

Choose a reason for hiding this comment

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

surprised this is going away. Did it just move somewhere? or it wasn't used?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, i found it


static constexpr size_t LEN_1 = 6; // arithmetic sub-relation
template <template <size_t...> typename AccumulatorTypesContainer>
using GetAccumulatorTypes = AccumulatorTypesContainer<LEN_1,
Copy link
Contributor

Choose a reason for hiding this comment

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

hah. I didn't know how silly this had gotten

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah that's a lotta LEN_1s

return std::get<subrelation_index>(Relation::SUBRELATION_LINEARLY_INDEPENDENT);
}
using UnivariateAccumulator0 = std::tuple_element_t<0, TupleOfUnivariatesOverSubrelations>;
using ValueAccumulator0 = std::tuple_element_t<0, ArrayOfValuesOverSubrelations>;
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems a bit funny. Why do we need a special alias for the type of the first element? Can you add a comment explaining why the first element in the tuple is special?

@codygunton codygunton mentioned this pull request Oct 11, 2023
4 tasks
@codygunton codygunton merged commit 99c5127 into master Oct 11, 2023
@codygunton codygunton deleted the cg/pg-simplify-relation-containers branch October 11, 2023 16:54
/**
* @brief Check whether a given subrelation is linearly independent from the other subrelations.
*
* @details More often than not, we want multiply each subrelation contribution by a power of the relation separator
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* @details More often than not, we want multiply each subrelation contribution by a power of the relation separator
* @details More often than not, we want to multiply each subrelation contribution by a power of the relation separator

*
* @details More often than not, we want multiply each subrelation contribution by a power of the relation separator
* challenge. In cases where we wish to define a subrelation that merges into another, we encode this in a boolean array
* `SUBRELATION_LINEARLY_INDEPENDENT` in the relation. If no such array is defined, then the default case where all
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a very helpful comment and I think what's missing is a sentence explaining why we use this array i.e. what is the connection between linear independence and a subrelation merging into another


// Types needed for sumcheck and folding.
template <typename FF, auto LENGTHS>
using TupleOfUnivariates = typename TupleOfContainersOverArray<barretenberg::Univariate, FF, LENGTHS>::type;
Copy link
Contributor

Choose a reason for hiding this comment

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

My slight confusion about this might be caused by English being my second language but it took me a bit to parse that TupleOfContainersOverArray means "we take a tuple of containers from an array", and I still want to double check with you that this is correct. Reading the *OverFoo phrasing is the part that confused me throught the changes in PR.

accumulator, input, relation_parameters, scaling_factor);
}
using TupleOfUnivariatesOverSubrelations = TupleOfUnivariates<FF, RelationImpl::SUBRELATION_LENGTHS>;
using ArrayOfValuesOverSubrelations = ArrayOfValues<FF, RelationImpl::SUBRELATION_LENGTHS>;

Copy link
Contributor

Choose a reason for hiding this comment

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

While reading through other modifications of the PR that use either of these two using declarations, I found myself going back to here to remind myself how to visualise their structure, maybe having a descriptive example as comments would really help in future use.

Also, I think ArrayOfValues is confusing because underneath it is several tuples of values (..right?). If that is the case ArrayOfScalarTuples instead of ArrayOfValues sprang to mind as a better name.

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

Successfully merging this pull request may close these issues.

3 participants