SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
feature_based.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "helper.h"
4 
5 #include <algorithm>
6 #include <carl-arith/core/Variable.h>
8 
9 #include <numeric>
10 
11 namespace smtrat {
12 namespace mcsat {
13 namespace variableordering {
14 
15 namespace detail {
16 
17 using carl::operator<<;
18 
19 /**
20  * This class manages features that are used to valuate variables on objects.
21  * Each feature consists of a valuation function, a level and a weight.
22  * All feature valuations of a certain level are combined linearly using the respective weights.
23  * Valuations are then compared lexicographically.
24  */
25 template<typename Objects>
27  using Extractor = std::function<double(Objects, carl::Variable)>;
28  using Valuation = std::vector<double>;
29  std::vector<std::tuple<Extractor, std::size_t, double>> mFeatures;
30 
31  void addFeature(Extractor&& e, std::size_t level, double weight) {
32  mFeatures.emplace_back(std::move(e), level, weight);
33  }
34 
35  Valuation valuateVariable(const Objects& o, carl::Variable v) const {
36  Valuation res;
37  for (const auto& f : mFeatures) {
38  if (res.size() <= std::get<1>(f)) {
39  res.resize(std::get<1>(f) + 1);
40  }
41  res[std::get<1>(f)] += std::get<2>(f) * std::get<0>(f)(o, v);
42  }
43  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Valuation of " << v << " is " << res);
44  return res;
45  }
46  std::vector<carl::Variable> sortVariables(const Objects& o, std::vector<carl::Variable> vars) const {
47  std::vector<std::pair<Valuation, carl::Variable>> valuations;
48  for (auto v : vars) {
49  valuations.emplace_back(valuateVariable(o, v), v);
50  }
51  std::sort(valuations.begin(), valuations.end());
52  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Evaluated to " << valuations);
53  std::transform(valuations.begin(), valuations.end(), vars.begin(), [](const auto& p) { return p.second; });
54  return vars;
55  }
56 };
57 
58 template<typename Constraints, typename Calculator>
59 double abstract_feature(const Constraints& constraints, double initial, std::function<double(double, double)>&& comb, Calculator&& calc) {
60  return std::accumulate(constraints.begin(), constraints.end(), initial,
61  [&comb, &calc](double cur, const auto& c) { return comb(cur, calc(c)); }
62  );
63 }
64 
65 /// The maximum degree of this variable.
66 template<typename Constraints>
67 double max_degree(const Constraints& constraints, carl::Variable v) {
68  return abstract_feature(
69  constraints, 0.0,
70  [](double a, double b) { return std::max(a, b); },
71  [v](const auto& c) { return static_cast<double>(c.maxDegree(v)); }
72  );
73 }
74 
75 /// The maximum total degree of a term involving this variable.
76 template<typename Constraints>
77 double max_term_total_degree(const Constraints& constraints, carl::Variable v) {
78  return abstract_feature(
79  constraints, 0.0,
80  [](double a, double b) { return std::max(a, b); },
81  [v](const auto& c) {
82  double max = 0;
83  for (const auto& t : c.lhs()) {
84  if (t.has(v)) max = std::max(max, static_cast<double>(t.tdeg()));
85  }
86  return max;
87  }
88  );
89 }
90 
91 template<typename Constraints>
92 double max_coefficient(const Constraints& constraints, carl::Variable v) {
93  return abstract_feature(
94  constraints, 0.0,
95  [](double a, double b) { return std::max(a, b); },
96  [v](const auto& c) {
97  double max = 0.0;
98  for (const auto& t : c.lhs()) {
99  if (t.has(v)) max = std::max(max, carl::to_double(carl::log(carl::abs(t.coeff()))));
100  }
101  return static_cast<double>(max);
102  }
103  );
104 }
105 
106 template<typename Constraints>
107 double num_occurrences(const Constraints& constraints, carl::Variable v) {
108  return abstract_feature(
109  constraints, 0.0,
110  [](double a, double b) { return a + b; },
111  [v](const auto& c) {
112  if (c.variables().has(v)) {
113  return 1;
114  } else {
115  return 0;
116  }
117  }
118  );
119 }
120 
121 template<typename Constraints>
122 double max_lcoeff_total_degree(const Constraints& constraints, carl::Variable v) {
123  return abstract_feature(
124  constraints, 0.0,
125  [](double a, double b) { return std::max(a, b); },
126  [v](const auto& c) {
127  return double(c.lhs().lcoeff(v).total_degree());
128  }
129  );
130 }
131 
132 
133 template<typename Constraints>
134 double sum_max_degree(const Constraints& constraints, carl::Variable v) {
135  return abstract_feature(constraints, 0.0,
136  [](double a, double b){ return a+b; },
137  [v](const auto& c){ return static_cast<double>(c.maxDegree(v)); }
138  );
139 }
140 
141 template<typename Constraints>
142 double sum_sum_degree(const Constraints& constraints, carl::Variable v) {
143  return abstract_feature(constraints, 0.0,
144  [](double a, double b){ return a+b; },
145  [v](const auto& c){
146  std::size_t sum = 0;
147  for (const auto& t: c.lhs()) {
148  if (t.monomial() == nullptr) continue;
149  std::size_t c = t.monomial()->exponent_of_variable(v);
150  sum += c;
151  }
152  return static_cast<double>(sum);
153  }
154  );
155 }
156 
157 template<typename Constraints>
158 double avg_avg_degree(const Constraints& constraints, carl::Variable v) {
159  auto num_constr = constraints.size();
160  return abstract_feature(constraints, 0.0,
161  [num_constr](double a, double b){ return a + b / (double)num_constr; },
162  [v](const auto& c){
163  std::size_t sum = 0;
164  std::size_t count = 0;
165  for (const auto& t: c.lhs()) {
166  if (t.monomial() == nullptr) continue;
167  std::size_t c = t.monomial()->exponent_of_variable(v);
168  sum += c;
169  count++;
170  }
171  return static_cast<double>(sum)/static_cast<double>(count);
172  }
173  );
174 }
175 
176 }
177 
178 template<typename Constraints>
179 std::vector<carl::Variable> feature_based(const Constraints& c) {
181 
182  features.addFeature(detail::max_degree<Constraints>, 0, -1.0);
183  features.addFeature(detail::max_term_total_degree<Constraints>, 0, -0.5);
184  features.addFeature(detail::max_coefficient<Constraints>, 1, 1);
185 
186  carl::carlVariables vars;
187  gatherVariables(vars, c);
188  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Collected variables " << vars);
189  auto orderedVars = features.sortVariables(c, vars.as_vector());
190 
191  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Calculated variable ordering " << orderedVars);
192  return orderedVars;
193 }
194 
195 template<typename Constraints>
196 std::vector<carl::Variable> feature_based_z3(const Constraints& c) {
198 
199  features.addFeature(detail::max_degree<Constraints>, 0, -1.0);
200  features.addFeature(detail::num_occurrences<Constraints>, 1, -1.0);
201 
202  carl::carlVariables vars;
203  gatherVariables(vars, c);
204  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Collected variables " << vars);
205  auto orderedVars = features.sortVariables(c, vars.as_vector());
206 
207  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Calculated variable ordering " << orderedVars);
208  return orderedVars;
209 }
210 
211 /**
212  * According to https://www.usna.edu/Users/cs/wcbrown/research/ISSAC04/handout.pdf
213  */
214 template<typename Constraints>
215 std::vector<carl::Variable> feature_based_brown(const Constraints& c) {
217 
218  features.addFeature(detail::max_degree<Constraints>, 0, -1.0);
219  features.addFeature(detail::max_term_total_degree<Constraints>, 1, -1.0);
220  features.addFeature(detail::num_occurrences<Constraints>, 2, -1.0);
221 
222  carl::carlVariables vars;
223  gatherVariables(vars, c);
224  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Collected variables " << vars);
225  auto orderedVars = features.sortVariables(c, vars.as_vector());
226 
227  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Calculated variable ordering " << orderedVars);
228  return orderedVars;
229 }
230 
231 template<typename Constraints>
232 std::vector<carl::Variable> feature_based_triangular(const Constraints& c) {
234 
235  features.addFeature(detail::max_degree<Constraints>, 0, -1.0);
236  features.addFeature(detail::max_lcoeff_total_degree<Constraints>, 1, -1.0);
237  features.addFeature(detail::num_occurrences<Constraints>, 2, -1.0);
238 
239  carl::carlVariables vars;
240  gatherVariables(vars, c);
241  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Collected variables " << vars);
242  auto orderedVars = features.sortVariables(c, vars.as_vector());
243  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Calculated variable ordering " << orderedVars);
244  return orderedVars;
245 }
246 
247 /**
248  * According to
249  * Pickering, Lynn, Tereso Del Rio Almajano, Matthew England, and Kelly Cohen. ‘Explainable AI Insights for Symbolic Computation: A Case Study on Selecting the Variable Ordering for Cylindrical Algebraic Decomposition’. arXiv, 29 August 2023. http://arxiv.org/abs/2304.12154.
250  *
251  */
252 template<typename Constraints>
253 std::vector<carl::Variable> feature_based_pickering(const Constraints& c) {
255 
256  features.addFeature(detail::sum_max_degree<Constraints>, 0, -1.0);
257  features.addFeature(detail::avg_avg_degree<Constraints>, 1, -1.0);
258  features.addFeature(detail::sum_sum_degree<Constraints>, 2, -1.0);
259 
260  carl::carlVariables vars;
261  gatherVariables(vars, c);
262  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Collected variables " << vars);
263  auto orderedVars = features.sortVariables(c, vars.as_vector());
264  SMTRAT_LOG_DEBUG("smtrat.mcsat.variableorder", "Calculated variable ordering " << orderedVars);
265  return orderedVars;
266 }
267 
268 template<typename Constraints>
269 std::vector<carl::Variable> feature_based_lexicographic(const Constraints& c) {
270  carl::carlVariables vars;
271  gatherVariables(vars, c);
272  auto var_order = vars.as_vector();
273  // sort lexicographically by name
274  std::sort(var_order.begin(), var_order.end(), [](const auto& lhs, const auto& rhs) {
275  const auto& lhs_name = lhs.name();
276  const auto& rhs_name = rhs.name();
277  return std::lexicographical_compare(lhs_name.begin(), lhs_name.end(), rhs_name.begin(), rhs_name.end()); });
278  return var_order;
279 }
280 
281 }
282 }
283 }
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
void log(const FormulaDB &db, const FormulaID id)
Numeric abs(const Numeric &_value)
Calculates the absolute value of the given Numeric.
Definition: Numeric.cpp:276
double max_degree(const Constraints &constraints, carl::Variable v)
The maximum degree of this variable.
Definition: feature_based.h:67
double abstract_feature(const Constraints &constraints, double initial, std::function< double(double, double)> &&comb, Calculator &&calc)
Definition: feature_based.h:59
double max_term_total_degree(const Constraints &constraints, carl::Variable v)
The maximum total degree of a term involving this variable.
Definition: feature_based.h:77
double max_coefficient(const Constraints &constraints, carl::Variable v)
Definition: feature_based.h:92
double sum_max_degree(const Constraints &constraints, carl::Variable v)
double sum_sum_degree(const Constraints &constraints, carl::Variable v)
double avg_avg_degree(const Constraints &constraints, carl::Variable v)
double max_lcoeff_total_degree(const Constraints &constraints, carl::Variable v)
double num_occurrences(const Constraints &constraints, carl::Variable v)
std::vector< carl::Variable > feature_based_lexicographic(const Constraints &c)
void gatherVariables(carl::carlVariables &vars, const Constraints &constraints)
Definition: helper.h:37
std::vector< carl::Variable > feature_based_z3(const Constraints &c)
std::vector< carl::Variable > feature_based_pickering(const Constraints &c)
According to Pickering, Lynn, Tereso Del Rio Almajano, Matthew England, and Kelly Cohen.
std::vector< carl::Variable > feature_based_brown(const Constraints &c)
According to https://www.usna.edu/Users/cs/wcbrown/research/ISSAC04/handout.pdf.
std::vector< carl::Variable > feature_based(const Constraints &c)
std::vector< carl::Variable > feature_based_triangular(const Constraints &c)
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.
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
This class manages features that are used to valuate variables on objects.
Definition: feature_based.h:26
Valuation valuateVariable(const Objects &o, carl::Variable v) const
Definition: feature_based.h:35
std::vector< carl::Variable > sortVariables(const Objects &o, std::vector< carl::Variable > vars) const
Definition: feature_based.h:46
void addFeature(Extractor &&e, std::size_t level, double weight)
Definition: feature_based.h:31
std::function< double(Objects, carl::Variable)> Extractor
Definition: feature_based.h:27
std::vector< std::tuple< Extractor, std::size_t, double > > mFeatures
Definition: feature_based.h:29