SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
utils.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <carl-arith/poly/umvpoly/functions/Derivative.h>
4 #include <carl-arith/poly/umvpoly/functions/Factorization.h>
5 #include <carl-arith/poly/umvpoly/functions/Resultant.h>
6 #include <carl-arith/poly/umvpoly/functions/Definiteness.h>
7 #include <carl-arith/poly/umvpoly/functions/Representation.h>
8 
10 #include <smtrat-common/model.h>
13 
14 #include <algorithm>
15 #include <optional>
16 #include <set>
17 #include <unordered_map>
18 #include <variant>
19 #include <vector>
20 
21 #include <carl-arith/ran/ran.h>
22 #include "RealAlgebraicPoint.h"
23 
24 #include "OCStatistics.h"
25 #include "Assertables.h"
26 
27 namespace smtrat {
28 namespace mcsat {
29 namespace onecellcad {
30 
31 using RAN = smtrat::RAN;
32 
33 using RANMap = std::map<carl::Variable, RAN>;
34 
35 #ifdef SMTRAT_DEVOPTION_Statistics
36  OCStatistics& getStatistic();
37 #endif
38 
39 /**
40  * Invariance Types
41  */
42 enum class InvarianceType {
43  ORD_INV,
44  SIGN_INV // order or sign invariance requirement
45 };
46 
47 inline std::ostream& operator<<(std::ostream& os, const InvarianceType& inv) {
48  switch (inv) {
50  return os << "ORD_INV";
52  return os << "SIGN_INV";
53  }
54  return os;
55 }
56 
57 // SIGN_INV < ORD_INV, since order invariance is a "stronger" property.
58 inline bool operator<(const InvarianceType& l, const InvarianceType& r) {
59  switch (l) {
61  return false;
63  return r == InvarianceType ::ORD_INV;
64  }
65  return false;
66 }
67 
68 /**
69  * Tagged Polynomials
70  */
71 struct TagPoly {
73 
75 
76  // Cache the poly's level to avoid recomputing it in many places.
77  std::size_t level;
78 
79  // Optional possibility to cache total degree of polynomial
80  std::size_t deg = 0;
81 };
82 
83 inline std::ostream& operator<<(std::ostream& os, const TagPoly& p) {
84  return os << "(poly " << p.tag << " " << p.poly << ")";
85 }
86 
87 inline bool operator==(const TagPoly& lhs, const TagPoly& rhs) {
88  return lhs.tag == rhs.tag && lhs.poly == rhs.poly;
89 }
90 
91 inline std::ostream& operator<<(std::ostream& os, const std::vector<TagPoly>& polys) {
92  os << "[ " << polys.size() << ": ";
93  for (const auto& poly : polys)
94  os << poly.tag << " " << poly.poly << ", ";
95  return os << "]";
96 }
97 
98 inline std::ostream& operator<<(std::ostream& os, const std::vector<std::vector<TagPoly>>& lvls) {
99  int lvl = (int)lvls.size() - 1;
100  for (auto it = lvls.rbegin(); it != lvls.rend(); ++it) {
101  os << lvl << ": ";
102  os << *it << "\n";
103  lvl--;
104  }
105  return os;
106 }
107 
108 
109 
110 /**
111 * @param p Polynomial to get degree from
112 * @param v Rootvariable for degree calc
113 * @return
114 */
115 inline std::size_t getDegree(TagPoly p, carl::Variable v) {
116  return carl::total_degree(carl::to_univariate_polynomial(p.poly, v));
117 }
118 
119 /**
120  * Find the index of the highest variable (wrt. the ordering
121  * in 'variableOrder') that occurs with positive degree in 'poly'.
122  * Although 'level' is a math concept that starts counting at 1
123  * we start counting at 0 and represent "no level/variable" as std::nullopt
124  * because it simplifies using the level directly as an index into arrays
125  * or vectors.
126  * Examples:
127  * - polyLevel(2) == nullopt wrt. any variable order
128  * - polyLevel(0*x+2) == nullopt wrt. any variable order
129  * - polyLevel(x+2) == 0 wrt. [x < y < z]
130  * - polyLevel(x+2) == 1 wrt. [y < x < z]
131  * - polyLevel(x+2) == 2 wrt. [y < z < x]
132  * - polyLevel(x*y+2) == 1 wrt. [x < y < z] because of y
133  * - polyLevel(x*y+2) == 1 wrt. [y < x < z] because of x
134  * - polyLevel(x*y+2) == 2 wrt. [x < z < y] because of y
135  * Preconditions:
136  * - 'variables(poly)' must be a subset of 'variableOrder'.
137  */
138 inline std::optional<std::size_t> levelOf(
139  const std::vector<carl::Variable>& variableOrder,
140  const Poly& poly) {
141  // precondition:
142  //assert(isSubset(asVector(variables(poly)), variableOrder));
143 
144  // Algorithm:
145  // Iterate through each variable inside 'variableOrder' in ascending order
146  // and remove it from 'polyVariables'. The last variable in 'polyVariables' before
147  // it becomes empty is the highest appearing variable in 'poly'.
148  //SMTRAT_LOG_DEBUG("smtrat.cad","poly " << poly);
149 
150  // 'gatherVariables()' collects only variables with positive degree
151  std::set<carl::Variable> polyVariables = carl::variables(poly).as_set();
152  //SMTRAT_LOG_DEBUG("smtrat.cad","variables " << polyVariables);
153 
154  if(polyVariables.empty()){
155  //SMTRAT_LOG_DEBUG("smtrat.cad", "level " << 0);
156  return std::nullopt;
157  }
158 
159  for (std::size_t level = 0; level < variableOrder.size(); ++level) {
160  polyVariables.erase(variableOrder[level]);
161  // Last variable before 'polyVariables' becomes empty is the highest variable.
162  if (polyVariables.empty()) {
163  //SMTRAT_LOG_DEBUG("smtrat.cad", "level " << level+1);
164  return level;
165  }
166  }
167  throw("Poly contains variable not found in variableOrder");
168  return std::nullopt;
169 }
170 
171 inline std::vector<TagPoly> nonConstIrreducibleFactors(
172  std::vector<carl::Variable> variableOrder,
173  Poly poly,
174  InvarianceType tag) {
175 
176  std::vector<TagPoly> factors;
177  for (const Poly& factor : carl::irreducible_factors(poly, false)) {
178  factors.emplace_back(TagPoly{tag, factor, *levelOf(variableOrder, factor)}); // inherit poly's tag
179  //SMTRAT_LOG_DEBUG("smtrat.cad", "factor " << factor);
180  assert(!factor.is_constant());
181  }
182 
183  return factors;
184 }
185 
186 inline void appendOnCorrectLevel(const Poly& poly, InvarianceType tag, std::vector<std::vector<TagPoly>>& polys, std::vector<carl::Variable> variableOrder) {
187  //The invariant of this alg is that we always only have a polynomial with either si or oi in polys
188  //This could be violated by the initially entered polys in OneCell construction but that only leads to less efficiency and no error
189  std::vector<TagPoly> factors = nonConstIrreducibleFactors(variableOrder, poly, tag);
190  // to do carl::normalize()
191  for (const auto& factor : factors) {
192  if (!factor.poly.is_constant()) {
193  #ifdef SMTRAT_DEVOPTION_Statistics
194  OCStatistics& mStatistics = getStatistic();
195  // change this to en-/disable mMaxDegree Statistic
196  bool maxDegStatisticOn = true;
197  if(maxDegStatisticOn){
198  std::size_t curDeg = getDegree(factor, variableOrder[factor.level]);
199  if(curDeg > mStatistics.getCurrentMaxDegree()){
200  mStatistics.updateMaxDegree(curDeg);
201  }
202  }
203  #endif
204  TagPoly siFactor = factor;
205  TagPoly oiFactor = factor;
206  siFactor.tag = InvarianceType::SIGN_INV;
207  oiFactor.tag = InvarianceType::ORD_INV;
208 
209  auto siContained = std::find(polys[factor.level].begin(), polys[factor.level].end(), siFactor);
210  auto oiContained = std::find(polys[factor.level].begin(), polys[factor.level].end(), oiFactor);
211 
212  if (siContained == polys[factor.level].end() && oiContained == polys[factor.level].end()) {
213  // poly is not yet in vector with either sign-inv. type
214  polys[factor.level].push_back(factor);
215  } else if (siContained != polys[factor.level].end() && tag == InvarianceType::ORD_INV) {
216  polys[factor.level].erase(siContained);
217  polys[factor.level].push_back(factor);
218  }
219  }
220  }
221 }
222 
223 
224 /**
225  * Represent a cell's (closed-interval-boundary) component along th k-th axis.
226  * A section is a
227  * function f: algReal^{k-1} -> algReal; from a multi-dimensional input point
228  * of level k-1 (whose components are algebraic reals) to an algebraic real.
229  * We use a root-expression with an irreducible, multivariate polynomial of level k.
230  */
231 struct Section {
232  // A section is always finite, a sector may have infty bounds!
234 
235  /**
236  * For performance we cache the isolated root from `boundFunction' that lies closest
237  * along this section's level to the main point.
238  */
240 };
241 
242 inline std::ostream& operator<<(std::ostream& os, const Section& s) {
243  return os << "[section " << s.boundFunction << " " << s.isolatedRoot << "]";
244 }
245 
246 
247 /**
248  * Represent a cell's open-interval boundary object along one single axis by two
249  * irreducible, multivariate polynomials of level k.
250  * A sector is an algebraic/"moving" boundary, because it's basically a
251  * function f: algReal^{k-1} -> (algReal,algReal); from a multi-dimensional
252  * input point of level k-1 (whose components are algebraic reals) to a pair
253  * of algebraic reals (the lower and upper bound for an open interval along
254  * k-th axis that changes depending on the input point).
255  * Note that if 'lowBound' or 'highBound' is not defined, then this
256  * represents negative and positive infinity, respectively.
257  */
258 struct Sector {
259  /** A std::nullopt lowBound represents negative infinity */
260  std::optional<Section> lowBound;
261 
262  /** A std:nullopt highBound represents infinity */
263  std::optional<Section> highBound;
264 };
265 
266 inline std::ostream& operator<<(std::ostream& os, const Sector& s) {
267  os << "(sector ";
268  s.lowBound ? os << s.lowBound.value() : os << "[-infty]";
269  os << " ";
270  s.highBound ? os << s.highBound.value() : os << "[infty]";
271  return os << ")";
272 }
273 
274 
275 /**
276  * Represent a single cell [brown15].
277  * A cell is a collection of boundary objects along each axis, called
278  * cell-components based on math. vectors and their components.
279  */
280 using CADCell = std::vector<std::variant<Sector, Section>>;
281 
282 inline std::ostream& operator<<(std::ostream& os, const CADCell& cell) {
283  os << "(cell [";
284  for (std::size_t i = 0; i < cell.size(); i++) {
285  if (std::holds_alternative<Sector>(cell[i])) {
286  const auto cellSctr = std::get<Sector>(cell[i]);
287  if (cellSctr.lowBound)
288  os << cellSctr.lowBound->boundFunction;
289  else
290  os << "-infty";
291  os << " < var_" << i << " < ";
292  if (cellSctr.highBound)
293  os << cellSctr.highBound->boundFunction;
294  else
295  os << "+infty";
296  } else {
297  os << "var_" << i << " = ";
298  const auto cellSctn = std::get<Section>(cell[i]);
299  os << cellSctn.boundFunction;
300  }
301  os << ", ";
302  }
303  return os << "])";
304 }
305 
306 
307 inline std::vector<Poly> asMultiPolys(const std::vector<TagPoly> polys) {
308  std::vector<Poly> mPolys;
309  for (const auto& poly : polys)
310  mPolys.emplace_back(poly.poly);
311  return mPolys;
312 }
313 
314 inline bool contains(const std::vector<TagPoly>& polys, const Poly& poly) {
315  auto isMatch = [&poly](const TagPoly& taggedPoly) {
316  return taggedPoly.poly == poly;
317  };
318  return std::find_if(polys.begin(), polys.end(), isMatch) != polys.end();
319 }
320 
321 template<typename T>
322 bool contains(const std::vector<T>& list, const T& elem) {
323  return std::find(list.begin(), list.end(), elem) != list.end();
324 }
325 
326 /**
327  * @param rootVariable The variable with respect to which the roots are computed in the end.
328  * It will be replaced by the special unique root-variable "_z" common in root-expressions.
329  */
330 inline MultivariateRootT asRootExpr(carl::Variable rootVariable, Poly poly, std::size_t rootIdx) {
331  assert(carl::variables(poly).has(rootVariable));
332  // Apparently we need this complicated construction. I forgot why a simple substitute is not okay.
333  return MultivariateRootT(poly, rootIdx, rootVariable);
334 }
335 
337  const mcsat::Bookkeeping& data) {
338  std::vector<RAN> point;
339  for (const auto variable : data.assignedVariables()) {
340  const auto& modelValue = data.model().evaluated(variable);
341  assert(modelValue.isRational() || modelValue.isRAN());
342  modelValue.isRational() ? point.emplace_back(modelValue.asRational()) : point.emplace_back(modelValue.asRAN());
343  }
344  return RealAlgebraicPoint<smtrat::Rational>(std::move(point));
345 }
346 
347 
348 template<typename T>
349 std::vector<T> prefix(const std::vector<T> vars, std::size_t prefixSize) {
350  std::vector<T> prefixVars(vars.begin(), std::next(vars.begin(), (long)prefixSize));
351  return prefixVars;
352 }
353 
354 
355 inline std::vector<std::pair<Poly, Poly>> duplicateElimination(std::vector<std::pair<Poly, Poly>> vec){
356  for (auto it1 = vec.begin(); it1 != vec.end();) {
357  // also eliminate reflexive pairs since those are already covered by discriminants
358  if(it1->first == it1->second){
359  it1 = vec.erase(it1);
360  continue;
361  }
362  for (auto it2 = it1 + 1; it2 != vec.end();) {
363  if (((*it1).first == (*it2).first && (*it1).second == (*it2).second) ||
364  ((*it1).first == (*it2).second && (*it1).second == (*it2).first)) {
365  it2 = vec.erase(it2);
366  } else {
367  it2++;
368  }
369  }
370  it1++;
371  }
372  return vec;
373 }
374 
375 inline void duplicateElimination(std::vector<Poly>& vec){
376  if(!vec.empty()) {
377  for (auto it1 = vec.begin(); it1 != vec.end() - 1; it1++) {
378  for (auto it2 = it1 + 1; it2 != vec.end();) {
379  if (*it1 == *it2) {
380  it2 = vec.erase(it2);
381  } else {
382  it2++;
383  }
384  }
385  }
386  }
387 }
388 
389 
390 /**
391  * Projection related utilities for onecellcad
392  */
393 
394 /* Components of Projection operators optimized for Single Cell Construction
395  -> For efficiency also return the resulting components level
396  -> Also normalize the resulting component w.r.t. the new highest ranked var in the poly
397  */
398 inline Poly discriminant(const carl::Variable& mainVariable, const Poly& p) {
399  auto disc = carl::discriminant(carl::to_univariate_polynomial(p, mainVariable));
400 
401  return Poly(disc);
402 }
403 
404 inline Poly resultant(const carl::Variable& mainVariable, const Poly& p1, const Poly& p2) {
405  const auto p1UPoly = carl::to_univariate_polynomial(p1, mainVariable);
406  const auto p2UPoly = carl::to_univariate_polynomial(p2, mainVariable);
407  auto res = carl::resultant(p1UPoly, p2UPoly);
408 
409  return Poly(res);
410 }
411 //No normalization for ldcf
412 inline Poly leadcoefficient(const carl::Variable& mainVariable, const Poly& p) {
413  return p.lcoeff(mainVariable);
414 }
415 
416 
417 inline void addResultants(std::vector<std::pair<Poly, Poly>>& resultants,
418  std::vector<std::vector<TagPoly>>& polys,
419  carl::Variable mainVar,
420  const std::vector<carl::Variable>& variableOrder){
421  if(!resultants.empty()) {
422  duplicateElimination(resultants);
423 
424  for (auto const& elem : resultants) {
425  Poly res = resultant(mainVar, elem.first, elem.second);
426  SMTRAT_LOG_TRACE("smtrat.cad", "Add resultant(" << elem.first << "," << elem.second << ") = " << res << " (if not const)");
427  appendOnCorrectLevel(res, InvarianceType::ORD_INV, polys, variableOrder);
428  }
429  }
430 }
431 
432 
433 /**
434  * @return Dimension of a hybercube to which the given cell is homeomorphic,
435  * i.e., count the number of sectors of the given Cell restricted to its first
436  * components (with index 0 to 'uptoLevel').
437  */
438 inline std::size_t cellDimension(const CADCell& cell, const std::size_t uptoLevel) {
439  std::size_t sectorCount = 0;
440  for (std::size_t i = 0; i <= uptoLevel; i++)
441  if (std::holds_alternative<Sector>(cell[i]))
442  sectorCount++;
443  return sectorCount;
444 }
445 
446 inline CADCell fullSpaceCell(std::size_t cellComponentCount) {
447  return CADCell(cellComponentCount);
448 }
449 
450 class OneCellCAD {
451 public:
452  /**
453  * Variables can also be indexed by level. Polys with mathematical level 1 contain the variable in variableOrder[0]
454  */
455  const std::vector<carl::Variable>& variableOrder;
457 
458 
459  OneCellCAD(const std::vector<carl::Variable>& variableOrder, const RealAlgebraicPoint<Rational>& point)
461  point(point) {
462  // precondition:
463  assert(!variableOrder.empty());
464  assert(hasUniqElems(variableOrder));
465  }
466 
467  /**
468  * Create a mapping from the first variables (with index 0 to 'componentCount') in the
469  * 'variableOrder' to the first components of the given 'point'.
470  */
471  std::map<carl::Variable, RAN> prefixPointToStdMap(
472  const std::size_t componentCount) {
473  std::map<carl::Variable, RAN> varToRANMap;
474  for (std::size_t i = 0; i < componentCount; i++)
475  varToRANMap[variableOrder[i]] = point[i];
476  return varToRANMap;
477  }
478 
479  /**src/lib/datastructures/mcsat/onecellcad/OneCellCAD.h
480  * Given a poly p(x1,..,xn), return all roots of the univariate poly
481  * p(a1,..,an-1, xn), where a1,..an-1 are the first algebraic real components
482  * from 'point' (SORTED!).
483  */
484  std::vector<RAN> isolateLastVariableRoots(
485  const std::size_t polyLevel,
486  const Poly& poly) {
487  // No checks for corectness
488  return carl::real_roots(
489  carl::to_univariate_polynomial(poly, variableOrder[polyLevel]),
490  prefixPointToStdMap(polyLevel)).roots();
491  }
492 
493  /**
494  * Check if an n-variate 'poly' p(x1,..,xn) with n>=1 already becomes the
495  * zero poly after plugging in p(a1,..,an-1, xn), where a1,..an-1 are the
496  * first n-1 algebraic real components from 'point'.
497  */
498  inline bool vanishesEarly(
499  const std::size_t polyLevel,
500  const Poly& poly) {
501  // precondition:
502  assert(!poly.is_constant());
503  if (poly.is_linear())
504  return false; // cannot vanish early
505 
506  const carl::Variable mainVariable = variableOrder[polyLevel];
507 
508  return carl::real_roots(carl::to_univariate_polynomial(poly, mainVariable), prefixPointToStdMap(polyLevel)).is_nullified();
509  }
510 
512  const std::size_t polyLevel,
513  const Poly& poly) {
514  const std::size_t componentCount = polyLevel + 1;
515 
516  //No fail-check here
517  auto res = carl::evaluate(
518  carl::BasicConstraint<Poly>(poly, carl::Relation::EQ),
519  prefixPointToStdMap(componentCount));
520  assert(!indeterminate(res));
521  return (bool) res;
522  }
523 
524  inline bool isPointRootOfPoly(
525  const TagPoly& poly) {
526  return isPointRootOfPoly(poly.level, poly.poly);
527  }
528 
529  std::optional<Poly> coeffNonNull(const TagPoly& boundCandidate) {
530  // This function is similar to "RefNonNull" from [brown15]
531  // precondition:
532  assert(isNonConstIrreducible(boundCandidate.poly));
533  assert(!vanishesEarly(boundCandidate.level, boundCandidate.poly));
534  SMTRAT_LOG_TRACE("smtrat.cad", "coeffNonNull");
535 
536  const auto mainVariable = variableOrder[boundCandidate.level];
537  const auto boundCandidateUniPoly =
538  carl::to_univariate_polynomial(boundCandidate.poly, mainVariable);
539 
540  // Do early-exit tests:
541  for (const auto& coeff : boundCandidateUniPoly.coefficients()) {
542  if (coeff.is_constant() && !carl::is_zero(coeff))
543  return std::nullopt;
544  }
545 
546  //removed && contains(polys[*lvl], ldcf) in if
547  Poly ldcf = leadcoefficient(mainVariable, boundCandidate.poly);
548  std::optional<size_t> lvl = levelOf(variableOrder, ldcf);
549  if (lvl.has_value() && !isPointRootOfPoly(*lvl, ldcf)) {
550  return std::nullopt;
551  }
552 
553  //removed && contains(polys[*lvl], disc) in if
554  Poly disc = discriminant(mainVariable, boundCandidate.poly);
555  lvl = levelOf(variableOrder, disc);
556  if (lvl.has_value() && !isPointRootOfPoly(*lvl, disc)) {
557  return std::nullopt;
558  }
559 
560  // optional early-exit check: if for every point in subcell, poly does not
561  // vanish, return success. No idea how to do that efficiently.
562 
563  for (const auto& coeff : boundCandidateUniPoly.coefficients()) {
564  // find first non-vanishing coefficient:
565  if (carl::is_zero(coeff)) continue;
566  const size_t coeffLevel = *levelOf(variableOrder, coeff); // certainly non-constant
567  if (!isPointRootOfPoly(coeffLevel, coeff)) {
568  return coeff;
569  }
570  }
571  return std::nullopt;
572  }
573 
574  bool isMainPointInsideCell(const CADCell& cell) {
575  for (std::size_t lvl = 0; lvl < cell.size(); lvl++) {
576  const RAN pointCmp = point[lvl];
577  const auto cellCmp = cell[lvl];
578  if (std::holds_alternative<Sector>(cellCmp)) {
579  // must be low < point_k < high
580  const auto cellSctr = std::get<Sector>(cellCmp);
581  if (cellSctr.lowBound) {
582  if (!(cellSctr.lowBound->isolatedRoot < pointCmp))
583  return false;
584  }
585  if (cellSctr.highBound) {
586  if (!(cellSctr.highBound->isolatedRoot > pointCmp))
587  return false;
588  }
589  } else {
590  const auto cellSctn = std::get<Section>(cellCmp);
591  // must be point_k == root
592  SMTRAT_LOG_DEBUG("smtrat.cad", "Section: " << cellSctn << " point_" << lvl << ": " << pointCmp);
593  if (!(cellSctn.isolatedRoot == pointCmp))
594  return false;
595  }
596  }
597  return true;
598  }
599 };
600 
601 
603  carl::Variable mainVar,
604  size_t currentLevel,
605  std::vector<std::vector<TagPoly>>& projectionLevels,
606  OneCellCAD& cad) {
607 
608  std::vector<TagPoly>& polys = projectionLevels[currentLevel];
609  SMTRAT_LOG_DEBUG("smtrat.cad", "Do optimized McCallum projection of " << polys);
610  //optimization: Calculate resultants similar to heuristic 2 in a chain (WC-complexity is equal to full projection)
611  std::vector<std::pair<RAN, Poly>> root_list;
612  for (auto const& tpoly : polys) {
613  auto poly = tpoly.poly;
614 
615  auto r = carl::real_roots(carl::to_univariate_polynomial(poly, mainVar), cad.prefixPointToStdMap(currentLevel));
616  //check for nullification
617  if(r.is_nullified()){
618  return false;
619  }
620  for(auto const& root : r.roots()){
621  root_list.emplace_back(std::make_pair(root, poly));
622  }
623 
624  Poly ldcf = leadcoefficient(mainVar, poly);
625  SMTRAT_LOG_TRACE("smtrat.cad.projection", "Add leadcoefficient(" << poly << ") = " << ldcf << " (if not const)");
626  appendOnCorrectLevel(ldcf, InvarianceType::SIGN_INV, projectionLevels, cad.variableOrder);
627 
628  auto coeff = cad.coeffNonNull(tpoly);
629  if (coeff.has_value()) {
630  SMTRAT_LOG_TRACE("smtrat.cad", "Add result of coeffNonNull: " << coeff.value() << " (if not const)");
631  appendOnCorrectLevel(coeff.value(), InvarianceType::SIGN_INV, projectionLevels, cad.variableOrder);
632  }
633 
634  Poly disc = discriminant(mainVar, poly);
635  SMTRAT_LOG_TRACE("smtrat.cad.projection", "Add discriminant(" << poly << ") = " << disc << " (if not const)");
636  appendOnCorrectLevel(disc, InvarianceType::ORD_INV, projectionLevels, cad.variableOrder);
637  }
638 
639  //Resultant calcultaion
640  std::sort(root_list.begin(), root_list.end(), [](auto const& t1, auto const& t2) {
641  return t1.first < t2.first;
642  });
643 
644  std::vector<std::pair<Poly, Poly>> resultants;
645  if(!root_list.empty()) {
646  for (auto it = root_list.begin(); it != root_list.end() - 1; it++) {
647  resultants.emplace_back(std::make_pair((*it).second, (*(it+1)).second));
648  }
649  }
650  addResultants(resultants, projectionLevels, mainVar, cad.variableOrder);
651 
652  return true;
653 }
654 
656  std::vector<carl::Variable>& variableOrder,
657  carl::Variable mainVar,
658  size_t currentLevel,
659  std::vector<std::vector<TagPoly>>& projectionLevels) {
660 
661  std::vector<TagPoly>& polys = projectionLevels[currentLevel];
662  SMTRAT_LOG_DEBUG("smtrat.cad", "Do full McCallum projection of " << polys);
663  for (std::size_t i = 0; i < polys.size(); i++) {
664  Poly poly = polys[i].poly;
665 
666  std::vector<Poly> coeffs = carl::to_univariate_polynomial(poly, mainVar).coefficients();
667  for (const auto& coeff : coeffs) {
668  SMTRAT_LOG_TRACE("smtrat.cad.projection", "Add coefficient(" << poly << ") = " << coeff << " (if not const)");
669  appendOnCorrectLevel(coeff, InvarianceType::SIGN_INV, projectionLevels, variableOrder);
670  }
671 
672  Poly disc = discriminant(mainVar, poly);
673  SMTRAT_LOG_TRACE("smtrat.cad.projection", "Add discriminant(" << poly << ") = " << disc << " (if not const)");
674  appendOnCorrectLevel(disc, InvarianceType::ORD_INV, projectionLevels, variableOrder);
675 
676  std::vector<std::pair<Poly, Poly>> resultants;
677  for (std::size_t j = i + 1; j < polys.size(); j++) {
678  auto poly2 = polys[j].poly;
679  resultants.emplace_back(std::make_pair(poly, poly2));
680  }
681  addResultants(resultants, projectionLevels, mainVar, variableOrder);
682  }
683 }
684 
685 } // namespace onecellcad
686 } // namespace mcsat
687 } // namespace smtrat
A collection of helper functions to check assertable conditions for CAD properties,...
Represent the trail, i.e.
Definition: Bookkeeping.h:19
const auto & assignedVariables() const
Definition: Bookkeeping.h:37
const auto & model() const
Definition: Bookkeeping.h:34
const std::vector< carl::Variable > & variableOrder
Variables can also be indexed by level.
Definition: utils.h:455
std::optional< Poly > coeffNonNull(const TagPoly &boundCandidate)
Definition: utils.h:529
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
std::map< carl::Variable, RAN > prefixPointToStdMap(const std::size_t componentCount)
Create a mapping from the first variables (with index 0 to 'componentCount') in the 'variableOrder' t...
Definition: utils.h:471
bool isPointRootOfPoly(const TagPoly &poly)
Definition: utils.h:524
OneCellCAD(const std::vector< carl::Variable > &variableOrder, const RealAlgebraicPoint< Rational > &point)
Definition: utils.h:459
Represent a multidimensional point whose components are algebraic reals.
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
static bool find(V &ts, const T &t)
Definition: Alg.h:47
Rational evaluate(carl::Variable v, const Poly &p, const Rational &r)
Definition: utils.h:11
bool operator<(const InvarianceType &l, const InvarianceType &r)
Definition: utils.h:58
std::ostream & operator<<(std::ostream &os, const RealAlgebraicPoint< Number > &r)
Streaming operator for a RealAlgebraicPoint.
std::vector< T > prefix(const std::vector< T > vars, std::size_t prefixSize)
Definition: utils.h:349
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< TagPoly > nonConstIrreducibleFactors(std::vector< carl::Variable > variableOrder, Poly poly, InvarianceType tag)
Definition: utils.h:171
std::vector< Poly > asMultiPolys(const std::vector< TagPoly > polys)
Definition: utils.h:307
void appendOnCorrectLevel(const Poly &poly, InvarianceType tag, std::vector< std::vector< TagPoly >> &polys, std::vector< carl::Variable > variableOrder)
Definition: utils.h:186
std::size_t getDegree(TagPoly p, carl::Variable v)
Definition: utils.h:115
Poly leadcoefficient(const carl::Variable &mainVariable, const Poly &p)
Definition: utils.h:412
RealAlgebraicPoint< smtrat::Rational > asRANPoint(const mcsat::Bookkeeping &data)
Definition: utils.h:336
bool operator==(RealAlgebraicPoint< Number > &lhs, RealAlgebraicPoint< Number > &rhs)
Check if two RealAlgebraicPoints are equal.
std::size_t cellDimension(const CADCell &cell, const std::size_t uptoLevel)
Definition: utils.h:438
void singleLevelFullProjection(std::vector< carl::Variable > &variableOrder, carl::Variable mainVar, size_t currentLevel, std::vector< std::vector< TagPoly >> &projectionLevels)
Definition: utils.h:655
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
bool optimized_singleLevelFullProjection(carl::Variable mainVar, size_t currentLevel, std::vector< std::vector< TagPoly >> &projectionLevels, OneCellCAD &cad)
Definition: utils.h:602
std::map< carl::Variable, RAN > RANMap
Definition: utils.h:33
InvarianceType
Invariance Types.
Definition: utils.h:42
void addResultants(std::vector< std::pair< Poly, Poly >> &resultants, std::vector< std::vector< TagPoly >> &polys, carl::Variable mainVar, const std::vector< carl::Variable > &variableOrder)
Definition: utils.h:417
std::vector< std::pair< Poly, Poly > > duplicateElimination(std::vector< std::pair< Poly, Poly >> vec)
Definition: utils.h:355
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
Poly discriminant(const carl::Variable &mainVariable, const Poly &p)
Projection related utilities for onecellcad.
Definition: utils.h:398
bool hasUniqElems(const std::vector< T > &container)
Definition: Assertables.h:42
Poly resultant(const carl::Variable &mainVariable, const Poly &p1, const Poly &p2)
Definition: utils.h:404
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:43
Class to create the formulas for axioms.
carl::IntRepRealAlgebraicNumber< Rational > RAN
Definition: types.h:47
carl::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
carl::MultivariateRoot< Poly > MultivariateRootT
Definition: model.h:24
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#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
RAN isolatedRoot
For performance we cache the isolated root from ‘boundFunction’ that lies closest along this section'...
Definition: utils.h:239
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