|  |  | @ -582,7 +582,8 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             reportStatus(status, iterations); | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             this->overallPerformedIterations += iterations; | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             // We take the means of the lower and upper bound so we guarantee the desired precision.
 | 
			
		
	
		
			
				
					|  |  |  |             ValueType two = storm::utility::convertNumber<ValueType>(2.0); | 
			
		
	
		
			
				
					|  |  |  |             storm::utility::vector::applyPointwise<ValueType, ValueType, ValueType>(*lowerX, *upperX, *lowerX, [&two] (ValueType const& a, ValueType const& b) -> ValueType { return (a + b) / two; }); | 
			
		
	
	
		
			
				
					|  |  | @ -718,90 +719,6 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             void performIterationStepMax(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType> const& b) { | 
			
		
	
		
			
				
					|  |  |  |                 if (!decisionValueBlocks) { | 
			
		
	
		
			
				
					|  |  |  |                     performIterationStepUpdateDecisionValueMax(A, b); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     assert(decisionValue == upperBound); | 
			
		
	
		
			
				
					|  |  |  |                     auto xIt = x.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     auto yIt = y.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     auto groupStartIt = A.getRowGroupIndices().rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     uint64_t groupEnd = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     ++groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     for (auto groupStartIte = A.getRowGroupIndices().rend(); groupStartIt != groupStartIte; groupEnd = *(groupStartIt++), ++xIt, ++yIt) { | 
			
		
	
		
			
				
					|  |  |  |                         // Perform the iteration for the first row in the group
 | 
			
		
	
		
			
				
					|  |  |  |                         uint64_t row = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                         ValueType xBest, yBest; | 
			
		
	
		
			
				
					|  |  |  |                         multiplyRow(row, A, b[row], xBest, yBest); | 
			
		
	
		
			
				
					|  |  |  |                         ++row; | 
			
		
	
		
			
				
					|  |  |  |                         // Only do more work if there are still rows in this row group
 | 
			
		
	
		
			
				
					|  |  |  |                         if (row != groupEnd) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType xi, yi; | 
			
		
	
		
			
				
					|  |  |  |                             ValueType bestValue = xBest + yBest * upperBound; | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 // Get the multiplication results
 | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType currentValue = xi + yi * upperBound; | 
			
		
	
		
			
				
					|  |  |  |                                 // Check if the current row is better then the previously found one
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (currentValue > bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     bestValue = std::move(currentValue); | 
			
		
	
		
			
				
					|  |  |  |                                 } else if (currentValue == bestValue && yBest > yi) { | 
			
		
	
		
			
				
					|  |  |  |                                     // If the value for this row is not strictly better, it might still be equal and have a better y value
 | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                         *xIt = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                         *yIt = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             void performIterationStepMin(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType> const& b) { | 
			
		
	
		
			
				
					|  |  |  |                 if (!decisionValueBlocks) { | 
			
		
	
		
			
				
					|  |  |  |                     performIterationStepUpdateDecisionValueMin(A, b); | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     assert(decisionValue == lowerBound); | 
			
		
	
		
			
				
					|  |  |  |                     auto xIt = x.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     auto yIt = y.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     auto groupStartIt = A.getRowGroupIndices().rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                     uint64_t groupEnd = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     ++groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     for (auto groupStartIte = A.getRowGroupIndices().rend(); groupStartIt != groupStartIte; groupEnd = *(groupStartIt++), ++xIt, ++yIt) { | 
			
		
	
		
			
				
					|  |  |  |                         // Perform the iteration for the first row in the group
 | 
			
		
	
		
			
				
					|  |  |  |                         uint64_t row = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                         ValueType xBest, yBest; | 
			
		
	
		
			
				
					|  |  |  |                         multiplyRow(row, A, b[row], xBest, yBest); | 
			
		
	
		
			
				
					|  |  |  |                         ++row; | 
			
		
	
		
			
				
					|  |  |  |                         // Only do more work if there are still rows in this row group
 | 
			
		
	
		
			
				
					|  |  |  |                         if (row != groupEnd) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType xi, yi; | 
			
		
	
		
			
				
					|  |  |  |                             ValueType bestValue = xBest + yBest * lowerBound; | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 // Get the multiplication results
 | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType currentValue = xi + yi * lowerBound; | 
			
		
	
		
			
				
					|  |  |  |                                 // Check if the current row is better then the previously found one
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (currentValue < bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     bestValue = std::move(currentValue); | 
			
		
	
		
			
				
					|  |  |  |                                 } else if (currentValue == bestValue && yBest > yi) { | 
			
		
	
		
			
				
					|  |  |  |                                     // If the value for this row is not strictly better, it might still be equal and have a better y value
 | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                         *xIt = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                         *yIt = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             template<OptimizationDirection dir> | 
			
		
	
		
			
				
					|  |  |  |             void performIterationStepUpdateDecisionValue(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType> const& b) { | 
			
		
	
		
			
				
					|  |  |  |                 auto xIt = x.rbegin(); | 
			
		
	
	
		
			
				
					|  |  | @ -883,166 +800,6 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             void performIterationStepUpdateDecisionValueMax(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType> const& b) { | 
			
		
	
		
			
				
					|  |  |  |                 auto xIt = x.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 auto yIt = y.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 auto groupStartIt = A.getRowGroupIndices().rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 uint64_t groupEnd = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                 ++groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                 for (auto groupStartIte = A.getRowGroupIndices().rend(); groupStartIt != groupStartIte; groupEnd = *(groupStartIt++), ++xIt, ++yIt) { | 
			
		
	
		
			
				
					|  |  |  |                     // Perform the iteration for the first row in the group
 | 
			
		
	
		
			
				
					|  |  |  |                     uint64_t row = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     ValueType xBest, yBest; | 
			
		
	
		
			
				
					|  |  |  |                     multiplyRow(row, A, b[row], xBest, yBest); | 
			
		
	
		
			
				
					|  |  |  |                     ++row; | 
			
		
	
		
			
				
					|  |  |  |                     // Only do more work if there are still rows in this row group
 | 
			
		
	
		
			
				
					|  |  |  |                     if (row != groupEnd) { | 
			
		
	
		
			
				
					|  |  |  |                         ValueType xi, yi; | 
			
		
	
		
			
				
					|  |  |  |                         uint64_t xyTmpIndex = 0; | 
			
		
	
		
			
				
					|  |  |  |                         if (hasUpperBound) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType bestValue = xBest + yBest * upperBound; | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 // Get the multiplication results
 | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType currentValue = xi + yi * upperBound; | 
			
		
	
		
			
				
					|  |  |  |                                 // Check if the current row is better then the previously found one
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (currentValue > bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     if (yBest < yi) { | 
			
		
	
		
			
				
					|  |  |  |                                         // We need to store the 'old' best value as it might be relevant for the decision value
 | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     } | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     bestValue = std::move(currentValue); | 
			
		
	
		
			
				
					|  |  |  |                                 } else if (yBest > yi) { | 
			
		
	
		
			
				
					|  |  |  |                                     // If the value for this row is not strictly better, it might still be equal and have a better y value
 | 
			
		
	
		
			
				
					|  |  |  |                                     if (currentValue == bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                         xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                         yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     } else { | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     } | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } else { | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 // Update the best choice
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (yi > yBest || (yi == yBest && xi > xBest)) { | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                 } else { | 
			
		
	
		
			
				
					|  |  |  |                                     xTmp[xyTmpIndex] = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yTmp[xyTmpIndex] = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                          | 
			
		
	
		
			
				
					|  |  |  |                         // Update the decision value
 | 
			
		
	
		
			
				
					|  |  |  |                         for (uint64_t i = 0; i < xyTmpIndex; ++i) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType deltaY = yBest - yTmp[i]; | 
			
		
	
		
			
				
					|  |  |  |                             if (deltaY > storm::utility::zero<ValueType>()) { | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType newDecisionValue = (xTmp[i] - xBest) / deltaY; | 
			
		
	
		
			
				
					|  |  |  |                                 if (!hasDecisionValue || newDecisionValue > decisionValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     decisionValue = std::move(newDecisionValue); | 
			
		
	
		
			
				
					|  |  |  |                                     hasDecisionValue = true; | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                     *xIt = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                     *yIt = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             void performIterationStepUpdateDecisionValueMin(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType> const& b) { | 
			
		
	
		
			
				
					|  |  |  |                 auto xIt = x.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 auto yIt = y.rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 auto groupStartIt = A.getRowGroupIndices().rbegin(); | 
			
		
	
		
			
				
					|  |  |  |                 uint64_t groupEnd = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                 ++groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                 for (auto groupStartIte = A.getRowGroupIndices().rend(); groupStartIt != groupStartIte; groupEnd = *(groupStartIt++), ++xIt, ++yIt) { | 
			
		
	
		
			
				
					|  |  |  |                     // Perform the iteration for the first row in the group
 | 
			
		
	
		
			
				
					|  |  |  |                     uint64_t row = *groupStartIt; | 
			
		
	
		
			
				
					|  |  |  |                     ValueType xBest, yBest; | 
			
		
	
		
			
				
					|  |  |  |                     multiplyRow(row, A, b[row], xBest, yBest); | 
			
		
	
		
			
				
					|  |  |  |                     ++row; | 
			
		
	
		
			
				
					|  |  |  |                     // Only do more work if there are still rows in this row group
 | 
			
		
	
		
			
				
					|  |  |  |                     if (row != groupEnd) { | 
			
		
	
		
			
				
					|  |  |  |                         ValueType xi, yi; | 
			
		
	
		
			
				
					|  |  |  |                         uint64_t xyTmpIndex = 0; | 
			
		
	
		
			
				
					|  |  |  |                         if (hasLowerBound) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType bestValue = xBest + yBest * lowerBound; | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 // Get the multiplication results
 | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType currentValue = xi + yi * lowerBound; | 
			
		
	
		
			
				
					|  |  |  |                                 // Check if the current row is better then the previously found one
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (currentValue < bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     if (yBest < yi) { | 
			
		
	
		
			
				
					|  |  |  |                                         // We need to store the 'old' best value as it might be relevant for the decision value
 | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     } | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     bestValue = std::move(currentValue); | 
			
		
	
		
			
				
					|  |  |  |                                 } else if (yBest > yi) { | 
			
		
	
		
			
				
					|  |  |  |                                     // If the value for this row is not strictly better, it might still be equal and have a better y value
 | 
			
		
	
		
			
				
					|  |  |  |                                     if (currentValue == bestValue) { | 
			
		
	
		
			
				
					|  |  |  |                                         xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                         yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     } else { | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     } | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } else { | 
			
		
	
		
			
				
					|  |  |  |                             for (;row < groupEnd; ++row) { | 
			
		
	
		
			
				
					|  |  |  |                                 multiplyRow(row, A, b[row], xi, yi); | 
			
		
	
		
			
				
					|  |  |  |                                 // Update the best choice
 | 
			
		
	
		
			
				
					|  |  |  |                                 if (yi > yBest || (yi == yBest && xi < xBest)) { | 
			
		
	
		
			
				
					|  |  |  |                                         xTmp[xyTmpIndex] = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                                         yTmp[xyTmpIndex] = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                                         ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                     xBest = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yBest = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                 } else { | 
			
		
	
		
			
				
					|  |  |  |                                     xTmp[xyTmpIndex] = std::move(xi); | 
			
		
	
		
			
				
					|  |  |  |                                     yTmp[xyTmpIndex] = std::move(yi); | 
			
		
	
		
			
				
					|  |  |  |                                     ++xyTmpIndex; | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                          | 
			
		
	
		
			
				
					|  |  |  |                         // Update the decision value
 | 
			
		
	
		
			
				
					|  |  |  |                         for (uint64_t i = 0; i < xyTmpIndex; ++i) { | 
			
		
	
		
			
				
					|  |  |  |                             ValueType deltaY = yBest - yTmp[i]; | 
			
		
	
		
			
				
					|  |  |  |                             if (deltaY > storm::utility::zero<ValueType>()) { | 
			
		
	
		
			
				
					|  |  |  |                                 ValueType newDecisionValue = (xTmp[i] - xBest) / deltaY; | 
			
		
	
		
			
				
					|  |  |  |                                 if (!hasDecisionValue || newDecisionValue < decisionValue) { | 
			
		
	
		
			
				
					|  |  |  |                                     decisionValue = std::move(newDecisionValue); | 
			
		
	
		
			
				
					|  |  |  |                                     hasDecisionValue = true; | 
			
		
	
		
			
				
					|  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |                             } | 
			
		
	
		
			
				
					|  |  |  |                         } | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                     *xIt = std::move(xBest); | 
			
		
	
		
			
				
					|  |  |  |                     *yIt = std::move(yBest); | 
			
		
	
		
			
				
					|  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             bool checkRestartCriterion() { | 
			
		
	
		
			
				
					|  |  |  |                 return false; | 
			
		
	
		
			
				
					|  |  |  |                 // iterations <= restartMaxIterations && (minimize(dir) ? restartThreshold * improvedPrimaryBound > primaryBound : restartThreshold * primaryBound > improvedPrimaryBound
 | 
			
		
	
	
		
			
				
					|  |  | @ -1249,13 +1006,13 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             while (status == SolverStatus::InProgress && iterations < env.solver().minMax().getMaximalNumberOfIterations()) { | 
			
		
	
		
			
				
					|  |  |  |                 if (minimize(dir)) { | 
			
		
	
		
			
				
					|  |  |  |                     helper.template performIterationStepMin(*this->A, b); | 
			
		
	
		
			
				
					|  |  |  |                     helper.template performIterationStep<OptimizationDirection::Minimize>(*this->A, b); | 
			
		
	
		
			
				
					|  |  |  |                     if (helper.template checkConvergenceUpdateBounds<OptimizationDirection::Minimize>(iterations, relevantValuesPtr)) { | 
			
		
	
		
			
				
					|  |  |  |                         status = SolverStatus::Converged; | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
		
			
				
					|  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |                     assert(maximize(dir)); | 
			
		
	
		
			
				
					|  |  |  |                     helper.template performIterationStepMax(*this->A, b); | 
			
		
	
		
			
				
					|  |  |  |                     helper.template performIterationStep<OptimizationDirection::Maximize>(*this->A, b); | 
			
		
	
		
			
				
					|  |  |  |                     if (helper.template checkConvergenceUpdateBounds<OptimizationDirection::Maximize>(iterations, relevantValuesPtr)) { | 
			
		
	
		
			
				
					|  |  |  |                         status = SolverStatus::Converged; | 
			
		
	
		
			
				
					|  |  |  |                     } | 
			
		
	
	
		
			
				
					|  |  | @ -1279,6 +1036,8 @@ namespace storm { | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |             reportStatus(status, iterations); | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             this->overallPerformedIterations += iterations; | 
			
		
	
		
			
				
					|  |  |  |              | 
			
		
	
		
			
				
					|  |  |  |             if (!this->isCachingEnabled()) { | 
			
		
	
		
			
				
					|  |  |  |                 clearCache(); | 
			
		
	
		
			
				
					|  |  |  |             } | 
			
		
	
	
		
			
				
					|  |  | 
 |