barretenberg
Loading...
Searching...
No Matches
logderivative_library.hpp
1#pragma once
2#include <typeinfo>
3
4namespace proof_system::honk::logderivative_library {
5
25template <typename Flavor, typename Relation, typename Polynomials>
26void compute_logderivative_inverse(Polynomials& polynomials, auto& relation_parameters, const size_t circuit_size)
27{
28 using FF = typename Flavor::FF;
29 using Accumulator = typename Relation::ValueAccumulator0;
30 constexpr size_t READ_TERMS = Relation::READ_TERMS;
31 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
32
33 auto lookup_relation = Relation();
34 auto& inverse_polynomial = lookup_relation.template get_inverse_polynomial(polynomials);
35 for (size_t i = 0; i < circuit_size; ++i) {
36 auto row = polynomials.get_row(i);
37 bool has_inverse = lookup_relation.operation_exists_at_row(row);
38 if (!has_inverse) {
39 continue;
40 }
41 FF denominator = 1;
42 barretenberg::constexpr_for<0, READ_TERMS, 1>([&]<size_t read_index> {
43 auto denominator_term =
44 lookup_relation.template compute_read_term<Accumulator, read_index>(row, relation_parameters);
45 denominator *= denominator_term;
46 });
47 barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]<size_t write_index> {
48 auto denominator_term =
49 lookup_relation.template compute_write_term<Accumulator, write_index>(row, relation_parameters);
50 denominator *= denominator_term;
51 });
52 inverse_polynomial[i] = denominator;
53 };
54
55 // todo might be inverting zero in field bleh bleh
56 FF::batch_invert(inverse_polynomial);
57}
58
86template <typename FF, typename Relation, typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
87void accumulate_logderivative_lookup_subrelation_contributions(ContainerOverSubrelations& accumulator,
88 const AllEntities& in,
89 const Parameters& params,
90 const FF& scaling_factor)
91{
92 constexpr size_t READ_TERMS = Relation::READ_TERMS;
93 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
94
95 auto lookup_relation = Relation();
96
97 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
98 using View = typename Accumulator::View;
99
100 auto lookup_inverses = View(lookup_relation.template get_inverse_polynomial(in));
101
102 constexpr size_t NUM_TOTAL_TERMS = READ_TERMS + WRITE_TERMS;
103 std::array<Accumulator, NUM_TOTAL_TERMS> lookup_terms;
104 std::array<Accumulator, NUM_TOTAL_TERMS> denominator_accumulator;
105
106 // The lookup relation = \sum_j (1 / read_term[j]) - \sum_k (read_counts[k] / write_term[k])
107 // To get the inverses (1 / read_term[i]), (1 / write_term[i]), we have a commitment to the product of all inverses
108 // i.e. lookup_inverse = \prod_j (1 / read_term[j]) * \prod_k (1 / write_term[k])
109 // The purpose of this next section is to derive individual inverse terms using `lookup_inverses`
110 // i.e. (1 / read_term[i]) = lookup_inverse * \prod_{j /ne i} (read_term[j]) * \prod_k (write_term[k])
111 // (1 / write_term[i]) = lookup_inverse * \prod_j (read_term[j]) * \prod_{k ne i} (write_term[k])
112 barretenberg::constexpr_for<0, READ_TERMS, 1>(
113 [&]<size_t i>() { lookup_terms[i] = lookup_relation.template compute_read_term<Accumulator, i>(in, params); });
114 barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]<size_t i>() {
115 lookup_terms[i + READ_TERMS] = lookup_relation.template compute_write_term<Accumulator, i>(in, params);
116 });
117
118 barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>(
119 [&]<size_t i>() { denominator_accumulator[i] = lookup_terms[i]; });
120
121 barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>(
122 [&]<size_t i>() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; });
123
124 auto inverse_accumulator = Accumulator(lookup_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1];
125
126 const auto inverse_exists = lookup_relation.template compute_inverse_exists<Accumulator>(in);
127
128 // Note: the lookup_inverses are computed so that the value is 0 if !inverse_exists
129 std::get<0>(accumulator) +=
130 (denominator_accumulator[NUM_TOTAL_TERMS - 1] * lookup_inverses - inverse_exists) * scaling_factor;
131
132 // After this algo, total degree of denominator_accumulator = NUM_TOTAL_TERMS
133 for (size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) {
134 denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] =
135 denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator;
136 inverse_accumulator = inverse_accumulator * lookup_terms[NUM_TOTAL_TERMS - 1 - i];
137 }
138 denominator_accumulator[0] = inverse_accumulator;
139
140 // each predicate is degree-1
141 // degree of relation at this point = NUM_TOTAL_TERMS + 1
142 barretenberg::constexpr_for<0, READ_TERMS, 1>([&]<size_t i>() {
143 std::get<1>(accumulator) +=
144 lookup_relation.template compute_read_term_predicate<Accumulator, i>(in) * denominator_accumulator[i];
145 });
146
147 // each predicate is degree-1, `lookup_read_counts` is degree-1
148 // degree of relation = NUM_TOTAL_TERMS + 2
149 barretenberg::constexpr_for<0, WRITE_TERMS, 1>([&]<size_t i>() {
150 const auto p = lookup_relation.template compute_write_term_predicate<Accumulator, i>(in);
151 const auto lookup_read_count = lookup_relation.template lookup_read_counts<Accumulator, i>(in);
152 std::get<1>(accumulator) -= p * (denominator_accumulator[i + READ_TERMS] * lookup_read_count);
153 });
154}
155
185template <typename FF, typename Relation, typename ContainerOverSubrelations, typename AllEntities, typename Parameters>
186void accumulate_logderivative_permutation_subrelation_contributions(ContainerOverSubrelations& accumulator,
187 const AllEntities& in,
188 const Parameters& params,
189 const FF& scaling_factor)
190{
191 constexpr size_t READ_TERMS = Relation::READ_TERMS;
192 constexpr size_t WRITE_TERMS = Relation::WRITE_TERMS;
193
194 // For now we only do simple permutations over tuples with 1 read and 1 write term
195 static_assert(READ_TERMS == 1);
196 static_assert(WRITE_TERMS == 1);
197
198 auto permutation_relation = Relation();
199
200 using Accumulator = typename std::tuple_element_t<0, ContainerOverSubrelations>;
201 using View = typename Accumulator::View;
202
203 auto permutation_inverses = View(permutation_relation.template get_inverse_polynomial(in));
204
205 constexpr size_t NUM_TOTAL_TERMS = 2;
206 std::array<Accumulator, NUM_TOTAL_TERMS> permutation_terms;
207 std::array<Accumulator, NUM_TOTAL_TERMS> denominator_accumulator;
208
209 // The permutation relation = 1 / read_term - 1 / write_term
210 // To get the inverses (1 / read_term), (1 / write_term), we have a commitment to the product ofinver ses
211 // i.e. permutation_inverses = (1 / read_term) * (1 / write_term)
212 // The purpose of this next section is to derive individual inverse terms using `permutation_inverses`
213 // i.e. (1 / read_term) = permutation_inverses * write_term
214 // (1 / write_term) = permutation_inverses * read_term
215 permutation_terms[0] = permutation_relation.template compute_read_term<Accumulator, 0>(in, params);
216 permutation_terms[1] = permutation_relation.template compute_write_term<Accumulator, 0>(in, params);
217
218 barretenberg::constexpr_for<0, NUM_TOTAL_TERMS, 1>(
219 [&]<size_t i>() { denominator_accumulator[i] = permutation_terms[i]; });
220
221 barretenberg::constexpr_for<0, NUM_TOTAL_TERMS - 1, 1>(
222 [&]<size_t i>() { denominator_accumulator[i + 1] *= denominator_accumulator[i]; });
223
224 auto inverse_accumulator = Accumulator(permutation_inverses); // denominator_accumulator[NUM_TOTAL_TERMS - 1];
225
226 const auto inverse_exists = permutation_relation.template compute_inverse_exists<Accumulator>(in);
227
228 // Note: the lookup_inverses are computed so that the value is 0 if !inverse_exists
229 std::get<0>(accumulator) +=
230 (denominator_accumulator[NUM_TOTAL_TERMS - 1] * permutation_inverses - inverse_exists) * scaling_factor;
231
232 // After this algo, total degree of denominator_accumulator = NUM_TOTAL_TERMS
233 for (size_t i = 0; i < NUM_TOTAL_TERMS - 1; ++i) {
234 denominator_accumulator[NUM_TOTAL_TERMS - 1 - i] =
235 denominator_accumulator[NUM_TOTAL_TERMS - 2 - i] * inverse_accumulator;
236 inverse_accumulator = inverse_accumulator * permutation_terms[NUM_TOTAL_TERMS - 1 - i];
237 }
238 denominator_accumulator[0] = inverse_accumulator;
239
240 // each predicate is degree-1
241 // degree of relation at this point = NUM_TOTAL_TERMS + 1
242 std::get<1>(accumulator) +=
243 permutation_relation.template compute_read_term_predicate<Accumulator, 0>(in) * denominator_accumulator[0];
244
245 // each predicate is degree-1
246 // degree of relation = NUM_TOTAL_TERMS + 1
247 std::get<1>(accumulator) -=
248 permutation_relation.template compute_write_term_predicate<Accumulator, 0>(in) * denominator_accumulator[1];
249}
250} // namespace proof_system::honk::logderivative_library
constexpr void constexpr_for(F &&f)
Implements a loop using a compile-time iterator. Requires c++20. Implementation (and description) fro...
Definition: constexpr_utils.hpp:65