Skip to content

Commit 0e2e339

Browse files
committed
Added SMT encoding of array_comprehension_exprt
Z3 treats arrays and lambdas as identical, so we can exploit that in the translation of `array_comprehension_exprt`. For other solvers, we would fall back to a universally quantified expression to initialize the array.
1 parent f899754 commit 0e2e339

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

regression/cbmc/byte_update15/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE broken-smt-backend
1+
CORE
22
main.c
33

44
^EXIT=0$

src/solvers/smt2/smt2_conv.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ smt2_convt::smt2_convt(
5656
: use_FPA_theory(false),
5757
use_datatypes(false),
5858
use_array_of_bool(false),
59+
use_lambda_for_array(false),
5960
emit_set_logic(true),
6061
ns(_ns),
6162
out(_out),
@@ -97,6 +98,7 @@ smt2_convt::smt2_convt(
9798

9899
case solvert::Z3:
99100
use_array_of_bool = true;
101+
use_lambda_for_array = true;
100102
emit_set_logic = false;
101103
use_datatypes = true;
102104
break;
@@ -1289,6 +1291,31 @@ void smt2_convt::convert_expr(const exprt &expr)
12891291
CHECK_RETURN(it != defined_expressions.end());
12901292
out << it->second;
12911293
}
1294+
else if(expr.id() == ID_array_comprehension)
1295+
{
1296+
const auto &array_comprehension = to_array_comprehension_expr(expr);
1297+
1298+
DATA_INVARIANT(
1299+
array_comprehension.type().id() == ID_array,
1300+
"array_comprehension expression shall have array type");
1301+
1302+
if(use_lambda_for_array)
1303+
{
1304+
out << "(lambda ((";
1305+
convert_expr(array_comprehension.arg());
1306+
out << " ";
1307+
convert_type(array_comprehension.type().size().type());
1308+
out << ")) ";
1309+
convert_expr(array_comprehension.body());
1310+
out << ")";
1311+
}
1312+
else
1313+
{
1314+
const auto &it = defined_expressions.find(array_comprehension);
1315+
CHECK_RETURN(it != defined_expressions.end());
1316+
out << it->second;
1317+
}
1318+
}
12921319
else if(expr.id()==ID_index)
12931320
{
12941321
convert_index(to_index_expr(expr));
@@ -4390,6 +4417,35 @@ void smt2_convt::find_symbols(const exprt &expr)
43904417
defined_expressions[expr]=id;
43914418
}
43924419
}
4420+
else if(expr.id() == ID_array_comprehension)
4421+
{
4422+
if(!use_lambda_for_array)
4423+
{
4424+
if(defined_expressions.find(expr) == defined_expressions.end())
4425+
{
4426+
const auto &array_comprehension = to_array_comprehension_expr(expr);
4427+
4428+
const irep_idt id =
4429+
"array_comprehension." + std::to_string(defined_expressions.size());
4430+
out << "(declare-fun " << id << " () ";
4431+
convert_type(array_comprehension.type());
4432+
out << ")\n";
4433+
4434+
out << "; the following is a substitute for lambda i . x(i)\n";
4435+
out << "(assert (forall ((";
4436+
convert_expr(array_comprehension.arg());
4437+
out << " ";
4438+
convert_type(array_comprehension.type().size().type());
4439+
out << ")) (= (select " << id << " ";
4440+
convert_expr(array_comprehension.arg());
4441+
out << ") ";
4442+
convert_expr(array_comprehension.body());
4443+
out << ")))\n";
4444+
4445+
defined_expressions[expr] = id;
4446+
}
4447+
}
4448+
}
43934449
else if(expr.id()==ID_array)
43944450
{
43954451
if(defined_expressions.find(expr)==defined_expressions.end())

src/solvers/smt2/smt2_conv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class smt2_convt : public stack_decision_proceduret
6161
bool use_FPA_theory;
6262
bool use_datatypes;
6363
bool use_array_of_bool;
64+
bool use_lambda_for_array;
6465
bool emit_set_logic;
6566

6667
exprt handle(const exprt &expr) override;

0 commit comments

Comments
 (0)