Skip to content

Commit 9b286d9

Browse files
Use sparse arrays in string_refinement::get
In the case of index_expressions this can use exponentialy less memory.
1 parent 037f631 commit 9b286d9

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

src/solvers/refinement/string_refinement.cpp

+37-2
Original file line numberDiff line numberDiff line change
@@ -2222,8 +2222,8 @@ exprt substitute_array_lists(exprt expr, size_t string_max_length)
22222222
/// Evaluates the given expression in the valuation found by
22232223
/// string_refinementt::dec_solve.
22242224
///
2225-
/// The difference with supert::get is that arrays of characters need to be
2226-
/// concretized. See concretize_arrays_in_expression for how it is done.
2225+
/// Arrays of characters are interpreted differently from the result of
2226+
/// supert::get: values are propagated to the left to fill unknown.
22272227
/// \param expr: an expression
22282228
/// \return evaluated expression
22292229
exprt string_refinementt::get(const exprt &expr) const
@@ -2234,6 +2234,41 @@ exprt string_refinementt::get(const exprt &expr) const
22342234
exprt ecopy(expr);
22352235
(void)symbol_resolve.replace_expr(ecopy);
22362236

2237+
// Special treatment for index expressions
2238+
const auto &index_expr = expr_try_dynamic_cast<index_exprt>(ecopy);
2239+
if(index_expr && is_char_type(index_expr->type()))
2240+
{
2241+
std::reference_wrapper<const exprt> current(index_expr->array());
2242+
while(current.get().id() == ID_if)
2243+
{
2244+
const auto &if_expr = expr_dynamic_cast<if_exprt>(current.get());
2245+
const exprt cond = get(if_expr.cond());
2246+
if(cond.is_true())
2247+
current = std::cref(if_expr.true_case());
2248+
else if(cond.is_false())
2249+
current = std::cref(if_expr.false_case());
2250+
else
2251+
UNREACHABLE;
2252+
}
2253+
const auto array = supert::get(current.get());
2254+
const auto index = get(index_expr->index());
2255+
const exprt unknown =
2256+
from_integer(CHARACTER_FOR_UNKNOWN, index_expr->type());
2257+
if(
2258+
const auto sparse_array = interval_sparse_arrayt::of_expr(array, unknown))
2259+
{
2260+
if(const auto index_value = numeric_cast<std::size_t>(index))
2261+
return sparse_array->at(*index_value);
2262+
return sparse_array->to_if_expression(index);
2263+
}
2264+
2265+
INVARIANT(
2266+
array.id() == ID_symbol,
2267+
"apart from symbols, array valuations can be interpreted as sparse "
2268+
"arrays");
2269+
return index_exprt(array, index);
2270+
}
2271+
22372272
if(is_char_array_type(ecopy.type(), ns))
22382273
{
22392274
array_string_exprt &arr = to_array_string_expr(ecopy);

0 commit comments

Comments
 (0)