Esempio n. 1
0
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( );
}
Esempio n. 2
0
//
// 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 );
  }
}
Esempio n. 3
0
void CoreSMTSolver::printModel( ostream & out )
{
  for (Var v = 2; v < model.size(); v++)
  {
    Enode * e = theory_handler->varToEnode( v );
    if ( e->isTAtom( ) )
      continue;
    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;
  }
}
Esempio n. 4
0
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" );
}
Esempio n. 5
0
void THandler::verifyCallWithExternalTool( bool res, size_t trail_size )
{
  // First stage: print declarations
  const char * name = "/tmp/verifycall.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 <= trail_size ; j ++ )
  {
    Var v = var( trail[ j ] );

    if ( v == var_True || v == var_False )
      continue;

    // Enode * e = var_to_enode[ v ];
    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;
  }
  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 ( res == false && tool_res == true )
    opensmt_error2( config.certifying_solver, " says SAT stack, but we say UNSAT" );

  if ( res == true && tool_res == false )
    opensmt_error2( config.certifying_solver, " says UNSAT stack, but we say SAT" );
}
Esempio n. 6
0
bool THandler::assertLits( )
{
  bool res = true;

  assert( checked_trail_size == stack.size( ) );
  assert( (int)stack.size( ) <= trail.size( ) );
  DREAL_LOG_DEBUG << "THandler::assertLits()" << endl;

  for ( int i = checked_trail_size ; i < trail.size( ) && res ; i ++ )
  {
    const Lit l = trail[ i ];
    const Var v = var( l );

    Enode * e = var_to_enode[ v ];
    assert( v <= 1 || e );
    stack.push_back( e );

    if ( v == var_True || v == var_False )
    {
      assert( v != var_True  || sign( l ) == false );
      assert( v != var_False || sign( l ) == true );
      continue;
    }

    if ( !e->isTAtom( ) )
      continue;

    // Push backtrack point
    core_solver.pushBacktrackPoint( );

    assert( !e->hasPolarity( ) );
    DREAL_LOG_DEBUG << "THandler::assertLits(): asserting " << e << " with sign = " << sign(l) << endl;
    e->setPolarity( (sign( l ) ? l_False : l_True) );
    assert( e->hasPolarity( ) );
    res = core_solver.assertLit( e );

    if ( !res && config.certification_level > 2 )
      verifyCallWithExternalTool( res, i );
  }

  checked_trail_size = stack.size( );
  assert( !res || trail.size( ) == (int)stack.size( ) );

  return res;
}
Esempio n. 7
0
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" );
}
Esempio n. 8
0
Enode * Egraph::canonizeDTC( Enode * formula, bool split_eqs )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFLRA
       || config.logic == QF_UFIDL );

  list< Enode * > dtc_axioms;
  vector< Enode * > unprocessed_enodes;
  initDupMap1( );

  unprocessed_enodes.push_back( formula );
  //
  // Visit the DAG of the formula from the leaves to the root
  //
  while( !unprocessed_enodes.empty( ) )
  {
    Enode * enode = unprocessed_enodes.back( );
    //
    // Skip if the node has already been processed before
    //
    if ( valDupMap1( enode ) != NULL )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( )
        ; arg_list != enil
        ; arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );
      assert( arg->isTerm( ) );
      //
      // Push only if it is unprocessed
      //
      if ( valDupMap1( arg ) == NULL )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // Replace arithmetic atoms with canonized version
    //
    if (  enode->isTAtom( )
      && !enode->isUp( ) )
    {
      // No need to do anything if node is purely UF
      if ( isRootUF( enode ) )
      {
        if ( config.verbosity > 2 )
          cerr << "# Egraph::Skipping canonization of " << enode << " as it's root is purely UF" << endl;
        result = enode;
      }
      else
      {
        LAExpression a( enode );
        result = a.toEnode( *this );
#ifdef PRODUCE_PROOF
        const uint64_t partitions = getIPartitions( enode );
        assert( partitions != 0 );
        setIPartitions( result, partitions );
#endif

        if ( split_eqs && result->isEq( ) )
        {
#ifdef PRODUCE_PROOF
          if ( config.produce_inter > 0 )
            opensmt_error2( "can't compute interpolant for equalities at the moment ", enode );
#endif
          LAExpression aa( enode );
          Enode * e = aa.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( e, partitions );
#endif
          Enode * lhs = e->get1st( );
          Enode * rhs = e->get2nd( );
          Enode * leq = mkLeq( cons( lhs, cons( rhs ) ) );
          LAExpression b( leq );
          leq = b.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( leq, partitions );
#endif
          Enode * geq = mkGeq( cons( lhs, cons( rhs ) ) );
          LAExpression c( geq );
          geq = c.toEnode( *this );
#ifdef PRODUCE_PROOF
          assert( partitions != 0 );
          setIPartitions( geq, partitions );
#endif
          Enode * not_e = mkNot( cons( enode ) );
          Enode * not_l = mkNot( cons( leq ) );
          Enode * not_g = mkNot( cons( geq ) );
          // Add clause ( !x=y v x<=y )
          Enode * c1 = mkOr( cons( not_e
                           , cons( leq ) ) );
          // Add clause ( !x=y v x>=y )
          Enode * c2 = mkOr( cons( not_e
                           , cons( geq ) ) );
          // Add clause ( x=y v !x>=y v !x<=y )
          Enode * c3 = mkOr( cons( enode
                           , cons( not_l
                           , cons( not_g ) ) ) );
          // Add conjunction of clauses
          Enode * ax = mkAnd( cons( c1
                            , cons( c2
                            , cons( c3 ) ) ) );

          dtc_axioms.push_back( ax );
          result = enode;
        }
      }
    }
    //
    // If nothing have been done copy and simplify
    //
    if ( result == NULL )
      result = copyEnodeEtypeTermWithCache( enode );

    assert( valDupMap1( enode ) == NULL );
    storeDupMap1( enode, result );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
    {
      // Setting partitions for result
      setIPartitions( result, getIPartitions( enode ) );
      // Setting partitions for negation as well occ if atom
      if ( result->hasSortBool( ) )
      {
        setIPartitions( mkNot( cons( result ) )
                      , getIPartitions( enode ) );
      }
    }
#endif
  }

  Enode * new_formula = valDupMap1( formula );
  assert( new_formula );
  doneDupMap1( );

  if ( !dtc_axioms.empty( ) )
  {
    dtc_axioms.push_back( new_formula );
    new_formula = mkAnd( cons( dtc_axioms ) );
  }

  return new_formula;
}
Esempio n. 9
0
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" );
  }
}
Esempio n. 10
0
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( );
}
Esempio n. 11
0
bool SimpSMTSolver::addClause( vec<Lit> & ps
#ifdef PRODUCE_PROOF
                             , const ipartitions_t & in 
#endif
			     )
{
  //=================================================================================================
  // Added code

  if ( !use_simplification )
#ifdef PRODUCE_PROOF
    return CoreSMTSolver::addClause( ps, in );
#else
    return CoreSMTSolver::addClause( ps );
#endif

  // Added code
  //=================================================================================================

  for (int i = 0; i < ps.size(); i++)
    if (isEliminated(var(ps[i])))
      remember(var(ps[i]));

  int nclauses = clauses.size();

  if (redundancy_check && implied(ps))
    return true;

  //=================================================================================================
  // Added code

  //
  // Hack to consider clauses of size 1 that
  // wouldn't otherwise be considered by
  // MiniSAT
  //
  if ( config.sat_preprocess_theory != 0
      && ps.size( ) == 1   // Consider unit clauses
      && var(ps[0]) >= 2 ) // Don't consider true/false
  {
    Var v = var( ps[0] );
    Enode * e = theory_handler->varToEnode( v );
    if ( e->isTAtom( ) )
    {
      Clause * uc = Clause_new(ps, false);
      unary_to_remove.push_back( uc );
      Clause &c = *(unary_to_remove.back( ));
      Enode * x, * y;
      getDLVars( e, sign(ps[0]), &x, &y );
      assert( x->isVar( ) );
      assert( y->isVar( ) );
      t_pos[ x->getId( ) ].push_back( &c );
      t_neg[ y->getId( ) ].push_back( &c );
      t_var[ x ].insert( y->getId( ) );
      t_var[ y ].insert( x->getId( ) );
    }
  }

  // Added code
  //=================================================================================================

  if (!CoreSMTSolver::addClause(ps))
    return false;

  if (use_simplification && clauses.size() == nclauses + 1)
  {
    Clause& c = *clauses.last();

    subsumption_queue.insert(&c);

    for (int i = 0; i < c.size(); i++)
    {
      assert(occurs.size() > var(c[i]));
      assert(!find(occurs[var(c[i])], &c));

      occurs[var(c[i])].push(&c);
      n_occ[toInt(c[i])]++;
      touched[var(c[i])] = 1;
      assert(elimtable[var(c[i])].order == 0);
      if (elim_heap.inHeap(var(c[i])))
	elim_heap.increase_(var(c[i]));

    }
  }

  return true;
}