17template<
typename ValueType>
20template<
typename ValueType>
21void IterationHelper<ValueType>::swipeWeights() {
22 const auto& rowGroupIndices = matrix.getRowGroupIndices();
28 auto weightOnGroup = weights[i] / den;
31 for (
auto row = rowGroupIndices[i]; row < rowGroupIndices[i + 1]; ++row) {
32 for (
auto const& entry : matrix.getRow(row)) {
33 weights[entry.getColumn()] += weightOnGroup * entry.getValue();
39template<
typename ValueType>
45 std::vector<ValueType> additiveWeights(weights.size(), 0);
46 for (
int i = 0; i < 50; i++) {
51 return static_cast<IndexType>(std::max_element(additiveWeights.begin(), additiveWeights.end()) - additiveWeights.begin());
54template<
typename ValueType>
56 ValueType
const& precision)
const {
57 auto itL = lower.begin();
58 const auto itLEnd = lower.end();
59 auto itU = upper.begin();
61 for (; itL != itLEnd; ++itL, ++itU) {
62 ValueType threshold = 2 * precision;
67 }
else if (*itU < 0) {
69 }
else if (*itL != *itU) {
73 if (*itU - *itL > threshold) {
80template<
typename ValueType>
83 auto itL = lower.begin();
84 const auto itLEnd = lower.end();
85 auto itU = upper.begin();
87 for (; itL != itLEnd; ++itL, ++itU) {
95template<
typename ValueType, storm::OptimizationDirection Dir>
101 GVIBackend(uint64_t guessedRowGroup) : guessedRowGroup(guessedRowGroup) {}
105 void firstRow(std::pair<ValueType, ValueType>&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
106 xBest = std::move(value.first);
107 yBest = std::move(value.second);
110 void nextRow(std::pair<ValueType, ValueType>&& value, [[maybe_unused]] uint64_t rowGroup, [[maybe_unused]] uint64_t row) {
111 xBest &= std::move(value.first);
112 yBest &= std::move(value.second);
115 void applyUpdate(ValueType& xCurr, ValueType& yCurr, uint64_t rowGroup) {
116 if (guessedRowGroup && rowGroup == *guessedRowGroup) {
121 xCurr = std::max(xCurr, *xBest);
122 yCurr = std::min(yCurr, *yBest);
137 std::optional<uint64_t> guessedRowGroup;
140template<
typename ValueType,
bool TrivialRowGrouping>
141gviinternal::IndexType GuessingValueIterationHelper<ValueType, TrivialRowGrouping>::selectRowGroupToGuess(std::vector<ValueType>& lowerX,
142 std::vector<ValueType>& upperX) {
143 return iterationHelper.selectRowGroupToGuess(lowerX, upperX);
146template<
typename ValueType,
bool TrivialRowGrouping>
147template<OptimizationDirection Dir>
148void GuessingValueIterationHelper<ValueType, TrivialRowGrouping>::applyInPlace(std::vector<ValueType>& lowerX, std::vector<ValueType>& upperX,
149 const std::vector<ValueType>& b, GVIBackend<ValueType, Dir>& backend) {
150 std::pair<std::vector<ValueType>, std::vector<ValueType>> xy;
151 xy.first.swap(lowerX);
152 xy.second.swap(upperX);
153 viOperator->applyInPlace(xy, b, backend);
154 lowerX.swap(xy.first);
155 upperX.swap(xy.second);
158template<
typename ValueType,
bool TrivialRowGrouping>
159template<OptimizationDirection Dir>
160std::pair<gviinternal::VerifyResult, SolverStatus> GuessingValueIterationHelper<ValueType, TrivialRowGrouping>::tryVerify(
161 std::vector<ValueType>& lowerX, std::vector<ValueType>& upperX,
const std::vector<ValueType>& b, uint64_t& numIterations,
163 std::function<
SolverStatus(GVIData<ValueType>
const&)>
const& iterationCallback) {
166 guessLower[rowGroupToGuess] = guessUpper[rowGroupToGuess] = guessValue;
167 ValueType sumLengthBefore = 0;
168 GVIBackend<ValueType, Dir> guessingBackend(rowGroupToGuess);
169 GVIBackend<ValueType, Dir> iiBackend;
174 applyInPlace<Dir>(lowerX, upperX, b, iiBackend);
175 applyInPlace<Dir>(guessLower, guessUpper, b, guessingBackend);
176 auto guessedNewLower = guessingBackend.xGuessed;
177 auto guessedNewUpper = guessingBackend.yGuessed;
178 if (guessValue <= guessedNewLower) {
180 lowerX[rowGroupToGuess] = guessedNewLower;
183 if (guessedNewUpper <= guessValue) {
185 upperX[rowGroupToGuess] = guessedNewUpper;
189 auto sumLength = iterationHelper.getSumLength(guessLower, guessUpper);
190 if (sumLength == sumLengthBefore) {
194 sumLengthBefore = sumLength;
196 if (iterationHelper.checkConvergence(lowerX, upperX, relative, precision)) {
200 if (iterationCallback) {
201 status = iterationCallback({lowerX, upperX, status});
207template<
typename ValueType,
bool TrivialRowGrouping>
209 std::vector<ValueType>& lowerX, std::vector<ValueType>& upperX,
const std::vector<ValueType>& b, uint64_t& numIterations,
bool relative,
210 ValueType precision, std::optional<storm::solver::OptimizationDirection> dir,
212 if (!dir.has_value() ||
minimize(dir.value())) {
219template<
typename ValueType,
bool TrivialRowGrouping>
220template<OptimizationDirection Dir>
222 std::vector<ValueType>& lowerX, std::vector<ValueType>& upperX,
const std::vector<ValueType>& b, uint64_t& numIterations,
bool relative,
225 auto status = doIterations<Dir>(lowerX, upperX, b, numIterations, lowerX.size(), relative, precision, iterationCallback);
230 auto rowGroupToGuess = selectRowGroupToGuess(lowerX, upperX);
231 bool didVerify =
false;
233 for (
int den = 2; den < 30 && !didVerify; ++den) {
234 for (
int num = 1; num < den; num++) {
235 if (std::gcd(num, den) != 1) {
238 auto guessValue = (lowerX[rowGroupToGuess] * num + upperX[rowGroupToGuess] * (den - num)) / den;
239 auto [verifyResult, verifyStatus] =
240 tryVerify<Dir>(lowerX, upperX, b, numIterations, rowGroupToGuess, guessValue, relative, precision, iterationCallback);
241 status = verifyStatus;
249 if (iterationHelper.checkConvergence(lowerX, upperX, relative, precision)) {
258 return doIterations<Dir>(lowerX, upperX, b, numIterations, {}, relative, precision, iterationCallback);
261template<
typename ValueType,
bool TrivialRowGrouping>
264 : viOperator(viOperator), iterationHelper(matrix) {
268template<
typename ValueType,
bool TrivialRowGrouping>
269template<OptimizationDirection Dir>
270SolverStatus GuessingValueIterationHelper<ValueType, TrivialRowGrouping>::doIterations(
271 std::vector<ValueType>& lowerX, std::vector<ValueType>& upperX,
const std::vector<ValueType>& b, uint64_t& numIterations,
272 std::optional<uint64_t> maxIterations,
bool relative,
const ValueType& precision,
274 ValueType sumLengthBefore = 0;
275 uint64_t localIterations = 0;
279 applyInPlace<Dir>(lowerX, upperX, b, iiBackend);
283 auto sumLength = iterationHelper.getSumLength(lowerX, upperX);
284 if (sumLengthBefore == sumLength) {
288 sumLengthBefore = sumLength;
290 if (iterationHelper.checkConvergence(lowerX, upperX, relative, precision)) {
293 if (iterationCallback) {
294 status = iterationCallback(GVIData<ValueType>{lowerX, upperX, status});
298 if (iterationHelper.checkConvergence(lowerX, upperX, relative, precision)) {
void nextRow(std::pair< ValueType, ValueType > &&value, uint64_t rowGroup, uint64_t row)
bool constexpr converged() const
void applyUpdate(ValueType &xCurr, ValueType &yCurr, uint64_t rowGroup)
void firstRow(std::pair< ValueType, ValueType > &&value, uint64_t rowGroup, uint64_t row)
GVIBackend(uint64_t guessedRowGroup)
bool constexpr abort() const
void endOfIteration() const
Implements guessing value iteration.
GuessingValueIterationHelper(std::shared_ptr< ValueIterationOperator< ValueType, TrivialRowGrouping > > viOperator, const storage::SparseMatrix< ValueType > &matrix)
SolverStatus solveEquations(std::vector< ValueType > &lowerX, std::vector< ValueType > &upperX, const std::vector< ValueType > &b, uint64_t &numIterations, bool relative, ValueType precision, std::optional< storm::solver::OptimizationDirection > dir, std::function< SolverStatus(GVIData< ValueType > const &)> const &iterationCallback)
This class represents the Value Iteration Operator (also known as Bellman operator).
ValueType getSumLength(std::vector< ValueType > &lower, std::vector< ValueType > &upper) const
bool checkConvergence(std::vector< ValueType > const &lower, std::vector< ValueType > const &upper, bool relative, ValueType const &precision) const
IndexType selectRowGroupToGuess(const std::vector< ValueType > &lowerX, const std::vector< ValueType > &upperX)
IterationHelper(storm::storage::SparseMatrix< ValueType > const &matrix_)
A class that holds a possibly non-square matrix in the compressed row storage format.
Stores and manages an extremal (maximal or minimal) value.
bool constexpr minimize(OptimizationDirection d)
void addScaledVector(std::vector< InValueType1 > &firstOperand, std::vector< InValueType2 > const &secondOperand, InValueType3 const &factor)
Computes x:= x + a*y, i.e., adds each element of the first vector and (the corresponding element of t...
TargetType convertNumber(SourceType const &number)