| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -356,7 +356,12 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        template<typename ValueType> | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					        bool IterativeMinMaxLinearEquationSolver<ValueType>::solveEquationsOptimisticValueIteration(Environment const& env, OptimizationDirection dir, std::vector<ValueType>& x, std::vector<ValueType> const& b) const { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // TODO: Differentiate between relative and absolute precision
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // TODO: Updating solver status when iterations exceed
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            uint64_t overallIterations = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            uint64_t lastValueIterationIterations = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            uint64_t currentVerificationIterations = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            uint64_t valueIterationInvocations = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            if (!this->multiplierA) { | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -369,12 +374,16 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // By default, we can not provide any guarantee
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            SolverGuarantee guarantee = SolverGuarantee::None; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Get handle to multiplier.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            storm::solver::Multiplier<ValueType> const &multiplier = *this->multiplierA; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            // Allow aliased multiplications.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            storm::solver::MultiplicationStyle multiplicationStyle = env.solver().minMax().getMultiplicationStyle(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            bool useGaussSeidelMultiplication = multiplicationStyle == storm::solver::MultiplicationStyle::GaussSeidel; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> *newX = auxiliaryRowGroupVector.get(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> *currentX = &x; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> newUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> currentUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> ubDiffV(newX->size()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            std::vector<ValueType> boundsDiffV(currentX->size()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -384,77 +393,81 @@ namespace storm { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            SolverStatus status = SolverStatus::InProgress; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            this->startMeasureProgress(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            while (status == SolverStatus::InProgress && | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                   overallIterations < env.solver().minMax().getMaximalNumberOfIterations()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                storm::solver::MultiplicationStyle multiplicationStyle = env.solver().minMax().getMultiplicationStyle(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					            while (status == SolverStatus::InProgress && overallIterations < env.solver().minMax().getMaximalNumberOfIterations()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                // Perform value iteration until convergence
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ++valueIterationInvocations; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ValueIterationResult result = performValueIteration(env, dir, currentX, newX, b, iterationPrecision, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                    env.solver().minMax().getRelativeTerminationCriterion(), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                    guarantee, overallIterations, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                    env.solver().minMax().getMaximalNumberOfIterations(), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                                                    multiplicationStyle); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                ValueIterationResult result = performValueIteration(env, dir, currentX, newX, b, iterationPrecision, env.solver().minMax().getRelativeTerminationCriterion(), guarantee, overallIterations, env.solver().minMax().getMaximalNumberOfIterations(), multiplicationStyle); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                lastValueIterationIterations = result.iterations; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                overallIterations += result.iterations; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                if (result.status != SolverStatus::Converged) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    status = result.status; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::vector<ValueType> upperBound = guessUpperBound(env, *currentX, precision); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    std::vector<ValueType> newUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    while (status == SolverStatus::InProgress && | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                           overallIterations < env.solver().minMax().getMaximalNumberOfIterations()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Perform value iteration stepwise for lower bound and guessed upper bound
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    currentVerificationIterations = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Allow aliased multiplications.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        bool useGaussSeidelMultiplication = multiplicationStyle == storm::solver::MultiplicationStyle::GaussSeidel; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    currentUpperBound = guessUpperBound(env, *currentX, precision); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    newUpperBound = currentUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    // TODO: More efficient check for verification iterations
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    while (status == SolverStatus::InProgress && overallIterations < env.solver().minMax().getMaximalNumberOfIterations() && (currentVerificationIterations / 10) < lastValueIterationIterations) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Perform value iteration stepwise for lower bound and guessed upper bound
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Lower and upper bound iteration
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Compute x' = min/max(A*x + b).
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (useGaussSeidelMultiplication) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Copy over the current vectors so we can modify them in-place.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            *newX = *currentX; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            newUpperBound = upperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            newUpperBound = currentUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Do the calculation
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            multiplier.multiplyAndReduceGaussSeidel(env, dir, *newX, &b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            multiplier.multiplyAndReduceGaussSeidel(env, dir, newUpperBound, &b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            multiplier.multiplyAndReduce(env, dir, *currentX, &b, *newX); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            multiplier.multiplyAndReduce(env, dir, upperBound, &b, newUpperBound); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            multiplier.multiplyAndReduce(env, dir, currentUpperBound, &b, newUpperBound); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Set iteration precision beforehand
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Calculate the maximum difference between the old and new iteration
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // This method adapts utility::vector::equalModuloPrecision from performValueIteration()
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        iterationPrecision = computeMaxAbsDiff(*newX, *currentX, this->getRelevantValues()); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        bool up, down = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        bool cross = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Calculate difference vector of upper bound and x
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        storm::utility::vector::subtractVectors<ValueType>(newUpperBound, *newX, boundsDiffV); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Calculate difference vector of new and old upper bound
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        storm::utility::vector::subtractVectors<ValueType>(upperBound, newUpperBound, ubDiffV); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        storm::utility::vector::subtractVectors<ValueType>(currentUpperBound, newUpperBound, ubDiffV); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Update current upper bound
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        std::swap(newUpperBound, currentUpperBound); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (storm::utility::vector::hasPositiveEntry(ubDiffV)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // up = false (Not all values moved up)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // TODO: Optimisation (if(this->hasUniqueSolution()) ?)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            up = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Not all values moved up or stayed the same
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // If we have a single fixed point, we can safely set the new lower bound, to the wrongly guessed upper bound
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            if (this->hasUniqueSolution()) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                                *currentX = currentUpperBound; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (storm::utility::vector::hasNegativeEntry(ubDiffV)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            down = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // Calculate difference vector of upper bound and x
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        storm::utility::vector::subtractVectors<ValueType>(newUpperBound, *newX, boundsDiffV); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (storm::utility::vector::hasNegativeEntry(boundsDiffV)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            cross = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Values crossed
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // TODO: else if down und s_i precision okay, calculate middle of both vectors
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // All values moved down or stayed the same and we have a maximum difference of twice the requested precision
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        // We can safely use twice the requested precision, as we calculate the center of both vectors
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        if (!storm::utility::vector::hasNegativeEntry(ubDiffV) && storm::utility::vector::max_if(boundsDiffV, this->getRelevantValues()) < storm::utility::convertNumber<ValueType>(2.0) * precision) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // Calculate the center of both vectors and store it in currentX
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // TODO: Do calculations in-place on currentX
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            // center = (1 / 2) * u + v
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            std::vector<ValueType> centerV = *currentX; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            storm::utility::vector::addVectors(*currentX, currentUpperBound, centerV); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            storm::utility::vector::scaleVectorInPlace(centerV, storm::utility::convertNumber<ValueType>(0.5)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            std::swap(centerV, *currentX); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                            status = SolverStatus::Converged; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        ++overallIterations; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                        ++currentVerificationIterations; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                    } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					                } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |