SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
LiftingTree.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <carl-common/datastructures/carlTree.h>
4 
6 
7 #include "../common.h"
8 #include "../utils/CADConstraints.h"
9 
10 #include "SampleIteratorQueue.h"
11 #include "SampleComparator.h"
12 
13 namespace smtrat {
14 namespace cad {
15  template<typename Settings>
16  class LiftingTree {
17  public:
18  using Tree = carl::tree<Sample>;
19  using Iterator = Tree::iterator;
23  private:
25  std::vector<carl::Variable> mVariables;
29  std::vector<Iterator> mRemovedFromLiftingQueue;
30 
31  std::size_t dim() const {
32  return mVariables.size();
33  }
34 
35  void addToQueue(Iterator it) {
36  assert(it.isValid());
37  if (it.depth() < dim()) {
38  mLiftingQueue.addNewSample(it);
39  } else {
40  mCheckingQueue.addNewSample(it);
41  }
42  }
43 
45  auto removeIf = [&](const auto& it){ return !mTree.is_valid(it); };
46  mLiftingQueue.cleanup(removeIf);
47  mCheckingQueue.cleanup(removeIf);
48  auto it = std::remove_if(mRemovedFromLiftingQueue.begin(), mRemovedFromLiftingQueue.end(), removeIf);
50  }
51 
52  bool insertRootSamples(Iterator parent, std::vector<Sample>& samples) {
53  if (samples.empty()) return false;
54  std::sort(samples.begin(), samples.end());
55  samples.erase(std::unique(samples.begin(), samples.end()), samples.end());
56  bool gotNewSamples = false;
57  auto tbegin = mTree.begin_children(parent);
58  auto tit = tbegin;
59  auto tend = mTree.end_children(parent);
60  // Insert roots
61  for (const auto& s: samples) {
62  while (tit != tend && *tit < s) tit++;
63  if (tit == tend) {
64  // Append as last sample
65  auto it = mTree.append(parent, s);
66  addToQueue(it);
67  gotNewSamples = true;
68  } else if (tit->value() == s.value()) {
69  // Replace non-root sample
70  if (!tit->isRoot()) gotNewSamples = true;
71  tit->merge(s);
72  } else {
73  // Insert before sample
74  auto it = mTree.insert(tit, s);
75  addToQueue(it);
76  gotNewSamples = true;
77  }
78  }
79  return gotNewSamples;
80  }
81 
82  bool mergeRootSamples(Iterator parent, std::vector<Sample>& samples) {
83  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Merging " << samples << " into" << std::endl << mTree);
84  bool gotNewSamples = insertRootSamples(parent, samples);
85  if (!gotNewSamples) {
86  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Nothing to merge");
87  if (mTree.is_leaf(parent)) {
88  auto var = mVariables[parent.depth()];
89  auto interval = mConstraints.bounds().getInterval(var);
90  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Inserting zero node for " << var << " from " << interval);
91  auto it = mTree.append(parent, Sample(RAN(sample(interval))));
92  addToQueue(it);
93  }
94  return false;
95  }
96  // Add samples
97  auto tbegin = mTree.begin_children(parent);
98  auto tend = mTree.end_children(parent);
99  auto tit = tbegin, tlast = tbegin;
100  if (tbegin->isRoot()) {
101  auto it = mTree.insert(tbegin, Sample(carl::sample_below(tlast->value())));
102  addToQueue(it);
103  }
104  while (true) {
105  tit++;
106  if (tit == tend) break;
107  if (tlast->isRoot() && tit->isRoot()) {
108  auto it = mTree.insert(tit, Sample(carl::sample_between(tlast->value(), tit->value())));
109  addToQueue(it);
110  }
111  tlast = tit;
112  }
113  if (tlast->isRoot()) {
114  auto it = mTree.append(parent, Sample(carl::sample_above(tlast->value())));
115  addToQueue(it);
116  }
117 
118  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Result: " << std::endl << mTree);
119  return true;
120  }
121 
122  public:
124  LiftingTree(const LiftingTree&) = delete;
126  LiftingTree& operator=(const LiftingTree&) = delete;
128 
129  const auto& getTree() const {
130  return mTree;
131  }
132  const auto& getLiftingQueue() const {
133  return mLiftingQueue;
134  }
135  void reset(std::vector<carl::Variable>&& vars) {
136  mVariables = std::move(vars);
137  mCheckingQueue.clear();
138  mLiftingQueue.clear();
139  mRemovedFromLiftingQueue.clear();
140  mTree.clear();
141  auto it = mTree.setRoot(Sample(RAN(0), false));
142  assert(mTree.is_valid(it));
143  mLiftingQueue.addNewSample(it);
144  }
145 
146  bool hasFullSamples() const {
147  return !mCheckingQueue.empty();
148  }
150  return mCheckingQueue.removeNextSample();
151  }
153  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Resetting samples of full dimension.");
154  mCheckingQueue.clear();
155  for (auto it = mTree.begin_depth(dim()); it != mTree.end_depth(); it++) {
156  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "\tadding " << *it);
157  mCheckingQueue.addNewSample(it);
158  }
159  }
160 
161  bool hasNextSample() const {
162  return !mLiftingQueue.empty();
163  }
165  assert(mTree.is_valid(mLiftingQueue.getNextSample()));
166  return mLiftingQueue.getNextSample();
167  }
169  assert(hasNextSample());
170  mRemovedFromLiftingQueue.emplace_back(mLiftingQueue.removeNextSample());
171  }
174  mRemovedFromLiftingQueue.clear();
175  }
176 
177  bool liftSample(Iterator sample, const UPoly& p, std::size_t pid, bool ignore_nullifications) {
178  assert(is_consistent());
179  auto m = extractSampleMap(sample);
180  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Lifting " << m << " on " << p);
181  std::vector<Sample> newSamples;
182  auto result = carl::real_roots(p, m, RationalInterval::unbounded_interval());
183  if (!ignore_nullifications && result.is_nullified()) return false; // McCallum is not safe!
184  if (!result.is_univariate() || result.roots().empty()) {
185  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "\tnew root sample: " << RAN(0));
186  newSamples.emplace_back(RAN(0), pid);
187  } else {
188  for (const auto& r: result.roots()) {
189  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "\tnew root sample: " << r);
190  newSamples.emplace_back(r, pid);
191  }
192  }
193  auto bounds = mConstraints.bounds().getInterval(mVariables[sample.depth()]);
194  if (bounds.lower_bound_type() != carl::BoundType::INFTY) {
195  newSamples.emplace_back(RAN(bounds.lower()), true);
196  }
197  if (bounds.upper_bound_type() != carl::BoundType::INFTY) {
198  newSamples.emplace_back(RAN(bounds.upper()), true);
199  }
200  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "\tmerging " << newSamples);
201  mergeRootSamples(sample, newSamples);
202  return true;
203  }
204  bool addTrivialSample(Iterator sample) {
205  if (!mTree.is_leaf(sample)) return false;
206  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Variables: " << mVariables);
207  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "For " << printSample(sample));
208  auto variable = mVariables[sample.depth()];
209  auto center = carl::sample(mConstraints.bounds().getInterval(variable));
210  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Selecting " << center << " for " << variable << " from " << mConstraints.bounds().getInterval(variable));
211  auto it = mTree.append(sample, Sample(RAN(center), false));
212  addToQueue(it);
213 
214  for (std::size_t i = 1; i < Settings::trivialSampleRadius; i++) {
215  auto itpos = mTree.append(sample, Sample(RAN(center + i), false));
216  addToQueue(itpos);
217  auto itneg = mTree.append(sample, Sample(RAN(center - i), false));
218  addToQueue(itneg);
219  }
220  return true;
221  }
223  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Extracting sample from" << std::endl << mTree);
224  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Variables: " << mVariables);
225  Assignment res;
226  auto cur = mTree.begin_path(it);
227  while (cur != mTree.end_path() && !cur.isRoot()) {
228  res.emplace(mVariables[cur.depth()-1], cur->value());
229  cur++;
230  }
231  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Result: " << res);
232  return res;
233  }
234 
235  void removedPolynomialsFromLevel(std::size_t level, const carl::Bitset& mask) {
236  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Cleanup after removing " << mask << " from level " << level);
237  for (auto it = mTree.begin_depth(level - 1); it != mTree.end_depth(); it++) {
238  it->liftedWith() -= mask;
239  }
240  std::vector<Iterator> deleteQueue;
241  for (auto it = mTree.begin_depth(level); it != mTree.end_depth(); it++) {
242  if (!it->isRoot()) continue;
243  it->rootOf() -= mask;
244  if (it->rootOf().none()) {
245  deleteQueue.emplace_back(it);
246  deleteQueue.emplace_back(mTree.left_sibling(Iterator(it)));
247  }
248  }
249  for (const auto& it: deleteQueue) {
250  SMTRAT_LOG_TRACE("smtrat.cad.lifting", "Purging " << printSample(it));
251  mTree.erase(it);
252  }
254  }
255 
256  void removedConstraint(const carl::Bitset& mask) {
257  for (auto& s: mTree) {
258  if (s.evaluatedWith().size() == 0) continue;
259  SMTRAT_LOG_DEBUG("smtrat.cad.lifting", "Purging " << s.evaluatedWith() << " by " << mask);
260  s.evaluatedWith() -= mask;
261  s.evaluationResult() -= mask;
262  }
263  }
264 
265  bool is_consistent() const {
266  if (!mCheckingQueue.is_consistent()) return false;
267  if (!mLiftingQueue.is_consistent()) return false;
268  return true;
269  }
270 
271  std::string printSample(Iterator sample) const {
272  std::vector<Sample> chunks(mTree.begin_path(sample), mTree.end_path());
273  std::stringstream ss;
274  for (std::size_t d = 0; d < sample.depth(); d++) {
275  if (d != 0) ss << " -> ";
276  ss << mVariables[d] << " = " << chunks[chunks.size()-2-d];
277  }
278  return ss.str();
279  }
280  std::string printFullSamples() const {
281  std::stringstream ss;
282  for (const auto& it: mCheckingQueue) {
283  ss << "\t" << printSample(it) << std::endl;
284  }
285  return ss.str();
286  }
287  };
288 }
289 }
const auto & bounds() const
LiftingTree & operator=(const LiftingTree &)=delete
void reset(std::vector< carl::Variable > &&vars)
Definition: LiftingTree.h:135
std::string printFullSamples() const
Definition: LiftingTree.h:280
LiftingTree(const Constraints &c)
Definition: LiftingTree.h:123
SampleIteratorQueue< Iterator, SC > mLiftingQueue
Definition: LiftingTree.h:28
const auto & getTree() const
Definition: LiftingTree.h:129
bool hasNextSample() const
Definition: LiftingTree.h:161
const Constraints & mConstraints
Definition: LiftingTree.h:24
LiftingTree(const LiftingTree &)=delete
carl::tree< Sample > Tree
Definition: LiftingTree.h:18
bool liftSample(Iterator sample, const UPoly &p, std::size_t pid, bool ignore_nullifications)
Definition: LiftingTree.h:177
const auto & getLiftingQueue() const
Definition: LiftingTree.h:132
std::string printSample(Iterator sample) const
Definition: LiftingTree.h:271
LiftingTree(LiftingTree &&)=delete
bool is_consistent() const
Definition: LiftingTree.h:265
bool addTrivialSample(Iterator sample)
Definition: LiftingTree.h:204
Iterator getNextFullSample()
Definition: LiftingTree.h:149
LiftingTree & operator=(LiftingTree &&)=delete
void addToQueue(Iterator it)
Definition: LiftingTree.h:35
std::vector< Iterator > mRemovedFromLiftingQueue
Definition: LiftingTree.h:29
bool mergeRootSamples(Iterator parent, std::vector< Sample > &samples)
Definition: LiftingTree.h:82
void removedConstraint(const carl::Bitset &mask)
Definition: LiftingTree.h:256
std::vector< carl::Variable > mVariables
Definition: LiftingTree.h:25
Assignment extractSampleMap(Iterator it) const
Definition: LiftingTree.h:222
bool hasFullSamples() const
Definition: LiftingTree.h:146
std::size_t dim() const
Definition: LiftingTree.h:31
Tree::iterator Iterator
Definition: LiftingTree.h:19
void removedPolynomialsFromLevel(std::size_t level, const carl::Bitset &mask)
Definition: LiftingTree.h:235
SampleIteratorQueue< Iterator, FSC > mCheckingQueue
Definition: LiftingTree.h:27
bool insertRootSamples(Iterator parent, std::vector< Sample > &samples)
Definition: LiftingTree.h:52
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
int var(Lit p)
Definition: SolverTypes.h:64
smtrat::RAN RAN
Definition: common.h:11
carl::UnivariatePolynomial< Poly > UPoly
Definition: common.h:17
std::map< carl::Variable, RAN > Assignment
Definition: common.h:14
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_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35