1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Gereon Kremer, Aina Niemetz |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* Implements the CDCAC approach as described in |
14 |
|
* https://arxiv.org/pdf/2003.05633.pdf. |
15 |
|
*/ |
16 |
|
|
17 |
|
#include "theory/arith/nl/cad/cdcac.h" |
18 |
|
|
19 |
|
#ifdef CVC5_POLY_IMP |
20 |
|
|
21 |
|
#include "options/arith_options.h" |
22 |
|
#include "theory/arith/nl/cad/projections.h" |
23 |
|
#include "theory/arith/nl/cad/variable_ordering.h" |
24 |
|
#include "theory/arith/nl/nl_model.h" |
25 |
|
|
26 |
|
namespace std { |
27 |
|
/** Generic streaming operator for std::vector. */ |
28 |
|
template <typename T> |
29 |
|
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) |
30 |
|
{ |
31 |
|
cvc5::container_to_stream(os, v); |
32 |
|
return os; |
33 |
|
} |
34 |
|
} // namespace std |
35 |
|
|
36 |
|
namespace cvc5 { |
37 |
|
namespace theory { |
38 |
|
namespace arith { |
39 |
|
namespace nl { |
40 |
|
namespace cad { |
41 |
|
|
42 |
4914 |
CDCAC::CDCAC(context::Context* ctx, |
43 |
|
ProofNodeManager* pnm, |
44 |
4914 |
const std::vector<poly::Variable>& ordering) |
45 |
4914 |
: d_variableOrdering(ordering) |
46 |
|
{ |
47 |
4914 |
if (pnm != nullptr) |
48 |
|
{ |
49 |
543 |
d_proof.reset(new CADProofGenerator(ctx, pnm)); |
50 |
|
} |
51 |
4914 |
} |
52 |
|
|
53 |
47 |
void CDCAC::reset() |
54 |
|
{ |
55 |
47 |
d_constraints.reset(); |
56 |
47 |
d_assignment.clear(); |
57 |
47 |
} |
58 |
|
|
59 |
47 |
void CDCAC::computeVariableOrdering() |
60 |
|
{ |
61 |
|
// Actually compute the variable ordering |
62 |
94 |
d_variableOrdering = d_varOrder(d_constraints.getConstraints(), |
63 |
47 |
VariableOrderingStrategy::BROWN); |
64 |
94 |
Trace("cdcac") << "Variable ordering is now " << d_variableOrdering |
65 |
47 |
<< std::endl; |
66 |
|
|
67 |
|
// Write variable ordering back to libpoly. |
68 |
47 |
lp_variable_order_t* vo = poly::Context::get_context().get_variable_order(); |
69 |
47 |
lp_variable_order_clear(vo); |
70 |
142 |
for (const auto& v : d_variableOrdering) |
71 |
|
{ |
72 |
95 |
lp_variable_order_push(vo, v.get_internal()); |
73 |
|
} |
74 |
47 |
} |
75 |
|
|
76 |
47 |
void CDCAC::retrieveInitialAssignment(NlModel& model, const Node& ran_variable) |
77 |
|
{ |
78 |
229 |
if (!options::nlCadUseInitial()) return; |
79 |
|
d_initialAssignment.clear(); |
80 |
|
Trace("cdcac") << "Retrieving initial assignment:" << std::endl; |
81 |
|
for (const auto& var : d_variableOrdering) |
82 |
|
{ |
83 |
|
Node v = getConstraints().varMapper()(var); |
84 |
|
Node val = model.computeConcreteModelValue(v); |
85 |
|
poly::Value value = node_to_value(val, ran_variable); |
86 |
|
Trace("cdcac") << "\t" << var << " = " << value << std::endl; |
87 |
|
d_initialAssignment.emplace_back(value); |
88 |
|
} |
89 |
|
} |
90 |
822 |
Constraints& CDCAC::getConstraints() { return d_constraints; } |
91 |
|
const Constraints& CDCAC::getConstraints() const { return d_constraints; } |
92 |
|
|
93 |
66 |
const poly::Assignment& CDCAC::getModel() const { return d_assignment; } |
94 |
|
|
95 |
17 |
const std::vector<poly::Variable>& CDCAC::getVariableOrdering() const |
96 |
|
{ |
97 |
17 |
return d_variableOrdering; |
98 |
|
} |
99 |
|
|
100 |
107 |
std::vector<CACInterval> CDCAC::getUnsatIntervals(std::size_t cur_variable) |
101 |
|
{ |
102 |
107 |
std::vector<CACInterval> res; |
103 |
1845 |
for (const auto& c : d_constraints.getConstraints()) |
104 |
|
{ |
105 |
1738 |
const poly::Polynomial& p = std::get<0>(c); |
106 |
1738 |
poly::SignCondition sc = std::get<1>(c); |
107 |
1738 |
const Node& n = std::get<2>(c); |
108 |
|
|
109 |
1738 |
if (main_variable(p) != d_variableOrdering[cur_variable]) |
110 |
|
{ |
111 |
|
// Constraint is in another variable, ignore it. |
112 |
928 |
continue; |
113 |
|
} |
114 |
|
|
115 |
1620 |
Trace("cdcac") << "Infeasible intervals for " << p << " " << sc |
116 |
810 |
<< " 0 over " << d_assignment << std::endl; |
117 |
1620 |
auto intervals = infeasible_regions(p, d_assignment, sc); |
118 |
1827 |
for (const auto& i : intervals) |
119 |
|
{ |
120 |
1017 |
Trace("cdcac") << "-> " << i << std::endl; |
121 |
2034 |
PolyVector l, u, m, d; |
122 |
1017 |
m.add(p); |
123 |
1017 |
m.pushDownPolys(d, d_variableOrdering[cur_variable]); |
124 |
1017 |
if (!is_minus_infinity(get_lower(i))) l = m; |
125 |
1017 |
if (!is_plus_infinity(get_upper(i))) u = m; |
126 |
1017 |
res.emplace_back(CACInterval{i, l, u, m, d, {n}}); |
127 |
1017 |
if (isProofEnabled()) |
128 |
|
{ |
129 |
12 |
d_proof->addDirect( |
130 |
8 |
d_constraints.varMapper()(d_variableOrdering[cur_variable]), |
131 |
|
d_constraints.varMapper(), |
132 |
|
p, |
133 |
|
d_assignment, |
134 |
|
sc, |
135 |
|
i, |
136 |
|
n); |
137 |
|
} |
138 |
|
} |
139 |
|
} |
140 |
107 |
pruneRedundantIntervals(res); |
141 |
107 |
return res; |
142 |
|
} |
143 |
|
|
144 |
135 |
bool CDCAC::sampleOutsideWithInitial(const std::vector<CACInterval>& infeasible, |
145 |
|
poly::Value& sample, |
146 |
|
std::size_t cur_variable) |
147 |
|
{ |
148 |
135 |
if (options::nlCadUseInitial() && cur_variable < d_initialAssignment.size()) |
149 |
|
{ |
150 |
|
const poly::Value& suggested = d_initialAssignment[cur_variable]; |
151 |
|
for (const auto& i : infeasible) |
152 |
|
{ |
153 |
|
if (poly::contains(i.d_interval, suggested)) |
154 |
|
{ |
155 |
|
d_initialAssignment.clear(); |
156 |
|
return sampleOutside(infeasible, sample); |
157 |
|
} |
158 |
|
} |
159 |
|
Trace("cdcac") << "Using suggested initial value" << std::endl; |
160 |
|
sample = suggested; |
161 |
|
return true; |
162 |
|
} |
163 |
135 |
return sampleOutside(infeasible, sample); |
164 |
|
} |
165 |
|
|
166 |
60 |
PolyVector CDCAC::requiredCoefficients(const poly::Polynomial& p) const |
167 |
|
{ |
168 |
60 |
PolyVector res; |
169 |
60 |
for (long deg = degree(p); deg >= 0; --deg) |
170 |
|
{ |
171 |
60 |
auto coeff = coefficient(p, deg); |
172 |
60 |
if (lp_polynomial_is_constant(coeff.get_internal())) break; |
173 |
8 |
res.add(coeff); |
174 |
8 |
if (evaluate_constraint(coeff, d_assignment, poly::SignCondition::NE)) |
175 |
|
{ |
176 |
8 |
break; |
177 |
|
} |
178 |
|
} |
179 |
60 |
return res; |
180 |
|
} |
181 |
|
|
182 |
28 |
PolyVector CDCAC::constructCharacterization(std::vector<CACInterval>& intervals) |
183 |
|
{ |
184 |
28 |
Assert(!intervals.empty()) << "A covering can not be empty"; |
185 |
28 |
Trace("cdcac") << "Constructing characterization now" << std::endl; |
186 |
28 |
PolyVector res; |
187 |
|
|
188 |
56 |
for (std::size_t i = 0, n = intervals.size(); i < n - 1; ++i) |
189 |
|
{ |
190 |
28 |
cad::makeFinestSquareFreeBasis(intervals[i], intervals[i + 1]); |
191 |
|
} |
192 |
|
|
193 |
84 |
for (const auto& i : intervals) |
194 |
|
{ |
195 |
56 |
Trace("cdcac") << "Considering " << i.d_interval << std::endl; |
196 |
112 |
Trace("cdcac") << "-> " << i.d_lowerPolys << " / " << i.d_upperPolys |
197 |
56 |
<< " and " << i.d_mainPolys << " / " << i.d_downPolys |
198 |
56 |
<< std::endl; |
199 |
56 |
Trace("cdcac") << "-> " << i.d_origins << std::endl; |
200 |
60 |
for (const auto& p : i.d_downPolys) |
201 |
|
{ |
202 |
|
// Add all polynomial from lower levels. |
203 |
4 |
res.add(p); |
204 |
|
} |
205 |
116 |
for (const auto& p : i.d_mainPolys) |
206 |
|
{ |
207 |
120 |
Trace("cdcac") << "Discriminant of " << p << " -> " << discriminant(p) |
208 |
60 |
<< std::endl; |
209 |
|
// Add all discriminants |
210 |
60 |
res.add(discriminant(p)); |
211 |
|
|
212 |
68 |
for (const auto& q : requiredCoefficients(p)) |
213 |
|
{ |
214 |
|
// Add all required coefficients |
215 |
8 |
Trace("cdcac") << "Coeff of " << p << " -> " << q << std::endl; |
216 |
8 |
res.add(q); |
217 |
|
} |
218 |
90 |
for (const auto& q : i.d_lowerPolys) |
219 |
|
{ |
220 |
30 |
if (p == q) continue; |
221 |
|
// Check whether p(s \times a) = 0 for some a <= l |
222 |
2 |
if (!hasRootBelow(q, get_lower(i.d_interval))) continue; |
223 |
4 |
Trace("cdcac") << "Resultant of " << p << " and " << q << " -> " |
224 |
2 |
<< resultant(p, q) << std::endl; |
225 |
2 |
res.add(resultant(p, q)); |
226 |
|
} |
227 |
90 |
for (const auto& q : i.d_upperPolys) |
228 |
|
{ |
229 |
30 |
if (p == q) continue; |
230 |
|
// Check whether p(s \times a) = 0 for some a >= u |
231 |
2 |
if (!hasRootAbove(q, get_upper(i.d_interval))) continue; |
232 |
4 |
Trace("cdcac") << "Resultant of " << p << " and " << q << " -> " |
233 |
2 |
<< resultant(p, q) << std::endl; |
234 |
2 |
res.add(resultant(p, q)); |
235 |
|
} |
236 |
|
} |
237 |
|
} |
238 |
|
|
239 |
56 |
for (std::size_t i = 0, n = intervals.size(); i < n - 1; ++i) |
240 |
|
{ |
241 |
|
// Add resultants of consecutive intervals. |
242 |
56 |
for (const auto& p : intervals[i].d_upperPolys) |
243 |
|
{ |
244 |
56 |
for (const auto& q : intervals[i + 1].d_lowerPolys) |
245 |
|
{ |
246 |
56 |
Trace("cdcac") << "Resultant of " << p << " and " << q << " -> " |
247 |
28 |
<< resultant(p, q) << std::endl; |
248 |
28 |
res.add(resultant(p, q)); |
249 |
|
} |
250 |
|
} |
251 |
|
} |
252 |
|
|
253 |
28 |
res.reduce(); |
254 |
28 |
res.makeFinestSquareFreeBasis(); |
255 |
|
|
256 |
28 |
return res; |
257 |
|
} |
258 |
|
|
259 |
28 |
CACInterval CDCAC::intervalFromCharacterization( |
260 |
|
const PolyVector& characterization, |
261 |
|
std::size_t cur_variable, |
262 |
|
const poly::Value& sample) |
263 |
|
{ |
264 |
56 |
PolyVector l; |
265 |
56 |
PolyVector u; |
266 |
56 |
PolyVector m; |
267 |
56 |
PolyVector d; |
268 |
|
|
269 |
66 |
for (const auto& p : characterization) |
270 |
|
{ |
271 |
|
// Add polynomials to main |
272 |
38 |
m.add(p); |
273 |
|
} |
274 |
|
// Push lower-dimensional polys to down |
275 |
28 |
m.pushDownPolys(d, d_variableOrdering[cur_variable]); |
276 |
|
|
277 |
|
// Collect -oo, all roots, oo |
278 |
56 |
std::vector<poly::Value> roots; |
279 |
28 |
roots.emplace_back(poly::Value::minus_infty()); |
280 |
66 |
for (const auto& p : m) |
281 |
|
{ |
282 |
76 |
auto tmp = isolate_real_roots(p, d_assignment); |
283 |
38 |
roots.insert(roots.end(), tmp.begin(), tmp.end()); |
284 |
|
} |
285 |
28 |
roots.emplace_back(poly::Value::plus_infty()); |
286 |
28 |
std::sort(roots.begin(), roots.end()); |
287 |
|
|
288 |
|
// Now find the interval bounds |
289 |
56 |
poly::Value lower; |
290 |
56 |
poly::Value upper; |
291 |
78 |
for (std::size_t i = 0, n = roots.size(); i < n; ++i) |
292 |
|
{ |
293 |
78 |
if (sample < roots[i]) |
294 |
|
{ |
295 |
24 |
lower = roots[i - 1]; |
296 |
24 |
upper = roots[i]; |
297 |
24 |
break; |
298 |
|
} |
299 |
54 |
if (roots[i] == sample) |
300 |
|
{ |
301 |
4 |
lower = sample; |
302 |
4 |
upper = sample; |
303 |
4 |
break; |
304 |
|
} |
305 |
|
} |
306 |
28 |
Assert(!is_none(lower) && !is_none(upper)); |
307 |
|
|
308 |
28 |
if (!is_minus_infinity(lower)) |
309 |
|
{ |
310 |
|
// Identify polynomials that have a root at the lower bound |
311 |
20 |
d_assignment.set(d_variableOrdering[cur_variable], lower); |
312 |
50 |
for (const auto& p : m) |
313 |
|
{ |
314 |
30 |
if (evaluate_constraint(p, d_assignment, poly::SignCondition::EQ)) |
315 |
|
{ |
316 |
20 |
l.add(p, true); |
317 |
|
} |
318 |
|
} |
319 |
20 |
d_assignment.unset(d_variableOrdering[cur_variable]); |
320 |
|
} |
321 |
28 |
if (!is_plus_infinity(upper)) |
322 |
|
{ |
323 |
|
// Identify polynomials that have a root at the upper bound |
324 |
20 |
d_assignment.set(d_variableOrdering[cur_variable], upper); |
325 |
48 |
for (const auto& p : m) |
326 |
|
{ |
327 |
28 |
if (evaluate_constraint(p, d_assignment, poly::SignCondition::EQ)) |
328 |
|
{ |
329 |
20 |
u.add(p, true); |
330 |
|
} |
331 |
|
} |
332 |
20 |
d_assignment.unset(d_variableOrdering[cur_variable]); |
333 |
|
} |
334 |
|
|
335 |
28 |
if (lower == upper) |
336 |
|
{ |
337 |
|
// construct a point interval |
338 |
|
return CACInterval{ |
339 |
4 |
poly::Interval(lower, false, upper, false), l, u, m, d, {}}; |
340 |
|
} |
341 |
|
else |
342 |
|
{ |
343 |
|
// construct an open interval |
344 |
24 |
Assert(lower < upper); |
345 |
|
return CACInterval{ |
346 |
24 |
poly::Interval(lower, true, upper, true), l, u, m, d, {}}; |
347 |
|
} |
348 |
|
} |
349 |
|
|
350 |
107 |
std::vector<CACInterval> CDCAC::getUnsatCover(std::size_t curVariable, |
351 |
|
bool returnFirstInterval) |
352 |
|
{ |
353 |
107 |
if (isProofEnabled()) |
354 |
|
{ |
355 |
2 |
d_proof->startRecursive(); |
356 |
|
} |
357 |
214 |
Trace("cdcac") << "Looking for unsat cover for " |
358 |
107 |
<< d_variableOrdering[curVariable] << std::endl; |
359 |
214 |
std::vector<CACInterval> intervals = getUnsatIntervals(curVariable); |
360 |
|
|
361 |
107 |
if (Trace.isOn("cdcac")) |
362 |
|
{ |
363 |
|
Trace("cdcac") << "Unsat intervals for " << d_variableOrdering[curVariable] |
364 |
|
<< ":" << std::endl; |
365 |
|
for (const auto& i : intervals) |
366 |
|
{ |
367 |
|
Trace("cdcac") << "-> " << i.d_interval << " from " << i.d_origins |
368 |
|
<< std::endl; |
369 |
|
} |
370 |
|
} |
371 |
214 |
poly::Value sample; |
372 |
|
|
373 |
163 |
while (sampleOutsideWithInitial(intervals, sample, curVariable)) |
374 |
|
{ |
375 |
93 |
if (!checkIntegrality(curVariable, sample)) |
376 |
|
{ |
377 |
|
// the variable is integral, but the sample is not. |
378 |
|
Trace("cdcac") << "Used " << sample << " for integer variable " |
379 |
|
<< d_variableOrdering[curVariable] << std::endl; |
380 |
|
auto newInterval = buildIntegralityInterval(curVariable, sample); |
381 |
|
Trace("cdcac") << "Adding integrality interval " << newInterval.d_interval |
382 |
|
<< std::endl; |
383 |
|
intervals.emplace_back(newInterval); |
384 |
|
pruneRedundantIntervals(intervals); |
385 |
|
continue; |
386 |
|
} |
387 |
93 |
d_assignment.set(d_variableOrdering[curVariable], sample); |
388 |
93 |
Trace("cdcac") << "Sample: " << d_assignment << std::endl; |
389 |
93 |
if (curVariable == d_variableOrdering.size() - 1) |
390 |
|
{ |
391 |
|
// We have a full assignment. SAT! |
392 |
33 |
Trace("cdcac") << "Found full assignment: " << d_assignment << std::endl; |
393 |
98 |
return {}; |
394 |
|
} |
395 |
60 |
if (isProofEnabled()) |
396 |
|
{ |
397 |
1 |
d_proof->startScope(); |
398 |
|
} |
399 |
|
// Recurse to next variable |
400 |
88 |
auto cov = getUnsatCover(curVariable + 1); |
401 |
60 |
if (cov.empty()) |
402 |
|
{ |
403 |
|
// Found SAT! |
404 |
32 |
Trace("cdcac") << "SAT!" << std::endl; |
405 |
32 |
return {}; |
406 |
|
} |
407 |
28 |
Trace("cdcac") << "Refuting Sample: " << d_assignment << std::endl; |
408 |
56 |
auto characterization = constructCharacterization(cov); |
409 |
28 |
Trace("cdcac") << "Characterization: " << characterization << std::endl; |
410 |
|
|
411 |
28 |
d_assignment.unset(d_variableOrdering[curVariable]); |
412 |
|
|
413 |
|
auto newInterval = |
414 |
56 |
intervalFromCharacterization(characterization, curVariable, sample); |
415 |
28 |
newInterval.d_origins = collectConstraints(cov); |
416 |
28 |
intervals.emplace_back(newInterval); |
417 |
28 |
if (isProofEnabled()) |
418 |
|
{ |
419 |
|
auto cell = d_proof->constructCell( |
420 |
2 |
d_constraints.varMapper()(d_variableOrdering[curVariable]), |
421 |
|
newInterval, |
422 |
|
d_assignment, |
423 |
|
sample, |
424 |
3 |
d_constraints.varMapper()); |
425 |
1 |
d_proof->endScope(cell); |
426 |
|
} |
427 |
|
|
428 |
28 |
if (returnFirstInterval) |
429 |
|
{ |
430 |
|
return intervals; |
431 |
|
} |
432 |
|
|
433 |
28 |
Trace("cdcac") << "Added " << intervals.back().d_interval << std::endl; |
434 |
56 |
Trace("cdcac") << "\tlower: " << intervals.back().d_lowerPolys |
435 |
28 |
<< std::endl; |
436 |
56 |
Trace("cdcac") << "\tupper: " << intervals.back().d_upperPolys |
437 |
28 |
<< std::endl; |
438 |
56 |
Trace("cdcac") << "\tmain: " << intervals.back().d_mainPolys |
439 |
28 |
<< std::endl; |
440 |
56 |
Trace("cdcac") << "\tdown: " << intervals.back().d_downPolys |
441 |
28 |
<< std::endl; |
442 |
28 |
Trace("cdcac") << "\torigins: " << intervals.back().d_origins << std::endl; |
443 |
|
|
444 |
|
// Remove redundant intervals |
445 |
28 |
pruneRedundantIntervals(intervals); |
446 |
|
} |
447 |
|
|
448 |
42 |
if (Trace.isOn("cdcac")) |
449 |
|
{ |
450 |
|
Trace("cdcac") << "Returning intervals for " |
451 |
|
<< d_variableOrdering[curVariable] << ":" << std::endl; |
452 |
|
for (const auto& i : intervals) |
453 |
|
{ |
454 |
|
Trace("cdcac") << "-> " << i.d_interval << std::endl; |
455 |
|
} |
456 |
|
} |
457 |
42 |
if (isProofEnabled()) |
458 |
|
{ |
459 |
2 |
d_proof->endRecursive(); |
460 |
|
} |
461 |
42 |
return intervals; |
462 |
|
} |
463 |
|
|
464 |
47 |
void CDCAC::startNewProof() |
465 |
|
{ |
466 |
47 |
if (isProofEnabled()) |
467 |
|
{ |
468 |
1 |
d_proof->startNewProof(); |
469 |
|
} |
470 |
47 |
} |
471 |
|
|
472 |
14 |
ProofGenerator* CDCAC::closeProof(const std::vector<Node>& assertions) |
473 |
|
{ |
474 |
14 |
if (isProofEnabled()) |
475 |
|
{ |
476 |
1 |
d_proof->endScope(assertions); |
477 |
1 |
return d_proof->getProofGenerator(); |
478 |
|
} |
479 |
13 |
return nullptr; |
480 |
|
} |
481 |
|
|
482 |
93 |
bool CDCAC::checkIntegrality(std::size_t cur_variable, const poly::Value& value) |
483 |
|
{ |
484 |
186 |
Node var = d_constraints.varMapper()(d_variableOrdering[cur_variable]); |
485 |
93 |
if (var.getType() != NodeManager::currentNM()->integerType()) |
486 |
|
{ |
487 |
|
// variable is not integral |
488 |
85 |
return true; |
489 |
|
} |
490 |
8 |
return poly::represents_integer(value); |
491 |
|
} |
492 |
|
|
493 |
|
CACInterval CDCAC::buildIntegralityInterval(std::size_t cur_variable, |
494 |
|
const poly::Value& value) |
495 |
|
{ |
496 |
|
poly::Variable var = d_variableOrdering[cur_variable]; |
497 |
|
poly::Integer below = poly::floor(value); |
498 |
|
poly::Integer above = poly::ceil(value); |
499 |
|
// construct var \in (below, above) |
500 |
|
return CACInterval{poly::Interval(below, above), |
501 |
|
{var - below}, |
502 |
|
{var - above}, |
503 |
|
{var - below, var - above}, |
504 |
|
{}, |
505 |
|
{}}; |
506 |
|
} |
507 |
|
|
508 |
2 |
bool CDCAC::hasRootAbove(const poly::Polynomial& p, |
509 |
|
const poly::Value& val) const |
510 |
|
{ |
511 |
4 |
auto roots = poly::isolate_real_roots(p, d_assignment); |
512 |
4 |
return std::any_of(roots.begin(), roots.end(), [&val](const poly::Value& r) { |
513 |
|
return r >= val; |
514 |
6 |
}); |
515 |
|
} |
516 |
|
|
517 |
2 |
bool CDCAC::hasRootBelow(const poly::Polynomial& p, |
518 |
|
const poly::Value& val) const |
519 |
|
{ |
520 |
4 |
auto roots = poly::isolate_real_roots(p, d_assignment); |
521 |
4 |
return std::any_of(roots.begin(), roots.end(), [&val](const poly::Value& r) { |
522 |
|
return r <= val; |
523 |
6 |
}); |
524 |
|
} |
525 |
|
|
526 |
135 |
void CDCAC::pruneRedundantIntervals(std::vector<CACInterval>& intervals) |
527 |
|
{ |
528 |
135 |
if (isProofEnabled()) |
529 |
|
{ |
530 |
6 |
std::vector<CACInterval> allIntervals = intervals; |
531 |
3 |
cleanIntervals(intervals); |
532 |
27 |
d_proof->pruneChildren([&allIntervals, &intervals](std::size_t i) { |
533 |
24 |
return std::find(intervals.begin(), intervals.end(), allIntervals[i]) |
534 |
12 |
!= intervals.end(); |
535 |
12 |
}); |
536 |
|
} |
537 |
|
else |
538 |
|
{ |
539 |
132 |
cleanIntervals(intervals); |
540 |
|
} |
541 |
135 |
} |
542 |
|
|
543 |
|
} // namespace cad |
544 |
|
} // namespace nl |
545 |
|
} // namespace arith |
546 |
|
} // namespace theory |
547 |
28373 |
} // namespace cvc5 |
548 |
|
|
549 |
|
#endif |