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 ); }
bool SimpSMTSolver::addSMTClause( vector< Enode * > & smt_clause #ifdef PRODUCE_PROOF , const ipartitions_t in #endif ) { assert( config.sat_preprocess_theory == 0 ); vec< Lit > sat_clause; #ifdef PRODUCE_PROOF assert( config.produce_inter == 0 || in != 0 ); #endif for ( vector< Enode * >::iterator it = smt_clause.begin( ) ; it != smt_clause.end( ) ; it ++ ) { Enode * e = *it; // Do not add false literals if ( e->isFalse( ) ) continue; // If a literal is true, the clause is true if ( e->isTrue( ) ) return true; // Keep track of atoms seen, as they may // be interface equalities to skip later if ( config.logic == QF_UFIDL || config.logic == QF_UFLRA ) atoms_seen.insert( e ); Lit l = theory_handler->enodeToLit( e ); sat_clause.push( l ); } #ifdef PRODUCE_PROOF return addClause( sat_clause, in ); #else return addClause( sat_clause ); #endif }
void OpenSMTContext::staticCheckSAT( ) { if ( config.verbosity > 1 ) cerr << "# OpenSMTContext::Statically Checking" << endl; // Retrieve the formula Enode * formula = egraph.getUncheckedAssertions( ); if ( config.dump_formula != 0 ) egraph.dumpToFile( "original.smt2", formula ); if ( formula == NULL ) opensmt_error( "formula undefined" ); if ( config.logic == UNDEF ) opensmt_error( "unable to determine logic" ); // Removes ITEs if there is any if ( egraph.hasItes( ) ) { #ifdef PRODUCE_PROOF if ( config.produce_inter > 0 ) opensmt_error( "Interpolation not supported for ite construct" ); #endif ExpandITEs expander( egraph, config ); formula = expander.doit( formula ); if ( config.dump_formula != 0 ) egraph.dumpToFile( "ite_expanded.smt2", formula ); } // Gather interface terms for DTC if ( ( config.logic == QF_UFIDL || config.logic == QF_UFLRA ) // Don't use with DTC of course && config.sat_lazy_dtc == 1 // Don't use when dumping interpolants && config.sat_dump_rnd_inter == 0 ) { Purify purifier( egraph, config ); formula = purifier.doit( formula ); if ( config.dump_formula != 0 ) egraph.dumpToFile( "purified.smt2", formula ); } // Ackermanize away functional symbols if ( ( config.logic == QF_UFIDL || config.logic == QF_UFLRA ) // Don't use with DTC of course && config.sat_lazy_dtc == 0 // Don't use when dumping interpolants && config.sat_dump_rnd_inter == 0 ) { Ackermanize ackermanizer( egraph, config ); formula = ackermanizer.doit( formula ); if ( config.dump_formula != 0 ) egraph.dumpToFile( "ackermanized.smt2", formula ); } // Artificially create a boolean // abstraction, if necessary if ( config.logic == QF_BV ) { BVBooleanize booleanizer( egraph, config ); formula = booleanizer.doit( formula ); } // Top-Level Propagator. It also canonize atoms TopLevelProp propagator( egraph, config ); formula = propagator.doit( formula ); // Applies array axioms where possible if( config.logic == QF_AX ) { ArraySimplify simplifier( egraph, config ); formula = simplifier.doit( formula ); } // Convert RDL into IDL, also compute if GMP is needed if ( config.logic == QF_RDL ) { DLRescale rescaler( egraph, config ); rescaler.doit( formula ); } // For static checking, make sure that if DTC is used // then incrementality is enabled if ( ( config.logic == QF_UFIDL || config.logic == QF_UFLRA ) && config.sat_lazy_dtc != 0 ) { config.incremental = 1; } if ( config.dump_formula != 0 ) egraph.dumpToFile( "presolve.smt2", formula ); // Solve only if not simplified already if ( formula->isTrue( ) ) { state = l_True; } else if ( formula->isFalse( ) ) { state = l_False; } else { // Initialize theory solvers egraph.initializeTheorySolvers( &solver ); // Compute polarities egraph.computePolarities( formula ); // CNFize the input formula and feed clauses to the solver state = cnfizer.cnfizeAndGiveToSolver( formula ); // Solve if ( state == l_Undef ) { state = solver.smtSolve( config.sat_preprocess_booleans != 0 || config.sat_preprocess_theory != 0 ); } // If computation has been stopped, return undef if ( opensmt::stop ) state = l_Undef; } }
Var CoreSMTSolver::generateNextEij( ) { if ( egraph.getInterfaceTermsNumber( ) == 0 ) return var_Undef; assert( config.sat_lazy_dtc != 0 ); Var v = var_Undef; lbool pol = l_Undef; while ( v == var_Undef ) { // Already returned all the possible eij if ( next_it_i == egraph.getInterfaceTermsNumber( ) - 1 && next_it_j == egraph.getInterfaceTermsNumber( ) ) return var_Undef; // Get terms // Enode * i = interface_terms[ next_it_i ]; // Enode * j = interface_terms[ next_it_j ]; Enode * i = egraph.getInterfaceTerm( next_it_i ); Enode * j = egraph.getInterfaceTerm( next_it_j ); // Increase counters next_it_j ++; if ( next_it_j == next_it_i ) next_it_j ++; // if ( next_it_j == static_cast< int >( interface_terms.size( ) ) ) if ( next_it_j == egraph.getInterfaceTermsNumber( ) ) { next_it_i ++; next_it_j = next_it_i + 1; } // No need to create eij if both numbers, // it's either trivially true or false if ( i->isConstant( ) && j->isConstant( ) ) continue; if ( config.logic == QF_UFLRA || config.logic == QF_UFIDL ) { // // Since arithmetic solvers do not // understand equalities, produce // the splitted versions of equalities // and add linking clauses // Enode * eij = egraph.mkEq( egraph.cons( i, egraph.cons( j ) ) ); if ( config.verbosity > 2 ) cerr << "# CoreSMTSolver::Adding eij: " << eij << endl; if ( eij->isTrue( ) || eij->isFalse( ) ) continue; // Canonize LAExpression la( eij ); Enode * eij_can = la.toEnode( egraph ); // Continue if already generated equality // if ( !interface_equalities.insert( eij_can ).second ) continue; if ( eij_can->isTrue( ) || eij_can->isFalse( ) ) continue; v = theory_handler->enodeToVar( eij ); // Created one equality that is already assigned // Skip it if ( value( v ) != l_Undef ) { v = var_Undef; continue; } // Get lhs and rhs Enode * lhs = eij_can->get1st( ); Enode * rhs = eij_can->get2nd( ); Enode * leq = egraph.mkLeq( egraph.cons( lhs, egraph.cons( rhs ) ) ); // Canonize lhs LAExpression b( leq ); leq = b.toEnode( egraph ); // Canonize rhs Enode * geq = egraph.mkGeq( egraph.cons( lhs, egraph.cons( rhs ) ) ); LAExpression c( geq ); geq = c.toEnode( egraph ); // Add clause ( !x=y v x<=y ) vector< Enode * > clause; clause.push_back( egraph.mkNot( egraph.cons( eij ) ) ); clause.push_back( leq ); addSMTAxiomClause( clause ); // Add clause ( !x=y v x>=y ) clause.pop_back( ); clause.push_back( geq ); addSMTAxiomClause( clause ); // Add clause ( x=y v !x>=y v !x<=y ) clause.clear( ); clause.push_back( eij ); clause.push_back( egraph.mkNot( egraph.cons( leq ) ) ); clause.push_back( egraph.mkNot( egraph.cons( geq ) ) ); addSMTAxiomClause( clause ); pol = theory_handler->evaluate( eij ); if ( pol == l_Undef ) pol = theory_handler->evaluate( leq ); if ( pol == l_Undef ) pol = theory_handler->evaluate( geq ); } else { Enode * eij = egraph.mkEq( egraph.cons( i, egraph.cons( j ) ) ); // Continue if already generated equality if ( !interface_equalities.insert( eij ).second ) continue; if ( eij->isTrue( ) || eij->isFalse( ) ) continue; // Add new atom and get variable v = theory_handler->enodeToVar( eij ); // Initialize congruence data structure egraph.initializeCong( eij ); } } #ifdef STATISTICS ie_generated ++; #endif assert( v != var_Undef ); assert( polarity.size( ) > v ); // Assign to false first. We merge the least possible // Alternatively we can merge the most, or polarity[ v ] = ( pol == l_True ? false : ( pol == l_False ? true : true ) ); return v; }