SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
ICEModule.tpp
Go to the documentation of this file.
1 /**
2  * @file ICEModule.cpp
3  */
4 
5 #include "ICEModule.h"
6 
7 namespace smtrat
8 {
9  template<class Settings>
10  ICEModule<Settings>::ICEModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
11  PModule( _formula, _conditionals, _manager, Settings::moduleName )
12  {}
13 
14  template<class Settings>
15  ICEModule<Settings>::~ICEModule()
16  {}
17 
18  template<class Settings>
19  bool ICEModule<Settings>::addCore( ModuleInput::const_iterator _subformula )
20  {
21  addReceivedSubformulaToPassedFormula(_subformula);
22  addFormula(_subformula->formula());
23  return true;
24  }
25 
26  template<class Settings>
27  void ICEModule<Settings>::removeCore( ModuleInput::const_iterator _subformula )
28  {
29  removeFormula(_subformula->formula());
30  }
31 
32  template<class Settings>
33  Answer ICEModule<Settings>::checkCore()
34  {
35  SMTRAT_LOG_DEBUG("smtrat.ice", "Obtained the following bounds: " << std::endl << mBounds);
36  Answer res = processConstraints();
37  if (res == UNSAT) return UNSAT;
38 
39  res = runBackends();
40  if (res == UNSAT) getInfeasibleSubsets();
41  return res;
42  }
43 
44  template<class Settings>
45  void ICEModule<Settings>::addFormula(const FormulaT& f) {
46  switch (f.type()) {
47  case carl::FormulaType::CONSTRAINT:
48  mBounds.addBound(f.constraint(), f);
49  if (!carl::is_bound(f.constraint())) {
50  mConstraints.emplace(f, f.constraint());
51  }
52  break;
53  case carl::FormulaType::NOT: {
54  if (f.subformula().type() == carl::FormulaType::CONSTRAINT) {
55  const ConstraintT& c = f.subformula().constraint();
56  ConstraintT newC(c.lhs(), inverse(c.relation()));
57  mBounds.addBound(newC, f);
58  if (!carl::is_bound(newC)) {
59  mConstraints.emplace(f, newC);
60  }
61  }
62  break;
63  }
64  default:
65  break;
66  }
67  }
68 
69  template<class Settings>
70  void ICEModule<Settings>::removeFormula(const FormulaT& f) {
71  switch (f.type()) {
72  case carl::FormulaType::CONSTRAINT:
73  mBounds.removeBound(f.constraint(), f);
74  if (!carl::is_bound(f.constraint())) {
75  mConstraints.erase(f);
76  }
77  break;
78  case carl::FormulaType::NOT: {
79  if (f.subformula().type() == carl::FormulaType::CONSTRAINT) {
80  const ConstraintT& c = f.subformula().constraint();
81  ConstraintT newC(c.lhs(), inverse(c.relation()));
82  mBounds.removeBound(newC, f);
83  if (!carl::is_bound(newC)) {
84  mConstraints.erase(f);
85  }
86  }
87  break;
88  }
89  default:
90  break;
91  }
92  }
93 
94  template<class Settings>
95  Answer ICEModule<Settings>::processConstraints() {
96  if (mBounds.isConflicting()) {
97  mInfeasibleSubsets.emplace_back(mBounds.getConflict());
98  return Answer::UNSAT;
99  }
100  FHG graph;
101  TermT src;
102  std::vector<TermT> dest;
103  Coefficient coeff;
104  for (const auto& c: mConstraints) {
105  if (isSuitable(c.second, src, dest, coeff)) {
106  auto& edge = graph.newEdge(graph.newVertex(src), EdgeProperty(coeff, c.first));
107  for (const auto& d: dest) {
108  edge.addOut(graph.newVertex(d));
109  }
110  }
111  }
112  if (Settings::dumpAsDot) {
113  SMTRAT_LOG_INFO("smtrat.ice", "Dumping resulting graph to " << Settings::dotFilename);
114  graph.toDot(Settings::dotFilename);
115  }
116 
117  CycleCollector collector;
118  CycleEnumerator<FHG,CycleCollector> enumerator(graph, collector);
119  enumerator.findAll();
120 
121  if (!collector.mInfeasibleSubset.empty()) {
122  SMTRAT_LOG_INFO("smtrat.ice", "Found input to be unsat, subset is " << collector.mInfeasibleSubset);
123  mInfeasibleSubsets.emplace_back(collector.mInfeasibleSubset);
124  return UNSAT;
125  }
126  for (const auto& lemma: collector.mLemmas) {
127  SMTRAT_LOG_DEBUG("smtrat.ice", "Adding " << lemma.first << " with origin " << lemma.second);
128  addSubformulaToPassedFormula(lemma.first, lemma.second);
129  }
130  return SAT;
131  }
132 
133  template<class Settings>
134  bool ICEModule<Settings>::isSuitable(const ConstraintT& c, TermT& src, std::vector<TermT>& dest, Coefficient& coeff) {
135  SMTRAT_LOG_FUNC("smtrat.ice", c);
136  bool invert = false;
137  src = TermT();
138  dest.clear();
139  coeff.strict = false;
140  coeff.r = 0;
141 
142  switch (c.relation()) {
143  case carl::Relation::EQ: break;
144  case carl::Relation::NEQ: return false;
145  case carl::Relation::LESS:
146  invert = true;
147  coeff.strict = true;
148  break;
149  case carl::Relation::LEQ:
150  invert = true;
151  break;
152  case carl::Relation::GREATER:
153  coeff.strict = true;
154  break;
155  case carl::Relation::GEQ: break;
156  }
157  Poly p = c.lhs();
158  if (invert) p = -p;
159 
160  for (const auto& term: p) {
161  if (term.is_constant()) {
162  coeff.r += term.coeff();
163  continue;
164  }
165  if (is_zero(term)) {
166  SMTRAT_LOG_WARN("smtrat.ice", "Term " << term << " is zero. We'll ignore it.");
167  continue;
168  }
169  if (isSemiPositive(term)) {
170  if (!carl::is_zero(src)) {
171  SMTRAT_LOG_TRACE("smtrat.ice", "No: Already has a source, but " << term << " was found.");
172  return false;
173  }
174  src = term;
175  } else if (isSemiNegative(term)) {
176  dest.push_back(-term);
177  } else {
178  SMTRAT_LOG_TRACE("smtrat.ice", "No: Has indefinite term " << term << ".");
179  return false;
180  }
181  }
182  if (dest.empty()) {
183  SMTRAT_LOG_TRACE("smtrat.ice", "No: No destinations were found.");
184  return false;
185  }
186  SMTRAT_LOG_TRACE("smtrat.ice", "Yes: " << src << " -> " << dest << " with coefficient " << coeff << ".");
187  return true;
188  }
189 }
190 
191