示例#1
0
//
// Subroutine of explain
// A step of explanation for x and y
//
void Egraph::expExplainAlongPath ( Enode * x, Enode * y )
{
    Enode * v  = expHighestNode( x );
    Enode * to = expHighestNode( y );

    while ( v != to )
    {
        Enode * p = v->getExpParent( );
        assert( p != NULL );
        Enode * r = v->getExpReason( );

        // If it is not a congruence edge
        if ( r != NULL )
        {
            if ( !isDup1( r ) )
            {
                assert( r->isTerm( ) );
                explanation.push_back( r );
                storeDup1( r );
            }
        }
        // Otherwise it is a congruence edge
        // This means that the edge is linking nodes
        // like (v)f(a1,...,an) (p)f(b1,...,bn), and that
        // a1,...,an = b1,...bn. For each pair ai,bi
        // we have therefore to compute the reasons
        else
        {
            assert( v->getCar( ) == p->getCar( ) );
            assert( v->getArity( ) == p->getArity( ) );
            expEnqueueArguments( v, p );
        }

#ifdef PRODUCE_PROOF
        if ( config.produce_inter > 0
                && config.logic != QF_AX )
        {
            cgraph.addCNode( v );
            cgraph.addCNode( p );
            cgraph.addCEdge( v, p, r );
        }
#endif

        expUnion( v, p );
        v = expHighestNode( p );
    }
}
示例#2
0
//
// Ackermann related routines
//
void
Egraph::retrieveFunctionApplications( Enode * formula )
{
  assert( formula );
  vector< Enode * > unprocessed_enodes;
  initDup1( );

  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 ( isDup1( enode ) )
    {
      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 ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      
    //
    // At this point, every child has been processed
    //
    if ( enode->isUf( ) || enode->isUp( ) )
    {
      if ( uf_to_appl_cache[ enode->getCar( ) ].insert( enode ).second )
      {
	uf_to_appl[ enode->getCar( ) ].push_back( enode );
	undo_stack_oper.push_back( ACK_APPL );
	undo_stack_term.push_back( enode );
      }
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}
示例#3
0
void Egraph::gatherInterfaceTerms( Enode * e )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );

  if ( config.verbosity > 2 )
    cerr << "# Egraph::Gathering interface terms" << endl;

  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term 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 ( isDup1( enode ) )
    {
      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 ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      
    //
    // At this point, every child has been processed
    //
    if ( enode->isUFOp( ) )
    {
      // Retrieve arguments
      for ( Enode * arg_list = enode->getCdr( ) 
	  ; !arg_list->isEnil( ) 
	  ; arg_list = arg_list->getCdr( ) )
      {
	Enode * arg = arg_list->getCar( );
	// This is for sure an interface term
	if ( ( arg->isArithmeticOp( ) 
	    || arg->isConstant( ) )
	  && interface_terms_cache.insert( arg ).second )
	{
	  if ( config.verbosity > 2 )
	    cerr << "# Egraph::Added interface term: " << arg << endl;
	  // Save info for backtracking
	  undo_stack_oper.push_back( INTERFACE_TERM );
	  undo_stack_term.push_back( arg );
	}
	// We add this variable to the potential
	// interface terms or to interface terms if
	// already seen in LA
	else if ( arg->isVar( ) || arg->isConstant( ) )
	{
	  if ( it_la.find( arg ) == it_la.end( ) )
	  {
	    if ( it_uf.insert( arg ).second )
	    {
	      // Insertion took place, save undo info
	      undo_stack_oper.push_back( INTERFACE_UF );
	      undo_stack_term.push_back( arg );
	    }
	  }
	  else if ( interface_terms_cache.insert( arg ).second )
	  {
	    interface_terms.push_back( arg );
	    if ( config.verbosity > 2 )
	      cerr << "# Egraph::Added interface term: " << arg << endl;
	    // Save info for backtracking
	    undo_stack_oper.push_back( INTERFACE_TERM );
	    undo_stack_term.push_back( arg );
	  }
	}
      }
    }

    if ( enode->isArithmeticOp( ) 
      && !isRootUF( enode ) )
    {
      // Retrieve arguments
      for ( Enode * arg_list = enode->getCdr( ) 
	  ; !arg_list->isEnil( ) 
	  ; arg_list = arg_list->getCdr( ) )
      {
	Enode * arg = arg_list->getCar( );
	// This is for sure an interface term
	if ( arg->isUFOp( ) 
	  && !arg->isUp( )
	  && interface_terms_cache.insert( arg ).second )
	{
	  interface_terms.push_back( arg );
	  if ( config.verbosity > 2 )
	    cerr << "# Egraph::Added interface term: " << arg << endl;
	  // Save info for backtracking
	  undo_stack_oper.push_back( INTERFACE_TERM );
	  undo_stack_term.push_back( arg );
	}
	// We add this variable to the potential
	// interface terms or to interface terms if
	// already seen in UF
	else if ( arg->isVar( ) || arg->isConstant( ) )
	{
	  if ( it_uf.find( arg ) == it_uf.end( ) )
	  {
	    if ( it_la.insert( arg ).second )
	    {
	      // Insertion took place, save undo info
	      undo_stack_oper.push_back( INTERFACE_LA );
	      undo_stack_term.push_back( arg );
	    }
	  }
	  else if ( interface_terms_cache.insert( arg ).second )
	  {
	    interface_terms.push_back( arg );
	    if ( config.verbosity > 2 )
	      cerr << "# Egraph::Added interface term: " << arg << endl;
	    // Save info for backtracking
	    undo_stack_oper.push_back( INTERFACE_TERM );
	    undo_stack_term.push_back( arg );
	  }
	}
      }
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}
示例#4
0
bool Egraph::isPureUF( Enode * e )
{
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );
  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term 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 ( isDup1( enode ) )
    {
      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 ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      

    //
    // At this point, every child has been processed
    //
    if ( enode->isArithmeticOp( ) )
    {
      doneDup1( );
      return false;
    }

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
  return true;
}
示例#5
0
void Egraph::getInterfaceVars( Enode * e, set< Enode * > & iv )
{
  assert( config.produce_inter != 0 );
  assert( config.sat_lazy_dtc != 0 );
  assert( config.logic == QF_UFIDL
       || config.logic == QF_UFLRA );

  assert( e );

  vector< Enode * > unprocessed_enodes;
  initDup1( );

  unprocessed_enodes.push_back( e );
  //
  // Visit the DAG of the term 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 ( isDup1( enode ) )
    {
      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 ( !isDup1( arg ) )
      {
	unprocessed_enodes.push_back( arg );
	unprocessed_children = true;
      }
    }
    //
    // SKip if unprocessed_children
    //
    if ( unprocessed_children )
      continue;

    unprocessed_enodes.pop_back( );                      

    if ( enode->isVar( )
      && interface_terms_cache.find( enode ) != interface_terms_cache.end( ) )
      iv.insert( enode );

    assert( !isDup1( enode ) );
    storeDup1( enode );
  }

  doneDup1( );
}