Skip to content

Commit

Permalink
feat: Simplify relation containers (#2619)
Browse files Browse the repository at this point in the history
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 `auto`s 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.
  • Loading branch information
codygunton authored Oct 11, 2023
1 parent 082ab56 commit 99c5127
Show file tree
Hide file tree
Showing 51 changed files with 1,201 additions and 1,378 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,17 @@ template <typename Flavor, typename Relation> void execute_relation(::benchmark:
.public_input_delta = public_input_delta,
};

using ClaimedEvaluations = typename Flavor::ClaimedEvaluations;
using RelationValues = typename Relation::RelationValues;
using AllValues = typename Flavor::AllValues;
using ArrayOfValuesOverSubrelations = typename Relation::ArrayOfValuesOverSubrelations;

// Extract an array containing all the polynomial evaluations at a given row i
ClaimedEvaluations new_value;
// Define the appropriate RelationValues type for this relation and initialize to zero
RelationValues accumulator;
AllValues new_value;
// Define the appropriate ArrayOfValuesOverSubrelations type for this relation and initialize to zero
ArrayOfValuesOverSubrelations accumulator;
// Evaluate each constraint in the relation and check that each is satisfied

Relation relation;
for (auto _ : state) {
relation.add_full_relation_value_contribution(accumulator, new_value, params);
Relation::accumulate(accumulator, new_value, params, 1);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
namespace barretenberg {
template <class Params_> struct alignas(32) field {
public:
using View = field;
using Params = Params_;
using in_buf = const uint8_t*;
using vec_in_buf = const uint8_t*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ template <ECCVMFlavor Flavor> void ECCVMComposer_<Flavor>::compute_witness(Circu
return;
}

auto polynomials = circuit_constructor.compute_full_polynomials();
auto polynomials = circuit_constructor.compute_polynomials();

auto key_wires = proving_key->get_wires();
auto poly_wires = polynomials.get_wires();
Expand Down
423 changes: 228 additions & 195 deletions barretenberg/cpp/src/barretenberg/honk/flavor/ecc_vm.hpp

Large diffs are not rendered by default.

21 changes: 20 additions & 1 deletion barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ TEST(Flavor, Getters)
Flavor::VerificationKey verification_key;
Flavor::ProverPolynomials prover_polynomials;
Flavor::ExtendedEdges<Flavor::NUM_ALL_ENTITIES> edges;
Flavor::ClaimedEvaluations evals;
Flavor::AllValues evals;
Flavor::CommitmentLabels commitment_labels;

// Globals are also available through STL container sizes
Expand Down Expand Up @@ -131,4 +131,23 @@ TEST(Flavor, AllEntitiesSpecialMemberFunctions)
ASSERT_EQ(random_poly, polynomials_C.w_l);
}

TEST(Flavor, GetRow)
{
using Flavor = proof_system::honk::flavor::Ultra;
using FF = typename Flavor::FF;
std::array<std::vector<FF>, Flavor::NUM_ALL_ENTITIES> data;
std::generate(data.begin(), data.end(), []() {
return std::vector<FF>({ FF::random_element(), FF::random_element() });
});
Flavor::ProverPolynomials prover_polynomials;
size_t poly_idx = 0;
for (auto& poly : prover_polynomials) {
poly = data[poly_idx];
poly_idx++;
}
auto row0 = prover_polynomials.get_row(0);
auto row1 = prover_polynomials.get_row(1);
EXPECT_EQ(row0.q_elliptic, prover_polynomials.q_elliptic[0]);
EXPECT_EQ(row1.w_4_shift, prover_polynomials.w_4_shift[1]);
}
} // namespace proof_system::test_flavor
11 changes: 5 additions & 6 deletions barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class GoblinUltra {
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;

// define the container for storing the univariate contribution from each relation in Sumcheck
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 TupleOfArraysOfValues = decltype(create_relation_values_container<FF, Relations>());

// Whether or not the first row of the execution trace is reserved for 0s to enable shifts
static constexpr bool has_zero_row = true;
Expand Down Expand Up @@ -332,14 +332,13 @@ class GoblinUltra {
barretenberg::Univariate<FF, MAX_RELATION_LENGTH>>;

/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
* @brief A field element for each entity of the flavor.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
class AllValues : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ template <typename BuilderType> class GoblinUltraRecursive_ {
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;

// define the container for storing the univariate contribution from each relation in Sumcheck
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 TupleOfArraysOfValues = decltype(create_relation_values_container<FF, Relations>());

private:
template <typename DataType, typename HandleType>
Expand Down Expand Up @@ -343,14 +343,13 @@ template <typename BuilderType> class GoblinUltraRecursive_ {
};

/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
* @brief A field element for each entity of the flavor.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
class AllValues : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
Expand Down
39 changes: 25 additions & 14 deletions barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ class Ultra {
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;

// define the container for storing the univariate contribution from each relation in Sumcheck
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 TupleOfArraysOfValues = decltype(create_relation_values_container<FF, Relations>());

// Whether or not the first row of the execution trace is reserved for 0s to enable shifts
static constexpr bool has_zero_row = true;
Expand Down Expand Up @@ -271,10 +271,32 @@ class Ultra {
*/
using VerificationKey = VerificationKey_<PrecomputedEntities<Commitment, CommitmentHandle>>;

/**
* @brief A field element for each entity of the flavor.
*/
class AllValues : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
* @brief A container for polynomials handles; only stores spans.
*/
using ProverPolynomials = AllEntities<PolynomialHandle, PolynomialHandle>;
class ProverPolynomials : public AllEntities<PolynomialHandle, PolynomialHandle> {
public:
AllValues get_row(const size_t row_idx)
{
AllValues result;
size_t column_idx = 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip
for (auto& column : this->_data) {
result[column_idx] = column[row_idx];
column_idx++;
}
return result;
}
};

/**
* @brief A container for storing the partially evaluated multivariates produced by sumcheck.
Expand All @@ -300,17 +322,6 @@ class Ultra {
using ExtendedEdges = AllEntities<barretenberg::Univariate<FF, MAX_RELATION_LENGTH>,
barretenberg::Univariate<FF, MAX_RELATION_LENGTH>>;

/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
* @brief A container for commitment labels.
* @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It
Expand Down
11 changes: 5 additions & 6 deletions barretenberg/cpp/src/barretenberg/honk/flavor/ultra_grumpkin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class UltraGrumpkin {
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;

// define the container for storing the univariate contribution from each relation in Sumcheck
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 TupleOfArraysOfValues = decltype(create_relation_values_container<FF, Relations>());

// Whether or not the first row of the execution trace is reserved for 0s to enable shifts
static constexpr bool has_zero_row = true;
Expand Down Expand Up @@ -308,14 +308,13 @@ class UltraGrumpkin {
barretenberg::Univariate<FF, MAX_RELATION_LENGTH>>;

/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
* @brief A field element for each entity of the flavor.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
class AllValues : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ template <typename BuilderType> class UltraRecursive_ {
static constexpr size_t NUM_RELATIONS = std::tuple_size<Relations>::value;

// define the container for storing the univariate contribution from each relation in Sumcheck
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 TupleOfArraysOfValues = decltype(create_relation_values_container<FF, Relations>());

private:
template <typename DataType, typename HandleType>
Expand Down Expand Up @@ -308,14 +308,13 @@ template <typename BuilderType> class UltraRecursive_ {
};

/**
* @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the
* evaluations of polynomials committed in earlier rounds.
* @brief A field element for each entity of the flavor.
*/
class ClaimedEvaluations : public AllEntities<FF, FF> {
class AllValues : public AllEntities<FF, FF> {
public:
using Base = AllEntities<FF, FF>;
using Base::Base;
ClaimedEvaluations(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
AllValues(std::array<FF, NUM_ALL_ENTITIES> _data_in) { this->_data = _data_in; }
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ std::shared_ptr<typename Flavor::VerificationKey> compute_verification_key_commo

auto commitment_key = typename Flavor::CommitmentKey(proving_key->circuit_size, proving_key->crs);

size_t poly_idx = 0; // TODO(#391) zip
size_t poly_idx = 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip
for (auto& polynomial : proving_key) {
verification_key[poly_idx] = commitment_key.commit(polynomial);
++polynomial_idx;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ ECCVMProver_<Flavor>::ECCVMProver_(std::shared_ptr<typename Flavor::ProvingKey>
prover_polynomials.lookup_inverses = key->lookup_inverses;
key->z_perm = Polynomial(key->circuit_size);
prover_polynomials.z_perm = key->z_perm;
prover_polynomials.z_perm_shift = key->z_perm; // this will be initialized properly later
}

/**
Expand Down Expand Up @@ -247,7 +248,7 @@ template <ECCVMFlavor Flavor> void ECCVMProver_<Flavor>::execute_univariatizatio

// Batch the unshifted polynomials and the to-be-shifted polynomials using ρ
Polynomial batched_poly_unshifted(key->circuit_size); // batched unshifted polynomials
size_t poly_idx = 0; // TODO(#391) zip
size_t poly_idx = 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip
for (auto& unshifted_poly : prover_polynomials.get_unshifted()) {
batched_poly_unshifted.add_scaled(unshifted_poly, rhos[poly_idx]);
++poly_idx;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ namespace proof_system::honk::grand_product_library {
*/
template <typename Flavor, typename GrandProdRelation>
void compute_grand_product(const size_t circuit_size,
auto& full_polynomials,
typename Flavor::ProverPolynomials& full_polynomials,
proof_system::RelationParameters<typename Flavor::FF>& relation_parameters)
{
using FF = typename Flavor::FF;
using Polynomial = typename Flavor::Polynomial;
using ValueAccumulatorsAndViews = typename GrandProdRelation::ValueAccumulatorsAndViews;
using Accumulator = std::tuple_element_t<0, typename GrandProdRelation::ArrayOfValuesOverSubrelations>;

// Allocate numerator/denominator polynomials that will serve as scratch space
// TODO(zac) we can re-use the permutation polynomial as the numerator polynomial. Reduces readability
Expand All @@ -67,15 +67,14 @@ void compute_grand_product(const size_t circuit_size,
const size_t start = thread_idx * block_size;
const size_t end = (thread_idx + 1) * block_size;
for (size_t i = start; i < end; ++i) {

typename Flavor::ClaimedEvaluations evaluations;
typename Flavor::AllValues evaluations;
for (size_t k = 0; k < Flavor::NUM_ALL_ENTITIES; ++k) {
evaluations[k] = full_polynomials[k].size() > i ? full_polynomials[k][i] : 0;
}
numerator[i] = GrandProdRelation::template compute_grand_product_numerator<ValueAccumulatorsAndViews>(
evaluations, relation_parameters, i);
denominator[i] = GrandProdRelation::template compute_grand_product_denominator<ValueAccumulatorsAndViews>(
evaluations, relation_parameters, i);
numerator[i] = GrandProdRelation::template compute_grand_product_numerator<Accumulator>(
evaluations, relation_parameters);
denominator[i] = GrandProdRelation::template compute_grand_product_denominator<Accumulator>(
evaluations, relation_parameters);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,33 +23,33 @@ namespace proof_system::honk::lookup_library {
* The specific algebraic relations that define read terms and write terms are defined in Flavor::LookupRelation
*
*/
template <typename Flavor, typename Relation>
void compute_logderivative_inverse(auto& polynomials,
template <typename Flavor, typename Relation, typename Polynomials>
void compute_logderivative_inverse(Polynomials& polynomials,
proof_system::RelationParameters<typename Flavor::FF>& relation_parameters,
const size_t circuit_size)
{
using FF = typename Flavor::FF;
using Accumulator = typename Relation::ValueAccumulatorsAndViews;
using Accumulator = typename Relation::ValueAccumulator0;
constexpr size_t READ_TERMS = Relation::READ_TERMS;
constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
auto& inverse_polynomial = polynomials.lookup_inverses;

auto lookup_relation = Relation();
for (size_t i = 0; i < circuit_size; ++i) {
bool has_inverse =
lookup_relation.template lookup_exists_at_row_index<Accumulator>(polynomials, relation_parameters, i);
auto row = polynomials.get_row(i);
bool has_inverse = lookup_relation.lookup_exists_at_row(row);
if (!has_inverse) {
continue;
}
FF denominator = 1;
barretenberg::constexpr_for<0, READ_TERMS, 1>([&]<size_t read_index> {
auto denominator_term = lookup_relation.template compute_read_term<Accumulator, read_index>(
polynomials, relation_parameters, i);
auto denominator_term =
lookup_relation.template compute_read_term<Accumulator, read_index>(row, relation_parameters);
denominator *= denominator_term;
});
barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]<size_t write_index> {
auto denominator_term = lookup_relation.template compute_write_term<Accumulator, write_index>(
polynomials, relation_parameters, i);
auto denominator_term =
lookup_relation.template compute_write_term<Accumulator, write_index>(row, relation_parameters);
denominator *= denominator_term;
});
inverse_polynomial[i] = denominator;
Expand Down
Loading

0 comments on commit 99c5127

Please sign in to comment.