| 
						
						
						
					 | 
				
				 | 
				
					@ -1,3 +1,5 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include <queue>
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "storm/models/sparse/MarkovAutomaton.h"
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#include "storm/adapters/RationalFunctionAdapter.h"
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -265,6 +267,108 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return std::make_shared<storm::models::sparse::Ctmc<ValueType, RewardModelType>>(std::move(rateMatrix), std::move(stateLabeling)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, typename RewardModelType> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::shared_ptr<MarkovAutomaton<ValueType, RewardModelType>> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            MarkovAutomaton<ValueType, RewardModelType>::eliminateNonmarkovianStates() const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (isClosed() && markovianStates.full()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    storm::storage::sparse::ModelComponents<ValueType, RewardModelType> components( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            this->getTransitionMatrix(), this->getStateLabeling(), this->getRewardModels(), false); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    components.exitRates = this->getExitRates(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (this->hasChoiceLabeling()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        components.choiceLabeling = this->getChoiceLabeling(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (this->hasStateValuations()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        components.stateValuations = this->getStateValuations(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (this->hasChoiceOrigins()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        components.choiceOrigins = this->getChoiceOrigins(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    return std::make_shared<MarkovAutomaton<ValueType, RewardModelType>>(std::move(components)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::map<uint_fast64_t, uint_fast64_t> stateRemapping; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::set<uint_fast64_t> statesToKeep; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::queue<uint_fast64_t> changedStates; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                std::queue<uint_fast64_t> queue; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                storm::storage::SparseMatrix<ValueType> backwards = this->getBackwardTransitions(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Determine the state remapping
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // TODO Consider state labels
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (uint_fast64_t base_state = 0; base_state < this->getNumberOfStates(); ++base_state) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    STORM_LOG_ASSERT(!this->isHybridState(base_state), "Base state is hybrid."); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    if (this->isMarkovianState(base_state)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        queue.push(base_state); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        while (!queue.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            auto currState = queue.front(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            queue.pop(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Get predecessors from matrix
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            typename storm::storage::SparseMatrix<ValueType>::rows entriesInRow = backwards.getRow( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    currState); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            for (auto entryIt = entriesInRow.begin(), entryIte = entriesInRow.end(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                 entryIt != entryIte; ++entryIt) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                uint_fast64_t predecessor = entryIt->getColumn(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                if (!this->isMarkovianState(predecessor) && !statesToKeep.count(predecessor)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    if (!stateRemapping.count(predecessor)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        stateRemapping[predecessor] = base_state; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        queue.push(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    } else if (stateRemapping[predecessor] != base_state) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        stateRemapping.erase(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        statesToKeep.insert(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                        changedStates.push(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Correct the mapping with the states which have to be kept
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                while (!changedStates.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    uint_fast64_t base_state = changedStates.front(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    queue.push(base_state); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    while (!queue.empty()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        auto currState = queue.front(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        queue.pop(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Get predecessors from matrix
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        typename storm::storage::SparseMatrix<ValueType>::rows entriesInRow = backwards.getRow( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                currState); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        for (auto entryIt = entriesInRow.begin(), entryIte = entriesInRow.end(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                             entryIt != entryIte; ++entryIt) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            uint_fast64_t predecessor = entryIt->getColumn(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (!this->isMarkovianState(predecessor) && !statesToKeep.count(predecessor)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                if (!stateRemapping.count(predecessor)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    stateRemapping[predecessor] = base_state; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    queue.push(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                } else if (stateRemapping[predecessor] != base_state) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    stateRemapping.erase(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    statesToKeep.insert(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                    changedStates.push(predecessor); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    changedStates.pop(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // At this point, we hopefully have a valid mapping which eliminates a lot of states
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                STORM_PRINT("Remapping \n") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                for (auto entry : stateRemapping) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    STORM_PRINT(std::to_string(entry.first) << " -> " << std::to_string(entry.second) << "\n") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                STORM_PRINT("Remapped States: " << stateRemapping.size() << "\n") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // TODO test some examples, especially ones containing non-determinism
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Build the new matrix
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // TODO
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                return nullptr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template<typename ValueType, typename RewardModelType> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            void MarkovAutomaton<ValueType, RewardModelType>::printModelInformationToStream(std::ostream& out) const { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -278,9 +382,11 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MarkovAutomaton<double>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#ifdef STORM_HAVE_CARL
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MarkovAutomaton<storm::RationalNumber>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MarkovAutomaton<double, storm::models::sparse::StandardRewardModel<storm::Interval>>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            template class MarkovAutomaton<storm::RationalFunction>; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					#endif
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        } // namespace sparse
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |