2  *****************************************************************************
 
    4  Implementation of interfaces for:
 
    5  - a BACS variable assignment,
 
    7  - a BACS primary input,
 
    8  - a BACS auxiliary input,
 
   13  *****************************************************************************
 
   14  * @author     This file is part of libsnark, developed by SCIPR Lab
 
   15  *             and contributors (see AUTHORS).
 
   16  * @copyright  MIT license (see LICENSE file)
 
   17  *****************************************************************************/
 
   23 #include <libff/common/profiling.hpp>
 
   24 #include <libff/common/utils.hpp>
 
   29 template<typename FieldT>
 
   30 FieldT bacs_gate<FieldT>::evaluate(
 
   31     const bacs_variable_assignment<FieldT> &input) const
 
   33     return lhs.evaluate(input) * rhs.evaluate(input);
 
   36 template<typename FieldT>
 
   37 void bacs_gate<FieldT>::print(
 
   38     const std::map<size_t, std::string> &variable_annotations) const
 
   41     lhs.print(variable_annotations);
 
   43     rhs.print(variable_annotations);
 
   45     auto it = variable_annotations.find(output.index);
 
   49         (it == variable_annotations.end() ? "no annotation"
 
   50                                           : it->second.c_str()),
 
   51         (is_circuit_output ? "circuit output" : "internal wire"));
 
   54 template<typename FieldT>
 
   55 bool bacs_gate<FieldT>::operator==(const bacs_gate<FieldT> &other) const
 
   58         this->lhs == other.lhs && this->rhs == other.rhs &&
 
   59         this->output == other.output &&
 
   60         this->is_circuit_output == other.is_circuit_output);
 
   63 template<typename FieldT>
 
   64 std::ostream &operator<<(std::ostream &out, const bacs_gate<FieldT> &g)
 
   66     out << (g.is_circuit_output ? 1 : 0) << "\n";
 
   67     out << g.lhs << OUTPUT_NEWLINE;
 
   68     out << g.rhs << OUTPUT_NEWLINE;
 
   69     out << g.output.index << "\n";
 
   74 template<typename FieldT>
 
   75 std::istream &operator>>(std::istream &in, bacs_gate<FieldT> &g)
 
   79     libff::consume_newline(in);
 
   80     g.is_circuit_output = (tmp != 0 ? true : false);
 
   82     libff::consume_OUTPUT_NEWLINE(in);
 
   84     libff::consume_OUTPUT_NEWLINE(in);
 
   86     libff::consume_newline(in);
 
   91 template<typename FieldT> size_t bacs_circuit<FieldT>::num_inputs() const
 
   93     return primary_input_size + auxiliary_input_size;
 
   96 template<typename FieldT> size_t bacs_circuit<FieldT>::num_gates() const
 
  101 template<typename FieldT> size_t bacs_circuit<FieldT>::num_wires() const
 
  103     return num_inputs() + num_gates();
 
  106 template<typename FieldT>
 
  107 std::vector<size_t> bacs_circuit<FieldT>::wire_depths() const
 
  109     std::vector<size_t> depths;
 
  110     depths.emplace_back(0);
 
  111     depths.resize(num_inputs() + 1, 1);
 
  113     for (auto &g : gates) {
 
  114         size_t max_depth = 0;
 
  115         for (auto &t : g.lhs) {
 
  116             max_depth = std::max(max_depth, depths[t.index]);
 
  119         for (auto &t : g.rhs) {
 
  120             max_depth = std::max(max_depth, depths[t.index]);
 
  123         depths.emplace_back(max_depth + 1);
 
  129 template<typename FieldT> size_t bacs_circuit<FieldT>::depth() const
 
  131     std::vector<size_t> all_depths = this->wire_depths();
 
  132     return *(std::max_element(all_depths.begin(), all_depths.end()));
 
  135 template<typename FieldT> bool bacs_circuit<FieldT>::is_valid() const
 
  137     for (size_t i = 0; i < num_gates(); ++i) {
 
  139          * The output wire of gates[i] must have index 1+num_inputs+i.
 
  140          * (The '1+' accounts for the the index of the constant wire.)
 
  142         if (gates[i].output.index != 1 + num_inputs() + i) {
 
  147          * Gates must be topologically sorted.
 
  149         if (!gates[i].lhs.is_valid(gates[i].output.index) ||
 
  150             !gates[i].rhs.is_valid(gates[i].output.index)) {
 
  158 template<typename FieldT>
 
  159 bacs_variable_assignment<FieldT> bacs_circuit<FieldT>::get_all_wires(
 
  160     const bacs_primary_input<FieldT> &primary_input,
 
  161     const bacs_auxiliary_input<FieldT> &auxiliary_input) const
 
  163     assert(primary_input.size() == primary_input_size);
 
  164     assert(auxiliary_input.size() == auxiliary_input_size);
 
  166     bacs_variable_assignment<FieldT> result;
 
  167     result.insert(result.end(), primary_input.begin(), primary_input.end());
 
  168     result.insert(result.end(), auxiliary_input.begin(), auxiliary_input.end());
 
  170     assert(result.size() == num_inputs());
 
  172     for (auto &g : gates) {
 
  173         const FieldT gate_output = g.evaluate(result);
 
  174         result.emplace_back(gate_output);
 
  180 template<typename FieldT>
 
  181 bacs_variable_assignment<FieldT> bacs_circuit<FieldT>::get_all_outputs(
 
  182     const bacs_primary_input<FieldT> &primary_input,
 
  183     const bacs_auxiliary_input<FieldT> &auxiliary_input) const
 
  185     const bacs_variable_assignment<FieldT> all_wires =
 
  186         get_all_wires(primary_input, auxiliary_input);
 
  188     bacs_variable_assignment<FieldT> all_outputs;
 
  190     for (auto &g : gates) {
 
  191         if (g.is_circuit_output) {
 
  192             all_outputs.emplace_back(all_wires[g.output.index - 1]);
 
  199 template<typename FieldT>
 
  200 bool bacs_circuit<FieldT>::is_satisfied(
 
  201     const bacs_primary_input<FieldT> &primary_input,
 
  202     const bacs_auxiliary_input<FieldT> &auxiliary_input) const
 
  204     const bacs_variable_assignment<FieldT> all_outputs =
 
  205         get_all_outputs(primary_input, auxiliary_input);
 
  207     for (size_t i = 0; i < all_outputs.size(); ++i) {
 
  208         if (!all_outputs[i].is_zero()) {
 
  216 template<typename FieldT>
 
  217 void bacs_circuit<FieldT>::add_gate(const bacs_gate<FieldT> &g)
 
  219     assert(g.output.index == num_wires() + 1);
 
  220     gates.emplace_back(g);
 
  223 template<typename FieldT>
 
  224 void bacs_circuit<FieldT>::add_gate(
 
  225     const bacs_gate<FieldT> &g, const std::string &annotation)
 
  227     libff::UNUSED(annotation);
 
  228     assert(g.output.index == num_wires() + 1);
 
  229     gates.emplace_back(g);
 
  231     gate_annotations[g.output.index] = annotation;
 
  235 template<typename FieldT>
 
  236 bool bacs_circuit<FieldT>::operator==(const bacs_circuit<FieldT> &other) const
 
  239         this->primary_input_size == other.primary_input_size &&
 
  240         this->auxiliary_input_size == other.auxiliary_input_size &&
 
  241         this->gates == other.gates);
 
  244 template<typename FieldT>
 
  245 std::ostream &operator<<(std::ostream &out, const bacs_circuit<FieldT> &circuit)
 
  247     out << circuit.primary_input_size << "\n";
 
  248     out << circuit.auxiliary_input_size << "\n";
 
  249     libff::operator<<(out, circuit.gates);
 
  250     out << OUTPUT_NEWLINE;
 
  255 template<typename FieldT>
 
  256 std::istream &operator>>(std::istream &in, bacs_circuit<FieldT> &circuit)
 
  258     in >> circuit.primary_input_size;
 
  259     libff::consume_newline(in);
 
  260     in >> circuit.auxiliary_input_size;
 
  261     libff::consume_newline(in);
 
  262     libff::operator>>(in, circuit.gates);
 
  263     libff::consume_OUTPUT_NEWLINE(in);
 
  268 template<typename FieldT> void bacs_circuit<FieldT>::print() const
 
  270     libff::print_indent();
 
  271     printf("General information about the circuit:\n");
 
  273     libff::print_indent();
 
  274     printf("All gates:\n");
 
  275     for (size_t i = 0; i < gates.size(); ++i) {
 
  276         std::string annotation = "no annotation";
 
  278         auto it = gate_annotations.find(i);
 
  279         if (it != gate_annotations.end()) {
 
  280             annotation = it->second;
 
  283         printf("Gate %zu (%s):\n", i, annotation.c_str());
 
  285         gates[i].print(variable_annotations);
 
  292 template<typename FieldT> void bacs_circuit<FieldT>::print_info() const
 
  294     libff::print_indent();
 
  295     printf("* Number of inputs: %zu\n", this->num_inputs());
 
  296     libff::print_indent();
 
  297     printf("* Number of gates: %zu\n", this->num_gates());
 
  298     libff::print_indent();
 
  299     printf("* Number of wires: %zu\n", this->num_wires());
 
  300     libff::print_indent();
 
  301     printf("* Depth: %zu\n", this->depth());
 
  304 } // namespace libsnark