// ∀a, i, b, j. ( a = b → i = j → W (a, i, R(b, j)) = a ) void Egraph::WoRAxiom( Enode * wor ) { assert( false ); Enode * a = wor->get1st( ); Enode * i = wor->get2nd( ); Enode * worElement = wor->get3rd( ); Enode * b = worElement->get1st( ); Enode * j = worElement->get2nd( ); assert( worElement->isDTypeArrayElement( ) ); assert( a->isDTypeArray( ) ); assert( i->isDTypeArrayIndex( ) ); assert( b->isDTypeArray( ) ); assert( j->isDTypeArrayIndex( ) ); // create term W(a,i,R(b,j)) Enode * select = mkSelect( b, j ); Enode * store = mkStore(a,i,select); // add clause IF a=b THEN IF i=j THEN W(a,i,R(b,j))=a // that is (NOT(a=b) OR NOT(i=j) OR W(a,i,R(b,j))=a) vector< Enode * > v; Enode * lit1 = mkNot(cons(mkEq(cons(a,cons(b))))); Enode * lit2 = mkNot(cons(mkEq(cons(i,cons(j))))); Enode * lit3 = mkEq(cons(store,cons(a))); v.push_back( lit1 ); v.push_back( lit2 ); v.push_back( lit3 ); #ifdef ARR_VERB cout << "Axiom WoR -> " << "(or " << lit1 << " " << lit2 << " " << lit3 << " )" << endl; #endif splitOnDemand( v, id ); handleArrayAssertedAtomTerm( a ); }
//∀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 ); } }
// a != b → R( a, i_{a,b} ) = R( b, i_{a,b} ) void Egraph::ExtAxiom( Enode * a, Enode * b ) { assert( isDynamic( a ) ); assert( isDynamic( b ) ); Enode * as = dynamicToStatic( a ); Enode * bs = dynamicToStatic( b ); assert( isStatic( as ) ); assert( isStatic( bs ) ); assert( as->isDTypeArray( ) ); assert( bs->isDTypeArray( ) ); // create fresh index i_a,b for pair a,b char def_name[ 48 ]; sprintf( def_name, IND_STR, as->getId( ), bs->getId( ) ); const unsigned type = DTYPE_ARRAY_INDEX; if ( lookupSymbol( def_name ) == NULL ) newSymbol( def_name, type ); // Create new variable Enode * i = mkVar( def_name ); // Create two new selections Enode * select1 = mkSelect( as, i ); Enode * select2 = mkSelect( bs, i ); // Create new literals Enode * lit1 = mkEq( cons( as, cons( bs ) ) ); Enode * lit2_pos = mkEq( cons( select1, cons( select2 ) ) ); Enode * lit2 = mkNot( cons( lit2_pos ) ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( as ) & getIPartitions( bs ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) { setIPartitions( i, 1 ); setIPartitions( select1, 1 ); setIPartitions( select2, 1 ); setIPartitions( lit1, 1 ); setIPartitions( lit2_pos, 1 ); setIPartitions( lit2, 1 ); } // Otherwise they share something else { setIPartitions( i, shared ); setIPartitions( select1, shared ); setIPartitions( select2, shared ); setIPartitions( lit1, shared ); setIPartitions( lit2_pos, shared ); setIPartitions( lit2, shared ); } } #endif vector< Enode * > v; v.push_back( lit1 ); v.push_back( lit2 ); #ifdef ARR_VERB cout << "Axiom Ext -> " << "( or " << lit1 << " " << lit2 << " )" << endl; #endif splitOnDemand( v, id ); handleArrayAssertedAtomTerm( select1 ); handleArrayAssertedAtomTerm( select2 ); // New contexts to propagate info about new index // Given R(a,new) look for all store users W(a,i,e) // and instantiate RoW over R(W(a,i,e),new) vector< Enode * > sela; vector< Enode * > stoa; vector< Enode * > selb; vector< Enode * > stob; Enode * select3 = NULL; // Act over a getUsers( a, sela, stoa ); for( size_t j = 0 ; j < stoa.size( ) ; j++ ) { assert( isDynamic( stoa[ j ] ) ); Enode * ss = dynamicToStatic( stoa[ j ] ); assert( isStatic( ss ) ); // Creation new select for each store user of a select3 = mkSelect( ss, i ); // RoW over new select handleArrayAssertedAtomTerm( select3 ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( ss ) & getIPartitions( i ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) setIPartitions( select3, 1 ); // Otherwise they share something else setIPartitions( select3, shared ); } #endif } // Act over b getUsers( b, selb, stob ); for ( size_t j = 0 ; j < stob.size( ) ; j++ ) { assert( isDynamic( stoa[ j ] ) ); Enode * ss = dynamicToStatic( stob[ j ] ); assert( isStatic( ss ) ); // Creation new select for each store user of b select3 = mkSelect( ss, i ); #ifdef PRODUCE_PROOF if ( config.gconfig.print_inter > 0 ) { const uint64_t shared = getIPartitions( ss ) & getIPartitions( i ); // Mixed can't be one at this point assert( shared != 1 ); // Set AB-mixed partition if no intersection if ( shared == 0 ) setIPartitions( select3, 1 ); // Otherwise they share something else setIPartitions( select3, shared ); } #endif // RoW over new select handleArrayAssertedAtomTerm( select3 ); } }