Skip to content

Commit b2d637d

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 d045df8 commit b2d637d

File tree

9 files changed

+44
-31
lines changed

9 files changed

+44
-31
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
--cover location
4+
^\*\* 1 of 46 covered \(2.2%\)
5+
^EXIT=0$
6+
^SIGNAL=0$
7+
--
8+
^warning: ignoring
9+
--
10+
All assertions are unreachable as each of the __CPROVER_assume evaluate to false
11+
(!exists i. i>=0 && i<2 ==> ... is equivalent to forall i. i>=0 && i<2 && ...,
12+
where neither i>=0 nor i<2 is actually true for all values of i).

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: 0 additions & 20 deletions
This file was deleted.

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)