//∀a, i, e, j, f i != j → W (W (a, i, e), j, f ) = W (W (a, j, f ), i, e) void Egraph::WoWNeqAxiom( Enode * wow ) { assert( false ); Enode * wowArray = wow->get1st( ); Enode * a = wowArray->get1st( ); Enode * i = wowArray->get2nd( ); Enode * e = wowArray->get3rd( ); Enode * j = wow->get2nd( ); Enode * f = wow->get3rd( ); assert( wowArray->isDTypeArray( ) ); assert( a->isDTypeArray( ) ); assert( i->isDTypeArrayIndex( ) ); assert( e->isDTypeArrayElement( ) ); assert( j->isDTypeArrayIndex( ) ); assert( f->isDTypeArrayElement( ) ); // Case i, j not coincident if( i != j ) { // create term W(W(a,j,f),i,e) Enode * store1 = mkStore(a,j,f); Enode * store2 = mkStore(store1,i,e); // add clause IF i!=j THEN W(W(a,i,e),j,f)=W(W(a,j,f),i,e) // that is (i=j OR W(W(a,i,e),j,f)=W(W(a,j,f),i,e)) vector< Enode * > v; Enode * lit1 = mkEq(cons(i,cons(j))); Enode * lit2 = mkEq(cons(wow,cons(store2))); v.push_back( lit1 ); v.push_back( lit2 ); #ifdef ARR_VERB cout << "Axiom WoW!= -> " << "(or " << lit1 << " " << lit2 << " )" << endl; #endif splitOnDemand( v, id ); handleArrayAssertedAtomTerm(store2); } }
// ∀a, i, e, j, f. ( i = j → W ( W ( a, i, e ), j, f ) = W ( a, j, f ) ) void Egraph::WoWEqAxiom( Enode * wow ) { assert( false ); Enode * wowArray = wow->get1st( ); Enode * a = wowArray->get1st( ); Enode * i = wowArray->get2nd( ); Enode * e = wowArray->get3rd( ); Enode * j = wow->get2nd( ); Enode * f = wow->get3rd( ); assert( wowArray->isDTypeArray( ) ); assert( a->isDTypeArray( ) ); assert( i->isDTypeArrayIndex( ) ); assert( e->isDTypeArrayElement( ) ); assert( j->isDTypeArrayIndex( ) ); assert( f->isDTypeArrayElement( ) ); //i,j not coincident if( i != j ) { // create term W(a,j,f) Enode * store = mkStore( a, j, f ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( a ) & getIPartitions( j ) & getIPartitions( f ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) setIPartitions( store, 1 ); // Otherwise they share something else setIPartitions( store, shared ); } #endif // add clause IF i=j THEN W(W(a,i,e),j,f)=W(a,j,f) // that is (NOT(i=j) OR W(W(a,i,e),j,f)=W(a,j,f)) vector< Enode * > v; Enode * lit1_pos = mkEq( cons( i, cons( j ) ) ); Enode * lit1 = mkNot( cons( lit1_pos ) ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( i ) & getIPartitions( j ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) { setIPartitions( lit1_pos, 1 ); setIPartitions( lit1, 1 ); } // Otherwise they share something else { setIPartitions( lit1_pos, shared ); setIPartitions( lit1, shared ); } } #endif Enode * lit2 = mkEq( cons( wow, cons( store ) ) ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( wow ) & getIPartitions( store ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) setIPartitions( lit2, 1 ); // Otherwise they share something else setIPartitions( lit2, shared ); } #endif v.push_back( lit1 ); v.push_back( lit2 ); #ifdef ARR_VERB cout << "Axiom WoW= -> " << "(or " << lit1 << " " << lit2 << " )" << endl; #endif splitOnDemand( v, id ); handleArrayAssertedAtomTerm( store ); } }
Enode * ExpandITEs::doit( Enode * formula ) { assert( formula ); list< Enode * > new_clauses; vector< Enode * > unprocessed_enodes; egraph.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 ( 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 unprocessed // if ( egraph.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; // // At this point, every child has been processed // char def_name[ 32 ]; if ( enode->isIte( ) ) { // // Retrieve arguments // Enode * i = egraph.valDupMap1( enode->get1st( ) ); Enode * t = egraph.valDupMap1( enode->get2nd( ) ); Enode * e = egraph.valDupMap1( enode->get3rd( ) ); Enode * not_i = egraph.mkNot( egraph.cons( i ) ); // // Generate variable symbol // sprintf( def_name, ITE_STR, enode->getId( ) ); Snode * sort = enode->getLastSort( ); egraph.newSymbol( def_name, sort ); // // Generate placeholder // result = egraph.mkVar( def_name ); // // Generate additional clauses // Enode * eq_then = egraph.mkEq( egraph.cons( result , egraph.cons( t ) ) ); Enode * eq_else = egraph.mkEq( egraph.cons( result , egraph.cons( e ) ) ); new_clauses.push_back( egraph.mkOr( egraph.cons( not_i , egraph.cons( eq_then ) ) ) ); new_clauses.push_back( egraph.mkOr( egraph.cons( i , egraph.cons( eq_else ) ) ) ); } else { result = egraph.copyEnodeEtypeTermWithCache( enode ); } assert( result ); assert( egraph.valDupMap1( enode ) == NULL ); egraph.storeDupMap1( enode, result ); } Enode * new_formula = egraph.valDupMap1( formula ); assert( new_formula ); egraph.doneDupMap1( ); new_clauses.push_back( new_formula ); return egraph.mkAnd( egraph.cons( new_clauses ) ); }