Skip to content

Commit d83fa17

Browse files
Merge pull request #1932 from romainbrenguier/stop-adding-counter-examples
[TG-2459] Only add counter examples when index set is exhausted
2 parents f3cb5bb + b5f12ff commit d83fa17

8 files changed

+168
-132
lines changed

src/solvers/refinement/string_constraint.h

+1-12
Original file line numberDiff line numberDiff line change
@@ -93,36 +93,25 @@ class string_constraintt : public exprt
9393
const symbol_exprt &_univ_var,
9494
const exprt &bound_inf,
9595
const exprt &bound_sup,
96-
const exprt &prem,
9796
const exprt &body):
9897
exprt(ID_string_constraint)
9998
{
100-
copy_to_operands(prem, body);
99+
copy_to_operands(true_exprt(), body);
101100
copy_to_operands(_univ_var, bound_sup, bound_inf);
102101
}
103102

104103
// Default bound inferior is 0
105104
string_constraintt(
106105
const symbol_exprt &_univ_var,
107106
const exprt &bound_sup,
108-
const exprt &prem,
109107
const exprt &body):
110108
string_constraintt(
111109
_univ_var,
112110
from_integer(0, _univ_var.type()),
113111
bound_sup,
114-
prem,
115112
body)
116113
{}
117114

118-
// Default premise is true
119-
string_constraintt(
120-
const symbol_exprt &_univ_var,
121-
const exprt &bound_sup,
122-
const exprt &body):
123-
string_constraintt(_univ_var, bound_sup, true_exprt(), body)
124-
{}
125-
126115
exprt univ_within_bounds() const
127116
{
128117
return and_exprt(

src/solvers/refinement/string_constraint_generator.h

+3
Original file line numberDiff line numberDiff line change
@@ -436,4 +436,7 @@ size_t max_printed_string_length(const typet &type, unsigned long ul_radix);
436436
std::string
437437
utf16_constant_array_to_java(const array_exprt &arr, std::size_t length);
438438

439+
/// \return expression representing the minimum of two expressions
440+
exprt minimum(const exprt &a, const exprt &b);
441+
439442
#endif

src/solvers/refinement/string_constraint_generator_comparison.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ exprt string_constraint_generatort::add_axioms_for_equals(
4343
lemmas.push_back(a1);
4444

4545
symbol_exprt qvar=fresh_univ_index("QA_equal", index_type);
46-
string_constraintt a2(qvar, s1.length(), eq, equal_exprt(s1[qvar], s2[qvar]));
46+
string_constraintt a2(
47+
qvar, s1.length(), implies_exprt(eq, equal_exprt(s1[qvar], s2[qvar])));
4748
constraints.push_back(a2);
4849

4950
symbol_exprt witness=fresh_exist_index("witness_unequal", index_type);
@@ -130,7 +131,7 @@ exprt string_constraint_generatort::add_axioms_for_equals_ignore_case(
130131
fresh_univ_index("QA_equal_ignore_case", index_type);
131132
const exprt constr2 =
132133
character_equals_ignore_case(s1[qvar], s2[qvar], char_a, char_A, char_Z);
133-
const string_constraintt a2(qvar, s1.length(), eq, constr2);
134+
const string_constraintt a2(qvar, s1.length(), implies_exprt(eq, constr2));
134135
constraints.push_back(a2);
135136

136137
const symbol_exprt witness =
@@ -224,7 +225,7 @@ exprt string_constraint_generatort::add_axioms_for_compare_to(
224225

225226
const symbol_exprt i = fresh_univ_index("QA_compare_to", index_type);
226227
const string_constraintt a2(
227-
i, s1.length(), res_null, equal_exprt(s1[i], s2[i]));
228+
i, s1.length(), implies_exprt(res_null, equal_exprt(s1[i], s2[i])));
228229
constraints.push_back(a2);
229230

230231
const symbol_exprt x = fresh_exist_index("index_compare_to", index_type);
@@ -255,7 +256,7 @@ exprt string_constraint_generatort::add_axioms_for_compare_to(
255256

256257
const symbol_exprt i2 = fresh_univ_index("QA_compare_to", index_type);
257258
const string_constraintt a4(
258-
i2, x, not_exprt(res_null), equal_exprt(s1[i2], s2[i2]));
259+
i2, x, implies_exprt(not_exprt(res_null), equal_exprt(s1[i2], s2[i2])));
259260
constraints.push_back(a4);
260261

261262
return res;

src/solvers/refinement/string_constraint_generator_indexof.cpp

+10-9
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,15 @@ exprt string_constraint_generatort::add_axioms_for_index_of(
6565

6666
symbol_exprt n=fresh_univ_index("QA_index_of", index_type);
6767
string_constraintt a4(
68-
n, lower_bound, index, contains, not_exprt(equal_exprt(str[n], c)));
68+
n, lower_bound, index, implies_exprt(contains, notequal_exprt(str[n], c)));
6969
constraints.push_back(a4);
7070

7171
symbol_exprt m=fresh_univ_index("QA_index_of", index_type);
7272
string_constraintt a5(
7373
m,
7474
lower_bound,
7575
str.length(),
76-
not_exprt(contains),
77-
not_exprt(equal_exprt(str[m], c)));
76+
implies_exprt(not_exprt(contains), not_exprt(equal_exprt(str[m], c))));
7877
constraints.push_back(a5);
7978

8079
return index;
@@ -130,8 +129,8 @@ exprt string_constraint_generatort::add_axioms_for_index_of_string(
130129
string_constraintt a3(
131130
qvar,
132131
needle.length(),
133-
contains,
134-
equal_exprt(haystack[plus_exprt(qvar, offset)], needle[qvar]));
132+
implies_exprt(
133+
contains, equal_exprt(haystack[plus_exprt(qvar, offset)], needle[qvar])));
135134
constraints.push_back(a3);
136135

137136
// string_not contains_constraintt are formulas of the form:
@@ -221,7 +220,8 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of_string(
221220

222221
symbol_exprt qvar=fresh_univ_index("QA_index_of_string", index_type);
223222
equal_exprt constr3(haystack[plus_exprt(qvar, offset)], needle[qvar]);
224-
string_constraintt a3(qvar, needle.length(), contains, constr3);
223+
const string_constraintt a3(
224+
qvar, needle.length(), implies_exprt(contains, constr3));
225225
constraints.push_back(a3);
226226

227227
// end_index is min(from_index, |str| - |substring|)
@@ -364,13 +364,14 @@ exprt string_constraint_generatort::add_axioms_for_last_index_of(
364364
n,
365365
plus_exprt(index, index1),
366366
end_index,
367-
contains,
368-
notequal_exprt(str[n], c));
367+
implies_exprt(contains, notequal_exprt(str[n], c)));
369368
constraints.push_back(a4);
370369

371370
const symbol_exprt m = fresh_univ_index("QA_last_index_of2", index_type);
372371
const string_constraintt a5(
373-
m, end_index, not_exprt(contains), notequal_exprt(str[m], c));
372+
m,
373+
end_index,
374+
implies_exprt(not_exprt(contains), notequal_exprt(str[m], c)));
374375
constraints.push_back(a5);
375376

376377
return index;

src/solvers/refinement/string_constraint_generator_main.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ void string_constraint_generatort::add_constraint_on_characters(
369369
const and_exprt char_in_set(
370370
binary_relation_exprt(chr, ID_ge, from_integer(low_char, chr.type())),
371371
binary_relation_exprt(chr, ID_le, from_integer(high_char, chr.type())));
372-
const string_constraintt sc(qvar, start, end, true_exprt(), char_in_set);
372+
const string_constraintt sc(qvar, start, end, char_in_set);
373373
constraints.push_back(sc);
374374
}
375375

@@ -662,3 +662,8 @@ exprt string_constraint_generatort::add_axioms_for_char_at(
662662
lemmas.push_back(equal_exprt(char_sym, str[f.arguments()[1]]));
663663
return char_sym;
664664
}
665+
666+
exprt minimum(const exprt &a, const exprt &b)
667+
{
668+
return if_exprt(binary_relation_exprt(a, ID_le, b), a, b);
669+
}

src/solvers/refinement/string_constraint_generator_testing.cpp

+8-4
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ exprt string_constraint_generatort::add_axioms_for_is_prefix(
4646
string_constraintt a2(
4747
qvar,
4848
prefix.length(),
49-
isprefix,
50-
equal_exprt(str[plus_exprt(qvar, offset)], prefix[qvar]));
49+
implies_exprt(
50+
isprefix, equal_exprt(str[plus_exprt(qvar, offset)], prefix[qvar])));
5151
constraints.push_back(a2);
5252

5353
symbol_exprt witness=fresh_exist_index("witness_not_isprefix", index_type);
@@ -153,7 +153,9 @@ exprt string_constraint_generatort::add_axioms_for_is_suffix(
153153
symbol_exprt qvar=fresh_univ_index("QA_suffix", index_type);
154154
const plus_exprt qvar_shifted(qvar, minus_exprt(s1.length(), s0.length()));
155155
string_constraintt a2(
156-
qvar, s0.length(), issuffix, equal_exprt(s0[qvar], s1[qvar_shifted]));
156+
qvar,
157+
s0.length(),
158+
implies_exprt(issuffix, equal_exprt(s0[qvar], s1[qvar_shifted])));
157159
constraints.push_back(a2);
158160

159161
symbol_exprt witness=fresh_exist_index("witness_not_suffix", index_type);
@@ -221,7 +223,9 @@ exprt string_constraint_generatort::add_axioms_for_contains(
221223
symbol_exprt qvar=fresh_univ_index("QA_contains", index_type);
222224
const plus_exprt qvar_shifted(qvar, startpos);
223225
string_constraintt a4(
224-
qvar, s1.length(), contains, equal_exprt(s1[qvar], s0[qvar_shifted]));
226+
qvar,
227+
s1.length(),
228+
implies_exprt(contains, equal_exprt(s1[qvar], s0[qvar_shifted])));
225229
constraints.push_back(a4);
226230

227231
string_not_contains_constraintt a5(

src/solvers/refinement/string_constraint_generator_transformation.cpp

+23-18
Original file line numberDiff line numberDiff line change
@@ -45,24 +45,21 @@ exprt string_constraint_generatort::add_axioms_for_set_length(
4545

4646
// We add axioms:
4747
// a1 : |res|=k
48-
// a2 : forall i<|res|. i < |s1| ==> res[i] = s1[i]
49-
// a3 : forall i<|res|. i >= |s1| ==> res[i] = 0
48+
// a2 : forall i< min(|s1|, k) .res[i] = s1[i]
49+
// a3 : forall |s1| <= i < |res|. res[i] = 0
5050

5151
lemmas.push_back(res.axiom_for_has_length(k));
5252

53-
symbol_exprt idx = fresh_univ_index("QA_index_set_length", index_type);
54-
string_constraintt a2(
55-
idx,
56-
res.length(),
57-
s1.axiom_for_length_gt(idx),
58-
equal_exprt(s1[idx], res[idx]));
53+
const symbol_exprt idx = fresh_univ_index("QA_index_set_length", index_type);
54+
const string_constraintt a2(
55+
idx, minimum(s1.length(), k), equal_exprt(s1[idx], res[idx]));
5956
constraints.push_back(a2);
6057

6158
symbol_exprt idx2 = fresh_univ_index("QA_index_set_length2", index_type);
6259
string_constraintt a3(
6360
idx2,
61+
s1.length(),
6462
res.length(),
65-
s1.axiom_for_length_le(idx2),
6663
equal_exprt(res[idx2], constant_char(0, char_type)));
6764
constraints.push_back(a3);
6865

@@ -395,8 +392,8 @@ exprt string_constraint_generatort::add_axioms_for_to_upper_case(
395392
/// These axioms are:
396393
/// 1. \f$ |{\tt res}| = |{\tt str}|\f$
397394
/// 2. \f$ {\tt res}[{\tt pos}]={\tt char}\f$
398-
/// 3. \f$ \forall i<|{\tt res}|.\ i \ne {\tt pos}
399-
/// \Rightarrow {\tt res}[i] = {\tt str}[i]\f$
395+
/// 3. \f$ \forall i < min(|{\tt res}|, pos). {\tt res}[i] = {\tt str}[i]\f$
396+
/// 4. \f$ \forall pos+1 <= i < |{\tt res}|.\ {\tt res}[i] = {\tt str}[i]\f$
400397
/// \param f: function application with arguments integer `|res|`, character
401398
/// pointer `&res[0]`, refined_string `str`, integer `pos`,
402399
/// and character `char`
@@ -413,14 +410,22 @@ exprt string_constraint_generatort::add_axioms_for_char_set(
413410
const exprt &character = f.arguments()[4];
414411

415412
const binary_relation_exprt out_of_bounds(position, ID_ge, str.length());
416-
lemmas.push_back(equal_exprt(res.length(), str.length()));
417-
lemmas.push_back(equal_exprt(res[position], character));
413+
const equal_exprt a1(res.length(), str.length());
414+
lemmas.push_back(a1);
415+
const equal_exprt a2(res[position], character);
416+
lemmas.push_back(a2);
417+
418418
const symbol_exprt q = fresh_univ_index("QA_char_set", position.type());
419-
equal_exprt a3_body(res[q], str[q]);
420-
notequal_exprt a3_guard(q, position);
421-
constraints.push_back(
422-
string_constraintt(
423-
q, from_integer(0, q.type()), res.length(), a3_guard, a3_body));
419+
const equal_exprt a3_body(res[q], str[q]);
420+
const string_constraintt a3(q, minimum(res.length(), position), a3_body);
421+
constraints.push_back(a3);
422+
423+
const symbol_exprt q2 = fresh_univ_index("QA_char_set2", position.type());
424+
const plus_exprt lower_bound(position, from_integer(1, position.type()));
425+
const equal_exprt a4_body(res[q2], str[q2]);
426+
const string_constraintt a4(q2, lower_bound, res.length(), a4_body);
427+
constraints.push_back(a4);
428+
424429
return if_exprt(
425430
out_of_bounds, from_integer(1, f.type()), from_integer(0, f.type()));
426431
}

0 commit comments

Comments
 (0)