carl  24.04
Computer ARithmetic Library
zeros.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <carl-arith/vs/SqrtEx.h>
4 #include <optional>
5 #include <vector>
6 
7 namespace carl::vs {
8 
9 /**
10  * A square root expression with side conditions.
11  */
12 template<typename Poly>
13 struct zero {
16 };
17 template<typename Poly>
18 std::ostream& operator<<(std::ostream& out, const zero<Poly>& z) {
19  out << z.sqrt_ex << " (if " << z.side_condition << ")";
20  return out;
21 }
22 
23 /**
24  * Gathers zeros with side conditions from the given constraint in the given variable.
25  */
26 template<typename Poly>
27 static bool gather_zeros(const Constraint<Poly>& constraint, const Variable& eliminationVar, std::vector<zero<Poly>>& results) {
28  using Rational = typename Poly::NumberType;
29 
30  if (!constraint.variables().has(eliminationVar)) {
31  return true;
32  }
33 
34  std::vector<Poly> factors;
35  Constraints<Poly> sideConditions;
36 
37  auto& factorization = constraint.lhs_factorization();
39  for (const auto& iter : factorization) {
40  if (carl::variables(iter.first).has(eliminationVar)) {
41  factors.push_back(iter.first);
42  } else {
44  if (cons != Constraint<Poly>(true)) {
45  assert(cons != Constraint<Poly>(false));
46  sideConditions.insert(cons);
47  }
48  }
49  }
50  } else {
51  factors.push_back(constraint.lhs());
52  }
53 
54  for (const auto& factor : factors) {
55  auto varInfo = carl::var_info(factor,eliminationVar,true);
56  const auto& coeffs = varInfo.coeffs();
57  assert(!coeffs.empty());
58 
59  switch (coeffs.rbegin()->first) {
60  case 0: {
61  assert(false);
62  break;
63  }
64  case 1: // degree = 1
65  {
66  Poly constantCoeff;
67  auto iter = coeffs.find(0);
68  if (iter != coeffs.end()) constantCoeff = iter->second;
69  // Create state ({b!=0} + oldConditions, [x -> -c/b]):
70  Constraint<Poly> cons = Constraint<Poly>(coeffs.rbegin()->second, carl::Relation::NEQ);
71  if (cons != Constraint<Poly>(false)) {
72  Constraints<Poly> sideCond = sideConditions;
73  if (cons != Constraint<Poly>(true)) {
74  sideCond.insert(cons);
75  }
76  SqrtEx<Poly> sqEx(-constantCoeff, Poly(), coeffs.rbegin()->second, Poly());
77  results.push_back({std::move(sqEx), std::move(sideCond)});
78  }
79  break;
80  }
81  case 2: // degree = 2
82  {
83  Poly constantCoeff;
84  auto iter = coeffs.find(0);
85  if (iter != coeffs.end()) constantCoeff = iter->second;
86  Poly linearCoeff;
87  iter = coeffs.find(1);
88  if (iter != coeffs.end()) linearCoeff = iter->second;
89  Poly radicand = carl::pow(linearCoeff, 2) - Rational(4) * coeffs.rbegin()->second * constantCoeff;
90  Constraint<Poly> cons11 = Constraint<Poly>(coeffs.rbegin()->second, carl::Relation::EQ);
91  if (cons11 != Constraint<Poly>(false)) {
92  // Create state ({a==0, b!=0} + oldConditions, [x -> -c/b]):
94  if (cons12 != Constraint<Poly>(false)) {
95  Constraints<Poly> sideCond = sideConditions;
96  if (cons11 != Constraint<Poly>(true))
97  sideCond.insert(cons11);
98  if (cons12 != Constraint<Poly>(true))
99  sideCond.insert(cons12);
100  SqrtEx<Poly> sqEx(-constantCoeff, Poly(), linearCoeff, Poly());
101  results.push_back({std::move(sqEx), std::move(sideCond)});
102  }
103  }
105  if (cons21 != Constraint<Poly>(false)) {
106  Constraint<Poly> cons22 = Constraint<Poly>(coeffs.rbegin()->second, carl::Relation::NEQ);
107  if (cons22 != Constraint<Poly>(false)) {
108  Constraints<Poly> sideCond = sideConditions;
109  if (cons21 != Constraint<Poly>(true)) {
110  sideCond.insert(cons21);
111  }
112  if (cons22 != Constraint<Poly>(true)) {
113  sideCond.insert(cons22);
114  }
115 
116  // Create ({a!=0, b^2-4ac>=0} + oldConditions, [x -> (-b-sqrt(b^2-4ac))/2a]):
117  SqrtEx<Poly> sqExA(-linearCoeff, Poly(-1), Rational(2) * coeffs.rbegin()->second, radicand);
118  results.push_back({std::move(sqExA), sideCond});
119 
120  // Create ({a!=0, b^2-4ac>=0} + oldConditions, [x -> (-b+sqrt(b^2-4ac))/2a]):
121  SqrtEx<Poly> sqExB(-linearCoeff, Poly(1), Rational(2) * coeffs.rbegin()->second, radicand);
122  results.push_back({std::move(sqExB), std::move(sideCond)});
123  }
124  }
125  break;
126  }
127  //degree > 2 (> 3)
128  default: {
129  // degree to high
130  return false;
131  break;
132  }
133  }
134  }
135  return true;
136 }
137 
138 template<typename Poly>
139 static bool gather_zeros(const VariableComparison<Poly>& varcomp, const Variable& eliminationVar, std::vector<zero<Poly>>& results) {
140  using Rational = typename Poly::NumberType;
141 
142  if (varcomp.var() != eliminationVar && !carl::variables(varcomp).has(eliminationVar) ) {
143  return true;
144  }
145  auto as_constr = carl::as_constraint(varcomp);
146  if (as_constr) {
147  return gather_zeros(Constraint<Poly>(*as_constr), eliminationVar, results);
148  }
149  if (std::holds_alternative<MultivariateRoot<Poly>>(varcomp.value())) {
150  return false;
151  }
152  assert(varcomp.var() == eliminationVar);
153 
154  const auto& ran = std::get<IntRepRealAlgebraicNumber<Rational>>(varcomp.value());
155  if (ran.is_numeric()) {
156  results.push_back({SqrtEx<Poly>(Poly(Rational(ran.value()))), Constraints<Poly>()});
157  return true;
158  }
159  else {
160  for (const auto& factor : carl::irreducible_factors(carl::defining_polynomial(varcomp), false)) {
161  assert(factor.degree(eliminationVar) > 0);
162  if (factor.degree(eliminationVar) > 2) continue;
163 
164  auto roots = real_roots(carl::to_univariate_polynomial(factor, eliminationVar));
165  assert(roots.is_univariate());
166  auto it = std::find(roots.roots().begin(), roots.roots().end(), ran);
167  if (it != roots.roots().end()) {
168  size_t idx = std::distance(roots.roots().begin(), it);
169 
170  auto varInfo = carl::var_info(factor,eliminationVar,true);
171  const auto& coeffs = varInfo.coeffs();
172  assert(!coeffs.empty());
173 
174  if (coeffs.rbegin()->first == 1) {
175  assert(idx == 0);
176  Poly constantCoeff;
177  auto iter = coeffs.find(0);
178  if (iter != coeffs.end()) constantCoeff = iter->second;
179  // b!=0
180  assert(!carl::is_zero(coeffs.rbegin()->second));
181  // Create state [x -> -c/b]
182  SqrtEx<Poly> sqEx(-constantCoeff, Poly(), coeffs.rbegin()->second, Poly());
183  results.push_back({std::move(sqEx), {}});
184  } else {
185  assert(coeffs.rbegin()->first == 2);
186 
187  Poly constantCoeff;
188  auto iter = coeffs.find(0);
189  if (iter != coeffs.end()) constantCoeff = iter->second;
190  Poly linearCoeff;
191  iter = coeffs.find(1);
192  if (iter != coeffs.end()) linearCoeff = iter->second;
193  Poly radicand = carl::pow(linearCoeff, 2) - Rational(4) * coeffs.rbegin()->second * constantCoeff;
194 
195  // a!=0, b^2-4ac>=0
196  assert(Constraint<Poly>(radicand, carl::Relation::GEQ) == Constraint<Poly>(true));
197  assert(Constraint<Poly>(coeffs.rbegin()->second, carl::Relation::NEQ) == Constraint<Poly>(true));
198 
199  if (idx == 0) {
200  // Create[x -> (-b-sqrt(b^2-4ac))/2a]
201  SqrtEx<Poly> sqExA(-linearCoeff, Poly(-1), Rational(2) * coeffs.rbegin()->second, radicand);
202  results.push_back({std::move(sqExA), {}});
203  } else {
204  assert(idx == 1);
205  // Create [x -> (-b+sqrt(b^2-4ac))/2a]
206  SqrtEx<Poly> sqExB(-linearCoeff, Poly(1), Rational(2) * coeffs.rbegin()->second, radicand);
207  results.push_back({std::move(sqExB), {}});
208  }
209  }
210  return true;
211  }
212  }
213  }
214  return false;
215 }
216 }
mpq_class Rational
Definition: HornerTest.cpp:12
UnivariatePolynomial< C > to_univariate_polynomial(const MultivariatePolynomial< C, O, P > &p)
Convert a univariate polynomial that is currently (mis)represented by a 'MultivariatePolynomial' into...
auto irreducible_factors(const ContextPolynomial< Coeff, Ordering, Policies > &p, bool constants=true)
Definition: Functions.h:8
std::set< Constraint< Poly >, carl::less< Constraint< Poly >, false > > Constraints
Definition: Constraint.h:28
RealRootsResult< IntRepRealAlgebraicNumber< Number > > real_roots(const UnivariatePolynomial< Coeff > &polynomial, const Interval< Number > &interval=Interval< Number >::unbounded_interval())
Find all real roots of a univariate 'polynomial' with numeric coefficients within a given 'interval'.
Definition: RealRoots.h:25
std::optional< BasicConstraint< Poly > > as_constraint(const VariableComparison< Poly > &f)
Convert this variable comparison "v < root(..)" into a simpler polynomial (in)equality against zero "...
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
VarInfo< MultivariatePolynomial< Coeff, Ordering, Policies > > var_info(const MultivariatePolynomial< Coeff, Ordering, Policies > &poly, const Variable var, bool collect_coeff=false)
Definition: VarInfo.h:54
bool is_trivial(const Factors< MultivariatePolynomial< C, O, P >> &f)
Definition: Factorization.h:62
Poly defining_polynomial(const VariableComparison< Poly > &f)
Return a polynomial containing the lhs-variable that has a same root for the this lhs-variable as the...
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
Factors< MultivariatePolynomial< C, O, P > > factorization(const MultivariatePolynomial< C, O, P > &p, bool includeConstants=true)
Try to factorize a multivariate polynomial.
Definition: Factorization.h:31
Interval< Number > pow(const Interval< Number > &i, Integer exp)
Definition: Power.h:11
static bool gather_zeros(const Constraint< Poly > &constraint, const Variable &eliminationVar, std::vector< zero< Poly >> &results)
Gathers zeros with side conditions from the given constraint in the given variable.
Definition: zeros.h:27
std::ostream & operator<<(std::ostream &os, const Term< Poly > &s)
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
Represent a sum type/variant of an (in)equality between a variable on the left-hand side and multivar...
const std::variant< MR, RAN > & value() const
Represent a polynomial (in)equality against zero.
Definition: Constraint.h:62
const auto & variables() const
Definition: Constraint.h:130
const Factors< Pol > & lhs_factorization() const
Definition: Constraint.h:143
const Pol & lhs() const
Definition: Constraint.h:109
A square root expression with side conditions.
Definition: zeros.h:13
SqrtEx< Poly > sqrt_ex
Definition: zeros.h:14
Constraints< Poly > side_condition
Definition: zeros.h:15