SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
ran_approximation.h
Go to the documentation of this file.
2 
4  return Rational(a.get_num()+b.get_num(), a.get_den()+b.get_den());
5 }
6 
7 inline Rational approximate_RAN(const RAN& r) {
8  if (r.is_numeric()) return r.value();
9  return carl::branching_point(r);
10 }
11 
12 inline Rational approximate_RAN_sb(const RAN& r) {
13  if (r.is_numeric()) return r.value();
14  return carl::sample_stern_brocot(r.interval(), false);
15 }
16 
18  if (r.is_numeric()) return r.value();
19  Rational res = carl::branching_point(r);
20  while (res > r) {
21  res = carl::sample_between(r.interval().lower(), res);
22  }
23  return res;
24 }
25 
27  if (r.is_numeric()) return r.value();
28  Rational res = carl::branching_point(r);
29  while (res < r) {
30  res = carl::sample_between(res, r.interval().upper());
31  }
32  return res;
33 }
34 
35 // inner is closer to the sample point
36 template<ApxRoot AR>
37 inline Rational approximate_root_above(const RAN& inner, const RAN& outer);
38 template<ApxRoot AR>
39 Rational approximate_root_below(const RAN& inner, const RAN& outer);
40 
41 template<>
42 inline Rational approximate_root_above<ApxRoot::SAMPLE_MID>(const RAN& inner, const RAN& outer) {
43  return carl::sample_between(inner, outer);
44 }
45 template<>
46 inline Rational approximate_root_below<ApxRoot::SAMPLE_MID>(const RAN& inner, const RAN& outer) {
47  return carl::sample_between(outer, inner);
48 }
49 
50 template<>
51 inline Rational approximate_root_above<ApxRoot::SIMPLE_REPRESENTATION>(const RAN& inner, const RAN& outer) {
52  assert(inner < outer);
53  Rational inner_simple, outer_simple;
54 
55  if (carl::is_integer(outer)) outer_simple = outer.value() - 1;
56  else if (outer.is_numeric()) outer_simple = carl::floor(outer.value());
57  else outer_simple = carl::floor(outer.interval().lower());
58  // If an integer is between inner and outer, return the closest to outer
59  if (outer_simple > inner) return outer_simple; // TODO: add option to choose another integer
60 
61  inner_simple = approximate_RAN_above(inner);
62  outer_simple = approximate_RAN_below(outer);
63  assert(inner_simple < outer_simple);
64  RationalInterval region = RationalInterval(inner_simple, carl::BoundType::STRICT, outer_simple, carl::BoundType::STRICT);
65  return carl::sample_stern_brocot(region, false);
66 }
67 
68 template<>
69 inline Rational approximate_root_below<ApxRoot::SIMPLE_REPRESENTATION>(const RAN& inner, const RAN& outer) {
70  assert(inner > outer);
71  Rational inner_simple, outer_simple;
72 
73  if (carl::is_integer(outer)) outer_simple = outer.value() + 1;
74  else if (outer.is_numeric()) outer_simple = carl::ceil(outer.value());
75  else outer_simple = carl::ceil(outer.interval().upper());
76  // If an integer is between inner and outer, return the closest to outer
77  if (outer_simple < inner) return outer_simple; // TODO: add option to choose another integer
78 
79  inner_simple = approximate_RAN_below(inner);
80  outer_simple = approximate_RAN_above(outer);
81 
82  assert(inner_simple > outer_simple);
83  RationalInterval region = RationalInterval(outer_simple, carl::BoundType::STRICT, inner_simple, carl::BoundType::STRICT);
84  return carl::sample_stern_brocot(region, false);
85 }
86 
87 template<>
88 inline Rational approximate_root_above<ApxRoot::STERN_BROCOT>(const RAN& inner, const RAN& outer) {
89  Rational inner_simple, outer_simple, mid;
90 
91  if (inner.is_numeric()) inner_simple = carl::ceil(inner.value());
92  else inner_simple = carl::ceil(inner.interval().upper());
93  if (outer.is_numeric()) outer_simple = carl::ceil(outer.value());
94  else outer_simple = carl::ceil(outer.interval().upper());
95 
96  // make sure inner_simple is below outer and outer_simple is the first integer > outer
97  while (inner_simple >= outer) {
98  if (inner_simple < outer_simple) outer_simple = inner_simple;
99  inner_simple = inner_simple - 1;
100  }
101 
102  for (std::size_t i = 0; i < apx_settings().n_sb_iterations;) {
103  mid = mediant(inner_simple, outer_simple);
104  if (mid >= outer) outer_simple = mid;
105  else { // mid < outer
106  inner_simple = mid;
107  if (inner < mid) ++i;
108  }
109  }
110 
111  return mid;
112 }
113 
114 template<>
115 inline Rational approximate_root_below<ApxRoot::STERN_BROCOT>(const RAN& inner, const RAN& outer) {
116  Rational inner_simple, outer_simple, mid;
117 
118  if (inner.is_numeric()) inner_simple = carl::floor(inner.value());
119  else inner_simple = carl::floor(inner.interval().lower());
120  if (outer.is_numeric()) outer_simple = carl::floor(outer.value());
121  else outer_simple = carl::floor(outer.interval().lower());
122 
123  // make sure inner_simple is above outer and outer_simple is the first integer < outer
124  while (inner_simple <= outer) {
125  if (inner_simple > outer_simple) outer_simple = inner_simple;
126  inner_simple = inner_simple + 1;
127  }
128 
129  for (std::size_t i = 0; i < apx_settings().n_sb_iterations;) {
130  mid = mediant(inner_simple, outer_simple);
131  if (mid <= outer) outer_simple = mid;
132  else { // mid > outer
133  inner_simple = mid;
134  if (inner > mid) ++i;
135  }
136  }
137 
138  return mid;
139 }
140 
141 template<>
142 inline Rational approximate_root_above<ApxRoot::FIXED_RATIO>(const RAN& inner, const RAN& outer) {
143  Rational apx_outer = approximate_RAN_below(outer);
144  Rational apx_inner = approximate_RAN_above(inner);
145  Rational upper_bound = (apx_settings().root_ratio_upper * apx_outer) + ((1 - apx_settings().root_ratio_upper) * apx_inner);
146  Rational lower_bound = (apx_settings().root_ratio_lower * apx_outer) + ((1 - apx_settings().root_ratio_lower) * apx_inner);
147  RationalInterval region = RationalInterval(lower_bound, carl::BoundType::STRICT, upper_bound, carl::BoundType::STRICT);
148  return carl::sample_stern_brocot(region, false);
149 }
150 
151 template<>
152 inline Rational approximate_root_below<ApxRoot::FIXED_RATIO>(const RAN& inner, const RAN& outer) {
153  Rational apx_outer = approximate_RAN_above(outer);
154  Rational apx_inner = approximate_RAN_below(inner);
155  Rational lower_bound = (apx_settings().root_ratio_upper * apx_outer) + ((1 - apx_settings().root_ratio_upper) * apx_inner);
156  Rational upper_bound = (apx_settings().root_ratio_lower * apx_outer) + ((1 - apx_settings().root_ratio_lower) * apx_inner);
157  RationalInterval region = RationalInterval(lower_bound, carl::BoundType::STRICT, upper_bound, carl::BoundType::STRICT);
158  return carl::sample_stern_brocot(region, false);
159 }
160 
161 template<ApxRoot AR>
162 inline Rational approximate_root(const RAN& inner, const RAN& outer, bool below) {
163  return below ? approximate_root_below<AR>(inner, outer) : approximate_root_above<AR>(inner, outer);
164 }
165 
166 }
Rational approximate_root_above(const RAN &inner, const RAN &outer)
Rational mediant(Rational a, Rational b)
Rational approximate_root_below(const RAN &inner, const RAN &outer)
Rational approximate_root(const RAN &inner, const RAN &outer, bool below)
Polynomial::RootType RAN
Definition: common.h:24
carl::Interval< Rational > RationalInterval
Definition: model.h:27
mpq_class Rational
Definition: types.h:19