示例#1
0
//
// Rewrite formula with maximum arity for operators
//
Enode * Cnfizer::rewriteMaxArity( Enode * formula, map< enodeid_t, int > & enodeid_to_incoming_edges )
{
  assert( formula );

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( formula );    // formula needs to be processed
  map< enodeid_t, Enode * > cache;            // Cache of processed nodes
  //
  // 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 ( cache.find( enode->getId( ) ) != cache.end( ) )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != egraph.enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is an unprocessed boolean operator
      //
      if ( arg->isBooleanOperator( )
        && cache.find( arg->getId( ) ) == cache.end( ) )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
      //
      // If it is an atom (either boolean or theory) just
      // store it in the cache
      //
      else if ( arg->isAtom( ) )
      {
        cache.insert( make_pair( arg->getId( ), arg ) );
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // At this point, every child has been processed
    //
    assert ( enode->isBooleanOperator( ) );

    if ( enode->isAnd( )
      || enode->isOr ( ) )
    {
      assert( enode->isAnd( ) || enode->isOr( ) );
      //
      // Construct the new lists for the operators
      //
      result = mergeEnodeArgs( enode, cache, enodeid_to_incoming_edges );
    }
    else
    {
      result = enode;
    }

    assert( result );
    assert( cache.find( enode->getId( ) ) == cache.end( ) );
    cache[ enode->getId( ) ] = result;
  }

  Enode * top_enode = cache[ formula->getId( ) ];
  return top_enode;
}
示例#2
0
//
// Performs the actual cnfization
//
bool Tseitin::cnfize( Enode * formula, map< enodeid_t, Enode * > & cnf_cache )
{
  (void)cnf_cache;
  assert( formula );
  assert( !formula->isAnd( ) );

  Enode * arg_def = egraph.valDupMap1( formula );
  if ( arg_def != NULL )
  {
    vector< Enode * > clause;
    clause.push_back( arg_def );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
      return solver.addSMTClause( clause, egraph.getIPartitions( formula ) );
#endif
    return solver.addSMTClause( clause );
  }

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( formula );    // formula needs to be processed
  //
  // 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 ( egraph.valDupMap1( enode ) != NULL )
    {
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    Enode * arg_list;
    for ( arg_list = enode->getCdr( ) ;
          arg_list != egraph.enil ;
          arg_list = arg_list->getCdr( ) )
    {
      Enode * arg = arg_list->getCar( );

      assert( arg->isTerm( ) );
      //
      // Push only if it is an unprocessed boolean operator
      //
      if ( enode->isBooleanOperator( )
        && egraph.valDupMap1( arg ) == NULL )
      {
        unprocessed_enodes.push_back( arg );
        unprocessed_children = true;
      }
      //
      // If it is an atom (either boolean or theory) just
      // store it in the cache
      //
      else if ( arg->isAtom( ) )
      {
        egraph.storeDupMap1( arg, arg );
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    Enode * result = NULL;
    //
    // At this point, every child has been processed
    //
    //
    // Do the actual cnfization, according to the node type
    //
    char def_name[ 32 ];

    if ( enode->isLit( ) )
    {
      result = enode;
    }
    else if ( enode->isNot( ) )
    {
      Enode * arg_def = egraph.valDupMap1( enode->get1st( ) );
      assert( arg_def );
      result = egraph.mkNot( egraph.cons( arg_def ) ); // Toggle the literal
    }
    else
    {
      Enode * arg_def = NULL;
      Enode * new_arg_list = egraph.copyEnodeEtypeListWithCache( enode->getCdr( ) );
      //
      // If the enode is not top-level it needs a definition
      //
      if ( formula != enode )
      {
        sprintf( def_name, CNF_STR, formula->getId( ), enode->getId( ) );
        egraph.newSymbol( def_name, sstore.mkBool( ) );
        arg_def = egraph.mkVar( def_name );
#ifdef PRODUCE_PROOF
        if ( config.produce_inter > 0 )
        {
          // Tag Positive and negative literals
          egraph.tagIFormula( arg_def
                            , egraph.getIPartitions( enode ) );
          egraph.tagIFormula( egraph.mkNot( egraph.cons( arg_def ) )
                            , egraph.getIPartitions( enode ) );
        }
#endif
      }
#ifdef PRODUCE_PROOF
      uint64_t partitions = 0;
      if ( config.produce_inter > 0 )
      {
        partitions = egraph.getIPartitions( enode );
        assert( partitions != 0 );
      }
#endif
      //
      // Handle boolean operators
      //
      if ( enode->isAnd( ) )
        cnfizeAnd( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isOr( ) )
        cnfizeOr( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isIff( ) )
        cnfizeIff( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else if ( enode->isXor( ) )
        cnfizeXor( new_arg_list, arg_def
#ifdef PRODUCE_PROOF
        , partitions
#endif
        );
      else
      {
        opensmt_error2( "operator not handled ", enode->getCar( ) );
      }

      if ( arg_def != NULL )
        result = arg_def;
    }

    assert( egraph.valDupMap1( enode ) == NULL );
    egraph.storeDupMap1( enode, result );
  }

  if ( formula->isNot( ) )
  {
    // Retrieve definition of argument
    Enode * arg_def = egraph.valDupMap1( formula->get1st( ) );
    assert( arg_def );
    vector< Enode * > clause;
    clause.push_back( toggleLit( arg_def ) );
#ifdef PRODUCE_PROOF
    if ( config.produce_inter > 0 )
      return solver.addSMTClause( clause, egraph.getIPartitions( formula ) );
#endif
    return solver.addSMTClause( clause );
  }

  return true;
}
示例#3
0
//
// Compute the number of incoming edges for e and children
//
void Cnfizer::computeIncomingEdges( Enode * e
                                  , map< enodeid_t, int > & enodeid_to_incoming_edges )
{
  assert( e );

  vector< Enode * > unprocessed_enodes;       // Stack for unprocessed enodes
  unprocessed_enodes.push_back( e );    // formula needs to be processed
  //
  // 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
    //
    map< enodeid_t, int >::iterator it = enodeid_to_incoming_edges.find( enode->getId( ) );
    if ( it != enodeid_to_incoming_edges.end( ) )
    {
      it->second++;
      unprocessed_enodes.pop_back( );
      continue;
    }

    bool unprocessed_children = false;
    if ( enode->isBooleanOperator( ) )
    {
      for ( Enode * arg_list = enode->getCdr( )
          ; !arg_list->isEnil( )
          ; arg_list = arg_list->getCdr( ) )
      {
        Enode * arg = arg_list->getCar( );
        //
        // Push only if it is an unprocessed boolean operator
        //
        map< enodeid_t, int >::iterator it = enodeid_to_incoming_edges.find( arg->getId( ) );
        if ( it == enodeid_to_incoming_edges.end( ) )
        {
          unprocessed_enodes.push_back( arg );
          unprocessed_children = true;
        }
        else
        {
          it->second ++;
        }
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );
    //
    // At this point, every child has been processed
    //
    assert ( enode->isBooleanOperator( ) || enode->isAtom( ) );
    assert ( enodeid_to_incoming_edges.find( enode->getId( ) ) == enodeid_to_incoming_edges.end( ) );
    enodeid_to_incoming_edges[ enode->getId( ) ] = 1;
  }
}