lbool SimpSMTSolver::solve( const vec< Enode * > & assumps , const unsigned conflicts , bool do_simp , bool turn_off_simp ) { vec<Lit> lits; for ( int i=0; i<assumps.size(); ++i ) { Enode * e = assumps[ i ]; if ( e->isFalse( ) ) { return l_False; } if ( e->isTrue( ) ) { continue; } Lit l = theory_handler->enodeToLit( e ); lits.push( l ); } return solve( lits, conflicts, do_simp, turn_off_simp ); }
// // Check if a formula is a clause // bool Cnfizer::checkClause( Enode * e, set< enodeid_t > & check_cache ) { assert( e ); if ( e->isLit( ) ) { check_cache.insert( e->getId( ) ); // Don't check again return true; } if ( !e->isOr( ) ) return false; if ( check_cache.find( e->getId( ) ) != check_cache.end( ) ) // Already visited term return true; bool is_clause = true; for ( Enode * list = e->getCdr( ) ; list != egraph.enil && is_clause ; list = list->getCdr( ) ) is_clause = checkClause( list->getCar( ), check_cache ); if ( !is_clause ) return false; check_cache.insert( e->getId( ) ); // Don't check again return true; }
vector<shared_ptr<nonlinear_constraint>> make_nlctrs(Enode * const e, unordered_set<Enode *> const & var_set, lbool const p) { vector<shared_ptr<nonlinear_constraint>> ret; if (e->isTrue()) { return ret; } if (e->isFalse()) { DREAL_LOG_FATAL << "false is not a valid invariant (forall_t constraint)"; throw logic_error("false is not a valid invariant (forall_t constraint)"); } if (e->isNot()) { return make_nlctrs(e->get1st(), var_set, !p); } if (e->isAnd()) { Enode * tmp = e->getCdr(); while (!tmp->isEnil()) { auto const nlctrs = make_nlctrs(e->get1st(), var_set, p); ret.insert(ret.end(), nlctrs.begin(), nlctrs.end()); tmp = tmp->getCdr(); } return ret; } if (e->isOr()) { DREAL_LOG_FATAL << "or is not a valid invariant for now, (forall_t constraint)"; throw logic_error("false is not a valid invariant for now, (forall_t constraint)"); } ret.push_back(make_shared<nonlinear_constraint>(e, var_set, p)); return ret; }
// // Check if its a pure conjunction of literals // bool Cnfizer::checkPureConj( Enode * e, set< enodeid_t > & check_cache ) { if ( check_cache.find( e->getId( ) ) != check_cache.end( ) ) return true; if ( e->isLit( ) ) { check_cache.insert( e->getId( ) ); return true; } if ( !e->isAnd( ) ) return false; bool is_pure_conj = true; for ( Enode * list = e->getCdr( ) ; list != egraph.enil && is_pure_conj ; list = list->getCdr( ) ) is_pure_conj = checkPureConj( list->getCar( ), check_cache ); if ( !is_pure_conj ) return false; check_cache.insert( e->getId( ) ); return true; }
ostream& display(ostream& out, box const & b, bool const exact, bool const old_style) { std::streamsize ss = out.precision(); out.precision(16); if (old_style) { out << "delta-sat with the following box:" << endl; unsigned const s = b.size(); for (unsigned i = 0; i < s; i++) { Enode * e = b.m_vars[i]; string const & name = e->getCar()->getName(); ibex::Interval const & v = b.m_values[i]; out << "\t" << name << " : " << v; if (i != (s - 1)) { out << ";"; } out << endl; } } else { unsigned const s = b.size(); for (unsigned i = 0; i < s; i++) { Enode * e = b.m_vars[i]; ibex::Interval const & v = b.m_values[i]; ibex::Interval const & d = b.m_domains[i]; out << e->getCar()->getName() << " : "; display(out, d, exact); out << " = "; display(out, v, exact); out << endl; } } out.precision(ss); return out; }
ibex::SystemFactory * contractor_ibex_polytope::build_system_factory( vector<Enode *> const & vars, vector<shared_ptr<nonlinear_constraint>> const & ctrs) { DREAL_LOG_DEBUG << "build_system_factory:"; ibex::SystemFactory * sf = new ibex::SystemFactory(); map<string, ibex::ExprSymbol const *> var_map; // Needed for translateEnodeToExprCtr // Construct System: add Variables for (Enode * e : vars) { string const & name = e->getCar()->getNameFull(); DREAL_LOG_INFO << "build_system_factory: Add Variable " << name; auto var_it = m_var_cache.find(e); ibex::ExprSymbol const * var = nullptr; if (var_it == m_var_cache.end()) { // Not found var = &ibex::ExprSymbol::new_(name.c_str(), ibex::Dim::scalar()); DREAL_LOG_INFO << "Added: var " << var << endl; m_var_cache.emplace(e, var); } else { // Found var = var_it->second; } var_map.emplace(name, var); sf->add_var(*var); } DREAL_LOG_DEBUG << "build_system_factory: Add Variable: DONE"; // Construct System: add constraints for (shared_ptr<nonlinear_constraint> const ctr : ctrs) { if (ctr->is_neq()) { continue; } DREAL_LOG_INFO << "build_system_factory: Add Constraint: " << *ctr; Enode * e = ctr->get_enode(); auto p = e->getPolarity(); assert(p == l_True || p == l_False); auto & m_exprctr_cache = (p == l_True) ? m_exprctr_cache_pos : m_exprctr_cache_neg; auto exprctr_it = m_exprctr_cache.find(e); ibex::ExprCtr const * exprctr = nullptr; if (exprctr_it == m_exprctr_cache.end()) { // Not found exprctr = translate_enode_to_exprctr(var_map, e); m_exprctr_cache.emplace(e, exprctr); DREAL_LOG_INFO << "Added: exprctr " << p << " " << *exprctr << endl; } else { // Found exprctr = exprctr_it->second; } if (exprctr) { DREAL_LOG_INFO << "build_system_factory: Add Constraint: expr: " << *exprctr; sf->add_ctr(*exprctr); } } DREAL_LOG_DEBUG << "build_system_factory: Add Constraint: " << "DONE"; DREAL_LOG_DEBUG << "build_system_factory: DONE"; return sf; }
void THandler::clearVar( Var v ) { assert( var_to_enode[ v ] != NULL ); Enode * e = var_to_enode[ v ]; assert( e->getId( ) < static_cast< int >( enode_id_to_var.size( ) ) ); assert( enode_id_to_var[ e->getId( ) ] == v ); var_to_enode[ v ] = NULL; enode_id_to_var[ e->getId( ) ] = var_Undef; }
double dreal_get_domain_ub(dreal_context c, dreal_expr v) { assert(c); assert(v); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; assert(context.getStatus() == l_True); Enode * var = static_cast<Enode *>(v); return var->getDomainUpperBound(); }
void dreal_set_domain_ub(dreal_context c, dreal_expr v, double n) { assert(c); assert(v); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; assert(context.getStatus() == l_True); Enode * var = static_cast<Enode *>(v); var->setDomainUpperBound(n); }
ostream & ode_constraint::display(ostream & out) const { out << "ode_constraint(" << m_int << ")" << endl; for (shared_ptr<forallt_constraint> const & inv : m_invs) { Enode * e = inv->get_enodes()[0]; if (e->hasPolarity() && e->getPolarity() == l_True) { out << *inv << endl; } } return out; }
double opensmt_get_domain_lb( opensmt_context c, opensmt_expr v ) { assert( c ); assert( v ); OpenSMTContext * c_ = static_cast< OpenSMTContext * >( c ); OpenSMTContext & context = *c_; assert( context.getStatus( ) == l_True ); Enode * var = static_cast< Enode * >( v ); return var->getDomainLowerBound(); }
// // Retrieve the formulae at the top-level // void Cnfizer::retrieveTopLevelFormulae( Enode * f, vector< Enode * > & top_level_formulae ) { if ( f->isAnd( ) ) for ( Enode * list = f->getCdr( ) ; list != egraph.enil ; list = list->getCdr( ) ) retrieveTopLevelFormulae( list->getCar( ), top_level_formulae ); else top_level_formulae.push_back( f ); }
void opensmt_set_domain_lb( opensmt_context c, opensmt_expr v, double n ) { assert( c ); assert( v ); OpenSMTContext * c_ = static_cast< OpenSMTContext * >( c ); OpenSMTContext & context = *c_; assert( context.getStatus( ) == l_True ); Enode * var = static_cast< Enode * >( v ); var->setDomainLowerBound(n); }
// // Inform Theory-Solvers of Theory-Atoms // void THandler::inform( ) { for ( ; tatoms_given < tatoms_list.size( ) ; tatoms_given ++ ) { if ( !tatoms_give[ tatoms_given ] ) continue; Enode * atm = tatoms_list[ tatoms_given ]; assert( atm ); assert( atm->isTAtom( ) ); core_solver.inform( atm ); } }
Lit THandler::getSuggestion( ) { Enode * e = core_solver.getSuggestion( ); if ( e == NULL ) return lit_Undef; bool negate = e->getDecPolarity( ) == l_False; Var v = enodeToVar( e ); return Lit( v, negate ); }
void CoreSMTSolver::printExtModel( ostream & out ) { for (Var v = 2; v < model.size(); v++) { Enode * e = theory_handler->varToEnode( v ); int tmp1, tmp2; if( sscanf( (e->getCar( )->getName( )).c_str( ), CNF_STR, &tmp1, &tmp2 ) != 1 ) if ( model[ v ] != l_Undef ) out << ( model[ v ] == l_True ? "" : "(not " ) << e << ( model[ v ] == l_True ? "" : ")" ) << endl; } }
dreal_expr dreal_get_value(dreal_context c, dreal_expr v) { assert(c); assert(v); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; assert(context.getStatus() == l_True); Enode * var = static_cast<Enode *>(v); const Real & value = var->getValue(); Enode * res = context.mkNum(value); return static_cast<void *>(res); }
void Egraph::expCleanup ( ) { // Destroy the eq classes of the explanation while ( !exp_cleanup.empty( ) ) { Enode * x = exp_cleanup.back( ); x->setExpRoot( x ); x->setExpHighestNode( x ); exp_cleanup.pop_back( ); } }
void opensmt_define_ode( opensmt_context c, const char * flowname, opensmt_expr * vars, opensmt_expr * rhses, unsigned n) { assert( c ); OpenSMTContext * c_ = static_cast< OpenSMTContext * >( c ); OpenSMTContext & context = *c_; vector<pair<string, Enode *> *> odes; for (unsigned i = 0; i < n; i++) { Enode * var = static_cast<Enode *>(vars[i]); Enode * rhs = static_cast<Enode *>(rhses[i]); odes.push_back(new pair<string, Enode*>(var->getCar()->getName(), rhs)); } context.DefineODE(flowname, &odes); }
void THandler::verifyDeductionWithExternalTool( Enode * imp ) { assert( imp->isDeduced( ) ); // First stage: print declarations const char * name = "/tmp/verifydeduction.smt2"; std::ofstream dump_out( name ); core_solver.dumpHeaderToFile( dump_out ); dump_out << "(assert" << endl; dump_out << "(and" << endl; for ( int j = 0 ; j < trail.size( ) ; j ++ ) { Var v = var( trail[ j ] ); if ( v == var_True || v == var_False ) continue; Enode * e = varToEnode( v ); assert( e ); if ( !e->isTAtom( ) ) continue; bool negated = sign( trail[ j ] ); if ( negated ) dump_out << "(not "; e->print( dump_out ); if ( negated ) dump_out << ")"; dump_out << endl; } if ( imp->getDeduced( ) == l_True ) dump_out << "(not " << imp << ")" << endl; else dump_out << imp << endl; dump_out << "))" << endl; dump_out << "(check-sat)" << endl; dump_out << "(exit)" << endl; dump_out.close( ); // Second stage, check the formula const bool tool_res = callCertifyingSolver( name ); if ( tool_res ) opensmt_error2( config.certifying_solver, " says this is not a valid deduction" ); }
ostream & print_infix_op(ostream & out, Enode * const e, string const & op, std::function<ostream &(ostream &, Enode * const)> const & f) { assert(e->getArity() >= 2); out << "("; f(out, e->get1st()); Enode * tmp = e->getCdr()->getCdr(); while (!tmp->isEnil()) { out << " " << op << " "; f(out, tmp->getCar()); tmp = tmp->getCdr(); } out << ")"; return out; }
// // Return the conflict generated by a theory solver // void THandler::getConflict ( vec< Lit > & conflict, int & max_decision_level ) { // First of all, the explanation in a tsolver is // stored as conjunction of enodes e1,...,en // with associated polarities p1,...,pn. Since the sat-solver // wants a clause we store it in the form ( l1 | ... | ln ) // where li is the literal corresponding with ei with polarity !pi vector< Enode * > & explanation = core_solver.getConflict( ); assert( !explanation.empty( ) ); if ( config.certification_level > 0 ) verifyExplanationWithExternalTool( explanation ); #ifdef PRODUCE_PROOF max_decision_level = -1; for ( vector< Enode * >::iterator it = explanation.begin( ) ; it != explanation.end( ) ; ++ it ) { Enode * ei = *it; assert( ei->hasPolarity( ) ); assert( ei->getPolarity( ) == l_True || ei->getPolarity( ) == l_False ); bool negate = ei->getPolarity( ) == l_False; Var v = enodeToVar( ei ); #if PEDANTIC_DEBUG assert( isOnTrail( Lit( v, negate ) ) ); #endif Lit l = Lit( v, !negate ); conflict.push( l ); if ( max_decision_level < level[ v ] ) max_decision_level = level[ v ]; } if ( config.produce_inter == 0 ) explanation.clear( ); #else max_decision_level = -1; while ( !explanation.empty( ) ) { Enode * ei = explanation.back( ); explanation.pop_back( ); assert( ei->hasPolarity( ) ); assert( ei->getPolarity( ) == l_True || ei->getPolarity( ) == l_False ); bool negate = ei->getPolarity( ) == l_False; Var v = enodeToVar( ei ); #if PEDANTIC_DEBUG assert( isOnTrail( Lit( v, negate ) ) ); #endif Lit l = Lit( v, !negate ); conflict.push( l ); if ( max_decision_level < level[ v ] ) max_decision_level = level[ v ]; } #endif }
void Egraph::expEnqueueArguments( Enode * x, Enode * y ) { assert( x->isTerm( ) ); assert( y->isTerm( ) ); assert( x->getArity( ) == y->getArity( ) ); // No explanation needed if they are the same if ( x == y ) return; // Simple explanation if they are arity 0 terms if ( x->getArity( ) == 0 ) { exp_pending.push_back( x ); exp_pending.push_back( y ); return; } // Otherwise they are the same function symbol // Recursively enqueue the explanations for the args assert( x->getCar( ) == y->getCar( ) ); Enode * xptr = x->getCdr( ); Enode * yptr = y->getCdr( ); while ( !xptr->isEnil( ) ) { exp_pending.push_back( xptr->getCar( ) ); exp_pending.push_back( yptr->getCar( ) ); xptr = xptr->getCdr( ); yptr = yptr->getCdr( ); } // Check both lists have the same length assert( yptr->isEnil( ) ); }
dreal_expr dreal_mk_real_var(dreal_context c, char const * s , double lb, double ub) { assert(c); assert(s); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; Snode * sort = context.mkSortReal(); context.DeclareFun(s, sort); Enode * res = context.mkVar(s, true); res->setDomainLowerBound(lb); res->setDomainUpperBound(ub); res->setValueLowerBound(lb); res->setValueUpperBound(ub); return static_cast<void *>(res); }
// // Subroutine of explainStoreExplanation // Re-root the tree containing x, in such a way that // the new root is x itself // void Egraph::expReRootOn ( Enode * x ) { Enode * p = x; Enode * parent = p->getExpParent( ); Enode * reason = p->getExpReason( ); x->setExpParent( NULL ); x->setExpReason( NULL ); while( parent != NULL ) { // Save grandparent Enode * grandparent = parent->getExpParent( ); // Save reason Enode * saved_reason = reason; reason = parent->getExpReason( ); // Reverse edge & reason parent->setExpParent( p ); parent->setExpReason( saved_reason ); #ifdef PEDANTIC_DEBUG assert( checkExpTree( parent ) ); #endif // Move the two pointers p = parent; parent = grandparent; } }
opensmt_expr opensmt_mk_int_var( opensmt_context c, char const * s , long lb, long ub) { assert( c ); assert( s ); OpenSMTContext * c_ = static_cast< OpenSMTContext * >( c ); OpenSMTContext & context = *c_; Snode * sort = context.mkSortInt( ); context.DeclareFun( s, sort ); Enode * res = context.mkVar( s, true ); res->setDomainLowerBound(lb); res->setDomainUpperBound(ub); res->setValueLowerBound(lb); res->setValueUpperBound(ub); return static_cast< void * >( res ); }
// // Give the formula to the solver // bool Cnfizer::giveToSolver( Enode * f ) { vector< Enode * > clause; // // A unit clause // if ( f->isLit( ) ) { clause.push_back( f ); #ifdef PRODUCE_PROOF if ( config.produce_inter > 0 ) return solver.addSMTClause( clause, current_partitions ); #endif return solver.addSMTClause( clause ); } // // A clause // if ( f->isOr( ) ) { vector< Enode * > lits; retrieveClause( f, lits ); for ( unsigned i = 0 ; i < lits.size( ) ; i ++ ) { Enode * arg = lits[ i ]; assert( arg->isLit( ) ); clause.push_back( arg ); } #ifdef PRODUCE_PROOF if ( config.produce_inter > 0 ) return solver.addSMTClause( clause, current_partitions ); return solver.addSMTClause( clause ); #else return solver.addSMTClause( clause ); #endif } // // Conjunction // assert( f->isAnd( ) ); vector< Enode * > conj; retrieveTopLevelFormulae( f, conj ); bool result = true; for ( unsigned i = 0 ; i < conj.size( ) && result ; i ++ ) result = giveToSolver( conj[ i ] ); return result; }
// // Retrieve a clause // void Cnfizer::retrieveClause( Enode * f, vector< Enode * > & clause ) { assert( f->isLit( ) || f->isOr( ) ); if ( f->isLit( ) ) { clause.push_back( f ); } else if ( f->isOr( ) ) { for ( Enode * list = f->getCdr( ) ; list != egraph.enil ; list = list->getCdr( ) ) retrieveClause( list->getCar( ), clause ); } }
// // Retrieve conjuncts // void Cnfizer::retrieveConjuncts( Enode * f, vector< Enode * > & conjuncts ) { assert( f->isLit( ) || f->isAnd( ) ); if ( f->isLit( ) ) { conjuncts.push_back( f ); } else if ( f->isAnd( ) ) { for ( Enode * list = f->getCdr( ) ; list != egraph.enil ; list = list->getCdr( ) ) retrieveConjuncts( list->getCar( ), conjuncts ); } }
dreal_expr dreal_mk_forall(dreal_context c, dreal_expr * varlist, unsigned n, dreal_expr body) { assert(c); OpenSMTContext * c_ = static_cast<OpenSMTContext *>(c); OpenSMTContext & context = *c_; vector<pair<string, Snode *>> sorted_var_list; for (unsigned i = 0; i <n; ++i) { dreal_expr var = varlist[i]; Enode * e = static_cast<Enode*>(var); Snode * sort = e->getSort(); string name = e->getCar()->getNameFull(); sorted_var_list.push_back(make_pair(name, sort)); } Enode * e_body = static_cast<Enode*>(body); Enode * res = context.mkForall(sorted_var_list, e_body); return static_cast<void *>(res); }