3 * @author YOUR NAME <YOUR EMAIL ADDRESS>
6 * Created on 2015-11-24.
9 #include "CubeLIAModule.h"
10 //#define DEBUG_CUBELIAMODULE
12 #include <carl-formula/model/Assignment.h>
16 template<class Settings>
17 CubeLIAModule<Settings>::CubeLIAModule(const ModuleInput* _formula, Conditionals& _conditionals, Manager* _manager):
18 Module( _formula, _conditionals, _manager ),
23 mLRAFormula( new ModuleInput() ),
24 mLRAFoundAnswer( std::vector< std::atomic_bool* >( 1, new std::atomic_bool( false ) ) ),
25 mLRA( mLRAFormula, mLRAFoundAnswer )
28 template<class Settings>
29 CubeLIAModule<Settings>::~CubeLIAModule()
31 while( !mLRAFoundAnswer.empty() )
33 std::atomic_bool* toDel = mLRAFoundAnswer.back();
34 mLRAFoundAnswer.pop_back();
37 mLRAFoundAnswer.clear();
41 template<class Settings>
42 bool CubeLIAModule<Settings>::addCore( ModuleInput::const_iterator _subformula )
44 if( _subformula->formula().type() == carl::FormulaType::CONSTRAINT && !_subformula->formula().property_holds( carl::PROP_CONTAINS_REAL_VALUED_VARS ) )
46 const ConstraintT& constraint = _subformula->formula().constraint();
47 if( constraint.lhs().is_linear() && constraint.relation() != carl::Relation::NEQ && constraint.relation() != carl::Relation::EQ )
49 auto iter = mCubifications.find( _subformula->formula() );
50 if( iter == mCubifications.end() )
52 // For all variables in the constraint, which do not yet have a real relaxation, create one.
53 for( carl::Variable::Arg var : carl::variables(constraint.lhs()) )
55 if( var.type() == carl::VariableType::VT_INT || var.type() == carl::VariableType::VT_BOOL )
57 auto iter = mIntToRealVarMap.find( var );
58 if( iter == mIntToRealVarMap.end() )
60 carl::Variable realVar = carl::fresh_real_variable();
61 mIntToRealVarMap[var] = Poly(realVar);
62 mRealToIntVarMap[realVar] = var;
66 // Create the real relaxation of the constraint's left-hand side.
67 Poly realRelax = carl::substitute(constraint.lhs(), mIntToRealVarMap);
68 #ifdef DEBUG_CUBELIAMODULE
69 std::cout << "mIntToRealVarMap: " << mIntToRealVarMap << std::endl;
70 std::cout << "Real relaxation of " << constraint.lhs() << " is " << realRelax << std::endl;
72 // Find the 1-norm of the left-hand side's coefficients.
74 for( auto& term : realRelax.terms() )
76 if( !term.is_constant() )
78 norm += carl::abs( term.coeff() );
81 // Add half of the found 1-norm to the real relaxation of the constraint's left-hand side.
82 realRelax += norm/Rational(2);
83 // Store this "cubification".
84 FormulaT cubification( realRelax, constraint.relation() );
85 auto ret = mLRAFormula->add( cubification, false );
87 #ifdef DEBUG_CUBELIAMODULE
88 std::cout << "Add to internal LRAModule: " << cubification << std::endl;
90 mLRA.inform( cubification );
91 mLRA.add( ret.first );
92 mCubifications.emplace( _subformula->formula(), Cubification( cubification, ret.first ) );
96 // If the cubification has already been created, update the usage counter.
97 if( iter->second.mUsages == 0 )
99 // If the cubification is now active again, add it to the internal LRAModule.
100 auto ret = mLRAFormula->add( iter->second.mCubification );
101 #ifdef DEBUG_CUBELIAMODULE
102 std::cout << "Add to internal LRAModule: " << iter->second.mCubification << std::endl;
104 assert( ret.second );
105 mLRA.add( ret.first );
106 assert( iter->second.mPosition == mLRAFormula->end() );
107 iter->second.mPosition = ret.first;
109 ++iter->second.mUsages;
113 addReceivedSubformulaToPassedFormula( _subformula );
117 template<class Settings>
118 void CubeLIAModule<Settings>::removeCore( ModuleInput::const_iterator _subformula )
120 auto iter = mCubifications.find( _subformula->formula() );
121 if( iter != mCubifications.end() )
123 // If a cubification of this formula exists, update the usage counter.
124 assert( iter->second.mUsages > 0 );
125 --iter->second.mUsages;
126 if( iter->second.mUsages == 0 )
128 // If the cubification got deactivated, remove it from the internal LRAModule.
129 #ifdef DEBUG_CUBELIAMODULE
130 std::cout << "Remove from internal LRAModule: " << iter->second.mPosition->formula() << std::endl;
132 mLRA.remove( iter->second.mPosition );
133 mLRAFormula->erase( iter->second.mPosition );
134 iter->second.mPosition = mLRAFormula->end();
139 template<class Settings>
140 void CubeLIAModule<Settings>::updateModel() const
142 if( !mModelComputed && !mModelUpdated )
145 if( solverState() != UNSAT )
149 mModelUpdated = true;
153 template<class Settings>
154 Answer CubeLIAModule<Settings>::checkCore()
156 #ifdef DEBUG_CUBELIAMODULE
160 if( !rReceivedFormula().is_real_constraint_conjunction() )
162 #ifdef DEBUG_CUBELIAMODULE
163 std::cout << "Call internal LRAModule:" << std::endl;
167 mLRAFormula->updateProperties();
168 ans = mLRA.check( false, mFullCheck, objective() );
174 // Get the model of mLRA
176 const Model& relaxedModel = mLRA.model();
177 auto iter = mRealToIntVarMap.begin();
178 for( auto& ass : relaxedModel )
180 assert( iter != mRealToIntVarMap.end() );
181 // Round the result to the next integer
182 mModel.emplace_hint( mModel.end(), iter->second, carl::round( ass.second.asRational() ) );
185 // Check if the rounded model satisfies the received formula
186 bool receivedFormulaSatisfied = true;
187 for( const FormulaWithOrigins& fwo : rReceivedFormula() )
189 unsigned res = satisfies( mModel, fwo.formula() );
194 receivedFormulaSatisfied = false;
198 if( !receivedFormulaSatisfied )
201 // If we found a model, we know that the formula is satisfiable, otherwise, we have to call the backends on the received formula
202 if( receivedFormulaSatisfied )
204 mModelUpdated = true;
212 if( Settings::exclude_unsatisfiable_cube_space )
214 // Exclude the space for which mLRA has detected unsatisfiability
215 for( auto& infsubset : mLRA.infeasibleSubsets() )
218 for( auto& formula : infsubset )
219 formulas.push_back( formula.negated() );
220 addLemma( FormulaT( carl::FormulaType::OR, formulas ) );
229 #ifdef DEBUG_CUBELIAMODULE
230 std::cout << "Call Backends:" << std::endl;
232 // Run backends on received formula
235 getInfeasibleSubsets();
236 else if( ans == SAT )
237 mModelUpdated = false;