SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
OneCellCAD.h
Go to the documentation of this file.
1 #pragma once
2 
3 /**
4  * @file
5  * Construct a single open CAD Cell around a given point that is sign-invariant
6  * on a given set of polynomials.
7  *
8  * References:
9  * [brown15] Brown, Christopher W., and Marek Košta.
10  * "Constructing a single cell in cylindrical algebraic decomposition."
11  * Journal of Symbolic Computation 70 (2015): 14-48.
12  * [mccallum84] Scott McCallum.
13  * "An Improved Projection Operation for Cylindrical Algebraic Decomposition"
14  * Ph.D. Dissertation. 1984. The University of Wisconsin - Madison
15  */
16 
17 #include "../Assertables.h"
18 #include "../utils.h"
19 
20 
21 namespace smtrat {
22 namespace mcsat {
23 namespace onecellcad {
24 namespace recursive {
25 
26 
27 
29 
30 enum class ShrinkResult {
31  SUCCESS,
32  FAIL
33 };
34 
35 inline std::ostream& operator<<(std::ostream& os, const ShrinkResult& s) {
36  switch (s) {
38  return os << "SUCCESS";
39  case ShrinkResult::FAIL:
40  return os << "FAIL";
41  }
42  return os;
43 }
44 
45 class RecursiveCAD : public OneCellCAD {
46 private:
47  /**
48  * Projection factor set divided into levels. Polys with mathematical level 1 are at projFactorSet[0]
49  * This collection is called "P_prj" in [brown15]
50  */
51  std::vector<std::vector<TagPoly>> projFactorSet; // init all levels with empty vector
52 
53  /** Only delinating polys. This collection is called "P_dln" in [brown15] */
54  std::vector<TagPoly> delineators;
55 
56 public:
58 
59  bool isAlreadyProcessed(const TagPoly& poly) {
60  // matches if poly is found with its tag or an oi-tag
61  auto isMatch = [&poly](const TagPoly& processedPoly) {
62  return processedPoly.poly == poly.poly &&
63  (processedPoly.tag == poly.tag || processedPoly.tag == InvarianceType::ORD_INV);
64  };
65  auto& log = projFactorSet[poly.level];
66  if (std::find_if(log.begin(), log.end(), isMatch) != log.end())
67  return true;
68 
69  return std::find_if(delineators.begin(), delineators.end(), isMatch) != delineators.end();
70  }
71 
72  /**
73  * Shrink the component of the 'cell' at the 'boundCandidate's level around
74  * the given point if the 'boundCandidate' is a tighter bound. Don't
75  * recursively shrink lower level components of the cell.
76  * Note that a cell's sector may collapse into a section, which is why we
77  * need to pass in a cell and not only its sector.
78  * Note that this shrink function is always "successful", even if the cell
79  * was not shrunk.
80  * @param boundCandidate Must be a non-const irreducible polynomial that does
81  * not vanish early.
82  */
84  const std::size_t polyLevel,
85  const Poly& poly,
86  CADCell& cell) {
87  // This function is called "Update" in [brown15]
88  // precondition:
89  assert(isNonConstIrreducible(poly));
90  assert(!vanishesEarly(polyLevel, poly));
91  if (std::holds_alternative<Section>(cell[polyLevel]))
92  return; // canot shrink further
93 
94  Sector& sector = std::get<Sector>(cell[polyLevel]);
95  const RAN pointComp = point[polyLevel]; // called alpha_k in [brown15]
96 
97  SMTRAT_LOG_DEBUG("smtrat.cad", "Shrink cell sector at lvl " << polyLevel);
98  SMTRAT_LOG_TRACE("smtrat.cad", "Sector: " << sector);
99  SMTRAT_LOG_TRACE("smtrat.cad", "Poly: " << poly);
100  SMTRAT_LOG_TRACE("smtrat.cad", "Lvl-Var: " << variableOrder[polyLevel]);
101  SMTRAT_LOG_DEBUG("smtrat.cad", "PointComp: " << pointComp);
102  //SMTRAT_LOG_TRACE("smtrat.cad", "Point: " << point.prefixPoint(polyLevel + 1));
103  // Isolate real isolatedRoots of level-k 'poly' after plugin in a level-(k-1) point.
104  // Poly must not vanish under this prefixPoint!
105  auto isolatedRoots =
106  isolateLastVariableRoots(polyLevel, poly);
107  if (isolatedRoots.empty()) {
108  SMTRAT_LOG_TRACE("smtrat.cad", "No isolatable isolatedRoots");
109  return;
110  }
111  SMTRAT_LOG_TRACE("smtrat.cad", "Isolated roots: " << isolatedRoots);
112 
113  if (sector.lowBound) {
114  SMTRAT_LOG_TRACE("smtrat.cad", "Existing low bound: " << (*(sector.lowBound)).isolatedRoot);
115  assert((*(sector.lowBound)).isolatedRoot < pointComp);
116  }
117  if (sector.highBound) {
118  SMTRAT_LOG_TRACE("smtrat.cad", "Existing high bound: " << (*(sector.highBound)).isolatedRoot);
119  assert((*(sector.highBound)).isolatedRoot > pointComp);
120  }
121 
122  // Search for closest isolatedRoots/boundPoints to pointComp, i.e.
123  // someRoot ... < closestLower <= pointComp <= closestUpper < ... someOtherRoot
124  std::optional<RAN> closestLower;
125  std::optional<RAN> closestUpper;
126 
127  std::size_t rootIdx = 0, lowerRootIdx = 0, upperRootIdx = 0;
128  carl::Variable rootVariable = variableOrder[polyLevel];
129  for (const auto& root : isolatedRoots) {
130  rootIdx++;
131  if (root < pointComp) {
132  SMTRAT_LOG_TRACE("smtrat.cad", "Smaller: " << root);
133  if (!closestLower || *closestLower < root) {
134  closestLower = root;
135  lowerRootIdx = rootIdx;
136  }
137  } else if (root == pointComp) {
138  SMTRAT_LOG_TRACE("smtrat.cad", "Equal: " << root);
139  // Sector collapses into a section
140  cell[polyLevel] = Section{asRootExpr(rootVariable, poly, rootIdx), root};
141  SMTRAT_LOG_TRACE("smtrat.cad", "Sector collapses: " << (Section{asRootExpr(rootVariable, poly, rootIdx), root}));
142  return;
143  } else { // pointComp < root
144  SMTRAT_LOG_TRACE("smtrat.cad", "Bigger: " << root);
145  if (!closestUpper || root < *closestUpper) {
146  closestUpper = root;
147  upperRootIdx = rootIdx;
148  }
149  }
150  }
151 
152  if (closestLower) {
153  if (!sector.lowBound || (*(sector.lowBound)).isolatedRoot < closestLower) {
154  sector.lowBound = Section{asRootExpr(rootVariable, poly, lowerRootIdx), *closestLower};
155  SMTRAT_LOG_TRACE("smtrat.cad", "New section: "
156  << " " << sector);
157  }
158  }
159 
160  if (closestUpper) {
161  if (!sector.highBound || closestUpper < (*(sector.highBound)).isolatedRoot) {
162  sector.highBound = Section{asRootExpr(rootVariable, poly, upperRootIdx), *closestUpper};
163  SMTRAT_LOG_TRACE("smtrat.cad", "New section: "
164  << " " << sector);
165  }
166  }
167  }
168 
169  /**
170  * Find the smallest index m such that in the set S of all m-th partial
171  * derivatives of the given poly, such that there is a derivative that does
172  * not vanish early [brown15].
173  * Note that m > 0 i.e, this function never just returns the given poly,
174  * which is the 0th partial derivative of itself.
175  * @param poly must not be a const-poly like 2, otherwise this function
176  * does not terminate.
177  * @return Actually only returns the set S
178  */
180  assert(!mainPoly.poly.is_constant());
181  // We search for this set of partial derivatives "layer by layer".
182  // The layer of 0-th partial derivatives is the mainPoly itself.
183  std::vector<Poly> layerOfDerivatives;
184  layerOfDerivatives.emplace_back(mainPoly.poly);
185  bool foundSomeNonEarlyVanishingDerivative = false;
186 
187  do {
188  std::vector<Poly> nextLayer;
189  for (const auto& poly : layerOfDerivatives) {
190  // Derive poly wrt to each variable (variables with idx 0 to 'mainPoly.level')
191  for (std::size_t varIdx = 0; varIdx <= mainPoly.level; varIdx++) {
192  const auto derivative = carl::derivative(poly, variableOrder[varIdx]);
193  if (carl::is_zero(derivative))
194  continue;
195  nextLayer.emplace_back(derivative);
196  if (foundSomeNonEarlyVanishingDerivative)
197  continue; // avoid expensive vanishing check
198 
199  if (derivative.is_constant() ||
200  !vanishesEarly(mainPoly.level, mainPoly.poly))
201  foundSomeNonEarlyVanishingDerivative = true;
202  // still need to compute all remaining nextLayer-polys
203  }
204  }
205  layerOfDerivatives = std::move(nextLayer);
206  } while (!foundSomeNonEarlyVanishingDerivative);
207 
208  return layerOfDerivatives;
209  }
210 
212  const TagPoly& boundCandidate,
213  CADCell& cell) {
214  // This function is called "RefNull" in [brown15]
215  // precondition:
216  assert(isNonConstIrreducible(boundCandidate.poly));
217  assert(isPointRootOfPoly(boundCandidate));
218  SMTRAT_LOG_TRACE("smtrat.cad", "RefineNull");
219  const auto mainVariable = variableOrder[boundCandidate.level];
220  const auto boundCandidateUniPoly =
221  carl::to_univariate_polynomial(boundCandidate.poly, mainVariable);
222  std::vector<TagPoly> projectionResult;
223 
224  Poly disc = discriminant(mainVariable, boundCandidate.poly);
225  if(!disc.is_constant()){
226  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, disc, *levelOf(variableOrder, disc)});
227 
228  }
229 
230  auto ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
231  if(!disc.is_constant()) {
232  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, ldcf, *levelOf(variableOrder, ldcf)});
233  }
234 
235  Poly tcf = boundCandidateUniPoly.tcoeff();
236  std::optional<size_t> lvl = levelOf(variableOrder, tcf);
237  if(lvl.has_value()) {
238  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, tcf, *lvl});
239  }
240 
241  for (auto& resultPoly : projectionResult) {
243  return ShrinkResult::FAIL;
244  }
245 
246  return ShrinkResult::SUCCESS;
247  }
248 
250  const TagPoly& boundCandidate,
251  CADCell& cell) {
252  // This function is called MergeNull in [brown15]
253  // precondition:
254  SMTRAT_LOG_TRACE("smtrat.cad", "ShrinkWithEarlyVanishingPoly");
255  assert(vanishesEarly(boundCandidate.level, boundCandidate.poly));
256  assert(isNonConstIrreducible(boundCandidate.poly));
257  SMTRAT_LOG_TRACE("smtrat.cad", "ShrinkWithEarlyVanishingPoly");
258 
259  auto shrinkResult = refineNull(boundCandidate, cell);
260  if (shrinkResult == ShrinkResult::FAIL)
261  return shrinkResult;
262 
263  if (boundCandidate.tag == InvarianceType::SIGN_INV) {
264  projFactorSet[boundCandidate.level].emplace_back(boundCandidate);
265  return ShrinkResult::SUCCESS;
266  } else { //boundCandidate.tag == InvarianceType::ORD_INV
267  if (cellDimension(cell, boundCandidate.level - 1) > 0)
268  return ShrinkResult::FAIL;
269 
270  // Construct a delineating poly as the sum of all non-earlyVanishing,
271  // squared m-th partial derivatives.
272  Poly delineator(0);
273  for (const auto& poly :
275  if (!vanishesEarly(boundCandidate.level, boundCandidate.poly))
276  delineator += poly * poly;
277  }
278 
279  if (!delineator.is_constant()) {
280  const std::size_t delineatorLevel = *levelOf(variableOrder, delineator);
281  shrinkSingleComponent(delineatorLevel, delineator, cell);
282 
283  const TagPoly taggedDelineator{
285  delineator,
286  delineatorLevel};
287  projFactorSet[delineatorLevel].emplace_back(taggedDelineator);
288  delineators.emplace_back(taggedDelineator);
289  }
290  return ShrinkResult::SUCCESS;
291  }
292  }
293 
295  const TagPoly& poly,
296  CADCell& cell) {
297  for (const auto& factor : carl::irreducible_factors(poly.poly, false)) {
298  SMTRAT_LOG_TRACE("smtrat.cad", "Shrink with irreducible factor: Poly: "
299  << poly.poly << " Factor: " << factor);
300  if (factor.is_constant())
301  continue;
302 
303  const std::size_t factorLevel = *levelOf(variableOrder, factor);
304  TagPoly factorWithInheritedTag{poly.tag, factor, factorLevel};
305  if (shrinkCell(factorWithInheritedTag, cell) == ShrinkResult::FAIL)
306  return ShrinkResult::FAIL;
307  }
308  return ShrinkResult::SUCCESS;
309  }
310 
312  const TagPoly& boundCandidate,
313  CADCell& cell) {
314  // This function is called "RefNonNull" in [brown15]
315  // precondition:
316  assert(isNonConstIrreducible(boundCandidate.poly));
317  assert(!vanishesEarly(boundCandidate.level, boundCandidate.poly));
318  SMTRAT_LOG_TRACE("smtrat.cad", "RefineNonNull");
319 
320  const auto mainVariable = variableOrder[boundCandidate.level];
321  const auto boundCandidateUniPoly =
322  carl::to_univariate_polynomial(boundCandidate.poly, mainVariable);
323 
324  // Do early-exit tests:
325  for (const auto& coeff : boundCandidateUniPoly.coefficients()) {
326  if (coeff.is_constant() && !carl::is_zero(coeff))
327  return ShrinkResult::SUCCESS;
328  }
329 
330  const Poly ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
331  std::optional<size_t> lvl = levelOf(variableOrder, ldcf);
332  if (lvl.has_value() && (contains(projFactorSet[*lvl], ldcf) || contains(delineators, ldcf)) && !isPointRootOfPoly(*lvl, ldcf)) {
333  return ShrinkResult::SUCCESS;
334  }
335 
336  const Poly disc = discriminant(mainVariable, boundCandidate.poly);
337  lvl = levelOf(variableOrder, disc);
338  if (lvl.has_value() && (contains(projFactorSet[*lvl], disc) || contains(delineators, disc)) && !isPointRootOfPoly(*lvl, disc)) {
339  return ShrinkResult::SUCCESS;
340  }
341 
342  // optional early-exit check: if for every point in subcell, poly does not
343  // vanish, return success. No idea how to do that efficiently.
344 
345  for (const auto& coeff : boundCandidateUniPoly.coefficients()) {
346  // find first non-vanishing coefficient:
347  if (carl::is_zero(coeff)) continue;
348  const auto coeffLevel = *levelOf(variableOrder, coeff); // certainly non-constant
349  if (!isPointRootOfPoly(coeffLevel, coeff)) {
351  {InvarianceType::SIGN_INV, coeff, coeffLevel},
352  cell);
353  }
354  }
355  return ShrinkResult::SUCCESS;
356  }
357 
359  const TagPoly& boundCandidate,
360  CADCell& cell) {
361  // This function is called MergeRoot in [brown15]
362  // precondition:
363  assert(!vanishesEarly(boundCandidate.level, boundCandidate.poly));
364  assert(isPointRootOfPoly(boundCandidate));
365  SMTRAT_LOG_TRACE("smtrat.cad", "ShrinkWithPolyHavingPointAsRoot");
366 
367  // Do a "model-based" Brown-McCallum projection.
368  std::vector<TagPoly> projectionResult;
369  const auto mainVariable = variableOrder[boundCandidate.level];
370  if (std::holds_alternative<Section>(cell[boundCandidate.level])) {
371  Poly res = resultant(mainVariable, boundCandidate.poly,
372  std::get<Section>(cell[boundCandidate.level]).boundFunction.poly());
373  if(!res.is_constant()){
374  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
375  }
376 
377  if (boundCandidate.tag == InvarianceType::ORD_INV) {
378  Poly ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
379  if(!ldcf.is_constant()) {
380  projectionResult.emplace_back(TagPoly{InvarianceType::SIGN_INV, ldcf, *levelOf(variableOrder, ldcf)});
381  }
382 
383  Poly disc = discriminant(mainVariable, boundCandidate.poly);
384  if(!disc.is_constant()) {
385  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, disc, *levelOf(variableOrder, disc)});
386  }
387  }
388  } else { // cellComponent is a Sector at 'boundCandidate's level
389  Poly ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
390  if(!ldcf.is_constant()) {
391  projectionResult.emplace_back(TagPoly{InvarianceType::SIGN_INV, ldcf, *levelOf(variableOrder, ldcf)});
392  }
393 
394  Poly disc = discriminant(mainVariable, boundCandidate.poly);
395  if(!disc.is_constant()) {
396  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, disc, *levelOf(variableOrder, disc)});
397  }
398 
399  Sector& sectorAtLvl = std::get<Sector>(cell[boundCandidate.level]);
400 
401  if (sectorAtLvl.lowBound) {
402  Poly res = resultant(mainVariable, boundCandidate.poly, sectorAtLvl.lowBound->boundFunction.poly());
403  if(!res.is_constant()) {
404  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
405  }
406  }
407  if (sectorAtLvl.highBound) {
408  Poly res = resultant(mainVariable, boundCandidate.poly, sectorAtLvl.highBound->boundFunction.poly());
409  if(!res.is_constant()) {
410  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
411  }
412  }
413  }
414 
415  for (auto& resultPoly : projectionResult) {
417  return ShrinkResult::FAIL;
418  }
419 
420  if (boundCandidate.tag == InvarianceType::ORD_INV ||
421  std::holds_alternative<Sector>(cell[boundCandidate.level])) {
422  if (refineNonNull(boundCandidate, cell) == ShrinkResult::FAIL)
423  return ShrinkResult::FAIL;
424 
425  shrinkSingleComponent(boundCandidate.level, boundCandidate.poly, cell);
426  }
427 
428  projFactorSet[boundCandidate.level].emplace_back(TagPoly{
430  boundCandidate.poly,
431  boundCandidate.level});
432 
433  return ShrinkResult::SUCCESS;
434  }
435 
436  /** Check if there is a root of the given polynomial---that becomes univariate
437  * after pluggin in all but the last variable wrt. the given variableOrder---,
438  * that lies between the given 'low' and 'high' bounds.
439  */
441  const RAN& low,
442  const RAN& high,
443  const Poly& poly,
444  const std::size_t polyLevel) {
445  for (const RAN& candidate :
446  isolateLastVariableRoots(polyLevel, poly)) {
447  if (low <= candidate && candidate <= high)
448  return true;
449  }
450  return false;
451  }
452 
454  const TagPoly& boundCandidate,
455  CADCell& cell) {
456  // This function is called "MergeNotRoot" in [brown15]
457  // precondition:
458  assert(isNonConstIrreducible(boundCandidate.poly));
459  assert(!isPointRootOfPoly(boundCandidate));
460  SMTRAT_LOG_TRACE("smtrat.cad", "ShrinkWithNonRootPoint");
461 
462  // Do a "model-based" Brown-McCallum projection.
463  std::vector<TagPoly> projectionResult;
464  const auto mainVariable = variableOrder[boundCandidate.level];
465  if (std::holds_alternative<Section>(cell[boundCandidate.level])) {
466  Section sectionAtLvl = std::get<Section>(cell[boundCandidate.level]);
467  Poly res = resultant(mainVariable, boundCandidate.poly, sectionAtLvl.boundFunction.poly());
468  if(!res.is_constant()) {
469  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
470  }
471  } else { // cellComponent is a Sector at 'boundCandidate's level
472  Poly disc = discriminant(mainVariable, boundCandidate.poly);
473  if(!disc.is_constant()) {
474  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, disc, *levelOf(variableOrder, disc)});
475  }
476 
477  Sector sectorAtLvl = std::get<Sector>(cell[boundCandidate.level]);
478  if (!sectorAtLvl.lowBound || !sectorAtLvl.highBound ||
480  sectorAtLvl.lowBound->isolatedRoot,
481  sectorAtLvl.highBound->isolatedRoot,
482  boundCandidate.poly,
483  boundCandidate.level)) {
484  Poly ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
485  if(!ldcf.is_constant()) {
486  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, ldcf, *levelOf(variableOrder, ldcf)});
487  }
488  }
489 
490  if (sectorAtLvl.lowBound) {
491  Poly res = resultant(mainVariable, boundCandidate.poly, sectorAtLvl.lowBound->boundFunction.poly());
492  if(!res.is_constant()) {
493  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
494  }
495  }
496  if (sectorAtLvl.highBound) {
497  Poly res = resultant(mainVariable, boundCandidate.poly, sectorAtLvl.highBound->boundFunction.poly());
498  if(!res.is_constant()) {
499  projectionResult.emplace_back(TagPoly{InvarianceType::ORD_INV, res, *levelOf(variableOrder, res)});
500  }
501  }
502  }
503 
504  for (auto resultPoly : projectionResult) {
506  return ShrinkResult::FAIL;
507  }
508 
509  if (std::holds_alternative<Sector>(cell[boundCandidate.level])) {
510  if (refineNonNull(boundCandidate, cell) == ShrinkResult::FAIL)
511  return ShrinkResult::FAIL;
512 
513  shrinkSingleComponent(boundCandidate.level, boundCandidate.poly, cell);
514  }
515 
516  projFactorSet[boundCandidate.level].emplace_back(TagPoly{
518  boundCandidate.poly,
519  boundCandidate.level});
520 
521  return ShrinkResult::SUCCESS;
522  }
523 
524  /**
525  * Merge the given open OpenCADCell 'cell' that contains the given 'point'
526  * (called "alpha" in [brown15]) with a polynomial 'poly'.
527  * Before the merge 'cell' represents a region that is sign-invariant
528  * on other (previously merged) polynomials (all signs are non-zero).
529  * The returned cell represents a region that is additionally sign-invariant on
530  * 'poly' (also with non-zero sign).
531  * @return either an OpenCADCell or nothing (representing a failed construction)
532  */
534  const TagPoly& boundCandidate,
535  CADCell& cell) {
536  // This function is called "Merge" in [brown15]
537  SMTRAT_LOG_INFO("smtrat.cad", "Shrink cell");
538  SMTRAT_LOG_DEBUG("smtrat.cad", "Poly: " << boundCandidate);
539  SMTRAT_LOG_DEBUG("smtrat.cad", "Cell: " << cell);
540  // precondition:
541  //if(!isPointInsideCell(cell)){
542  // std::exit(77);
543  //}
544  assert(isMainPointInsideCell(cell));
545 
546  if (isAlreadyProcessed(boundCandidate))
547  return ShrinkResult::SUCCESS;
548 
549  if (cellDimension(cell, boundCandidate.level) == 0) {
550  projFactorSet[boundCandidate.level].emplace_back(TagPoly{InvarianceType::ORD_INV, boundCandidate.poly, boundCandidate.level});
551  return ShrinkResult::SUCCESS;
552  }
553 
554  if (boundCandidate.level == 0) {
555  if (std::holds_alternative<Sector>(cell[boundCandidate.level]))
556  shrinkSingleComponent(boundCandidate.level, boundCandidate.poly, cell);
557  projFactorSet[boundCandidate.level].emplace_back(TagPoly{InvarianceType::ORD_INV, boundCandidate.poly, boundCandidate.level});
558  return ShrinkResult::SUCCESS;
559  }
560 
561  if (vanishesEarly(boundCandidate.level, boundCandidate.poly)) {
562  if (cover_nullification) {
563  return shrinkCellWithEarlyVanishingPoly(boundCandidate, cell);
564  } else {
565  return ShrinkResult::FAIL;
566  }
567  }
568 
569  // lower level subcell
570  if (cellDimension(cell, boundCandidate.level - 1) == 0) {
571  shrinkSingleComponent(boundCandidate.level, boundCandidate.poly, cell);
572  projFactorSet[boundCandidate.level].emplace_back(TagPoly{InvarianceType::ORD_INV, boundCandidate.poly, boundCandidate.level});
573  return ShrinkResult::SUCCESS;
574  }
575 
576  if (isPointRootOfPoly(boundCandidate))
577  return shrinkCellWithPolyHavingPointAsRoot(boundCandidate, cell);
578  else
579  return shrinkCellWithNonRootPoint(boundCandidate, cell);
580  }
581 
582  /**
583  * Construct a single CADCell that contains the given 'point' and is
584  * sign-invariant for the given polynomials in 'polys'. The construction
585  * fails if 'polys' are not well-oriented [mccallum84]. Note that
586  * this cell is cylindrical only with respect to the given 'variableOrder'.
587  *
588  * @param variableOrder must contain unique variables and at least one,
589  * because constant polynomials (without a variable) are prohibited.
590  * @param point point.size() >= variables.size().
591  * @param polys must contain only non-constant, irreducible polynomials that
592  * mention only variables that appear in 'variableOrder'.
593  *
594  */
595  std::optional<CADCell> pointEnclosingCADCell(
596  const std::vector<std::vector<onecellcad::TagPoly>>& polys) {
597 
598  SMTRAT_LOG_INFO("smtrat.cad", "Build point enclosing CADcell");
599  SMTRAT_LOG_DEBUG("smtrat.cad", "Variable order: " << variableOrder);
600  SMTRAT_LOG_DEBUG("smtrat.cad", "Point: " << point);
601  auto it = polys.rbegin();
602  while(it != polys.rend()) {
603  auto pVec = asMultiPolys(*it);
604  SMTRAT_LOG_DEBUG("smtrat.cad", "Polys: " << pVec);
605  assert(hasOnlyNonConstIrreducibles(pVec));
606  assert(polyVarsAreAllInList(pVec, variableOrder));
607  it++;
608  }
609 
610  projFactorSet.resize(point.dim());
611  CADCell cell = fullSpaceCell(point.dim());
612  SMTRAT_LOG_DEBUG("smtrat.cad", "Cell: " << cell);
613 
614  for (const auto& polyVec : polys) {
615  for (const auto& poly : polyVec) {
616  if (shrinkCell(poly, cell) == ShrinkResult::FAIL) {
617  SMTRAT_LOG_WARN("smtrat.cad", "Building failed");
618  return std::nullopt;
619  }
620  }
621  }
622 
623  SMTRAT_LOG_DEBUG("smtrat.cad", "Finished Cell: " << cell);
624  assert(isMainPointInsideCell(cell));
625  return cell;
626  }
627 };
628 
629 } // namespace recursive
630 } // namespace onecellcad
631 } // namespace mcsat
632 } // namespace smtrat
const std::vector< carl::Variable > & variableOrder
Variables can also be indexed by level.
Definition: utils.h:455
bool isPointRootOfPoly(const std::size_t polyLevel, const Poly &poly)
Definition: utils.h:511
bool vanishesEarly(const std::size_t polyLevel, const Poly &poly)
Check if an n-variate 'poly' p(x1,..,xn) with n>=1 already becomes the zero poly after plugging in p(...
Definition: utils.h:498
std::vector< RAN > isolateLastVariableRoots(const std::size_t polyLevel, const Poly &poly)
src/lib/datastructures/mcsat/onecellcad/OneCellCAD.h Given a poly p(x1,..,xn), return all roots of th...
Definition: utils.h:484
bool isMainPointInsideCell(const CADCell &cell)
Definition: utils.h:574
const RealAlgebraicPoint< Rational > & point
Definition: utils.h:456
OneCellCAD(const std::vector< carl::Variable > &variableOrder, const RealAlgebraicPoint< Rational > &point)
Definition: utils.h:459
std::size_t dim() const
Give the dimension/number of components of this point.
ShrinkResult shrinkCell(const TagPoly &boundCandidate, CADCell &cell)
Merge the given open OpenCADCell 'cell' that contains the given 'point' (called "alpha" in [brown15])...
Definition: OneCellCAD.h:533
ShrinkResult refineNonNull(const TagPoly &boundCandidate, CADCell &cell)
Definition: OneCellCAD.h:311
ShrinkResult shrinkCellWithEarlyVanishingPoly(const TagPoly &boundCandidate, CADCell &cell)
Definition: OneCellCAD.h:249
std::optional< CADCell > pointEnclosingCADCell(const std::vector< std::vector< onecellcad::TagPoly >> &polys)
Construct a single CADCell that contains the given 'point' and is sign-invariant for the given polyno...
Definition: OneCellCAD.h:595
ShrinkResult shrinkCellWithPolyHavingPointAsRoot(const TagPoly &boundCandidate, CADCell &cell)
Definition: OneCellCAD.h:358
std::vector< Poly > partialDerivativesLayerWithSomeNonEarlyVanishingPoly(const TagPoly &mainPoly)
Find the smallest index m such that in the set S of all m-th partial derivatives of the given poly,...
Definition: OneCellCAD.h:179
bool hasPolyLastVariableRootWithinBounds(const RAN &low, const RAN &high, const Poly &poly, const std::size_t polyLevel)
Check if there is a root of the given polynomial—that becomes univariate after pluggin in all but the...
Definition: OneCellCAD.h:440
std::vector< TagPoly > delineators
Only delinating polys.
Definition: OneCellCAD.h:54
ShrinkResult shrinkCellWithIrreducibleFactorsOfPoly(const TagPoly &poly, CADCell &cell)
Definition: OneCellCAD.h:294
ShrinkResult shrinkCellWithNonRootPoint(const TagPoly &boundCandidate, CADCell &cell)
Definition: OneCellCAD.h:453
void shrinkSingleComponent(const std::size_t polyLevel, const Poly &poly, CADCell &cell)
Shrink the component of the 'cell' at the 'boundCandidate's level around the given point if the 'boun...
Definition: OneCellCAD.h:83
ShrinkResult refineNull(const TagPoly &boundCandidate, CADCell &cell)
Definition: OneCellCAD.h:211
std::vector< std::vector< TagPoly > > projFactorSet
Projection factor set divided into levels.
Definition: OneCellCAD.h:51
projection_compare::Candidate< Poly > candidate(const Poly &p, const Poly &q, std::size_t level)
void log(const FormulaDB &db, const FormulaID id)
std::ostream & operator<<(std::ostream &os, const ShrinkResult &s)
Definition: OneCellCAD.h:35
std::vector< std::variant< Sector, Section > > CADCell
Represent a single cell [brown15].
Definition: utils.h:280
bool isNonConstIrreducible(const PolyType &poly)
Definition: Assertables.h:37
bool contains(const std::vector< TagPoly > &polys, const Poly &poly)
Definition: utils.h:314
smtrat::RAN RAN
Definition: utils.h:31
std::vector< Poly > asMultiPolys(const std::vector< TagPoly > polys)
Definition: utils.h:307
bool polyVarsAreAllInList(const std::vector< PolyType > &polys, const std::vector< carl::Variable > &variables)
Definition: Assertables.h:69
Poly leadcoefficient(const carl::Variable &mainVariable, const Poly &p)
Definition: utils.h:412
std::size_t cellDimension(const CADCell &cell, const std::size_t uptoLevel)
Definition: utils.h:438
MultivariateRootT asRootExpr(carl::Variable rootVariable, Poly poly, std::size_t rootIdx)
Definition: utils.h:330
CADCell fullSpaceCell(std::size_t cellComponentCount)
Definition: utils.h:446
std::optional< std::size_t > levelOf(const std::vector< carl::Variable > &variableOrder, const Poly &poly)
Find the index of the highest variable (wrt.
Definition: utils.h:138
bool hasOnlyNonConstIrreducibles(const std::vector< PolyType > &polys)
Definition: Assertables.h:23
Poly discriminant(const carl::Variable &mainVariable, const Poly &p)
Projection related utilities for onecellcad.
Definition: utils.h:398
Poly resultant(const carl::Variable &mainVariable, const Poly &p1, const Poly &p2)
Definition: utils.h:404
Class to create the formulas for axioms.
carl::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_WARN(channel, msg)
Definition: logging.h:33
#define SMTRAT_LOG_INFO(channel, msg)
Definition: logging.h:34
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
Represent a cell's (closed-interval-boundary) component along th k-th axis.
Definition: utils.h:231
MultivariateRootT boundFunction
Definition: utils.h:233
Represent a cell's open-interval boundary object along one single axis by two irreducible,...
Definition: utils.h:258
std::optional< Section > highBound
A std:nullopt highBound represents infinity.
Definition: utils.h:263
std::optional< Section > lowBound
A std::nullopt lowBound represents negative infinity.
Definition: utils.h:260
Tagged Polynomials.
Definition: utils.h:71