@@ -1202,51 +1202,38 @@ exprt substitute_array_access(
12021202// / have been replaced by their valuation in the current model.
12031203// / \pre Symbols other than the universal variable should have been replaced by
12041204// / 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
12061206// / \param univ_var: the universal variable for the negation of the axiom
1207+ // / \param get: valuation function, the result should have been simplified
12071208// / \return: the negation of the axiom under the current evaluation
12081209static 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)
12111213{
12121214 // 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));
12341222
12351223 // The negated existential becomes an universal, and this is the unrolling of
12361224 // that universal quantifier.
12371225 std::vector<exprt> conjuncts;
1226+ conjuncts.reserve (numeric_cast_v<std::size_t >(ube - lbe));
12381227 for (mp_integer i=lbe; i<ube; ++i)
12391228 {
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) );
12451234 }
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);
12501237}
12511238
12521239// / 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(
14061393 for (std::size_t i = 0 ; i < axioms.not_contains .size (); i++)
14071394 {
14081395 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 (
14181397 " 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); });
14391401
14401402 stream << indent << i << " .\n " ;
14411403 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 );
14431405
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))
14451409 {
14461410 stream << indent2 << " - violated_for: " << univ_var.get_identifier ()
14471411 << " =" << format (*witness) << eom;
0 commit comments