@@ -1202,51 +1202,38 @@ exprt substitute_array_access(
1202
1202
// / have been replaced by their valuation in the current model.
1203
1203
// / \pre Symbols other than the universal variable should have been replaced by
1204
1204
// / their valuation in the current model.
1205
- // / \param axiom : the not_contains constraint to add the negation of
1205
+ // / \param constraint : the not_contains constraint to add the negation of
1206
1206
// / \param univ_var: the universal variable for the negation of the axiom
1207
+ // / \param get: valuation function, the result should have been simplified
1207
1208
// / \return: the negation of the axiom under the current evaluation
1208
1209
static exprt negation_of_not_contains_constraint (
1209
- const string_not_contains_constraintt &axiom,
1210
- const symbol_exprt &univ_var)
1210
+ const string_not_contains_constraintt &constraint,
1211
+ const symbol_exprt &univ_var,
1212
+ const std::function<exprt(const exprt &)> &get)
1211
1213
{
1212
1214
// If the for all is vacuously true, the negation is false.
1213
- const exprt &lbu=axiom.univ_lower_bound ();
1214
- const exprt &ubu=axiom.univ_upper_bound ();
1215
- if (lbu.id ()==ID_constant && ubu.id ()==ID_constant)
1216
- {
1217
- const auto lb_int = numeric_cast<mp_integer>(lbu);
1218
- const auto ub_int = numeric_cast<mp_integer>(ubu);
1219
- if (!lb_int || !ub_int || *ub_int<=*lb_int)
1220
- return false_exprt ();
1221
- }
1222
-
1223
- const auto lbe = numeric_cast_v<mp_integer>(axiom.exists_lower_bound ());
1224
- const auto ube = numeric_cast_v<mp_integer>(axiom.exists_upper_bound ());
1225
-
1226
- // If the premise is false, the implication is trivially true, so the
1227
- // negation is false.
1228
- if (axiom.premise ()==false_exprt ())
1229
- return false_exprt ();
1230
-
1231
- and_exprt univ_bounds (
1232
- binary_relation_exprt (lbu, ID_le, univ_var),
1233
- binary_relation_exprt (ubu, ID_gt, univ_var));
1215
+ const auto lbe =
1216
+ numeric_cast_v<mp_integer>(get (constraint.exists_lower_bound ()));
1217
+ const auto ube =
1218
+ numeric_cast_v<mp_integer>(get (constraint.exists_upper_bound ()));
1219
+ const auto univ_bounds = and_exprt (
1220
+ binary_relation_exprt (get (constraint.univ_lower_bound ()), ID_le, univ_var),
1221
+ binary_relation_exprt (get (constraint.univ_upper_bound ()), ID_gt, univ_var));
1234
1222
1235
1223
// The negated existential becomes an universal, and this is the unrolling of
1236
1224
// that universal quantifier.
1237
1225
std::vector<exprt> conjuncts;
1226
+ conjuncts.reserve (numeric_cast_v<std::size_t >(ube - lbe));
1238
1227
for (mp_integer i=lbe; i<ube; ++i)
1239
1228
{
1240
- const constant_exprt i_exprt= from_integer (i, univ_var.type ());
1241
- const equal_exprt equal_chars (
1242
- axiom .s0 ()[ plus_exprt (univ_var, i_exprt)],
1243
- axiom .s1 ()[i_exprt] );
1244
- conjuncts.push_back (equal_chars );
1229
+ const constant_exprt i_expr = from_integer (i, univ_var.type ());
1230
+ const exprt s0_char =
1231
+ get ( index_exprt (constraint .s0 (), plus_exprt (univ_var, i_expr)));
1232
+ const exprt s1_char = get ( index_exprt (constraint .s1 (), i_expr) );
1233
+ conjuncts.push_back (equal_exprt (s0_char, s1_char) );
1245
1234
}
1246
- exprt equal_strings=conjunction (conjuncts);
1247
- and_exprt negaxiom (univ_bounds, axiom.premise (), equal_strings);
1248
-
1249
- return negaxiom;
1235
+ const exprt equal_strings = conjunction (conjuncts);
1236
+ return and_exprt (univ_bounds, get (constraint.premise ()), equal_strings);
1250
1237
}
1251
1238
1252
1239
// / Negates the constraint to be fed to a solver. The intended usage is to find
@@ -1406,42 +1393,19 @@ static std::pair<bool, std::vector<exprt>> check_axioms(
1406
1393
for (std::size_t i = 0 ; i < axioms.not_contains .size (); i++)
1407
1394
{
1408
1395
const string_not_contains_constraintt &nc_axiom=axioms.not_contains [i];
1409
- const exprt &univ_bound_inf=nc_axiom.univ_lower_bound ();
1410
- const exprt &univ_bound_sup=nc_axiom.univ_upper_bound ();
1411
- const exprt &prem=nc_axiom.premise ();
1412
- const exprt &exists_bound_inf=nc_axiom.exists_lower_bound ();
1413
- const exprt &exists_bound_sup=nc_axiom.exists_upper_bound ();
1414
- const array_string_exprt &s0 = nc_axiom.s0 ();
1415
- const array_string_exprt &s1 = nc_axiom.s1 ();
1416
-
1417
- symbol_exprt univ_var=generator.fresh_univ_index (
1396
+ const symbol_exprt univ_var = generator.fresh_univ_index (
1418
1397
" not_contains_univ_var" , nc_axiom.s0 ().length ().type ());
1419
- string_not_contains_constraintt nc_axiom_in_model (
1420
- get (univ_bound_inf),
1421
- get (univ_bound_sup),
1422
- get (prem),
1423
- get (exists_bound_inf),
1424
- get (exists_bound_sup),
1425
- to_array_string_expr (get (s0)),
1426
- to_array_string_expr (get (s1)));
1427
-
1428
- // necessary so that expressions such as `1 + (3 - (TRUE ? 0 : 0))` do not
1429
- // appear in bounds
1430
- nc_axiom_in_model =
1431
- to_string_not_contains_constraint (simplify_expr (nc_axiom_in_model, ns));
1432
-
1433
- exprt negaxiom =
1434
- negation_of_not_contains_constraint (nc_axiom_in_model, univ_var);
1435
-
1436
- negaxiom = simplify_expr (negaxiom, ns);
1437
- const exprt with_concrete_arrays =
1438
- substitute_array_access (negaxiom, gen_symbol, true );
1398
+ const exprt negated_axiom = negation_of_not_contains_constraint (
1399
+ nc_axiom, univ_var, [&](const exprt &expr) {
1400
+ return simplify_expr (get (expr), ns); });
1439
1401
1440
1402
stream << indent << i << " .\n " ;
1441
1403
debug_check_axioms_step (
1442
- stream, ns, nc_axiom, nc_axiom_in_model, negaxiom, with_concrete_arrays );
1404
+ stream, ns, nc_axiom, nc_axiom, negated_axiom, negated_axiom );
1443
1405
1444
- if (const auto witness = find_counter_example (ns, ui, negaxiom, univ_var))
1406
+ if (
1407
+ const auto witness =
1408
+ find_counter_example (ns, ui, negated_axiom, univ_var))
1445
1409
{
1446
1410
stream << indent2 << " - violated_for: " << univ_var.get_identifier ()
1447
1411
<< " =" << format (*witness) << eom;
0 commit comments