| 
					
					
						
							
						
					
					
				 | 
				@ -48,18 +48,26 @@ namespace storm { | 
			
		
		
	
		
			
				 | 
				 | 
				            // Initialize the maximal end component list to be the full state space.
 | 
				 | 
				 | 
				            // Initialize the maximal end component list to be the full state space.
 | 
			
		
		
	
		
			
				 | 
				 | 
				            std::list<StateBlock> endComponentStateSets; | 
				 | 
				 | 
				            std::list<StateBlock> endComponentStateSets; | 
			
		
		
	
		
			
				 | 
				 | 
				            endComponentStateSets.emplace_back(0, model.getNumberOfStates()); | 
				 | 
				 | 
				            endComponentStateSets.emplace_back(0, model.getNumberOfStates()); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            storm::storage::BitVector statesToCheck(model.getNumberOfStates()); | 
			
		
		
	
		
			
				 | 
				 | 
				             | 
				 | 
				 | 
				             | 
			
		
		
	
		
			
				 | 
				 | 
				            do { | 
				 | 
				 | 
				 | 
			
		
		
	
		
			
				 | 
				 | 
				                StronglyConnectedComponentDecomposition<ValueType> sccs(model, true); | 
				 | 
				 | 
				 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            for (std::list<StateBlock>::const_iterator mecIterator = endComponentStateSets.begin(); mecIterator != endComponentStateSets.end();) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                StateBlock const& mec = *mecIterator; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                // Keep track of whether the MEC changed during this iteration.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                bool mecChanged = false; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                // Get an SCC decomposition of the current MEC candidate.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                StronglyConnectedComponentDecomposition<ValueType> sccs(model, mec, true); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                mecChanged |= sccs.size() > 1; | 
			
		
		
	
		
			
				 | 
				 | 
				                 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				                // Check for each of the SCCs whether there is at least one action for each state that does not leave the SCC.
 | 
				 | 
				 | 
				                // Check for each of the SCCs whether there is at least one action for each state that does not leave the SCC.
 | 
			
		
		
	
		
			
				 | 
				 | 
				                for (auto& scc : sccs) { | 
				 | 
				 | 
				                for (auto& scc : sccs) { | 
			
		
		
	
		
			
				 | 
				 | 
				                    storm::storage::BitVector statesToCheck(model.getNumberOfStates(), scc.begin(), scc.end()); | 
				 | 
				 | 
				 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    statesToCheck.set(scc.begin(), scc.end()); | 
			
		
		
	
		
			
				 | 
				 | 
				                     | 
				 | 
				 | 
				                     | 
			
		
		
	
		
			
				 | 
				 | 
				                    while (!statesToCheck.empty()) { | 
				 | 
				 | 
				                    while (!statesToCheck.empty()) { | 
			
		
		
	
		
			
				 | 
				 | 
				                        storm::storage::BitVector statesToRemove(model.getNumberOfStates()); | 
				 | 
				 | 
				                        storm::storage::BitVector statesToRemove(model.getNumberOfStates()); | 
			
		
		
	
		
			
				 | 
				 | 
				                         | 
				 | 
				 | 
				                         | 
			
		
		
	
		
			
				 | 
				 | 
				                        for (auto state : scc) { | 
				 | 
				 | 
				 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        for (auto state : statesToCheck) { | 
			
		
		
	
		
			
				 | 
				 | 
				                            bool keepStateInMEC = false; | 
				 | 
				 | 
				                            bool keepStateInMEC = false; | 
			
		
		
	
		
			
				 | 
				 | 
				                             | 
				 | 
				 | 
				                             | 
			
		
		
	
		
			
				 | 
				 | 
				                            for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { | 
				 | 
				 | 
				                            for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { | 
			
		
		
	
	
		
			
				| 
					
					
					
						
							
						
					
				 | 
				@ -84,16 +92,65 @@ namespace storm { | 
			
		
		
	
		
			
				 | 
				 | 
				                        } | 
				 | 
				 | 
				                        } | 
			
		
		
	
		
			
				 | 
				 | 
				                         | 
				 | 
				 | 
				                         | 
			
		
		
	
		
			
				 | 
				 | 
				                        // Now erase the states that have no option to stay inside the MEC with all successors.
 | 
				 | 
				 | 
				                        // Now erase the states that have no option to stay inside the MEC with all successors.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        mecChanged |= !statesToRemove.empty(); | 
			
		
		
	
		
			
				 | 
				 | 
				                        std::vector<uint_fast64_t> statesToRemoveList = statesToRemove.getSetIndicesList(); | 
				 | 
				 | 
				                        std::vector<uint_fast64_t> statesToRemoveList = statesToRemove.getSetIndicesList(); | 
			
		
		
	
		
			
				 | 
				 | 
				                        scc.erase(storm::storage::VectorSet<uint_fast64_t>(statesToRemoveList.begin(), statesToRemoveList.end())); | 
				 | 
				 | 
				                        scc.erase(storm::storage::VectorSet<uint_fast64_t>(statesToRemoveList.begin(), statesToRemoveList.end())); | 
			
		
		
	
		
			
				 | 
				 | 
				                         | 
				 | 
				 | 
				                         | 
			
		
		
	
		
			
				 | 
				 | 
				                        // Now check which states should be reconsidered, because successors of them were removed.
 | 
				 | 
				 | 
				                        // Now check which states should be reconsidered, because successors of them were removed.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        statesToCheck.clear(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        for (auto state : statesToRemove) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                            for (typename storm::storage::SparseMatrix<ValueType>::ConstIndexIterator predIt = backwardTransitions.constColumnIteratorBegin(state), predIte = backwardTransitions.constColumnIteratorEnd(state); predIt != predIte; ++predIt) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                                if (scc.contains(*predIt)) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                                    statesToCheck.set(*predIt); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                                } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                            } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                // If the MEC changed, we delete it from the list of MECs and append the possible new MEC candidates to the list instead.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                if (mecChanged) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    std::list<StateBlock>::const_iterator eraseIterator(mecIterator); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    for (StateBlock& scc : sccs) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        endComponentStateSets.push_back(std::move(scc)); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        ++mecIterator; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    endComponentStateSets.erase(eraseIterator); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                } else { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    // Otherwise, we proceed with the next MEC candidate.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    ++mecIterator; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            } // end of loop over all MEC candidates
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				             | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            // Now that we computed the underlying state sets of the MECs, we need to properly identify the choices contained in the MEC.
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            this->blocks.reserve(endComponentStateSets.size()); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            for (auto const& mecStateSet : endComponentStateSets) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                MaximalEndComponent newMec; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                for (auto state : mecStateSet) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    std::vector<uint_fast64_t> containedChoices; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        bool choiceContained = true; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        for (typename storm::storage::SparseMatrix<ValueType>::ConstIndexIterator successorIt = transitionMatrix.constColumnIteratorBegin(choice), successorIte = transitionMatrix.constColumnIteratorEnd(choice); successorIt != successorIte; ++successorIt) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                            if (!mecStateSet.contains(*successorIt)) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                                choiceContained = false; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                                break; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                            } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                         | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        if (choiceContained) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                            containedChoices.push_back(choice); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                        } | 
			
		
		
	
		
			
				 | 
				 | 
				                    } | 
				 | 
				 | 
				                    } | 
			
		
		
	
		
			
				 | 
				 | 
				                     | 
				 | 
				 | 
				                     | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                    newMec.addState(state, std::move(containedChoices)); | 
			
		
		
	
		
			
				 | 
				 | 
				                } | 
				 | 
				 | 
				                } | 
			
		
		
	
		
			
				 | 
				 | 
				                 | 
				 | 
				 | 
				                 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				                this->blocks.emplace_back(std::move(newMec)); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            } | 
			
		
		
	
		
			
				 | 
				 | 
				             | 
				 | 
				 | 
				             | 
			
		
		
	
		
			
				 | 
				 | 
				            } while (true); | 
				 | 
				 | 
				 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				            LOG4CPLUS_INFO(logger, "Computed MEC decomposition of size " << this->size() << "."); | 
			
		
		
	
		
			
				 | 
				 | 
				        } | 
				 | 
				 | 
				        } | 
			
		
		
	
		
			
				 | 
				 | 
				         | 
				 | 
				 | 
				         | 
			
		
		
	
		
			
				 | 
				 | 
				        template class MaximalEndComponentDecomposition<double>; | 
				 | 
				 | 
				        template class MaximalEndComponentDecomposition<double>; | 
			
		
		
	
	
		
			
				| 
					
					
					
				 | 
				
  |