@ -8,23 +8,30 @@ 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					namespace  storm  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    namespace  storage  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        static  in t  globalId  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        static  std : : size_ t  globalId  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        BisimulationDecomposition2 < ValueType > : : Block : : Block ( storm : : storage : : sparse : : state_type  begin ,  storm : : storage : : sparse : : state_type  end ,  Block *  prev ,  Block *  next )  :  originalBegin ( begin ) ,  begin ( begin ) ,  end ( end ) ,  prev ( prev ) ,  next ( next ) ,  numberOfStates ( end  -  begin ) ,  isMarked ( false ) ,  myId ( globalId + + )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Intentionally left empty.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " created new block from  "  < <  begin  < <  "  to  "  < <  end  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        BisimulationDecomposition2 < ValueType > : : Block : : Block ( storm : : storage : : sparse : : state_type  begin ,  storm : : storage : : sparse : : state_type  end ,  Block *  prev ,  Block *  next )  :  next ( next ) ,  prev ( prev ) ,  begin ( begin ) ,  end ( end ) ,  markedAsSplitter ( false ) ,  markedPosition ( begin ) ,  id ( globalId + + )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( next  ! =  nullptr )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                next - > prev  =  this ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( prev  ! =  nullptr )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                prev - > next  =  this ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : print ( Partition  const &  partition )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " block  "  < <  this - > myId  < <  "  and ptr  "  < <  this  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " begin:  "  < <  this - > begin  < <  "  and end:  "  < <  this - > end  < <  "  (number of states:  "  < <  this - > numberOfStates  < <  " ) "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " next:  "  < <  this - > next  < <  "  and prev  "  < <  this - > prev  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " block  "  < <  this - > getId ( )  < <  "  with marked position  "  < <  this - > getMarkedPosition ( )  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " begin:  "  < <  this - > begin  < <  "  and end:  "  < <  this - > end  < <  "  (number of states:  "  < <  this - > getNumberOfStates ( )  < <  " ) "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " states: "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( storm : : storage : : sparse : : state_type  index  =  this - > begin ;  index  <  this - > end ;  + + index )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  partition . states [ index ]  < <  "   " ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  std : : endl  < <  " original:  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( storm : : storage : : sparse : : state_type  index  =  this - > getOriginalBegin ( ) ;  index  <  this - > end ;  + + index )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  partition . states [ index ]  < <  "   " ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  std : : endl  < <  " values: "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( storm : : storage : : sparse : : state_type  index  =  this - > begin ;  index  <  this - > end ;  + + index )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  std : : setprecision ( 3 )  < <  partition . values [ index ]  < <  "   " ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -35,13 +42,187 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : setBegin ( storm : : storage : : sparse : : state_type  begin )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > begin  =  begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > originalBegin  =  begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedPosition  =  begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : setEnd ( storm : : storage : : sparse : : state_type  end )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > end  =  end ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : incrementBegin ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            + + this - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " incremented begin to  "  < <  this - > begin  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : decrementEnd ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            + + this - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  BisimulationDecomposition2 < ValueType > : : Block : : getBegin ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  BisimulationDecomposition2 < ValueType > : : Block : : getOriginalBegin ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( this - > hasPreviousBlock ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                return  this - > getPreviousBlock ( ) . getEnd ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                return  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  BisimulationDecomposition2 < ValueType > : : Block : : getEnd ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > end ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : setIterator ( const_iterator  it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > selfIt  =  it ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block : : const_iterator  BisimulationDecomposition2 < ValueType > : : Block : : getIterator ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > selfIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block : : const_iterator  BisimulationDecomposition2 < ValueType > : : Block : : getNextIterator ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > getNextBlock ( ) . getIterator ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block : : const_iterator  BisimulationDecomposition2 < ValueType > : : Block : : getPreviousIterator ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > getPreviousBlock ( ) . getIterator ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block &  BisimulationDecomposition2 < ValueType > : : Block : : getNextBlock ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * this - > next ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block  const &  BisimulationDecomposition2 < ValueType > : : Block : : getNextBlock ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * this - > next ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Block : : hasNextBlock ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > next  ! =  nullptr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block &  BisimulationDecomposition2 < ValueType > : : Block : : getPreviousBlock ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * this - > prev ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block *  BisimulationDecomposition2 < ValueType > : : Block : : getPreviousBlockPointer ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > prev ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block *  BisimulationDecomposition2 < ValueType > : : Block : : getNextBlockPointer ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > next ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block  const &  BisimulationDecomposition2 < ValueType > : : Block : : getPreviousBlock ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * this - > prev ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Block : : hasPreviousBlock ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > prev  ! =  nullptr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Block : : check ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( this - > begin  > =  this - > end )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " beg:  "  < <  this - > begin  < <  "  and end  "  < <  this - > end  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                assert ( false ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( this - > prev  ! =  nullptr )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                assert  ( this - > prev - > next  = =  this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( this - > next  ! =  nullptr )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                assert  ( this - > next - > prev  = =  this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : Block : : getNumberOfStates ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // We need to take the original begin here, because the begin is temporarily moved.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  ( this - > end  -  this - > getOriginalBegin ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Block : : isMarkedAsSplitter ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > markedAsSplitter ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : markAsSplitter ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedAsSplitter  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : unmarkAsSplitter ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedAsSplitter  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : Block : : getId ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > id ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  BisimulationDecomposition2 < ValueType > : : Block : : getMarkedPosition ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > markedPosition ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : setMarkedPosition ( storm : : storage : : sparse : : state_type  position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedPosition  =  position ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : resetMarkedPosition ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedPosition  =  this - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : incrementMarkedPosition ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            + + this - > markedPosition ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : markAsPredecessorBlock ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedAsPredecessorBlock  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Block : : unmarkAsPredecessorBlock ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > markedAsPredecessorBlock  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Block : : isMarkedAsPredecessor ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  markedAsPredecessorBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        BisimulationDecomposition2 < ValueType > : : Partition : : Partition ( std : : size_t  numberOfStates )  :  stateToBlockMapping ( numberOfStates ) ,  states ( numberOfStates ) ,  positions ( numberOfStates ) ,  values ( numberOfStates )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Create the block and give it an iterator to itself.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            typename  std : : list < Block > : : iterator  it  =  blocks . emplace ( this - > blocks . end ( ) ,  0 ,  numberOfStates ,  nullptr ,  nullptr ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            it - > itToSelf  =  it ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            it - > setIterator ( it ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Set up the different parts of the internal structure.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( storm : : storage : : sparse : : state_type  state  =  0 ;  state  <  numberOfStates ;  + + state )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                states [ state ]  =  state ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                positions [ state ]  =  state ;  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -49,45 +230,231 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : swapStates ( storm : : storage : : sparse : : state_type  state1 ,  storm : : storage : : sparse : : state_type  state2 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " swapping states  "  < <  state1  < <  "  and  "  < <  state2  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : swap ( this - > states [ this - > positions [ state1 ] ] ,  this - > states [ this - > positions [ state2 ] ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : swap ( this - > values [ this - > positions [ state1 ] ] ,  this - > values [ this - > positions [ state2 ] ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : swap ( this - > positions [ state1 ] ,  this - > positions [ state2 ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( this - > check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : swapStatesAtPositions ( storm : : storage : : sparse : : state_type  position1 ,  storm : : storage : : sparse : : state_type  position2 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  state1  =  this - > states [ position1 ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  state2  =  this - > states [ position2 ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " swapping states  "  < <  state1  < <  "  and  "  < <  state2  < <  "  at positions  "  < <  position1  < <  "  and  "  < <  position2  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : swap ( this - > states [ position1 ] ,  this - > states [ position2 ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : swap ( this - > values [ position1 ] ,  this - > values [ position2 ] ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > positions [ state1 ]  =  position2 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > positions [ state2 ]  =  position1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " pos of  "  < <  state1  < <  "  is now  "  < <  position2  < <  "  and pos of  "  < <  state2  < <  "  is now  "  < <  position1  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  this - > states [ position1 ]  < <  "  vs  "  < <  state2  < <  "  and  "  < <  this - > states [ position2 ]  < <  "  vs  "  < <  state1  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( this - > check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  const &  BisimulationDecomposition2 < ValueType > : : Partition : : getPosition ( storm : : storage : : sparse : : state_type  state )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > positions [ state ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : setPosition ( storm : : storage : : sparse : : state_type  state ,  storm : : storage : : sparse : : state_type  position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > positions [ state ]  =  position ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        storm : : storage : : sparse : : state_type  const &  BisimulationDecomposition2 < ValueType > : : Partition : : getState ( storm : : storage : : sparse : : state_type  position )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states [ position ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        ValueType  const &  BisimulationDecomposition2 < ValueType > : : Partition : : getValue ( storm : : storage : : sparse : : state_type  state )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > values [ this - > positions [ state ] ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        ValueType  const &  BisimulationDecomposition2 < ValueType > : : Partition : : getValueAtPosition ( storm : : storage : : sparse : : state_type  position )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > values [ position ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : setValue ( storm : : storage : : sparse : : state_type  state ,  ValueType  value )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > values [ this - > positions [ state ] ]  =  value ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < ValueType > &  BisimulationDecomposition2 < ValueType > : : Partition : : getValues ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > values ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : increaseValue ( storm : : storage : : sparse : : state_type  state ,  ValueType  value )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            this - > values [ this - > positions [ state ] ]  + =  value ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : updateBlockMapping ( Block &  block ,  std : : vector < storm : : storage : : sparse : : state_type > : : iterator  first ,  std : : vector < storm : : storage : : sparse : : state_type > : : iterator  last )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( ;  first  ! =  last ;  + + first )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                this - > stateToBlockMapping [ * first ]  =  & block ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block &  BisimulationDecomposition2 < ValueType > : : Partition : : getBlock ( storm : : storage : : sparse : : state_type  state )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * this - > stateToBlockMapping [ state ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < storm : : storage : : sparse : : state_type > : : iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getBeginOfStates ( Block  const &  block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states . begin ( )  +  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < storm : : storage : : sparse : : state_type > : : iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getEndOfStates ( Block  const &  block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states . begin ( )  +  block . getEnd ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < storm : : storage : : sparse : : state_type > : : const_iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getBeginOfStates ( Block  const &  block )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states . begin ( )  +  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < storm : : storage : : sparse : : state_type > : : const_iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getEndOfStates ( Block  const &  block )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states . begin ( )  +  block . getEnd ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  std : : vector < ValueType > : : iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getBeginOfValues ( Block  const &  block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > values . begin ( )  +  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  std : : vector < ValueType > : : iterator  BisimulationDecomposition2 < ValueType > : : Partition : : getEndOfValues ( Block  const &  block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > values . begin ( )  +  block . getEnd ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block &  BisimulationDecomposition2 < ValueType > : : Partition : : splitBlock ( Block &  block ,  storm : : storage : : sparse : : state_type  position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // FIXME: this could be improved by splitting off the smaller of the two resulting blocks.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " splitting block ( "  < <  block . getBegin ( )  < <  " , "  < <  block . getEnd ( )  < <  " ) at position  "  < <  position  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            block . print ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // In case one of the resulting blocks would be empty, we simply return the current block and do not create
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // a new one.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( position  = =  block . getBegin ( )  | |  position  = =  block . getEnd ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                return  block ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Actually create the new block and insert it at the correct position.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            typename  std : : list < Block > : : iterator  selfIt  =  this - > blocks . emplace ( block . getIterator ( ) ,  block . getBegin ( ) ,  position ,  block . getPreviousBlockPointer ( ) ,  & block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " created new block from  "  < <  block . getBegin ( )  < <  "  to  "  < <  position  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            selfIt - > setIterator ( selfIt ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            Block &  newBlock  =  * selfIt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Make the current block end at the given position.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            block . setBegin ( position ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " old block:  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            block . print ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Update the mapping of the states in the newly created block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  it  =  this - > getBeginOfStates ( newBlock ) ,  ite  =  this - > getEndOfStates ( newBlock ) ;  it  ! =  ite ;  + + it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                stateToBlockMapping [ * it ]  =  & newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        typename  BisimulationDecomposition2 < ValueType > : : Block &  BisimulationDecomposition2 < ValueType > : : Partition : : insertBlock ( Block &  block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Find the beginning of the new block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( block . hasPreviousBlock ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                begin  =  block . getPreviousBlock ( ) . getEnd ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " previous block ended at  "  < <  begin  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block . getPreviousBlock ( ) . print ( * this ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                begin  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Actually insert the new block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            typename  std : : list < Block > : : iterator  it  =  this - > blocks . emplace ( block . getIterator ( ) ,  begin ,  block . getBegin ( ) ,  block . getPreviousBlockPointer ( ) ,  & block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            Block &  newBlock  =  * it ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            newBlock . setIterator ( it ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Update the mapping of the states in the newly created block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  it  =  this - > getBeginOfStates ( newBlock ) ,  ite  =  this - > getEndOfStates ( newBlock ) ;  it  ! =  ite ;  + + it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                stateToBlockMapping [ * it ]  =  & newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  * it ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        void  BisimulationDecomposition2 < ValueType > : : Partition : : splitLabel ( storm : : storage : : BitVector  const &  statesWithLabel )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  blockIterator  =  this - > blocks . begin ( ) ,  ite  =  this - > blocks . end ( ) ;  blockIterator  ! =  ite ;  )  {  // The update of the loop was intentionally moved to the bottom of the loop.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                Block &  block  =  * blockIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Sort the range of the block such that all states that have the label are moved to the front.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : sort ( this - > states . begin ( )  +  block . begin ,  this - > states . begin ( )  +  block . end ,  [ & statesWithLabel ]  ( storm : : storage : : sparse : : state_type  const &  a ,  storm : : storage : : sparse : : state_type  const &  b )  {  return  statesWithLabel . get ( a )  & &  ! statesWithLabel . get ( b ) ;  }  ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : sort ( this - > getBeginOfStates ( block ) ,  this - > getEndOfStates ( block ) ,  [ & statesWithLabel ]  ( storm : : storage : : sparse : : state_type  const &  a ,  storm : : storage : : sparse : : state_type  const &  b )  {  return  statesWithLabel . get ( a )  & &  ! statesWithLabel . get ( b ) ;  }  ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Update the positions vector.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : state_type  position  =  block . begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  stateIt  =  this - > states . begin ( )  +  block . begin ,  stateIte  =  this - > states . begin ( )  +  block . end ;  stateIt  ! =  stateIte ;  + + stateIt ,  + + position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : state_type  position  =  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  stateIt  =  this - > getBeginOfStates ( block ) ,  stateIte  =  this - > getEndOfStates ( block ) ;  stateIt  ! =  stateIte ;  + + stateIt ,  + + position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    this - > positions [ * stateIt ]  =  position ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Now we can find the first position in the block that does not have the label and create new blocks.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : vector < storm : : storage : : sparse : : state_type > : : iterator  it  =  std : : find_if ( this - > states . begin ( )  +  block . begin ,  this - > states . begin ( )  +  block . end ,  [ & ]  ( storm : : storage : : sparse : : state_type  const &  a )  {  return  ! statesWithLabel . get ( a ) ;  } ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : vector < storm : : storage : : sparse : : state_type > : : iterator  it  =  std : : find_if ( this - > getBeginOfStates ( block ) ,  this - > getEndOfStates ( block ) ,  [ & ]  ( storm : : storage : : sparse : : state_type  const &  a )  {  return  ! statesWithLabel . get ( a ) ;  } ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // If not all the states agreed on the validity of the label, we need to split the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( it  ! =  this - > states . begin ( )  +  block . begin  & &  it  ! =  this - > states . begin ( )  +  block . end )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( it  ! =  this - > getBeginOfStates ( block )   & &  it  ! =  this - > getEndOfStates ( block ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  cutPoint  =  std : : distance ( this - > states . begin ( ) ,  it ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    this - > splitBlock ( block ,  cutPoint ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Otherwise, we simply proceed to the next block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + blockIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    auto  newBlockIterator  =  this - > blocks . emplace ( blockIterator ,  cutPoint ,  block . end ,  & block ,  block . next ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    newBlockIterator - > itToSelf  =  newBlockIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : list < typename  BisimulationDecomposition2 < ValueType > : : Block >  const &  BisimulationDecomposition2 < ValueType > : : Partition : : getBlocks ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > blocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Make the old block end at the cut position and insert a new block after it.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block . end  =  cutPoint ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block . next  =  & ( * newBlockIterator ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block . numberOfStates  =  block . end  -  block . begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : vector < storm : : storage : : sparse : : state_type > &  BisimulationDecomposition2 < ValueType > : : Partition : : getStates ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > states ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Update the block mapping for all states that we just removed from the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto  it  =  this - > states . begin ( )  +  newBlockIterator - > begin ,  ite  =  this - > states . begin ( )  +  newBlockIterator - > end ;  it  ! =  ite ;  + + it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        stateToBlockMapping [ * it ]  =  & ( * newBlockIterator ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : list < typename  BisimulationDecomposition2 < ValueType > : : Block > &  BisimulationDecomposition2 < ValueType > : : Partition : : getBlocks ( )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  this - > blocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Otherwise, we simply proceed to the next block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + blockIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        bool  BisimulationDecomposition2 < ValueType > : : Partition : : check ( )  const  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( uint_fast64_t  state  =  0 ;  state  <  this - > positions . size ( ) ;  + + state )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( this - > states [ this - > positions [ state ] ]  ! =  state )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    assert ( false ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  const &  block  :  this - > blocks )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                assert ( block . check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  stateIt  =  this - > getBeginOfStates ( block ) ,  stateIte  =  this - > getEndOfStates ( block ) ;  stateIt  ! =  stateIte ;  + + stateIt )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( this - > stateToBlockMapping [ * stateIt ]  ! =  & block )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : cout  < <  " state  "  < <  * stateIt  < <  "  has wrong block mapping  "  < <  this - > stateToBlockMapping [ * stateIt ]  < <  "  (should have  "  < <  & block  < <  " ) "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        assert ( false ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -109,6 +476,7 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " size:  "  < <  this - > blocks . size ( )  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( this - > check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				
					@ -142,10 +510,11 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " initial partition: "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            partition . print ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( partition . check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Initially, all blocks are potential splitter, so we insert them in the splitterQueue.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : deque < Block * >  splitterQueue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : for_each ( partition . blocks . begin ( ) ,  partition . blocks . end ( ) ,  [ & ]  ( Block &  a )  {  splitterQueue . push_back ( & a ) ;  } ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : for_each ( partition . getBlocks ( ) . begin ( ) ,  partition . getBlocks ( ) . end ( ) ,  [ & ]  ( Block &  a )  {  splitterQueue . push_back ( & a ) ;  } ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : SparseMatrix < ValueType >  backwardTransitions  =  dtmc . getBackwardTransitions ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
	
		
			
				
					
						
						
						
							
								 
							 
						
					 
				
				 
				
					@ -166,318 +535,213 @@ namespace storm { 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : splitBlockProbabilities ( Block *   block ,  Partition &  partition ,  std : : deque < Block * > &  splitterQueue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : splitBlockProbabilities ( Block &   block ,  Partition &  partition ,  std : : deque < Block * > &  splitterQueue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " part before split prob "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            partition . print ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            Block &  currentBlock  =  * block ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Sort the states in the block based on their probabilities.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : sort ( partition . states . begin ( )  +  currentBlock . begin ,  partition . states . begin ( )  +  currentBlock . end ,  [ & partition ]  ( storm : : storage : : sparse : : state_type  const &  a ,  storm : : storage : : sparse : : state_type  const &  b )  {  return  partition . values [ a ]   <  partition . values [ b ] ;  }  ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : sort ( partition . getBeginOfStates ( block ) ,  partition . getEndOfStates ( block ) ,  [ & partition ]  ( storm : : storage : : sparse : : state_type  const &  a ,  storm : : storage : : sparse : : state_type  const &  b )  {  return  partition . getValue ( a )  <  partition . getValue ( b ) ;  }  ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // FIXME: This can probably be done more efficiently.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : sort ( partition . values . begin ( )  +  currentBlock . begin ,  partition . values . begin ( )  +  currentBlock . end ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : sort ( partition . getBeginOfValues ( block ) ,  partition . getEndOfValues ( block ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Update the positions vector.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  position  =  currentBlock . begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  stateIt  =  partition . states . begin ( )  +  currentBlock . begin ,  stateIte  =  partition . states . begin ( )  +  currentBlock . end ;  stateIt  ! =  stateIte ;  + + stateIt ,  + + position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                partition . positions [ * stateIt ]  =  position ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  position  =  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  stateIt  =  partition . getBeginOfStates ( block ) ,  stateIte  =  partition . getEndOfStates ( block ) ;  stateIt  ! =  stateIte ;  + + stateIt ,  + + position )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                partition . setPosition ( * stateIt ,  position ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Finally, we need to scan the ranges of states that agree on the probability.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  beginIndex  =  currentBlock . begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  beginIndex  =  block . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  currentIndex  =  beginIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  endIndex  =  currentB lock. end ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  endIndex  =  b lock. g etE nd( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now we can check whether the block needs to be split, which is the case iff the probabilities for the
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // first and the last state are different.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Note that this check requires the block to be non-empty.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( std : : abs ( partition . values [ beginIndex ]  -  partition . values [ endIndex  -  1 ] )  <  1e-6 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                return  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : size_t  createdBlocks  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            while  ( std : : abs ( partition . getValueAtPosition ( beginIndex )  -  partition . getValueAtPosition ( endIndex ) )  > =  1e-6 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Now we scan for the first state in the block that disagrees on the probability value.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Note that we do not have to check currentIndex for staying within bounds, because we know the matching
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // state is within bounds.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            ValueType  currentValue  =  partition . values [ beginIndex ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            ValueType *  valueIterator  =  & ( partition . values [ beginIndex ] )  +  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            + + currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            while  ( std : : abs ( * valueIterator  -  currentValue )  <  1e-6 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " prob:  "  < <  * valueIterator  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + valueIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now resize the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " resizing block from  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            currentBlock . print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            currentBlock . end  =  currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            currentBlock . numberOfStates  =  currentBlock . end  -  currentBlock . begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  "  to  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            currentBlock . print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            beginIndex  =  currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // If it is not already a splitter, we mark it as such.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            if  ( ! currentBlock . isMarked )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                currentBlock . isMarked  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            Block *  prevBlock  =  & currentBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now scan for new blocks.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : list < Block * >  createdBlocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  currentIndex  < <  "  <  "  < <  endIndex  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            typename  std : : list < Block > : : const_iterator  insertPosition  =  currentBlock . itToSelf ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            + + insertPosition ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            while  ( currentIndex  <  endIndex )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ValueType  currentValue  =  * ( partition . values . begin ( )  +  currentIndex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ValueType  const &  currentValue  =  partition . getValueAtPosition ( beginIndex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                typename  std : : vector < ValueType > : : const_iterator  valueIterator  =  partition . getValues ( ) . begin ( )  +  beginIndex  +  1 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                ValueType *  nextValuePtr  =  & currentValue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                while  ( currentIndex  <  endIndex  & &  std : : abs ( currentValue  -  * nextValuePtr )  <  1e-6 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                while  ( currentIndex  <  endIndex  & &  std : : abs ( * valueIterator  -  currentValue )  < =  1e-6 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + valueIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    + + nextValuePtr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Create a new block from the states that agree on the values.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + insertPosition ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                typename  std : : list < Block > : : iterator  newBlockIterator  =  partition . blocks . emplace ( insertPosition ,  beginIndex ,  currentIndex ,  prevBlock ,  prevBlock - > next ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                newBlockIterator - > itToSelf  =  newBlockIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                Block *  newBlock  =  & ( * newBlockIterator ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                prevBlock - > next  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                prevBlock  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( prevBlock - > numberOfStates  >  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    createdBlocks . emplace_back ( prevBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Now we split the block and mark it as a potential splitter.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                + + createdBlocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                Block &  newBlock  =  partition . splitBlock ( block ,  currentIndex ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( ! newBlock . isMarkedAsPredecessor ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    newBlock . markAsSplitter ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    splitterQueue . push_back ( & newBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                beginIndex  =  currentIndex ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Update the block mapping for the moved states.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  it  =  partition . states . begin ( )  +  newBlock - > begin ,  ite  =  partition . states . begin ( )  +  newBlock - > end ;  it  ! =  ite ;  + + it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    partition . stateToBlockMapping [ * it ]  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  block  :  createdBlocks )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                splitterQueue . push_back ( block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block - > isMarked  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " created  "  < <  createdBlocks . size ( )  < <  "  blocks "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( partition . check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  createdBlocks . size ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  createdBlocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template < typename  ValueType >  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : splitPartition ( storm : : storage : : SparseMatrix < ValueType >  const &  backwardTransitions ,  Block  const &  splitter ,  Partition &  partition ,  std : : deque < Block * > &  splitterQueue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " getting block  "  < <  splitter . myId  < <  "  as splitter "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        std : : size_t  BisimulationDecomposition2 < ValueType > : : splitPartition ( storm : : storage : : SparseMatrix < ValueType >  const &  backwardTransitions ,  Block &  splitter ,  Partition &  partition ,  std : : deque < Block * > &  splitterQueue )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " treating block  "  < <  splitter . getId ( )  < <  "  as splitter "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            splitter . print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : list < Block * >  predecessorBlocks ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Iterate over all states of the splitter and check its predecessors.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  stateIterator  =  partition . states . begin ( )  +  splitter . begin ,  stateIte  =  partition . states . begin ( )  +  splitter . end ;  stateIterator  ! =  stateIte ;  + + stateIterator )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : state_type &  state  =  * stateIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            storm : : storage : : sparse : : state_type  currentPosition  =  splitter . getBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  stateIterator  =  partition . getBeginOfStates ( splitter ) ,  stateIte  =  partition . getEndOfStates ( splitter ) ;  stateIterator  ! =  stateIte ;  + + stateIterator ,  + + currentPosition )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " states ----- "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  stateIterator  =  partition . getStates ( ) . begin ( )  +  splitter . getOriginalBegin ( ) ,  stateIte  =  partition . getStates ( ) . begin ( )  +  splitter . getEnd ( ) ;  stateIterator  ! =  stateIte ;  + + stateIterator )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  * stateIterator  < <  "   " ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : state_type  currentState  =  * stateIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " current state  "  < <  currentState  < <  "  at pos  "  < <  currentPosition  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  predecessorEntry  :  backwardTransitions . getRow ( state ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                uint_fast64_t  elementsToSkip  =  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  predecessorEntry  :  backwardTransitions . getRow ( currentState ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  predecessor  =  predecessorEntry . getColumn ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " found predecessor  "  < <  predecessor  < <  "  of state  "  < <  * stateIterator  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    Block *  predecessorBlock  =  partition . stateToBlockMapping [ predecessor ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " predecessor block  "  < <  predecessorBlock - > myId  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " found predecessor  "  < <  predecessor  < <  "  of state  "  < <  currentState  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    Block &  predecessorBlock  =  partition . getBlock ( predecessor ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " predecessor block  "  < <  predecessorBlock . getId ( )  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // If the predecessor block has just one state, there is no point in splitting it.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( predecessorBlock - > numberOfStates   < =  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( predecessorBlock . getNumberOfStates ( )   < =  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        continue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  predecessorPosition  =  partition . positions [ predecessor ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  predecessorPosition  =  partition . getPosition ( predecessor ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // If we have not seen this predecessor before, we move it to a part near the beginning of the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " predecessor position:  "  < <  predecessorPosition  < <  "  and begin  "  < <  predecessorBlock - > begin  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( predecessorPosition  > =  predecessorBlock - > begin )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        We cannot directly move the states at this point, otherwise we would consider states multiple
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        times while others are skipped.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        std::swap(partition.states[predecessorPosition], partition.states[predecessorBlock->begin]);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        std::cout << "swapping positions of " << predecessor << " and " << partition.states[predecessorPosition] << std::endl;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Instead, we only virtually move the states by setting their positions and move them in place
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // later.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        storm : : storage : : sparse : : state_type  tmp  =  partition . positions [ predecessor ] ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . positions [ predecessor ]  =  predecessorBlock - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : cout  < <  " moved  "  < <  predecessor  < <  "  to pos  "  < <  predecessorBlock - > begin  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . positions [ partition . states [ predecessorBlock - > begin ] ]  =  tmp ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        storm::storage::sparse::state_type tmp = partition.positions[partition.states[predecessorPosition]];
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        partition.positions[partition.states[predecessorPosition]] = partition.positions[predecessor];
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        partition.positions[predecessor] = tmp;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        std::swap(partition.positions[predecessor], partition.positions[predecessorBlock->begin]);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        + + predecessorBlock - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : cout  < <  " incrementing begin, setting probability at  "  < <  partition . positions [ predecessor ]  < <  "  to  "  < <  predecessorEntry . getValue ( )  < <  "  ...  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . values [ partition . positions [ predecessor ] ]  =  predecessorEntry . getValue ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        assert ( partition . values [ partition . positions [ predecessor ] ]  < =  1 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( predecessorPosition  > =  predecessorBlock . getBegin ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        if  ( & predecessorBlock  = =  & splitter )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // If the predecessor we just found was already processed (in terms of visiting its predecessors),
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // we swap it with the state that is currently at the beginning of the block and move the start
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            // of the block one step further.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            if  ( predecessorPosition  < =  currentPosition )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                partition . swapStates ( predecessor ,  partition . getState ( predecessorBlock . getBegin ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                predecessorBlock . incrementBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Otherwise, we just need to update the probability for this predecessor.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . values [ predecessorPosition ]  + =  predecessorEntry . getValue ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        std : : cout  < <  " updating probability  "  < <  predecessorPosition  < <  "  to  "  < <  std : : setprecision ( 10 )  < <  partition . values [ predecessorPosition ]  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        assert ( partition . values [ predecessorPosition ]  < =  1  +  1e-6 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                std : : cout  < <  " current position is  "  < <  currentPosition  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                // Otherwise, we need to move the predecessor, but we need to make sure that we explore its
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                // predecessors later.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                if  ( predecessorBlock . getMarkedPosition ( )  = =  predecessorBlock . getBegin ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    partition . swapStatesAtPositions ( predecessorBlock . getMarkedPosition ( ) ,  predecessorPosition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    partition . swapStatesAtPositions ( predecessorPosition ,  currentPosition  +  elementsToSkip  +  1 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    partition . swapStatesAtPositions ( predecessorBlock . getMarkedPosition ( ) ,  predecessorPosition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    partition . swapStatesAtPositions ( predecessorPosition ,  predecessorBlock . getBegin ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                    partition . swapStatesAtPositions ( predecessorPosition ,  currentPosition  +  elementsToSkip  +  1 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( ! predecessorBlock - > isMarked )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlocks . emplace_back ( predecessorBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlock - > isMarked  =  true ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                + + elementsToSkip ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                predecessorBlock . incrementMarkedPosition ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                                predecessorBlock . incrementBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            partition . swapStates ( predecessor ,  partition . getState ( predecessorBlock . getBegin ( ) ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                            predecessorBlock . incrementBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . setValue ( predecessor ,  predecessorEntry . getValue ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        // Otherwise, we just need to update the probability for this predecessor.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . increaseValue ( predecessor ,  predecessorEntry . getValue ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now that we have computed the new positions of the states we want to move, we need to actually move them.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  block  :  predecessorBlocks )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " moving block  "  < <  block - > myId  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  stateIterator  =  partition . states . begin ( )  +  block - > originalBegin ,  stateIte  =  partition . states . begin ( )  +  block - > end ;  stateIterator  ! =  stateIte ;  + + stateIterator )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " swapping  "  < <  * stateIterator  < <  "  to  "  < <  partition . positions [ * stateIterator ]  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : swap ( partition . states [ partition . positions [ * stateIterator ] ] ,  * stateIterator ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( ! predecessorBlock . isMarkedAsPredecessor ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlocks . emplace_back ( & predecessorBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlock . markAsPredecessorBlock ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // Set the original begin and begin to the same value.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block - > setBegin ( block - > begin ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : list < Block * >  blocksToSplit ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // If we had to move some elements beyond the current element, we may have to skip them.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( elementsToSkip  >  0 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " skipping  "  < <  elementsToSkip  < <  "  elements "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    stateIterator  + =  elementsToSkip ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    currentPosition  + =  elementsToSkip ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now, we can iterate over the predecessor blocks and see whether we have to create a new block for
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // predecessors of the splitter.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  block  :  predecessorBlocks )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block - > isMarked  =  false ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now we can traverse the list of states of the splitter whose predecessors we have not yet explored.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  stateIterator  =  partition . getStates ( ) . begin ( )  +  splitter . getOriginalBegin ( ) ,  stateIte  =  partition . getStates ( ) . begin ( )  +  splitter . getMarkedPosition ( ) ;  stateIterator  ! =  stateIte ;  + + stateIterator )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                storm : : storage : : sparse : : state_type  currentState  =  * stateIterator ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // If we have moved the begin of the block to somewhere in the middle of the block, we need to split it.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( block - > begin  ! =  block - > end )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " moved begin to  "  < <  block - > begin  < <  "  and end to  "  < <  block - > end  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  tmpBegin  =  block - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  tmpEnd  =  block - > end ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                for  ( auto  const &  predecessorEntry  :  backwardTransitions . getRow ( currentState ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  predecessor  =  predecessorEntry . getColumn ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    Block &  predecessorBlock  =  partition . getBlock ( predecessor ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    storm : : storage : : sparse : : state_type  predecessorPosition  =  partition . getPosition ( predecessor ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > setBegin ( block - > prev  ! =  nullptr  ?  block - > prev - > end  :  0 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > end  =  tmpBegin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > numberOfStates  =  block - > end  -  block - > begin ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( predecessorPosition  > =  predecessorBlock . getBegin ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . swapStatesAtPositions ( predecessorPosition ,  predecessorBlock . getBegin ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlock . incrementBegin ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . setValue ( predecessor ,  predecessorEntry . getValue ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . increaseValue ( predecessor ,  predecessorEntry . getValue ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Create a new block that holds all states that do not have a successor in the current splitter.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    typename  std : : list < Block > : : iterator  it  =  partition . blocks . emplace ( block - > next  ! =  nullptr  ?  block - > next - > itToSelf  :  partition . blocks . end ( ) ,  tmpBegin ,  tmpEnd ,  block ,  block - > next ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    Block *  newBlock  =  & ( * it ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    newBlock - > itToSelf  =  it ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( block - > next  ! =  nullptr )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        block - > next - > prev  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    if  ( ! predecessorBlock . isMarkedAsPredecessor ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlocks . emplace_back ( & predecessorBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        predecessorBlock . markAsPredecessorBlock ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > next  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " created new block  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    newBlock - > print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            splitter . setMarkedPosition ( splitter . getBegin ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Update the block mapping in the partition.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    for  ( auto  it  =  partition . states . begin ( )  +  newBlock - > begin ,  ite  =  partition . states . begin ( )  +  newBlock - > end ;  it  ! =  ite ;  + + it )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                        partition . stateToBlockMapping [ * it ]  =  newBlock ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : list < Block * >  blocksToSplit ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            std : : cout  < <  " having  "  < <  predecessorBlocks . size ( )  < <  "  pred blocks  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Now, we can iterate over the predecessor blocks and see whether we have to create a new block for
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // predecessors of the splitter.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  blockPtr  :  predecessorBlocks )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                Block &  block  =  * blockPtr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // Mark the half of the block that can be further refined using the probability information.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    blocksToSplit . emplace_back ( block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block . unmarkAsPredecessorBlock ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block . resetMarkedPosition ( ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                // If we have moved the begin of the block to somewhere in the middle of the block, we need to split it.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( block . getBegin ( )  ! =  block . getEnd ( ) )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " moved begin of block  "  < <  block . getId ( )  < <  "  to  "  < <  block . getBegin ( )  < <  "  and end to  "  < <  block . getEnd ( )  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    splitterQueue . push_back ( newBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    Block &  newBlock  =  partition . insertBlock ( block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " created new block  "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    newBlock . print ( partition ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    splitterQueue . push_back ( & newBlock ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  else  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " found block to split "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    std : : cout  < <  " all states are predecessors "  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                     
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    // In this case, we can keep the block by setting its begin to the old value.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block - > setBegin ( ( block - > prev  ! =  nullptr )  ?  block - > prev - > end  :  0 ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    blocksToSplit . emplace_back ( block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    block . setBegin ( block . getOriginalBegin ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    blocksToSplit . emplace_back ( & block ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                block - > setBegin ( block - > begin ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            assert ( partition . check ( ) ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // Finally, we walk through the blocks that have a transition to the splitter and split them using
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            // probabilistic information.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  block  :  blocksToSplit )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( block - > numberOfStates  < =  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            for  ( auto  blockPtr  :  blocksToSplit )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                std : : cout  < <  " block to split:  "  < <  blockPtr - > getId ( )  < <  std : : endl ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                if  ( blockPtr - > getNumberOfStates ( )  < =  1 )  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                    continue ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                splitBlockProbabilities ( block ,  partition ,  splitterQueue ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					                splitBlockProbabilities ( * blockPtr  ,  partition ,  splitterQueue ) ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					             
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					            return  0 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//        template<typename ValueType>
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//        std::size_t BisimulationDecomposition2<ValueType>::splitPartition(storm::models::Dtmc<ValueType> const& dtmc, storm::storage::SparseMatrix<ValueType> const& backwardTransitions, std::size_t const& blockId, std::vector<std::size_t>& stateToBlockMapping, storm::storage::BitVector& blocksInSplitterQueue, std::deque<std::size_t>& splitterQueue, bool weakBisimulation) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::chrono::high_resolution_clock::time_point totalStart = std::chrono::high_resolution_clock::now();
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::unordered_map<storm::storage::Distribution<ValueType>, typename BisimulationDecomposition2<ValueType>::block_type> distributionToNewBlocks;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            // Traverse all states of the block and check whether they have different distributions.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::chrono::high_resolution_clock::time_point gatherStart = std::chrono::high_resolution_clock::now();
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            for (auto const& state : this->blocks[blockId]) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // Now construct the distribution of this state wrt. to the current partitioning.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                storm::storage::Distribution<ValueType> distribution;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                for (auto const& successorEntry : dtmc.getTransitionMatrix().getRow(state)) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    distribution.addProbability(static_cast<storm::storage::sparse::state_type>(stateToBlockMapping[successorEntry.getColumn()]), successorEntry.getValue());
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // If we are requested to compute a weak bisimulation, we need to scale the distribution with the
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // self-loop probability.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                if (weakBisimulation) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    distribution.scale(blockId);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // If the distribution already exists, we simply add the state. Otherwise, we open a new block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                auto distributionIterator = distributionToNewBlocks.find(distribution);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                if (distributionIterator != distributionToNewBlocks.end()) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    distributionIterator->second.insert(state);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                } else {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    distributionToNewBlocks[distribution].insert(state);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::chrono::high_resolution_clock::duration gatherTime = std::chrono::high_resolution_clock::now() - gatherStart;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::cout << "time to iterate over all states was " << std::chrono::duration_cast<std::chrono::milliseconds>(gatherTime).count() << "ms." << std::endl;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            // Now we are ready to split the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            if (distributionToNewBlocks.size() == 1) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // If there is just one behavior, we just set the distribution as the new one for this block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // distributions[blockId] = std::move(distributionToNewBlocks.begin()->first);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            } else {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // In this case, we need to split the block.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                typename BisimulationDecomposition2<ValueType>::block_type tmpBlock;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                auto distributionIterator = distributionToNewBlocks.begin();
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                tmpBlock = std::move(distributionIterator->second);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                std::swap(this->blocks[blockId], tmpBlock);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                ++distributionIterator;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // Remember the number of blocks prior to splitting for later use.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                std::size_t beforeNumberOfBlocks = this->blocks.size();
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                for (; distributionIterator != distributionToNewBlocks.end(); ++distributionIterator) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    // In this case, we need to move the newly created block to the end of the list of actual blocks.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    this->blocks.emplace_back(std::move(distributionIterator->second));
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    // Update the mapping of states to their blocks.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    std::size_t newBlockId = this->blocks.size() - 1;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    for (auto const& state : this->blocks.back()) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        stateToBlockMapping[state] = newBlockId;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                // Insert blocks that possibly need a refinement into the queue.
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                for (auto const& state : tmpBlock) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    for (auto const& predecessor : backwardTransitions.getRow(state)) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        if (!blocksInRefinementQueue.get(stateToBlockMapping[predecessor.getColumn()])) {
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                            blocksInRefinementQueue.set(stateToBlockMapping[predecessor.getColumn()]);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                            refinementQueue.push_back(stateToBlockMapping[predecessor.getColumn()]);
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                        }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                    }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//                }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//        
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::chrono::high_resolution_clock::duration totalTime = std::chrono::high_resolution_clock::now() - totalStart;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            std::cout << "refinement of block " << blockId << " took " << std::chrono::duration_cast<std::chrono::milliseconds>(totalTime).count() << "ms." << std::endl;
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//            return distributionToNewBlocks.size();
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					//        }
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					         
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					        template  class  BisimulationDecomposition2 < double > ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					    }  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				
					}