SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
CADConstraints.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <algorithm>
4 #include <map>
5 #include <set>
6 #include <vector>
7 #include <stack>
8 
10 #include "../common.h"
11 #include "../Settings.h"
12 #include "../debug/DotHelper.h"
13 #include <carl-arith/constraint/IntervalEvaluation.h>
14 
15 namespace smtrat {
16 namespace cad {
17 
18 template<Backtracking BT>
20 public:
21  using Callback = std::function<void(const UPoly&, std::size_t, bool)>;
23  template<Backtracking B>
24  friend std::ostream& operator<<(std::ostream& os, const CADConstraints<B>& cc);
25 protected:
27  std::size_t complexity(const ConstraintT& c) const {
28  return c.max_degree() * variables(c).size() * c.lhs().size();
29  }
30  bool operator()(const ConstraintT& lhs, const ConstraintT& rhs) const {
31  auto cl = complexity(lhs);
32  auto cr = complexity(rhs);
33  if (cl != cr) return cl < cr;
34  return lhs < rhs;
35  }
36  };
37  using ConstraintMap = std::map<ConstraintT, std::size_t, ConstraintComparator>;
38  using ConstraintIts = std::vector<typename ConstraintMap::iterator>;
39 
40  std::vector<carl::Variable> mVariables;
46  std::vector<typename ConstraintMap::iterator> mConstraintIts;
47  std::vector<std::size_t> mConstraintLevels;
48  carl::IDPool mIDPool;
50  /// List of constraints that are satisfied by bounds.
51  carl::Bitset mSatByBounds;
52  /// List of constraints that are infeasible due to bounds.
53  carl::Bitset mUnsatByBounds;
54 
55  template<typename CB, typename... Args>
56  void callCallback(const CB& cb, const ConstraintT& c, Args... args) const {
57  if (cb) cb(carl::to_univariate_polynomial(c.lhs(), mVariables.front()), std::forward<Args>(args)...);
58  }
59 public:
60  CADConstraints(const Callback& onAdd, const Callback& onAddEq, const Callback& onRemove): mAddCallback(onAdd), mAddEqCallback(onAddEq), mRemoveCallback(onRemove) {}
61  CADConstraints(const CADConstraints&) = delete;
62  void reset(const std::vector<carl::Variable>& vars) {
63  mVariables = vars;
64  mActiveConstraintMap.clear();
65  mConstraintMap.clear();
66  mConstraintIts.clear();
67  mConstraintLevels.clear();
68  mIDPool.clear();
69  mBounds.clear();
70  mSatByBounds = carl::Bitset();
71  mUnsatByBounds = carl::Bitset();
72  }
73  const std::vector<carl::Variable>& vars() const {
74  return mVariables;
75  }
76  std::size_t size() const {
77  return mConstraintIts.size();
78  }
79  bool valid(std::size_t id) const {
80  return mConstraintIts[id] != mConstraintMap.end();
81  }
82  const auto& indexed() const {
83  return mConstraintIts;
84  }
85  const auto& ordered() const {
86  return mActiveConstraintMap;
87  }
88  const auto& bounds() const {
89  return mBounds;
90  }
91  const auto& unsatByBounds() const {
92  return mUnsatByBounds;
93  }
94  std::size_t add(const ConstraintT& c) {
95  SMTRAT_LOG_DEBUG("smtrat.cad.constraints", "Adding " << c << " to " << std::endl << *this);
96  bool isBound = mBounds.addBound(c, c);
97  assert(!mVariables.empty());
98  std::size_t id = 0;
99  if (BT == Backtracking::ORDERED) {
100  id = mConstraintIts.size();
101  mConstraintIts.push_back(mConstraintMap.end());
102  mConstraintLevels.emplace_back(0);
103 
104  mActiveConstraintMap.emplace(c, id);
105  auto r = mConstraintMap.emplace(c, id);
106  assert(r.second);
107  mConstraintIts[id] = r.first;
108  } else if (BT == Backtracking::HIDE) {
109  auto it = mConstraintMap.find(c);
110  if (it != mConstraintMap.end()) {
111  id = it->second;
112  mActiveConstraintMap.emplace(c, id);
113  mConstraintIts[id] = it;
114  } else {
115  id = mIDPool.get();
116  if (id >= mConstraintIts.size()) {
117  mConstraintIts.resize(id+1, mConstraintMap.end());
118  mConstraintLevels.resize(id+1);
119  }
120  mActiveConstraintMap.emplace(c, id);
121  auto r = mConstraintMap.emplace(c, id);
122  assert(r.second);
123  mConstraintIts[id] = r.first;
124  }
125  } else {
126  id = mIDPool.get();
127  if (id >= mConstraintIts.size()) {
128  mConstraintIts.resize(id+1, mConstraintMap.end());
129  mConstraintLevels.resize(id+1);
130  }
131  mActiveConstraintMap.emplace(c, id);
132  auto r = mConstraintMap.emplace(c, id);
133  assert(r.second);
134  mConstraintIts[id] = r.first;
135  }
136  auto vars = carl::variables(c);
137  for (std::size_t level = mVariables.size(); level > 0; level--) {
138  vars.erase(mVariables[level - 1]);
139  if (vars.empty()) {
140  mConstraintLevels[id] = level;
141  break;
142  }
143  }
144  SMTRAT_LOG_DEBUG("smtrat.cad.constraints", "Identified " << c << " as level " << mConstraintLevels[id]);
145  if(c.relation() == carl::Relation::EQ) {
146  callCallback(mAddEqCallback, c, id, isBound);
147  } else {
148  callCallback(mAddCallback, c, id, isBound);
149  }
150  SMTRAT_LOG_DEBUG("smtrat.cad.constraints", "Added " << c << " to " << std::endl << *this);
151  return id;
152  }
153 
154  /**
155  * Removes a constraint.
156  * Returns the set of constraint ids that have (possibly) been reassigned and should be cleared from the sample evaluations.
157  */
158  carl::Bitset remove(const ConstraintT& c) {
159  SMTRAT_LOG_DEBUG("smtrat.cad.constraints", "Removing " << c << " from " << std::endl << *this);
160  bool isBound = mBounds.removeBound(c, c);
161  auto it = mConstraintMap.find(c);
162  assert(it != mConstraintMap.end());
163  std::size_t id = it->second;
164  carl::Bitset res = {id};
165  mSatByBounds.reset(id);
166  mUnsatByBounds.reset(id);
167  assert(mConstraintIts[id] == it);
168  if (BT == Backtracking::ORDERED) {
169  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Removing " << id << " in ordered mode");
170  std::stack<ConstraintT> cache;
171  // Remove constraints added after c
172  while (mConstraintIts.back()->second > id) {
173  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Preliminary removal of " << mConstraintIts.back()->first);
174  cache.push(mConstraintIts.back()->first);
175  res |= remove(mConstraintIts.back()->first);
176  }
177  // Remove c
178  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Actual removal of " << mConstraintIts.back()->first);
179  callCallback(mRemoveCallback, mConstraintIts.back()->first, mConstraintIts.back()->second, isBound);
180  mActiveConstraintMap.erase(mConstraintIts.back()->first);
181  mConstraintMap.erase(mConstraintIts.back());
182  mConstraintIts.pop_back();
183  assert(mConstraintIts.size() == id);
184  // Add constraints removed before
185  while (!cache.empty()) {
186  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Readding of " << cache.top());
187  add(cache.top());
188  cache.pop();
189  }
190  } else if(BT == Backtracking::HIDE) {
191  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Removing " << id << " in unordered mode");
192  callCallback(mRemoveCallback, c, id, isBound);
193  mActiveConstraintMap.erase(it->first);
194  mConstraintIts[id] = mConstraintMap.end();
195  } else {
196  SMTRAT_LOG_TRACE("smtrat.cad.constraints", "Removing " << id << " in unordered mode");
197  callCallback(mRemoveCallback, c, id, isBound);
198  mActiveConstraintMap.erase(it->first);
199  mConstraintMap.erase(it);
200  mConstraintIts[id] = mConstraintMap.end();
201  mIDPool.free(id);
202  }
203  SMTRAT_LOG_DEBUG("smtrat.cad.constraints", "Removed " << c << " from " << std::endl << *this);
204  return res;
205  }
206  const ConstraintT& operator[](std::size_t id) const {
207  assert(id < mConstraintIts.size());
208  assert(mConstraintIts[id] != mConstraintMap.end());
209  return mConstraintIts[id]->first;
210  }
211  std::size_t level(std::size_t id) const {
212  return mConstraintLevels[id];
213  }
214  bool checkForTrivialConflict(std::vector<FormulaSetT>& mis) const {
215  if (bounds().isConflicting()) {
216  SMTRAT_LOG_INFO("smtrat.cad", "Trivially unsat due to bounds" << std::endl << bounds());
217  mis.emplace_back();
218  for (const auto& c: bounds().getOriginsOfBounds()) {
219  mis.back().emplace(c);
220  }
221  return true;
222  }
223  const auto& intervalmap = mBounds.getIntervalMap();
224  for (const auto& c: mConstraintIts) {
225  if (c == mConstraintMap.end()) continue;
226  SMTRAT_LOG_TRACE("smtrat.cad", "Checking " << c->first << " against " << intervalmap);
227  switch (consistent_with(c->first.constr(),intervalmap)) {
228  case 0: {
229  SMTRAT_LOG_INFO("smtrat.cad", "Single constraint conflicts with bounds: " << c->first << std::endl << bounds());
230  mis.emplace_back();
231  for (const auto& b: bounds().getOriginsOfBounds()) {
232  mis.back().emplace(b);
233  }
234  mis.back().emplace(c->first);
235  return true;
236  }
237  default: break;
238  }
239  }
240  return false;
241  }
242  void exportAsDot(std::ostream& out) const {
243  debug::DotSubgraph dsg("constraints");
244  for (const auto& c: mActiveConstraintMap) {
245  out << "\t\tc_" << c.second << " [label=\"" << c.first << "\"];" << std::endl;
246  dsg.add("c_" + std::to_string(c.second));
247  }
248  out << "\t" << dsg << std::endl;
249  }
250 };
251 
252 template<Backtracking BT>
253 std::ostream& operator<<(std::ostream& os, const CADConstraints<BT>& cc) {
254  for (const auto& c: cc.mConstraintIts) {
255  if (c == cc.mConstraintMap.end()) continue;
256  os << "\t" << c->second << ": " << c->first << std::endl;
257  }
258  assert(long(cc.mActiveConstraintMap.size()) == std::count_if(cc.mConstraintIts.begin(), cc.mConstraintIts.end(), [&cc](auto it){ return it != cc.mConstraintMap.end(); }));
259  return os;
260 }
261 
262 }
263 }
std::size_t add(const ConstraintT &c)
const auto & unsatByBounds() const
carl::Bitset mUnsatByBounds
List of constraints that are infeasible due to bounds.
std::vector< typename ConstraintMap::iterator > mConstraintIts
const ConstraintT & operator[](std::size_t id) const
void exportAsDot(std::ostream &out) const
bool valid(std::size_t id) const
std::function< void(const UPoly &, std::size_t, bool)> Callback
CADConstraints(const Callback &onAdd, const Callback &onAddEq, const Callback &onRemove)
std::vector< typename ConstraintMap::iterator > ConstraintIts
carl::Bitset mSatByBounds
List of constraints that are satisfied by bounds.
const auto & indexed() const
friend std::ostream & operator<<(std::ostream &os, const CADConstraints< B > &cc)
const auto & ordered() const
carl::Bitset remove(const ConstraintT &c)
Removes a constraint.
CADConstraints(const CADConstraints &)=delete
void reset(const std::vector< carl::Variable > &vars)
void callCallback(const CB &cb, const ConstraintT &c, Args... args) const
const auto & bounds() const
ConstraintMap mActiveConstraintMap
bool checkForTrivialConflict(std::vector< FormulaSetT > &mis) const
std::size_t size() const
std::vector< std::size_t > mConstraintLevels
std::size_t level(std::size_t id) const
std::map< ConstraintT, std::size_t, ConstraintComparator > ConstraintMap
const std::vector< carl::Variable > & vars() const
std::vector< carl::Variable > mVariables
const smtrat::EvalDoubleIntervalMap & getIntervalMap() const
Creates an interval map corresponding to the variable bounds.
unsigned removeBound(const ConstraintT &_constraint, const T &_origin)
Removes all effects the given constraint has on the variable bounds.
bool addBound(const ConstraintT &_constraint, const T &_origin)
Updates the variable bounds by the given constraint.
std::ostream & operator<<(std::ostream &os, const SampleIteratorQueue< I, C > &siq)
carl::UnivariatePolynomial< Poly > UPoly
Definition: common.h:17
Class to create the formulas for axioms.
carl::Constraint< Poly > ConstraintT
Definition: types.h:29
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_INFO(channel, msg)
Definition: logging.h:34
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
std::size_t complexity(const ConstraintT &c) const
bool operator()(const ConstraintT &lhs, const ConstraintT &rhs) const
void add(const std::string &n)
Definition: DotHelper.h:14