2 *****************************************************************************
4 Implementation of functions to sample BACS examples with prescribed parameters
5 (according to some distribution).
7 See bacs_examples.hpp .
9 *****************************************************************************
10 * @author This file is part of libsnark, developed by SCIPR Lab
11 * and contributors (see AUTHORS).
12 * @copyright MIT license (see LICENSE file)
13 *****************************************************************************/
15 #ifndef BACS_EXAMPLES_TCC_
16 #define BACS_EXAMPLES_TCC_
19 #include <libff/common/utils.hpp>
24 template<typename FieldT>
25 linear_combination<FieldT> random_linear_combination(const size_t num_variables)
27 const size_t terms = 1 + (std::rand() % 3);
28 linear_combination<FieldT> result;
30 for (size_t i = 0; i < terms; ++i) {
32 FieldT(std::rand()); // TODO: replace with FieldT::random_element(),
33 // when it becomes faster...
35 coeff * variable<FieldT>(std::rand() % (num_variables + 1));
41 template<typename FieldT>
42 bacs_example<FieldT> generate_bacs_example(
43 const size_t primary_input_size,
44 const size_t auxiliary_input_size,
45 const size_t num_gates,
46 const size_t num_outputs)
48 bacs_example<FieldT> example;
49 for (size_t i = 0; i < primary_input_size; ++i) {
50 example.primary_input.emplace_back(FieldT::random_element());
53 for (size_t i = 0; i < auxiliary_input_size; ++i) {
54 example.auxiliary_input.emplace_back(FieldT::random_element());
57 example.circuit.primary_input_size = primary_input_size;
58 example.circuit.auxiliary_input_size = auxiliary_input_size;
60 bacs_variable_assignment<FieldT> all_vals;
63 example.primary_input.begin(),
64 example.primary_input.end());
67 example.auxiliary_input.begin(),
68 example.auxiliary_input.end());
70 for (size_t i = 0; i < num_gates; ++i) {
71 const size_t num_variables =
72 primary_input_size + auxiliary_input_size + i;
73 bacs_gate<FieldT> gate;
74 gate.lhs = random_linear_combination<FieldT>(num_variables);
75 gate.rhs = random_linear_combination<FieldT>(num_variables);
76 gate.output = variable<FieldT>(num_variables + 1);
78 if (i >= num_gates - num_outputs) {
79 /* make gate a circuit output and fix */
80 gate.is_circuit_output = true;
81 const var_index_t var_idx =
83 (1 + primary_input_size + std::min(num_gates - num_outputs, i));
84 const FieldT var_val =
85 (var_idx == 0 ? FieldT::one() : all_vals[var_idx - 1]);
87 if (std::rand() % 2 == 0) {
88 const FieldT lhs_val = gate.lhs.evaluate(all_vals);
89 const FieldT coeff = -(lhs_val * var_val.inverse());
90 gate.lhs = gate.lhs + coeff * variable<FieldT>(var_idx);
92 const FieldT rhs_val = gate.rhs.evaluate(all_vals);
93 const FieldT coeff = -(rhs_val * var_val.inverse());
94 gate.rhs = gate.rhs + coeff * variable<FieldT>(var_idx);
97 assert(gate.evaluate(all_vals).is_zero());
99 gate.is_circuit_output = false;
102 example.circuit.add_gate(gate);
103 all_vals.emplace_back(gate.evaluate(all_vals));
106 assert(example.circuit.is_satisfied(
107 example.primary_input, example.auxiliary_input));
112 } // namespace libsnark
114 #endif // BACS_EXAMPLES_TCC