1 /********************* */
4 ** Top contributors (to current version):
5 ** Aina Niemetz, Tim King, Andrew Reynolds
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 by the authors listed in the file AUTHORS
8 ** in the top-level source directory and their institutional affiliations.
9 ** All rights reserved. See the file COPYING in the top-level source
10 ** directory for licensing information.\endverbatim
12 ** \brief ITE simplification preprocessing pass.
15 #include "preprocessing/passes/ite_simp.h"
19 #include "options/smt_options.h"
20 #include "smt/smt_statistics_registry.h"
21 #include "smt_util/nary_builder.h"
22 #include "theory/arith/arith_ite_utils.h"
25 using namespace CVC4::theory
;
28 namespace preprocessing
{
31 /* -------------------------------------------------------------------------- */
35 Node
simpITE(util::ITEUtilities
* ite_utils
, TNode assertion
)
37 if (!ite_utils
->containsTermITE(assertion
))
43 Node result
= ite_utils
->simpITE(assertion
);
44 Node res_rewritten
= Rewriter::rewrite(result
);
46 if (options::simplifyWithCareEnabled())
48 Chat() << "starting simplifyWithCare()" << endl
;
49 Node postSimpWithCare
= ite_utils
->simplifyWithCare(res_rewritten
);
50 Chat() << "ending simplifyWithCare()"
51 << " post simplifyWithCare()" << postSimpWithCare
.getId() << endl
;
52 result
= Rewriter::rewrite(postSimpWithCare
);
56 result
= res_rewritten
;
63 * Ensures the assertions asserted after index 'before' now effectively come
64 * before 'real_assertions_end'.
66 void compressBeforeRealAssertions(AssertionPipeline
* assertionsToPreprocess
,
69 size_t cur_size
= assertionsToPreprocess
->size();
70 if (before
>= cur_size
|| assertionsToPreprocess
->getRealAssertionsEnd() <= 0
71 || assertionsToPreprocess
->getRealAssertionsEnd() >= cur_size
)
77 // original: [0 ... assertionsToPreprocess.getRealAssertionsEnd())
79 // ites skolems [assertionsToPreprocess.getRealAssertionsEnd(), before)
81 // added [before, cur_size)
83 Assert(0 < assertionsToPreprocess
->getRealAssertionsEnd());
84 Assert(assertionsToPreprocess
->getRealAssertionsEnd() <= before
);
85 Assert(before
< cur_size
);
87 std::vector
<Node
> intoConjunction
;
88 for (size_t i
= before
; i
< cur_size
; ++i
)
90 intoConjunction
.push_back((*assertionsToPreprocess
)[i
]);
92 assertionsToPreprocess
->resize(before
);
93 size_t lastBeforeItes
= assertionsToPreprocess
->getRealAssertionsEnd() - 1;
94 intoConjunction
.push_back((*assertionsToPreprocess
)[lastBeforeItes
]);
95 Node newLast
= CVC4::util::NaryBuilder::mkAssoc(kind::AND
, intoConjunction
);
96 assertionsToPreprocess
->replace(lastBeforeItes
, newLast
);
97 Assert(assertionsToPreprocess
->size() == before
);
102 /* -------------------------------------------------------------------------- */
104 ITESimp::Statistics::Statistics()
105 : d_arithSubstitutionsAdded(
106 "preprocessing::passes::ITESimp::ArithSubstitutionsAdded", 0)
108 smtStatisticsRegistry()->registerStat(&d_arithSubstitutionsAdded
);
111 ITESimp::Statistics::~Statistics()
113 smtStatisticsRegistry()->unregisterStat(&d_arithSubstitutionsAdded
);
116 bool ITESimp::doneSimpITE(AssertionPipeline
* assertionsToPreprocess
)
118 Assert(!options::unsatCores());
120 bool simpDidALotOfWork
= d_iteUtilities
.simpIteDidALotOfWorkHeuristic();
121 if (simpDidALotOfWork
)
123 if (options::compressItes())
125 result
= d_iteUtilities
.compress(assertionsToPreprocess
);
130 // if false, don't bother to reclaim memory here.
131 NodeManager
* nm
= NodeManager::currentNM();
132 if (nm
->poolSize() >= options::zombieHuntThreshold())
134 Chat() << "..ite simplifier did quite a bit of work.. "
135 << nm
->poolSize() << endl
;
136 Chat() << "....node manager contains " << nm
->poolSize()
137 << " nodes before cleanup" << endl
;
138 d_iteUtilities
.clear();
139 Rewriter::clearCaches();
140 nm
->reclaimZombiesUntil(options::zombieHuntThreshold());
141 Chat() << "....node manager contains " << nm
->poolSize()
142 << " nodes after cleanup" << endl
;
147 // Do theory specific preprocessing passes
148 TheoryEngine
* theory_engine
= d_preprocContext
->getTheoryEngine();
149 if (theory_engine
->getLogicInfo().isTheoryEnabled(theory::THEORY_ARITH
)
150 && !options::incrementalSolving())
152 if (!simpDidALotOfWork
)
154 util::ContainsTermITEVisitor
& contains
=
155 *(d_iteUtilities
.getContainsVisitor());
156 arith::ArithIteUtils
aiteu(contains
,
157 d_preprocContext
->getUserContext(),
158 theory_engine
->getModel());
159 bool anyItes
= false;
160 for (size_t i
= 0, size
= assertionsToPreprocess
->size(); i
< size
; ++i
)
162 Node curr
= (*assertionsToPreprocess
)[i
];
163 if (contains
.containsTermITE(curr
))
166 Node res
= aiteu
.reduceVariablesInItes(curr
);
167 Debug("arith::ite::red") << "@ " << i
<< " ... " << curr
<< endl
168 << " ->" << res
<< endl
;
171 Node more
= aiteu
.reduceConstantIteByGCD(res
);
172 Debug("arith::ite::red") << " gcd->" << more
<< endl
;
173 Node morer
= Rewriter::rewrite(more
);
174 assertionsToPreprocess
->replace(i
, morer
);
180 unsigned prevSubCount
= aiteu
.getSubCount();
181 aiteu
.learnSubstitutions(assertionsToPreprocess
->ref());
182 if (prevSubCount
< aiteu
.getSubCount())
184 d_statistics
.d_arithSubstitutionsAdded
+=
185 aiteu
.getSubCount() - prevSubCount
;
186 bool anySuccess
= false;
187 for (size_t i
= 0, N
= assertionsToPreprocess
->size(); i
< N
; ++i
)
189 Node curr
= (*assertionsToPreprocess
)[i
];
190 Node next
= Rewriter::rewrite(aiteu
.applySubstitutions(curr
));
191 Node res
= aiteu
.reduceVariablesInItes(next
);
192 Debug("arith::ite::red") << "@ " << i
<< " ... " << next
<< endl
193 << " ->" << res
<< endl
;
194 Node more
= aiteu
.reduceConstantIteByGCD(res
);
195 Debug("arith::ite::red") << " gcd->" << more
<< endl
;
202 for (size_t i
= 0, N
= assertionsToPreprocess
->size();
206 Node curr
= (*assertionsToPreprocess
)[i
];
207 Node next
= Rewriter::rewrite(aiteu
.applySubstitutions(curr
));
208 Node res
= aiteu
.reduceVariablesInItes(next
);
209 Debug("arith::ite::red") << "@ " << i
<< " ... " << next
<< endl
210 << " ->" << res
<< endl
;
211 Node more
= aiteu
.reduceConstantIteByGCD(res
);
212 Debug("arith::ite::red") << " gcd->" << more
<< endl
;
213 Node morer
= Rewriter::rewrite(more
);
214 assertionsToPreprocess
->replace(i
, morer
);
223 /* -------------------------------------------------------------------------- */
225 ITESimp::ITESimp(PreprocessingPassContext
* preprocContext
)
226 : PreprocessingPass(preprocContext
, "ite-simp")
230 PreprocessingPassResult
ITESimp::applyInternal(
231 AssertionPipeline
* assertionsToPreprocess
)
233 d_preprocContext
->spendResource(ResourceManager::Resource::PreprocessStep
);
235 size_t nasserts
= assertionsToPreprocess
->size();
236 for (size_t i
= 0; i
< nasserts
; ++i
)
238 d_preprocContext
->spendResource(ResourceManager::Resource::PreprocessStep
);
239 Node simp
= simpITE(&d_iteUtilities
, (*assertionsToPreprocess
)[i
]);
240 assertionsToPreprocess
->replace(i
, simp
);
241 if (simp
.isConst() && !simp
.getConst
<bool>())
243 return PreprocessingPassResult::CONFLICT
;
246 bool done
= doneSimpITE(assertionsToPreprocess
);
247 if (nasserts
< assertionsToPreprocess
->size())
249 compressBeforeRealAssertions(assertionsToPreprocess
, nasserts
);
251 return done
? PreprocessingPassResult::NO_CONFLICT
252 : PreprocessingPassResult::CONFLICT
;
256 /* -------------------------------------------------------------------------- */
258 } // namespace passes
259 } // namespace preprocessing