Skip to content

Commit 5347b3c

Browse files
committed
Add constraints for bounded quantification
These can only be omitted when the instantiations trivially make them true. This surfaced further misinterpretations in the regression tests of the "==>" operator: bounded existential quantification should generally use &&.
1 parent b0e3df0 commit 5347b3c

File tree

7 files changed

+35
-22
lines changed

7 files changed

+35
-22
lines changed

regression/cbmc/Quantifiers-assertion/test.desc

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

44
^\*\* Results:$

regression/cbmc/Quantifiers-if/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ int main()
99
if(__CPROVER_forall { int i; (i>=0 && i<2) ==> a[i]>=1 && a[i]<=10 })
1010
__CPROVER_assert(0, "failure 1");
1111

12-
if(__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=1 && a[i]<=10 })
12+
if(__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=1 && a[i]<=10 })
1313
__CPROVER_assert(0, "failure 2");
1414

1515
if(__CPROVER_forall { int i; (i>=0 && i<2) ==> a[i]>=2 && a[i]<=10 })
1616
__CPROVER_assert(0, "success 1");
1717

18-
if(__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=2 && a[i]<=10 })
18+
if(__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=2 && a[i]<=10 })
1919
__CPROVER_assert(0, "failure 3");
2020

21-
if(__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=5 && a[i]<=10 })
21+
if(__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=5 && a[i]<=10 })
2222
__CPROVER_assert(0, "success 2");
2323
// clang-format on
2424

regression/cbmc/Quantifiers-invalid-var-range/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ int main()
44
int a[3][3];
55
// clang-format off
66
// clang-format would rewrite the "==>" as "== >"
7-
__CPROVER_assume(__CPROVER_forall { int i; (i>=0 && i<5) ==> __CPROVER_exists{int j; (j>=i && j<3) ==> a[i][j]==10} });
7+
// NOLINTNEXTLINE(whitespace/line_length)
8+
__CPROVER_assume(__CPROVER_forall { int i; (i>=0 && i<5) ==> __CPROVER_exists{int j; (j>=i && j<3) && a[i][j]==10} });
89
// clang-format on
910

1011
assert(a[0][0]==10||a[0][1]==10||a[0][2]==10);

regression/cbmc/Quantifiers-not-exists/test.desc

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,7 @@
1-
KNOWNBUG
1+
CORE
22
main.c
3-
4-
^\*\* Results:$
5-
^\[main.assertion.5\] line 28 assertion a\[.*\]\[.*\] > 10: SUCCESS$
6-
^\[main.assertion.6\] line 30 assertion tmp_if_expr\$\d+: SUCCESS$
7-
^\[main.assertion.7\] line 31 assertion tmp_if_expr\$\d+: SUCCESS$
8-
^\[main.assertion.8\] line 33 assertion tmp_if_expr\$\d+: SUCCESS$
9-
^\[main.assertion.9\] line 35 assertion tmp_if_expr\$\d+: SUCCESS$
10-
^\[main.assertion.10\] line 36 assertion tmp_if_expr\$\d+: SUCCESS$
11-
^\*\* 0 of 10 failed
12-
^VERIFICATION SUCCESSFUL$
3+
--cover location
4+
^\*\* 1 of 46 covered \(2.2%\)
135
^EXIT=0$
146
^SIGNAL=0$
157
--

regression/cbmc/Quantifiers-not/main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ int main()
99
if(!__CPROVER_forall { int i; (i>=0 && i<2) ==> a[i]>=1 && a[i]<=10 })
1010
__CPROVER_assert(0, "success 1");
1111

12-
if(!__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=1 && a[i]<=10 })
12+
if(!__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=1 && a[i]<=10 })
1313
__CPROVER_assert(0, "success 2");
1414

1515
if(!__CPROVER_forall { int i; (i>=0 && i<2) ==> a[i]>=2 && a[i]<=10 })
1616
__CPROVER_assert(0, "failure 1");
1717

18-
if(!__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=2 && a[i]<=10 })
18+
if(!__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=2 && a[i]<=10 })
1919
__CPROVER_assert(0, "success 3");
2020

21-
if(!__CPROVER_exists { int i; (i>=0 && i<2) ==> a[i]>=5 && a[i]<=10 })
21+
if(!__CPROVER_exists { int i; (i>=0 && i<2) && a[i]>=5 && a[i]<=10 })
2222
__CPROVER_assert(0, "failure 2");
2323
// clang-format on
2424

regression/cbmc/Quantifiers-two-dimension-array/test.desc

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

44
^\*\* Results:$

src/solvers/flattening/boolbv_quantifier.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,31 @@ instantiate_quantifier(const quantifier_exprt &expr, const namespacet &ns)
169169

170170
if(expr.id()==ID_forall)
171171
{
172-
return conjunction(expr_insts);
172+
// maintain the domain constraint if it isn't guaranteed by the
173+
// instantiations (for a disjunction the domain constraint is implied by the
174+
// instantiations)
175+
if(re.id() == ID_and)
176+
{
177+
expr_insts.push_back(binary_predicate_exprt(
178+
var_expr, ID_gt, from_integer(lb, var_expr.type())));
179+
expr_insts.push_back(binary_predicate_exprt(
180+
var_expr, ID_le, from_integer(ub, var_expr.type())));
181+
}
182+
return simplify_expr(conjunction(expr_insts), ns);
173183
}
174184
else if(expr.id() == ID_exists)
175185
{
176-
return disjunction(expr_insts);
186+
// maintain the domain constraint if it isn't trivially satisfied by the
187+
// instantiations (for a conjunction the instantiations are stronger
188+
// constraints)
189+
if(re.id() == ID_or)
190+
{
191+
expr_insts.push_back(binary_predicate_exprt(
192+
var_expr, ID_gt, from_integer(lb, var_expr.type())));
193+
expr_insts.push_back(binary_predicate_exprt(
194+
var_expr, ID_le, from_integer(ub, var_expr.type())));
195+
}
196+
return simplify_expr(disjunction(expr_insts), ns);
177197
}
178198

179199
UNREACHABLE;

0 commit comments

Comments
 (0)