// // 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 THandler::backtrack( ) { // Undoes the state of theory atoms if needed while ( (int)stack.size( ) > trail.size( ) ) { Enode * e = stack.back( ); stack.pop_back( ); // It was var_True or var_False if ( e == NULL ) continue; if ( !e->isTAtom( ) ) continue; core_solver.popBacktrackPoint( ); assert( e->isTAtom( ) ); assert( e->hasPolarity( ) ); assert( e->getPolarity( ) == l_True || e->getPolarity( ) == l_False ); // Reset polarity e->resetPolarity( ); assert( !e->hasPolarity( ) ); } checked_trail_size = stack.size( ); }
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; }
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; }
void THandler::verifyExplanationWithExternalTool( vector< Enode * > & expl ) { // First stage: print declarations const char * name = "/tmp/verifyexp.smt2"; std::ofstream dump_out( name ); core_solver.dumpHeaderToFile( dump_out ); dump_out << "(assert " << endl; dump_out << "(and" << endl; for ( size_t j = 0 ; j < expl.size( ) ; j ++ ) { Enode * e = expl[ j ]; assert( e->isTAtom( ) ); assert( e->getPolarity( ) != l_Undef ); bool negated = e->getPolarity( ) == l_False; if ( negated ) dump_out << "(not "; e->print( dump_out ); if ( negated ) dump_out << ")"; dump_out << endl; } dump_out << "))" << endl; dump_out << "(check-sat)" << endl; dump_out << "(exit)" << endl; dump_out.close( ); // Third stage, check the formula const bool tool_res = callCertifyingSolver( name ); if ( tool_res == true ) opensmt_error2( config.certifying_solver, " says this is not an explanation" ); }
void CostSolver::check_status() { #ifndef NDEBUG for ( costfuns_t::iterator it = costfuns_.begin(); it != costfuns_.end(); ++it ) { costfun & fun = **it; codomain slack = 0; for ( incurnode * n=fun.unassigned.head; n; n=n->next ) { assert( !n->atom->hasPolarity() ); if ( n->next ) { assert( n != n->next ); if ( n->cost > n->next->cost ) { cout << n->cost << " > " << n->next->cost << endl; } assert( n->cost <= n->next->cost ); assert( n->next->prev == n ); } if ( n->prev ) { assert( n->prev != n ); assert( n->prev->next == n ); } slack += get_incurred( n->atom ); } assert( slack == fun.slack ); { codomain incurred = 0; for ( costfun::nodes_t::iterator it = fun.assigned.begin(); it != fun.assigned.end(); ++it ) { incurnode * node = *it; assert( node->atom->hasPolarity() ); if ( node->atom->getPolarity() == l_True ) { incurred += get_incurred( node->atom ); } } if ( fun.incurred != incurred ) { if ( conflict_ ) { cout << "conflict = " << conflict_ << endl; } cout << "incurred = " << incurred << endl; print_status( cout, fun ); } assert( fun.incurred == incurred ); } } if ( conflict_ ) { cout << "ct conflict " << conflict_ << endl; costfun & fun = *nodemap_.find( conflict_ )->second; codomain incurred = 0; Enode * upper_bound = 0; Enode * lower_bound = 0; for ( vector<Enode*>::iterator it = explanation.begin(); it != explanation.end(); ++it ) { Enode * atom = *it; assert( atom->hasPolarity() ); if ( atom->isCostIncur() ) { if ( atom->getPolarity() == l_True ) { incurred += get_incurred( atom ); } } if ( atom->isCostBound() ) { if ( atom->getPolarity() == l_True ) { assert( !upper_bound ); upper_bound = atom; } else { assert( !lower_bound ); assert( atom->getPolarity() == l_False ); lower_bound = atom; } } } if ( !fun.lowerbound.empty() && fun.upperbound.empty() ) { assert( fun.incurred + fun.slack < get_bound( fun.lowerbound.top() ) ); } if ( fun.lowerbound.empty() && !fun.upperbound.empty() ) { assert( fun.incurred >= get_bound( fun.upperbound.top() ) ); assert( incurred >= get_bound( upper_bound ) ); } } #endif }
void THandler::verifyInterpolantWithExternalTool( vector< Enode * > & expl , Enode * interp_list ) { uint64_t mask = 0xFFFFFFFFFFFFFFFEULL; for ( unsigned in = 1 ; in < core_solver.getNofPartitions( ) ; in ++ ) { Enode * args = interp_list; // Advance in the interpolants list for ( unsigned i = 0 ; i < in - 1 ; i ++ ) args = args->getCdr( ); Enode * interp = args->getCar( ); mask &= ~SETBIT( in ); // Check A -> I, i.e., A & !I // First stage: print declarations const char * name = "/tmp/verifyinterp.smt2"; std::ofstream dump_out( name ); core_solver.dumpHeaderToFile( dump_out ); // Print only A atoms dump_out << "(assert " << endl; dump_out << "(and" << endl; for ( size_t j = 0 ; j < expl.size( ) ; j ++ ) { Enode * e = expl[ j ]; assert( e->isTAtom( ) ); assert( e->getPolarity( ) != l_Undef ); assert( (core_solver.getIPartitions( e ) & mask) != 0 || (core_solver.getIPartitions( e ) & ~mask) != 0 ); if ( (core_solver.getIPartitions( e ) & ~mask) != 0 ) { bool negated = e->getPolarity( ) == l_False; if ( negated ) dump_out << "(not "; e->print( dump_out ); if ( negated ) dump_out << ")"; dump_out << endl; } } dump_out << "(not " << interp << ")" << endl; dump_out << "))" << endl; dump_out << "(check-sat)" << endl; dump_out << "(exit)" << endl; dump_out.close( ); // Check ! bool tool_res; if ( int pid = fork() ) { int status; waitpid(pid, &status, 0); switch ( WEXITSTATUS( status ) ) { case 0: tool_res = false; break; case 1: tool_res = true; break; default: perror( "Tool" ); exit( EXIT_FAILURE ); } } else { execlp( "tool_wrapper.sh", "tool_wrapper.sh", name, 0 ); perror( "Tool" ); exit( 1 ); } if ( tool_res == true ) opensmt_error2( config.certifying_solver, " says A -> I does not hold" ); // Now check B & I dump_out.open( name ); core_solver.dumpHeaderToFile( dump_out ); // Print only B atoms dump_out << "(assert " << endl; dump_out << "(and" << endl; for ( size_t j = 0 ; j < expl.size( ) ; j ++ ) { Enode * e = expl[ j ]; assert( e->isTAtom( ) ); assert( e->getPolarity( ) != l_Undef ); assert( (core_solver.getIPartitions( e ) & mask) != 0 || (core_solver.getIPartitions( e ) & ~mask) != 0 ); if ( (core_solver.getIPartitions( e ) & mask) != 0 ) { bool negated = e->getPolarity( ) == l_False; if ( negated ) dump_out << "(not "; e->print( dump_out ); if ( negated ) dump_out << ")"; dump_out << endl; } } dump_out << interp << endl; dump_out << "))" << endl; dump_out << "(check-sat)" << endl; dump_out << "(exit)" << endl; dump_out.close( ); // Check ! tool_res; if ( int pid = fork() ) { int status; waitpid(pid, &status, 0); switch ( WEXITSTATUS( status ) ) { case 0: tool_res = false; break; case 1: tool_res = true; break; default: perror( "Tool" ); exit( EXIT_FAILURE ); } } else { execlp( "tool_wrapper.sh", "tool_wrapper.sh", name, 0 ); perror( "Tool" ); exit( 1 ); } if ( tool_res == true ) opensmt_error2( config.certifying_solver, " says B & I does not hold" ); } }
void THandler::getReason( Lit l, vec< Lit > & reason ) { #if LAZY_COMMUNICATION assert( checked_trail_size == stack.size( ) ); assert( static_cast< int >( checked_trail_size ) == trail.size( ) ); #else #endif Var v = var(l); Enode * e = varToEnode( v ); // It must be a TAtom and already disabled assert( e->isTAtom( ) ); assert( !e->hasPolarity( ) ); assert( e->isDeduced( ) ); assert( e->getDeduced( ) != l_Undef ); // Last assigned deduction #if LAZY_COMMUNICATION assert( e->getPolarity( ) != l_Undef ); // Last assigned polarity assert( e->getPolarity( ) == e->getDeduced( ) ); // The two coincide #else #endif core_solver.pushBacktrackPoint( ); // Assign reversed polarity temporairly e->setPolarity( e->getDeduced( ) == l_True ? l_False : l_True ); // Compute reason in whatever solver const bool res = core_solver.assertLit( e, true ) && core_solver.check( true ); // Result must be false if ( res ) { cout << endl << "unknown" << endl; exit( 1 ); } // Get Explanation vector< Enode * > & explanation = core_solver.getConflict( true ); if ( config.certification_level > 0 ) verifyExplanationWithExternalTool( explanation ); // Reserve room for implied lit reason.push( lit_Undef ); // Copy explanation 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 ); // Toggle polarity for deduced literal if ( e == ei ) { assert( e->getDeduced( ) != l_Undef ); // But still holds the deduced polarity // The deduced literal must have been pushed // with the the same polarity that has been deduced reason[ 0 ] = Lit( v, !negate ); } else { assert( ei->hasPolarity( ) ); // Lit in explanation is active // This assertion might fail if in your theory solver // you do not skip deduced literals during assertLit // // TODO: check ! It could be deduced: by another solver // For instance BV found conflict and ei was deduced by EUF solver // // assert( !ei->isDeduced( ) ); // and not deduced Lit l = Lit( v, !negate ); reason.push( l ); } } core_solver.popBacktrackPoint( ); // Resetting polarity e->resetPolarity( ); }