@@ -169,58 +169,80 @@ static optionalt<exprt> eager_quantifier_instantiation(
169
169
return re;
170
170
}
171
171
172
- const optionalt<constant_exprt> min_i = get_quantifier_var_min (var_expr, re);
173
- const optionalt<constant_exprt> max_i = get_quantifier_var_max (var_expr, re);
172
+ if (re.is_boolean ())
173
+ {
174
+ // Expand in full.
175
+ // This grows worst-case exponentially in the quantifier nesting depth.
176
+ if (expr.id () == ID_forall)
177
+ {
178
+ // ∀b.f(b) <===> f(0)∧f(1)
179
+ return and_exprt (
180
+ expr.instantiate ({false_exprt ()}), expr.instantiate ({true_exprt ()}));
181
+ }
182
+ else if (expr.id () == ID_exists)
183
+ {
184
+ // ∃b.f(b) <===> f(0)∨f(1)
185
+ return or_exprt (
186
+ expr.instantiate ({false_exprt ()}), expr.instantiate ({true_exprt ()}));
187
+ }
188
+ else
189
+ UNREACHABLE;
190
+ }
191
+ else
192
+ {
193
+ const optionalt<constant_exprt> min_i =
194
+ get_quantifier_var_min (var_expr, re);
195
+ const optionalt<constant_exprt> max_i =
196
+ get_quantifier_var_max (var_expr, re);
174
197
175
- if (!min_i.has_value () || !max_i.has_value ())
176
- return nullopt;
198
+ if (!min_i.has_value () || !max_i.has_value ())
199
+ return nullopt;
177
200
178
- mp_integer lb = numeric_cast_v<mp_integer>(min_i.value ());
179
- mp_integer ub = numeric_cast_v<mp_integer>(max_i.value ());
201
+ mp_integer lb = numeric_cast_v<mp_integer>(min_i.value ());
202
+ mp_integer ub = numeric_cast_v<mp_integer>(max_i.value ());
180
203
181
- if (lb> ub)
182
- return nullopt;
204
+ if (lb > ub)
205
+ return nullopt;
183
206
184
- std::vector<exprt> expr_insts;
185
- for (mp_integer i=lb; i<=ub; ++i)
186
- {
187
- exprt constraint_expr = re;
188
- replace_expr (var_expr,
189
- from_integer (i, var_expr.type ()),
190
- constraint_expr);
191
- expr_insts.push_back (constraint_expr);
192
- }
207
+ std::vector<exprt> expr_insts;
208
+ for (mp_integer i = lb; i <= ub; ++i)
209
+ {
210
+ exprt constraint_expr = re;
211
+ replace_expr (var_expr, from_integer (i, var_expr.type ()), constraint_expr);
212
+ expr_insts.push_back (constraint_expr);
213
+ }
193
214
194
- if (expr.id ()==ID_forall)
195
- {
196
- // maintain the domain constraint if it isn't guaranteed by the
197
- // instantiations (for a disjunction the domain constraint is implied by the
198
- // instantiations)
199
- if (re.id () == ID_and)
215
+ if (expr.id () == ID_forall)
200
216
{
201
- expr_insts.push_back (binary_predicate_exprt (
202
- var_expr, ID_gt, from_integer (lb, var_expr.type ())));
203
- expr_insts.push_back (binary_predicate_exprt (
204
- var_expr, ID_le, from_integer (ub, var_expr.type ())));
217
+ // maintain the domain constraint if it isn't guaranteed by the
218
+ // instantiations (for a disjunction the domain constraint is implied by the
219
+ // instantiations)
220
+ if (re.id () == ID_and)
221
+ {
222
+ expr_insts.push_back (binary_predicate_exprt (
223
+ var_expr, ID_gt, from_integer (lb, var_expr.type ())));
224
+ expr_insts.push_back (binary_predicate_exprt (
225
+ var_expr, ID_le, from_integer (ub, var_expr.type ())));
226
+ }
227
+ return simplify_expr (conjunction (expr_insts), ns);
205
228
}
206
- return simplify_expr (conjunction (expr_insts), ns);
207
- }
208
- else if (expr.id () == ID_exists)
209
- {
210
- // maintain the domain constraint if it isn't trivially satisfied by the
211
- // instantiations (for a conjunction the instantiations are stronger
212
- // constraints)
213
- if (re.id () == ID_or)
229
+ else if (expr.id () == ID_exists)
214
230
{
215
- expr_insts.push_back (binary_predicate_exprt (
216
- var_expr, ID_gt, from_integer (lb, var_expr.type ())));
217
- expr_insts.push_back (binary_predicate_exprt (
218
- var_expr, ID_le, from_integer (ub, var_expr.type ())));
231
+ // maintain the domain constraint if it isn't trivially satisfied by the
232
+ // instantiations (for a conjunction the instantiations are stronger
233
+ // constraints)
234
+ if (re.id () == ID_or)
235
+ {
236
+ expr_insts.push_back (binary_predicate_exprt (
237
+ var_expr, ID_gt, from_integer (lb, var_expr.type ())));
238
+ expr_insts.push_back (binary_predicate_exprt (
239
+ var_expr, ID_le, from_integer (ub, var_expr.type ())));
240
+ }
241
+ return simplify_expr (disjunction (expr_insts), ns);
219
242
}
220
- return simplify_expr (disjunction (expr_insts), ns);
221
- }
222
243
223
- UNREACHABLE;
244
+ UNREACHABLE;
245
+ }
224
246
}
225
247
226
248
literalt boolbvt::convert_quantifier (const quantifier_exprt &src)
0 commit comments