Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
solver.cpp
Go to the documentation of this file.
1#include "solver.hpp"
3
4namespace smt_solver {
5
12{
13 cvc5::Result result = this->solver.checkSat();
14 this->checked = true;
15 this->cvc_result = result;
16
17 if (result.isUnknown()) {
18 info("Unknown Result");
19 }
20 this->res = result.isSat();
21 return this->res;
22}
23
32std::string Solver::get(const cvc5::Term& term) const
33{
34 if (term.getKind() == cvc5::Kind::CONST_FINITE_FIELD) {
35 return term.getFiniteFieldValue();
36 }
37 if (term.getKind() == cvc5::Kind::CONST_INTEGER) {
38 return term.getIntegerValue();
39 }
40 if (term.getKind() == cvc5::Kind::CONST_BITVECTOR) {
41 return term.getBitVectorValue();
42 }
43 if (term.getKind() == cvc5::Kind::CONST_BOOLEAN) {
44 return std::to_string(static_cast<size_t>(term.getBooleanValue()));
45 }
46
47 if (!this->checked) {
48 throw std::length_error("Haven't checked yet");
49 }
50 if (!this->res) {
51 throw std::length_error("There's no solution");
52 }
53
54 cvc5::Term val = this->solver.getValue(term);
55 std::string str_val;
56 if (val.isIntegerValue()) {
57 str_val = val.getIntegerValue();
58 } else if (val.isFiniteFieldValue()) {
59 str_val = val.getFiniteFieldValue();
60 } else if (val.isBitVectorValue()) {
61 str_val = val.getBitVectorValue();
62 } else if (val.isBooleanValue()) {
63 str_val = std::to_string(static_cast<size_t>(val.getBooleanValue()));
64 } else {
65 throw std::invalid_argument("Expected Integer or FiniteField sorts. Got: " + val.getSort().toString());
66 }
67 return str_val;
68}
69
88
101{
103 for (auto& term : terms) {
104 resulting_model.insert({ term.toString(), this->get(term) });
105 }
106 return resulting_model;
107}
108
117{
118 bool is_store = term.getKind() == cvc5::Kind::STORE;
119 bool is_array = term.getSort().isArray() && term.getKind() == cvc5::Kind::CONSTANT;
120 if (!is_store && !is_array) {
121 throw std::invalid_argument("Expected ARRAY or STORE. Got: " + term.toString());
122 };
123
124 if (term.getSort().isArray() && term.getKind() == cvc5::Kind::CONSTANT) {
125 std::string arr_name = term.toString();
126 if (!this->cached_array_traces.contains(arr_name)) {
127 this->cached_array_traces.insert({ arr_name, 0 });
128 }
129 return { term.toString(), 1 };
130 }
131 auto [arr_name, cur_depth] = print_array_trace(term[0], /*is_head=*/false);
133 info(arr_name, "[", stringify_term(term[1]), "] = ", stringify_term(term[2]));
134 }
135 if (is_head) {
137 }
138 return { arr_name, cur_depth + 1 };
139}
140
147std::string Solver::get_array_name(const cvc5::Term& term)
148{
149 bool is_store = term.getKind() == cvc5::Kind::STORE;
150 bool is_array = term.getSort().isArray() && term.getKind() == cvc5::Kind::CONSTANT;
151 if (!is_store && !is_array) {
152 throw std::invalid_argument("Expected ARRAY or STORE. Got: " + term.toString());
153 };
154
155 if (term.getKind() == cvc5::Kind::STORE) {
156 return get_array_name(term[0]);
157 }
158 return stringify_term(term);
159}
160
168std::pair<std::string, size_t> Solver::print_set_trace(const cvc5::Term& term, bool is_head)
169{
170 bool is_insert = term.getKind() == cvc5::Kind::SET_INSERT;
171 bool is_set = term.getSort().isSet() && term.getKind() == cvc5::Kind::CONSTANT;
172 if (!is_insert && !is_set) {
173 throw std::invalid_argument("Expected ARRAY or STORE. Got: " + term.toString());
174 };
175
176 if (term.getSort().isSet() && term.getKind() == cvc5::Kind::CONSTANT) {
177 std::string set_name = term.toString();
178 if (!this->cached_set_traces.contains(set_name)) {
179 this->cached_set_traces.insert({ set_name, 0 });
180 }
181 return { term.toString(), 1 };
182 }
183 auto [set_name, cur_depth] = print_set_trace(term[term.getNumChildren() - 1], /*is_head=*/false);
184 if (this->cached_set_traces[set_name] < cur_depth) {
185 std::string res = stringify_term(term[term.getNumChildren() - 1]) + " <- {";
186
187 size_t to_print = term.getNumChildren() > 257 ? 128 : term.getNumChildren() - 2;
188 for (size_t i = 0; i < to_print; i++) {
189 res += stringify_term(term[i]) + ", ";
190 }
191 if (to_print != term.getNumChildren() - 2) {
192 res += "... , ";
193 }
194 res += stringify_term(term[term.getNumChildren() - 2]);
195 res += "}";
196 info(res);
197 }
198 if (is_head) {
200 }
201 return { set_name, cur_depth + 1 };
202}
203
210std::string Solver::get_set_name(const cvc5::Term& term)
211{
212 bool is_insert = term.getKind() == cvc5::Kind::SET_INSERT;
213 bool is_set = term.getSort().isSet() && term.getKind() == cvc5::Kind::CONSTANT;
214 if (!is_insert && !is_set) {
215 throw std::invalid_argument("Expected SET or INSERT. Got: " + term.toString());
216 };
217
218 if (term.getKind() == cvc5::Kind::SET_INSERT) {
219 return get_set_name(term[term.getNumChildren() - 1]);
220 }
221 return stringify_term(term);
222}
223
235std::string Solver::stringify_term(const cvc5::Term& term, bool parenthesis)
236{
237 if (term.getKind() == cvc5::Kind::CONST_FINITE_FIELD) {
238 return term.getFiniteFieldValue();
239 }
240 if (term.getKind() == cvc5::Kind::CONST_INTEGER) {
241 return term.getIntegerValue();
242 }
243 if (term.getKind() == cvc5::Kind::CONST_BITVECTOR) {
244 return term.getBitVectorValue();
245 }
246 if (term.getKind() == cvc5::Kind::CONST_BOOLEAN) {
247 std::vector<std::string> bool_res = { "false", "true" };
248 return bool_res[static_cast<size_t>(term.getBooleanValue())];
249 }
250 // handling tuples
251 if (term.getSort().isTuple() && term.getKind() == cvc5::Kind::APPLY_CONSTRUCTOR) {
252 std::string res = "(";
253 for (size_t i = 1; i < term.getNumChildren() - 1; i++) {
254 res += stringify_term(term[i]) + ", ";
255 }
256 res += stringify_term(term[term.getNumChildren() - 1]);
257 return res + ")";
258 }
259 if (term.getKind() == cvc5::Kind::SET_EMPTY) {
260 return "{}";
261 }
262 if (term.getKind() == cvc5::Kind::CONSTANT) {
263 if (term.getSort().isSet()) {
264 return "{" + term.toString() + "}";
265 }
266 if (term.getSort().isArray()) {
267 return "[" + term.toString() + "]";
268 }
269 return term.toString();
270 }
271
272 std::string res;
273 std::string op;
274 bool child_parenthesis = true;
275 bool back = false;
276 switch (term.getKind()) {
277 case cvc5::Kind::ADD:
278 case cvc5::Kind::FINITE_FIELD_ADD:
279 case cvc5::Kind::BITVECTOR_ADD:
280 op = " + ";
281 child_parenthesis = false;
282 break;
283 case cvc5::Kind::SUB:
284 case cvc5::Kind::BITVECTOR_SUB:
285 op = " - ";
286 break;
287 case cvc5::Kind::NEG:
288 case cvc5::Kind::FINITE_FIELD_NEG:
289 case cvc5::Kind::BITVECTOR_NEG:
290 res = "-";
291 break;
292 case cvc5::Kind::MULT:
293 case cvc5::Kind::FINITE_FIELD_MULT:
294 case cvc5::Kind::BITVECTOR_MULT:
295 op = " * ";
296 break;
297 case cvc5::Kind::EQUAL:
298 op = " == ";
299 child_parenthesis = false;
300 break;
301 case cvc5::Kind::LT:
302 case cvc5::Kind::BITVECTOR_ULT:
303 op = " < ";
304 break;
305 case cvc5::Kind::GT:
306 case cvc5::Kind::BITVECTOR_UGT:
307 op = " > ";
308 break;
309 case cvc5::Kind::LEQ:
310 case cvc5::Kind::BITVECTOR_ULE:
311 op = " <= ";
312 break;
313 case cvc5::Kind::GEQ:
314 case cvc5::Kind::BITVECTOR_UGE:
315 op = " >= ";
316 break;
317 case cvc5::Kind::BITVECTOR_UREM:
318 op = " % ";
319 break;
320 case cvc5::Kind::BITVECTOR_UDIV:
321 op = " / ";
322 break;
323 case cvc5::Kind::XOR:
324 case cvc5::Kind::BITVECTOR_XOR:
325 op = " ^ ";
326 break;
327 case cvc5::Kind::BITVECTOR_OR:
328 op = " | ";
329 break;
330 case cvc5::Kind::OR:
331 op = " || ";
332 break;
333 case cvc5::Kind::BITVECTOR_AND:
334 op = " & ";
335 break;
336 case cvc5::Kind::BITVECTOR_SHL:
337 op = " << ";
338 break;
339 case cvc5::Kind::BITVECTOR_LSHR:
340 op = " >> ";
341 break;
342 case cvc5::Kind::BITVECTOR_ROTATE_LEFT:
343 back = true;
344 op = " ><< " + term.getOp()[0].toString();
345 break;
346 case cvc5::Kind::BITVECTOR_ROTATE_RIGHT:
347 back = true;
348 op = " >>< " + term.getOp()[0].toString();
349 break;
350 case cvc5::Kind::AND:
351 op = " && ";
352 break;
353 case cvc5::Kind::NOT:
354 res = "!";
355 break;
356 case cvc5::Kind::INTS_MODULUS:
357 op = " % ";
358 parenthesis = true;
359 break;
360 case cvc5::Kind::SET_INSERT:
361 // Due to the specifics of sets implementation
362 // We can't print all the INSERTs in place
363 // In such case we will just return the array name
364 return get_set_name(term[term.getNumChildren() - 1]);
365 case cvc5::Kind::SET_MEMBER: {
366 // On the other hand, here I'll be printing the whole trace of the set
367 // initializations up to the previous print
368 if (term.getNumChildren() != 2) {
369 throw std::runtime_error("Expected set_member op. Got: " + term.toString());
370 }
371 std::string set_name = get_set_name(term[1]);
372 print_set_trace(term[1]);
373 std::string res = stringify_term(term[0], /*parenthesis=*/true) + " in " + set_name;
374 if (parenthesis) {
375 return "(" + res + ")";
376 }
377 return res;
378 }
379 case cvc5::Kind::STORE: {
380 // Due to the specifics of arrays implementation
381 // We can't print all the STOREs in place
382 // In such case we will just return the array name
383 return get_array_name(term[0]);
384 }
385 case cvc5::Kind::SELECT: {
386 // On the other hand, here I'll be printing the whole trace of the array
387 // initializations up to the previous print
388 if (term.getNumChildren() != 2) {
389 throw std::runtime_error("Expected SELECT op. Got: " + term.toString());
390 }
391 std::string res = get_array_name(term[0]);
392 print_array_trace(term[0]);
393 res += "[" + stringify_term(term[1]) + "]";
394 return res;
395 }
396 default:
397 info("\033[31m", "Unprocessed operand :", term.getKind(), "\033[0m");
398 info("\033[31m", term, "\033[0m");
399 return "failed to process";
400 }
401
402 for (size_t i = 0; i < term.getNumChildren() - 1; i++) {
403 res += stringify_term(term[i], child_parenthesis) + op;
404 }
405 cvc5::Term child = term[term.getNumChildren() - 1];
406
408 if (back) {
409 res += op;
410 }
411 if (parenthesis) {
412 return "(" + res + ")";
413 }
414 return res;
415}
416
422{
423 for (const auto& t : this->solver.getAssertions()) {
424 info(this->stringify_term(t));
425 }
426}
427}; // namespace smt_solver
std::pair< std::string, size_t > print_set_trace(const cvc5::Term &term, bool is_head=true)
print the trace of SET insertions up to previously printed ones
Definition solver.cpp:168
std::pair< std::string, size_t > print_array_trace(const cvc5::Term &term, bool is_head=true)
print the trace of array assigments up to previously printed ones
Definition solver.cpp:116
std::string get(const cvc5::Term &term) const
Returns.
Definition solver.cpp:32
cvc5::Solver solver
Definition solver.hpp:83
void print_assertions()
Definition solver.cpp:421
std::unordered_map< std::string, std::string > model(std::unordered_map< std::string, cvc5::Term > &terms) const
Definition solver.cpp:80
std::string get_array_name(const cvc5::Term &term)
recover the array name from the nested assigments
Definition solver.cpp:147
std::unordered_map< std::string, size_t > cached_array_traces
Definition solver.hpp:184
std::unordered_map< std::string, size_t > cached_set_traces
Definition solver.hpp:189
std::string get_set_name(const cvc5::Term &term)
recover the set name from the nested assigments
Definition solver.cpp:210
cvc5::Result cvc_result
Definition solver.hpp:88
std::string stringify_term(const cvc5::Term &term, bool parenthesis=false)
Definition solver.cpp:235
void info(Args... args)
Definition log.hpp:70
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
std::string to_string(bb::avm2::ValueTag tag)