SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
rules_filter.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "rules_filter_util.h"
4 
6 
7 namespace ordering_util {
8  using Decomposition = boost::container::flat_map<std::pair<datastructures::PolyRef,datastructures::PolyRef>,std::vector<datastructures::IndexedRootRelation>>;
9 
11  if (p1 != p2) {
12  if (p1 < p2) {
13  result.try_emplace(std::make_pair(p1, p2)).first->second.push_back(rel);
14  } else {
15  result.try_emplace(std::make_pair(p2, p1)).first->second.push_back(rel);
16  }
17  }
18  }
19 
20  inline auto decompose(const datastructures::IndexedRootOrdering& ordering) {
22  for (const auto& rel : ordering.data()) {
23  if (rel.first.is_root() && rel.second.is_root()) {
24  add_to_decomposition(result, rel.first.root().poly, rel.second.root().poly, rel);
25  } else if (rel.first.is_root() && !rel.second.is_root()) {
26  const auto& roots = rel.second.is_cminmax() ? rel.second.cminmax().roots : rel.second.cmaxmin().roots;
27  for (const auto& rootsp : roots) {
28  for (const auto& root : rootsp) {
29  add_to_decomposition(result, rel.first.root().poly, root.poly, rel);
30  }
31  }
32  } else if (!rel.first.is_root() && rel.second.is_root()) {
33  const auto& roots = rel.first.is_cminmax() ? rel.first.cminmax().roots : rel.first.cmaxmin().roots;
34  for (const auto& rootsp : roots) {
35  for (const auto& root : rootsp) {
36  add_to_decomposition(result, root.poly, rel.second.root().poly, rel);
37  }
38  }
39  } else {
40  const auto& roots1 = rel.first.is_cminmax() ? rel.first.cminmax().roots : rel.first.cmaxmin().roots;
41  const auto& roots2 = rel.second.is_cminmax() ? rel.second.cminmax().roots : rel.second.cmaxmin().roots;
42  for (const auto& roots1p : roots1) {
43  for (const auto& root1 : roots1p) {
44  for (const auto& roots2p : roots2) {
45  for (const auto& root2 : roots2p) {
46  add_to_decomposition(result, root1.poly, root2.poly, rel);
47  }
48  }
49  }
50  }
51  }
52  }
53  return result;
54  }
55 
56  template<typename P>
58  for (const auto& rel : ordering.data()) {
59  if (deriv.proj().evaluate(deriv.sample(), rel.first).first == deriv.proj().evaluate(deriv.sample(), rel.second).first) {
60  return true;
61  }
62  }
63  return false;
64  }
65 }
66 
67 template<typename P>
68 void delineate_all_compound(datastructures::SampledDerivation<P>& deriv, const properties::root_ordering_holds& prop, bool enable_weak = true, bool enable_regular = true) {
69  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ", " << enable_weak << ")");
70 
71  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
72 
73  auto decomposed = ordering_util::decompose(prop.ordering);
74  for (const auto& d : decomposed) {
75  const auto& poly1 = d.first.first;
76  const auto& poly2 = d.first.second;
77  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
78  bool all_relations_weak = std::find_if(d.second.begin(), d.second.end(), [](const auto& pair){ return pair.is_strict; }) == d.second.end();
79  boost::container::flat_set<datastructures::PolyRef> polys({ poly1, poly2 });
80  auto delineable_interval = filter_util::delineable_interval(deriv.proj(), deriv.sample(), polys);
81  assert(delineable_interval);
82  bool only_regular = std::find_if(d.second.begin(), d.second.end(), [](const auto& pair) { return !(pair.first.is_root() && pair.second.is_root()); }) == d.second.end();
83  filter_util::delineable_interval_roots<P>(deriv, polys, deriv.proj().res(poly1, poly2));
84  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN& ran) {
85  if (!enable_regular && only_regular) return filter_util::result::NORMAL;
86  Assignment ass = filter_util::projection_root(*deriv.delineated(), ran);
87  if (!delineable_interval->contains(ran)) {
88  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " outside of " << delineable_interval);
89  if (!enable_regular) return filter_util::result::NORMAL;
90  if (filter_util::has_common_real_root(deriv.proj(),ass,poly1,poly2)) {
91  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> common root at " << ran);
92  if (all_relations_weak && enable_weak) return filter_util::result::INCLUSIVE;
93  else return filter_util::result::NORMAL;
94  } else {
95  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no intersection at " << ran);
96  if (enable_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
97  else return filter_util::result::NORMAL_OPTIONAL;
98  }
99  } else {
100  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " in " << delineable_interval);
101  assert(!deriv.proj().is_nullified(ass,poly1));
102  assert(!deriv.proj().is_nullified(ass,poly2));
103  auto roots1 = deriv.proj().real_roots(ass,poly1);
104  auto roots2 = deriv.proj().real_roots(ass,poly2);
105  for (const auto& pair : d.second) {
106  if (pair.first.is_root() && pair.second.is_root()) {
107  if (!enable_regular) return filter_util::result::NORMAL;
108  const auto& roots_first = pair.first.root().poly == poly1 ? roots1 : roots2;
109  const auto& roots_second = pair.first.root().poly == poly1 ? roots2 : roots1;
110  auto index_first = pair.first.root().index;
111  auto index_second = pair.second.root().index;
112  assert(index_first <= roots_first.size());
113  assert(index_second <= roots_second.size());
114  if (roots_first[index_first-1] == roots_second[index_second-1]) {
115  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
116  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
117  else return filter_util::result::NORMAL;
118  }
119  } else if (pair.first.is_root()) {
120  const auto& roots_first = pair.first.root().poly == poly1 ? roots1 : roots2;
121  auto index_first = pair.first.root().index;
122  assert(index_first <= roots_first.size());
123  auto poly_second = pair.first.root().poly == poly1 ? poly2 : poly1;
124 
125  bool relevant = true;
126  assert(pair.second.is_cminmax() || pair.second.is_cmaxmin());
127  auto delineable_interval_cb = filter_util::delineable_interval(deriv.proj(), deriv.sample(), pair.second.polys());
128  assert(delineable_interval_cb);
129  if (delineable_interval_cb->contains(ran)) {
130  auto res = pair.second.is_cminmax() ? deriv.proj().evaluate(ass, pair.second.cminmax()) : deriv.proj().evaluate(ass, pair.second.cmaxmin());
131  relevant = false;
132  if (res.first == roots_first[index_first-1]) {
133  relevant = std::find_if(res.second.begin(), res.second.end(), [&](const auto& ir) { return ir.poly == poly_second; }) != res.second.end();
134  }
135  }
136  if (relevant) {
137  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
138  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
139  else return filter_util::result::NORMAL;
140  }
141  } else if (pair.second.is_root()) {
142  const auto& roots_second = pair.second.root().poly == poly1 ? roots1 : roots2;
143  auto index_second = pair.second.root().index;
144  assert(index_second <= roots_second.size());
145  auto poly_first = pair.second.root().poly == poly1 ? poly2 : poly1;
146 
147  bool relevant = true;
148  assert(pair.first.is_cminmax() || pair.first.is_cmaxmin());
149  auto delineable_interval_cb = filter_util::delineable_interval(deriv.proj(), deriv.sample(), pair.first.polys());
150  assert(delineable_interval_cb);
151  if (delineable_interval_cb->contains(ran)) {
152  auto res = pair.first.is_cminmax() ? deriv.proj().evaluate(ass, pair.first.cminmax()) : deriv.proj().evaluate(ass, pair.first.cmaxmin());
153  relevant = false;
154  if (res.first == roots_second[index_second-1]) {
155  relevant = std::find_if(res.second.begin(), res.second.end(), [&](const auto& ir) { return ir.poly == poly_first; }) != res.second.end();
156  }
157  }
158  if (relevant) {
159  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
160  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
161  else return filter_util::result::NORMAL;
162  }
163  } else {
164  assert(pair.first.is_cmaxmin() && pair.second.is_cminmax());
165  auto poly_first = (pair.first.has_poly(poly1) && pair.second.has_poly(poly2)) ? poly1 : poly2;
166  auto poly_second = (pair.first.has_poly(poly1) && pair.second.has_poly(poly2)) ? poly2 : poly1;
167  assert(pair.first.has_poly(poly_first) && pair.second.has_poly(poly_second));
168 
169  bool relevant = true;
170  auto cb_polys = pair.first.polys();
171  cb_polys.merge(pair.second.polys());
172  auto delineable_interval_cb = filter_util::delineable_interval(deriv.proj(), deriv.sample(), cb_polys);
173  assert(delineable_interval_cb);
174  if (delineable_interval_cb->contains(ran)) {
175  auto res1 = deriv.proj().evaluate(ass, pair.first.cmaxmin());
176  auto res2 = deriv.proj().evaluate(ass, pair.second.cminmax());
177  relevant = false;
178  if (res1.first == res2.first) {
179  relevant = std::find_if(res1.second.begin(), res1.second.end(), [&](const auto& ir) { return ir.poly == poly_first; }) != res1.second.end() && std::find_if(res2.second.begin(), res2.second.end(), [&](const auto& ir) { return ir.poly == poly_second; }) != res2.second.end();
180  }
181  }
182  if (relevant) {
183  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
184  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
185  else return filter_util::result::NORMAL;
186  }
187  }
188  }
189  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no relevant intersection at " << ran);
190  if (enable_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
192  }
193  });
194  }
195 }
196 
198  static constexpr bool only_rational_samples = false;
199  static constexpr bool only_irreducible_resultants = false;
200  static constexpr bool only_if_no_intersections = false;
201  static constexpr std::size_t only_if_total_degree_below = 0;
202 };
203 
204 template<typename Settings, typename P>
205 void delineate_all(datastructures::SampledDerivation<P>& deriv, const properties::root_ordering_holds& prop, bool enable_weak = true) {
206  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ")");
207 
208  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
209 
210  bool underlying_sample_algebraic = std::find_if(deriv.underlying_sample().begin(), deriv.underlying_sample().end(), [](const auto& m) { return !m.second.is_numeric(); }) != deriv.underlying_sample().end();
211 
212  auto decomposed = ordering_util::decompose(prop.ordering);
213  for (const auto& d : decomposed) {
214  const auto& poly1 = d.first.first;
215  const auto& poly2 = d.first.second;
216  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
217 
218  bool all_relations_weak = std::find_if(d.second.begin(), d.second.end(), [](const auto& pair){ return pair.is_strict; }) == d.second.end();
219  bool irreducible = deriv.proj().res(poly1, poly2).level == 0 || deriv.proj().factors_nonconst(deriv.proj().res(poly1, poly2)).size() == 1;
220  bool all_roots_algebraic = true;
221  if (!underlying_sample_algebraic) {
222  if (deriv.proj().is_const(deriv.proj().res(poly1, poly2))) {
223  all_roots_algebraic = false;
224  } else {
225  auto roots = deriv.proj().real_roots_reducible(deriv.underlying_sample(), deriv.proj().res(poly1, poly2));
226  all_roots_algebraic = std::find_if(roots.begin(), roots.end(), [](const auto& r) { return !r.is_numeric(); }) != roots.end();
227  }
228  }
229 
230  if (
231  (!Settings::only_rational_samples || !all_roots_algebraic) &&
232  (!Settings::only_irreducible_resultants || irreducible) &&
233  (!Settings::only_if_no_intersections || !ordering_util::has_intersection(deriv, prop.ordering)) &&
234  (Settings::only_if_total_degree_below == 0 || deriv.proj().total_degree(deriv.proj().res(poly1, poly2)) < Settings::only_if_total_degree_below)
235  ) {
236  boost::container::flat_set<datastructures::PolyRef> polys({ poly1, poly2 });
237  auto delineable_interval = filter_util::delineable_interval(deriv.proj(), deriv.sample(), polys);
238  assert(delineable_interval);
239  filter_util::delineable_interval_roots<P>(deriv, polys, deriv.proj().res(poly1, poly2));
240  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN& ran) {
241  if (Settings::only_rational_samples && !ran.is_numeric()) {
242  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> sample is algebraic, adding " << ran);
243  // return filter_util::result::NORMAL;
244  if (enable_weak && all_relations_weak) return filter_util::result::INCLUSIVE;
245  else return filter_util::result::NORMAL;
246  }
247 
249  if (!delineable_interval->contains(ran)) {
250  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " outside of " << delineable_interval);
251  if (filter_util::has_common_real_root(deriv.proj(),ass,poly1,poly2)) {
252  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> common root at " << ran);
253  if (enable_weak && all_relations_weak) return filter_util::result::INCLUSIVE;
254  else return filter_util::result::NORMAL;
255  } else {
256  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no intersection at " << ran);
257  if (all_relations_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
258  else return filter_util::result::NORMAL_OPTIONAL;
259  }
260  } else {
261  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " in " << delineable_interval);
262  assert(!deriv.proj().is_nullified(ass,poly1));
263  assert(!deriv.proj().is_nullified(ass,poly2));
264  auto roots1 = deriv.proj().real_roots(ass,poly1);
265  auto roots2 = deriv.proj().real_roots(ass,poly2);
266  for (const auto& pair : d.second) {
267  assert(pair.first.is_root() && pair.second.is_root());
268  auto index1 = pair.first.root().poly == poly1 ? pair.first.root().index : pair.second.root().index;
269  auto index2 = pair.first.root().poly == poly1 ? pair.second.root().index : pair.first.root().index;
270  assert(index1 <= roots1.size());
271  assert(index2 <= roots2.size());
272  // if (roots1[index1-1] == roots2[index2-1]) {
273  if (filter_util::has_intersection(roots1[index1-1], roots2[index2-1])) {
274  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
275  // if (all_relations_weak) return filter_util::result::INCLUSIVE;
276  // else return filter_util::result::NORMAL;
277  if (enable_weak && !pair.is_strict) return filter_util::result::INCLUSIVE;
278  else return filter_util::result::NORMAL;
279  }
280  }
281  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no relevant intersection at " << ran);
282  if (all_relations_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
283  else return filter_util::result::NORMAL_OPTIONAL;
284  }
285  });
286  } else {
287  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN& ran) {
288  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> skip filter, adding " << ran);
289  // return filter_util::result::NORMAL;
290  if (enable_weak && all_relations_weak) return filter_util::result::INCLUSIVE;
291  else return filter_util::result::NORMAL;
292  });
293  }
294  }
295 }
296 
297 template<typename P>
299  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ")");
300 
301  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
302 
303  auto decomposed = ordering_util::decompose(prop.ordering);
304  for (const auto& d : decomposed) {
305  const auto& poly1 = d.first.first;
306  const auto& poly2 = d.first.second;
307  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
308  bool all_relations_weak = std::find_if(d.second.begin(), d.second.end(), [](const auto& pair){ return pair.is_strict; }) == d.second.end();
309  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN&) {
310  if (all_relations_weak) return filter_util::result::INCLUSIVE;
311  else return filter_util::result::NORMAL;
312  });
313  }
314 }
315 
316 template<typename P>
318  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ")");
319 
320  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
321 
322  auto decomposed = ordering_util::decompose(prop.ordering);
323  for (const auto& d : decomposed) {
324  const auto& poly1 = d.first.first;
325  const auto& poly2 = d.first.second;
326  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
327  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN&) {
328  return filter_util::result::NORMAL;
329  });
330  }
331 }
332 
333 template<typename P>
335  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ")");
336  // only correct with biggest cell heuristics
337 
338  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
339 
340  auto decomposed = ordering_util::decompose(prop.ordering);
341  for (const auto& d : decomposed) {
342  const auto& poly1 = d.first.first;
343  const auto& poly2 = d.first.second;
344  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
345  bool all_relations_weak = std::find_if(d.second.begin(), d.second.end(), [](const auto& pair){ return pair.is_strict; }) == d.second.end();
346  boost::container::flat_set<datastructures::PolyRef> polys({ poly1, poly2 });
347  auto delineable_interval = filter_util::delineable_interval(deriv.proj(), deriv.sample(), polys);
348  assert(delineable_interval);
349  filter_util::delineable_interval_roots<P>(deriv, polys, deriv.proj().res(poly1, poly2));
350  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN& ran) {
351  Assignment ass = filter_util::projection_root(*deriv.delineated(), ran);
352  if (!delineable_interval->contains(ran)) {
353  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " outside of " << delineable_interval);
354  if (all_relations_weak) return filter_util::result::INCLUSIVE;
355  else return filter_util::result::NORMAL;
356  } else {
357  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " in " << delineable_interval);
358  assert(poly1 != poly2);
359  if (!prop.ordering.biggest_cell_wrt) {
360  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> not biggest_cell_wrt");
361  for (const auto& pair : d.second) {
362  if (enable_weak && !pair.is_strict) return filter_util::result::INCLUSIVE;
363  }
364  return filter_util::result::NORMAL;
365  }
366  for (const auto& pair : d.second) {
367  assert(pair.first.is_root() && pair.second.is_root());
368  if (!prop.ordering.biggest_cell_wrt->lower().is_infty() && pair.second == prop.ordering.biggest_cell_wrt->lower().value()) {
369  auto root = deriv.proj().evaluate(ass, pair.second.root());
370  Assignment ass2 = ass;
371  ass2.emplace(deriv.proj().main_var(pair.first.root().poly), root);
372  if (deriv.proj().is_zero(ass2, pair.first.root().poly)) {
373  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
374  if (enable_weak && !pair.is_strict) return filter_util::result::INCLUSIVE;
375  else return filter_util::result::NORMAL;
376  }
377  } else if (!prop.ordering.biggest_cell_wrt->upper().is_infty() && pair.first == prop.ordering.biggest_cell_wrt->upper().value()) {
378  auto root = deriv.proj().evaluate(ass, pair.first.root());
379  Assignment ass2 = ass;
380  ass2.emplace(deriv.proj().main_var(pair.second.root().poly), root);
381  if (deriv.proj().is_zero(ass2, pair.second.root().poly)) {
382  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
383  if (enable_weak && !pair.is_strict) return filter_util::result::INCLUSIVE;
384  else return filter_util::result::NORMAL;
385  }
386  } else {
387  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> not an intersection with an interval bound at " << ran);
388  if (enable_weak && !pair.is_strict) return filter_util::result::INCLUSIVE;
389  else return filter_util::result::NORMAL;
390  }
391  }
392  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no relevant intersection at " << ran);
393  if (all_relations_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
394  else return filter_util::result::NORMAL_OPTIONAL;
395  }
396  });
397  }
398 }
399 
400 template<typename P>
402  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "delineate(" << prop << ", " << enable_weak << ")");
403 
404  SMTRAT_STATISTICS_CALL(if (ordering_util::has_intersection(deriv, prop.ordering)) { statistics().detect_intersection(); });
405 
406  auto decomposed = ordering_util::decompose(prop.ordering);
407  for (const auto& d : decomposed) {
408  const auto& poly1 = d.first.first;
409  const auto& poly2 = d.first.second;
410  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
411  bool all_relations_weak = enable_weak && std::find_if(d.second.begin(), d.second.end(), [](const auto& pair){ return pair.is_strict; }) == d.second.end();
412  boost::container::flat_set<datastructures::PolyRef> polys({ poly1, poly2 });
413  auto delineable_interval = filter_util::delineable_interval(deriv.proj(), deriv.sample(), polys);
414  assert(delineable_interval);
415  filter_util::delineable_interval_roots<P>(deriv, polys, deriv.proj().res(poly1, poly2));
416  filter_util::filter_roots(*deriv.delineated(), deriv.proj().res(poly1, poly2), [&](const RAN& ran) {
417  Assignment ass = filter_util::projection_root(*deriv.delineated(), ran);
418  if (!delineable_interval->contains(ran)) {
419  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " outside of " << delineable_interval);
420  if (all_relations_weak && enable_weak) return filter_util::result::INCLUSIVE;
421  else return filter_util::result::NORMAL;
422  } else {
423  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> resultant's root " << ran << " in " << delineable_interval);
424  for (const auto& pair : d.second) {
425  if (pair.first.is_root() && pair.second.is_root()) {
426  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
427  else return filter_util::result::NORMAL;
428  } else if (pair.first.is_root()) {
429  assert(pair.second.is_cminmax() || pair.second.is_cmaxmin());
430  auto poly_second = pair.first.root().poly == poly1 ? poly2 : poly1;
431  if ((pair.second.is_cminmax() && pair.second.cminmax().bounds->poly_bound_at(poly_second, ran)) ||
432  (pair.second.is_cmaxmin() && pair.second.cmaxmin().bounds->poly_bound_at(poly_second, ran))) {
433  // we could check whether the correct roots intersect at the given point (i.e. check whether the first indexed root expression is equal to the corresponding bound; but we omit that here...)
434  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
435  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
436  else return filter_util::result::NORMAL;
437  }
438  } else if (pair.second.is_root()) {
439  assert(pair.first.is_cminmax() || pair.first.is_cmaxmin());
440  auto poly_first = pair.second.root().poly == poly1 ? poly2 : poly1;
441  if ((pair.first.is_cminmax() && pair.first.cminmax().bounds->poly_bound_at(poly_first, ran)) ||
442  (pair.first.is_cmaxmin() && pair.first.cmaxmin().bounds->poly_bound_at(poly_first, ran))) {
443  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
444  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
445  else return filter_util::result::NORMAL;
446  }
447  } else {
448  assert(pair.first.is_cmaxmin() && pair.second.is_cminmax());
449  auto poly_first = (pair.first.has_poly(poly1) && pair.second.has_poly(poly2)) ? poly1 : poly2;
450  auto poly_second = (pair.first.has_poly(poly1) && pair.second.has_poly(poly2)) ? poly2 : poly1;
451  assert(pair.first.has_poly(poly_first) && pair.second.has_poly(poly_second));
452  if (pair.first.cmaxmin().bounds->poly_bound_at(poly_first, ran) && pair.second.cminmax().bounds->poly_bound_at(poly_second, ran)) {
453  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> relevant intersection at " << ran);
454  if (!pair.is_strict && enable_weak) return filter_util::result::INCLUSIVE;
455  else return filter_util::result::NORMAL;
456  }
457  }
458  }
459  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> no relevant intersection at " << ran);
460  if (enable_weak) return filter_util::result::INCLUSIVE_OPTIONAL;
461  else return filter_util::result::NORMAL_OPTIONAL;
462  }
463  });
464  }
465 }
466 
467 template<typename P>
468 inline void poly_loc_del(datastructures::SampledDerivation<P>& deriv, const datastructures::SymbolicInterval& underlying_cell, const datastructures::IndexedRootOrdering& underlying_ordering, const boost::container::flat_set<datastructures::PolyRef>& ordering_polys, const datastructures::PolyRef poly) {
469  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "poly_loc_del(" << poly << ", " << underlying_ordering << ")");
470  if (deriv.proj().is_const(poly)) return;
471  for (const auto& factor : deriv.proj().factors_nonconst(poly)) {
472  deriv.insert(properties::poly_ord_inv_base{ factor });
473  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add ord_inv_base(" << factor << ") ");
474  if (factor.level == deriv.level()) {
475  if (deriv.proj().is_nullified(deriv.underlying_sample(), factor)) {
477  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add sgn_inv(" << factor << ") ");
478  } else {
479  auto roots = deriv.proj().real_roots(deriv.underlying_sample(), factor);
480  if (roots.empty()) {
482  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add sgn_inv(" << factor << ") ");
483  } else {
484  if (ordering_polys.contains(factor)) {
485  deriv.insert(properties::poly_del{ factor });
486  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add del(" << factor << ") ");
487  } else {
488  assert(underlying_cell.is_section());
490  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add sgn_inv(" << factor << ") ");
491  }
492  }
493  }
494  } else {
495  assert(factor.level < deriv.level());
497  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> add sgn_inv(" << factor << ") ");
498  }
499  }
500 }
501 
502 template<typename P>
504  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "ord_inv_base(" << poly << "), " << poly << " irreducible");
505  if (deriv.proj().is_const(poly)) return;
506 
507  if (cell.is_section() && !deriv.proj().is_zero(deriv.sample(), poly)) {
508  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> ord_inv_base(" << poly << ") <= " << poly << "(" << deriv.sample() << ") != 0 && sgn_inv(" << poly << ")");
510  } else {
511  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> ord_inv_base(" << poly << ") <= del(" << poly << ") && cell_connected(" << poly.level << ")");
512  deriv.insert(properties::poly_del{ poly });
513  deriv.insert(properties::cell_connected{ poly.level });
514  }
515 }
516 
517 template<typename P>
518 bool root_ordering_holds_delineated(datastructures::SampledDerivation<P>& deriv, const datastructures::SymbolicInterval& underlying_cell, const datastructures::IndexedRootOrdering& underlying_ordering, const boost::container::flat_set<datastructures::PolyRef>& ordering_polys, const datastructures::IndexedRootOrdering& ordering) {
519  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "ir_ord(" << ordering << ", " << deriv.sample() << ")");
520  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "using underlying_cell=" << underlying_cell << ", underlying_ordering=" << underlying_ordering << ", ordering_polys=" << ordering_polys);
521 
522  deriv.insert(properties::cell_connected{ deriv.level() });
523  assert(properties::contains_root_ordering_holds(deriv, underlying_ordering));
524 
525  auto decomposed = ordering_util::decompose(ordering);
526  for (const auto& d : decomposed) {
527  const auto& poly1 = d.first.first;
528  const auto& poly2 = d.first.second;
529  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "consider pair " << poly1 << " and " << poly2 << "");
530  assert(deriv.contains(properties::poly_del{ poly1 }));
531  assert(deriv.contains(properties::poly_del{ poly2 }));
532  poly_loc_del(deriv, underlying_cell, underlying_ordering, ordering_polys, deriv.proj().res(poly1, poly2));
533  }
534  return true;
535 }
536 
537 template<typename P>
539  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "sgn_inv(" << poly << "), " << poly << " irreducible");
540 }
541 
542 template<typename P>
544  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "semi_sgn_inv(" << poly << "), " << poly << " irreducible");
545 }
546 
547 template<typename P>
549  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "semi_sgn_inv(" << poly << "), " << poly << " irreducible and non-zero");
550  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= sgn_inv(" << poly << ")");
552 }
553 
554 template<typename P>
556  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "semi_sgn_inv(" << poly << "), " << poly << " irreducible and nullified");
557  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= sgn_inv(" << poly << ")");
558  poly_irreducible_null_sgn_inv(deriv, poly);
559 }
560 
561 template<typename P>
563  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "semi_sgn_inv(" << poly << ")");
564  if (deriv.proj().is_const(poly)) {
565  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= " << poly << " const");
566  } else if (deriv.contains(properties::poly_ord_inv{ poly })) {
567  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= ord_inv(" << poly << ")");
568  } else if (deriv.contains(properties::poly_sgn_inv{ poly }) || deriv.contains(properties::poly_irreducible_sgn_inv{ poly })) {
569  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= poly_sgn_inv(" << poly << ")");
570  } else {
571  std::optional<datastructures::PolyRef> lowest_zero_factor;
572  for (const auto& factor : deriv.proj().factors_nonconst(poly)) {
573  if (deriv.proj().is_zero(deriv.sample(), factor)) {
574  if (lowest_zero_factor == std::nullopt ||
575  factor.level < lowest_zero_factor->level ||
576  (factor.level == lowest_zero_factor->level && (factor.level == poly.level && deriv.proj().is_nullified(deriv.underlying_sample(), factor) && !deriv.proj().is_nullified(deriv.underlying_sample(), *lowest_zero_factor))) ||
577  (factor.level == lowest_zero_factor->level && (factor.level != poly.level || (deriv.proj().is_nullified(deriv.underlying_sample(), factor) && deriv.proj().is_nullified(deriv.underlying_sample(), *lowest_zero_factor))) && deriv.proj().total_degree(factor) < deriv.proj().total_degree(*lowest_zero_factor))
578  ) {
579  lowest_zero_factor = factor;
580  }
581  }
582  }
583 
584  if (lowest_zero_factor) {
585  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= sgn_inv(" << *lowest_zero_factor << ") && "<< *lowest_zero_factor <<"("<< deriv.sample() <<")=0");
586  deriv.insert(properties::poly_irreducible_sgn_inv{ *lowest_zero_factor });
587  } else {
588  SMTRAT_LOG_TRACE("smtrat.cadcells.operators.rules", "-> semi_sgn_inv(" << poly << ") <= semi_sgn_inv(factors(" << poly << ")) <=> semi_sgn_inv(" << deriv.proj().factors_nonconst(poly) << ")");
589  for (const auto& factor : deriv.proj().factors_nonconst(poly)) {
591  }
592  }
593  }
594 }
595 
596 }
A DelineatedDerivation is a BaseDerivation with a Delineation and an underlying SampledDerivation.
Definition: derivation.h:219
Describes an ordering of IndexedRoots.
Definition: roots.h:400
std::optional< SymbolicInterval > biggest_cell_wrt
Definition: roots.h:418
const std::vector< PolyRef > & factors_nonconst(PolyRef p)
Definition: projections.h:238
RAN evaluate(const Assignment &sample, IndexedRoot r)
Definition: projections.h:429
bool is_nullified(const Assignment &sample, PolyRef p)
Definition: projections.h:309
const std::vector< RAN > & real_roots(const Assignment &sample, PolyRef p)
Definition: projections.h:277
PolyRef res(PolyRef p, PolyRef q)
Definition: projections.h:165
bool is_zero(const Assignment &sample, PolyRef p)
Definition: projections.h:250
const std::vector< RAN > real_roots_reducible(const Assignment &sample, PolyRef p)
Definition: projections.h:292
A SampledDerivation is a DelineatedDerivation with a sample and an DelineationInterval w....
Definition: derivation.h:299
DelineatedDerivationRef< Properties > & delineated()
Definition: derivation.h:314
A symbolic interal whose bounds are defined by indexed root expressions.
Definition: roots.h:250
bool contains_root_ordering_holds(P &deriv, const datastructures::IndexedRootOrdering &ordering)
void filter_roots(datastructures::DelineatedDerivation< P > &deriv, const datastructures::PolyRef poly, std::function< result(const RAN &)> filter_condition)
auto projection_root(const datastructures::DelineatedDerivation< P > &deriv, const RAN &root)
std::optional< carl::Interval< RAN > > delineable_interval(datastructures::Projections &proj, const Assignment &sample, const boost::container::flat_set< datastructures::PolyRef > &polys)
boost::container::flat_map< std::pair< datastructures::PolyRef, datastructures::PolyRef >, std::vector< datastructures::IndexedRootRelation > > Decomposition
Definition: rules_filter.h:8
auto decompose(const datastructures::IndexedRootOrdering &ordering)
Definition: rules_filter.h:20
void add_to_decomposition(Decomposition &result, datastructures::PolyRef p1, datastructures::PolyRef p2, const datastructures::IndexedRootRelation &rel)
Definition: rules_filter.h:10
auto has_intersection(datastructures::SampledDerivation< P > &deriv, const datastructures::IndexedRootOrdering &ordering)
Definition: rules_filter.h:57
Implementation of derivation rules.
Definition: rules.h:13
void poly_irreducible_semi_sgn_inv_filtered(datastructures::SampledDerivation< P > &, const datastructures::SymbolicInterval &, const datastructures::IndexedRootOrdering &, [[maybe_unused]] datastructures::PolyRef poly)
Definition: rules_filter.h:543
void delineate_all(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop, bool enable_weak=true)
Definition: rules_filter.h:205
void delineate_bounds_only(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop)
Definition: rules_filter.h:298
void poly_irreducible_sgn_inv_filtered(datastructures::SampledDerivation< P > &, const datastructures::SymbolicInterval &, const datastructures::IndexedRootOrdering &, [[maybe_unused]] datastructures::PolyRef poly)
Definition: rules_filter.h:538
void poly_irreducible_null_sgn_inv(datastructures::SampledDerivation< P > &deriv, datastructures::PolyRef poly)
Definition: rules.h:244
void poly_irreducible_nonzero_sgn_inv(datastructures::DelineatedDerivation< P > &deriv, datastructures::PolyRef poly)
Definition: rules.h:118
void poly_irreducible_null_semi_sgn_inv(datastructures::SampledDerivation< P > &deriv, datastructures::PolyRef poly)
Definition: rules_filter.h:555
void poly_semi_sgn_inv(datastructures::SampledDerivation< P > &deriv, datastructures::PolyRef poly)
Definition: rules_filter.h:562
bool root_ordering_holds_delineated(datastructures::SampledDerivation< P > &deriv, const datastructures::SymbolicInterval &underlying_cell, const datastructures::IndexedRootOrdering &underlying_ordering, const boost::container::flat_set< datastructures::PolyRef > &ordering_polys, const datastructures::IndexedRootOrdering &ordering)
Definition: rules_filter.h:518
void poly_loc_del(datastructures::SampledDerivation< P > &deriv, const datastructures::SymbolicInterval &underlying_cell, const datastructures::IndexedRootOrdering &underlying_ordering, const boost::container::flat_set< datastructures::PolyRef > &ordering_polys, const datastructures::PolyRef poly)
Definition: rules_filter.h:468
void delineate_all_compound(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop, bool enable_weak=true, bool enable_regular=true)
Definition: rules_filter.h:68
void delineate_compound_piecewiselinear(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop, bool enable_weak=true)
Definition: rules_filter.h:401
void poly_irreducible_nonzero_semi_sgn_inv(datastructures::DelineatedDerivation< P > &deriv, datastructures::PolyRef poly)
Definition: rules_filter.h:548
void poly_ord_inv_base(datastructures::SampledDerivation< P > &deriv, const datastructures::SymbolicInterval &cell, const datastructures::IndexedRootOrdering &, datastructures::PolyRef poly)
Definition: rules_filter.h:503
void delineate_noop(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop)
Definition: rules_filter.h:317
void delineate_all_biggest_cell(datastructures::SampledDerivation< P > &deriv, const properties::root_ordering_holds &prop, bool enable_weak=true)
Definition: rules_filter.h:334
Polynomial::RootType RAN
Definition: common.h:24
carl::Assignment< RAN > Assignment
Definition: common.h:25
@ NORMAL
Definition: types.h:53
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_STATISTICS_CALL(function)
Definition: Statistics.h:23
level_t level
The level of the polynomial.
Definition: polynomials.h:18