3 * @author YOUR NAME <YOUR EMAIL ADDRESS>
6 * Created on 2015-12-10.
11 #include <smtrat-common/model.h>
12 #include <carl-formula/formula/functions/Substitution.h>
16 class MCBModelSubstitution: public ModelSubstitution {
18 std::map<carl::Variable,Rational> mAssignments;
21 MCBModelSubstitution(const std::map<carl::Variable,Rational>& assignments): ModelSubstitution(), mAssignments(assignments), mDefault(0) {
22 for (const auto& a: mAssignments) {
23 if (a.second >= mDefault) mDefault = carl::ceil(a.second) + 1;
26 virtual void multiplyBy(const Rational& _number) {
27 for (auto& a: mAssignments)
30 virtual void add(const Rational& _number) {
31 for (auto& a: mAssignments)
34 virtual carl::ModelSubstitutionPtr<Rational,Poly> clone() const {
35 return carl::createSubstitutionPtr<Rational,Poly,MCBModelSubstitution>(mAssignments);
37 virtual FormulaT representingFormula( const ModelVariable& ) {
41 virtual ModelValue evaluateSubstitution(const Model& model) const {
42 auto selection = mAssignments.end();
43 for (auto it = mAssignments.begin(); it != mAssignments.end(); it++) {
44 if (model.find(ModelVariable(it->first)) == model.end()) return carl::createSubstitution<Rational,Poly,MCBModelSubstitution>(*this);
45 const ModelValue& mv = model.evaluated(ModelVariable(it->first));
48 assert(selection == mAssignments.end());
50 SMTRAT_LOG_DEBUG("smtrat.mcb", "Evaluating " << *this << " to " << selection->second << " on " << model);
54 if (selection == mAssignments.end()) {
55 SMTRAT_LOG_DEBUG("smtrat.mcb", "Evaluating " << *this << " to default " << mDefault << " on " << model);
56 return ModelValue(mDefault);
58 return ModelValue(selection->second);
60 virtual bool dependsOn(const ModelVariable& var) const {
61 if (!var.is_variable()) return false;
62 return mAssignments.find(var.asVariable()) != mAssignments.end();
64 virtual void print(std::ostream& os) const {
66 for (auto it = mAssignments.begin(); it != mAssignments.end(); it++) {
67 if (it != mAssignments.begin()) os << ", ";
68 os << it->first << " -> " << it->second;
74 template<class Settings>
75 MCBModule<Settings>::MCBModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
76 PModule( _formula, _conditionals, _manager, Settings::moduleName )
78 collectChoicesFunction = std::bind(&MCBModule<Settings>::collectChoices, this, std::placeholders::_1);
81 template<class Settings>
82 MCBModule<Settings>::~MCBModule()
85 template<class Settings>
86 Answer MCBModule<Settings>::checkCore()
90 auto receivedFormula = firstUncheckedReceivedSubformula();
91 while (receivedFormula != rReceivedFormula().end()) {
92 carl::visit(receivedFormula->formula(), collectChoicesFunction);
95 FormulaT newFormula = applyReplacements(FormulaT(rReceivedFormula()));
97 addSubformulaToPassedFormula(newFormula);
99 Answer ans = runBackends();
101 generateTrivialInfeasibleSubset();
106 template<typename Settings>
107 void MCBModule<Settings>::updateModel() const {
109 if (solverState() == SAT || (solverState() != UNSAT && appliedPreprocessing())) {
111 mModel.update(mAssignments);
112 mAssignments.clear();
116 template<typename Settings>
117 void MCBModule<Settings>::collectBounds(carl::ConstraintBounds<Poly>& cb, const FormulaT& formula, bool conjunction) const {
118 for (const auto& f: formula.subformulas()) {
119 if (f.type() == carl::FormulaType::CONSTRAINT || (f.type() == carl::FormulaType::NOT && f.subformula().type() == carl::FormulaType::CONSTRAINT)) {
120 addConstraintBound(cb, f, conjunction);
125 template<typename Settings>
126 void MCBModule<Settings>::collectChoices(const FormulaT& formula) {
127 if (formula.type() != carl::FormulaType::OR) return;
129 carl::ConstraintBounds<Poly> cb;
130 collectBounds(cb, formula, false);
131 if (cb.empty()) return;
133 for (const auto& poly: cb) {
134 if (!poly.first.is_variable()) continue;
135 AVar var = poly.first.single_variable();
136 std::vector<std::pair<Rational,FormulaT>> choices;
137 for (const auto& entry: poly.second) {
138 if (entry.second.first != carl::Relation::EQ) break;
139 choices.emplace_back(entry.first, entry.second.second);
141 if (choices.size() != poly.second.size()) continue;
142 auto& m = mChoices[var];
143 for (const auto& c: choices) {
144 auto it = m.find(c.first);
146 m.emplace(c.first, std::make_pair(carl::fresh_boolean_variable(), c.second));
152 template<typename Settings>
153 FormulaT MCBModule<Settings>::applyReplacements(const FormulaT& f) {
154 if (mChoices.empty()) return f;
155 std::set<AVar> variables;
156 std::map<FormulaT, FormulaT> repl;
157 for (const auto& r: mChoices) {
158 variables.insert(r.first);
159 for (const auto& f: r.second) {
160 BVar v = f.second.first;
161 const FormulaT& form = f.second.second;
162 repl.emplace(form, FormulaT(v));
165 SMTRAT_LOG_DEBUG("smtrat.mcb", "Applying " << repl << " on \n\t" << f);
166 FormulaT res = carl::substitute(f, repl);
167 SMTRAT_LOG_DEBUG("smtrat.mcb", "Resulting in\n\t" << res);
170 mRemaining = carl::variables(res).as_set();
172 for (const auto& v: variables) {
173 if (mRemaining.count(v) > 0) {
174 // Variable is still in the formula
175 for (const auto& r: mChoices.at(v)) {
176 equiv.push_back(FormulaT(carl::FormulaType::IFF, {FormulaT(r.second.first), r.second.second}));
179 // Variable has been eliminated
180 ModelVariable var(v);
181 std::map<BVar,Rational> assignment;
182 for (const auto& c: mChoices.at(v)) {
183 assignment.emplace(c.second.first, c.first);
185 SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding " << var << " = " << assignment);
186 mAssignments.emplace(var, carl::createSubstitution<Rational,Poly,MCBModelSubstitution>(assignment));
188 for (const auto& c1: mChoices.at(v)) {
189 for (const auto& c2: mChoices.at(v)) {
190 if (c1.second.first >= c2.second.first) continue;
191 equiv.push_back(FormulaT(carl::FormulaType::OR, {FormulaT(c1.second.first).negated(), FormulaT(c2.second.first).negated()}));
192 SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding exclusion " << equiv.back());
196 if (equiv.empty()) return res;
197 SMTRAT_LOG_DEBUG("smtrat.mcb", "Adding equivalences " << equiv);
198 equiv.push_back(res);
199 return FormulaT(carl::FormulaType::AND, std::move(equiv));