@@ -168,29 +168,49 @@ static optionalt<exprt> eager_quantifier_instantiation(
168168 return re;
169169 }
170170
171- const optionalt<constant_exprt> min_i = get_quantifier_var_min (var_expr, re);
172- const optionalt<constant_exprt> max_i = get_quantifier_var_max (var_expr, re);
171+ if (var_expr.is_boolean ())
172+ {
173+ // Expand in full.
174+ // This grows worst-case exponentially in the quantifier nesting depth.
175+ if (expr.id () == ID_forall)
176+ {
177+ // ∀b.f(b) <===> f(0)∧f(1)
178+ return and_exprt (
179+ expr.instantiate ({false_exprt ()}), expr.instantiate ({true_exprt ()}));
180+ }
181+ else if (expr.id () == ID_exists)
182+ {
183+ // ∃b.f(b) <===> f(0)∨f(1)
184+ return or_exprt (
185+ expr.instantiate ({false_exprt ()}), expr.instantiate ({true_exprt ()}));
186+ }
187+ else
188+ UNREACHABLE;
189+ }
190+
191+ const optionalt<constant_exprt> min_i =
192+ get_quantifier_var_min (var_expr, re);
193+ const optionalt<constant_exprt> max_i =
194+ get_quantifier_var_max (var_expr, re);
173195
174196 if (!min_i.has_value () || !max_i.has_value ())
175197 return nullopt ;
176198
177199 mp_integer lb = numeric_cast_v<mp_integer>(min_i.value ());
178200 mp_integer ub = numeric_cast_v<mp_integer>(max_i.value ());
179201
180- if (lb> ub)
202+ if (lb > ub)
181203 return nullopt ;
182204
183205 std::vector<exprt> expr_insts;
184- for (mp_integer i= lb; i<= ub; ++i)
206+ for (mp_integer i = lb; i <= ub; ++i)
185207 {
186208 exprt constraint_expr = re;
187- replace_expr (var_expr,
188- from_integer (i, var_expr.type ()),
189- constraint_expr);
209+ replace_expr (var_expr, from_integer (i, var_expr.type ()), constraint_expr);
190210 expr_insts.push_back (constraint_expr);
191211 }
192212
193- if (expr.id ()== ID_forall)
213+ if (expr.id () == ID_forall)
194214 {
195215 // maintain the domain constraint if it isn't guaranteed by the
196216 // instantiations (for a disjunction the domain constraint is implied by the
0 commit comments