From b698a7cfcb0ffbe394b12848df9261d106da7396 Mon Sep 17 00:00:00 2001 From: Stefan Pranger Date: Fri, 29 Jan 2021 19:15:17 +0100 Subject: [PATCH] native multiplying now supports optdir overrides --- src/storm/solver/NativeMultiplier.cpp | 34 +++--- src/storm/solver/NativeMultiplier.h | 24 ++-- src/storm/storage/SparseMatrix.cpp | 159 +++++++++++++++++++------- src/storm/storage/SparseMatrix.h | 24 ++-- 4 files changed, 157 insertions(+), 84 deletions(-) diff --git a/src/storm/solver/NativeMultiplier.cpp b/src/storm/solver/NativeMultiplier.cpp index 8b13d07cc..26dad0b22 100644 --- a/src/storm/solver/NativeMultiplier.cpp +++ b/src/storm/solver/NativeMultiplier.cpp @@ -60,9 +60,9 @@ namespace storm { this->matrix.multiplyWithVectorForward(x, x, b); } } - + template - void NativeMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices) const { + void NativeMultiplier::multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { std::vector* target = &result; if (&x == &result) { if (this->cachedVector) { @@ -73,31 +73,31 @@ namespace storm { target = this->cachedVector.get(); } if (parallelize(env)) { - multAddReduceParallel(dir, rowGroupIndices, x, b, *target, choices); + multAddReduceParallel(dir, rowGroupIndices, x, b, *target, choices, dirOverride); } else { - multAddReduce(dir, rowGroupIndices, x, b, *target, choices); + multAddReduce(dir, rowGroupIndices, x, b, *target, choices, dirOverride); } if (&x == &result) { std::swap(result, *this->cachedVector); } } - + template - void NativeMultiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices, bool backwards) const { + void NativeMultiplier::multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices, storm::storage::BitVector* dirOverride, bool backwards) const { if (backwards) { - this->matrix.multiplyAndReduceBackward(dir, rowGroupIndices, x, b, x, choices); + this->matrix.multiplyAndReduceBackward(dir, rowGroupIndices, x, b, x, choices, dirOverride); } else { - this->matrix.multiplyAndReduceForward(dir, rowGroupIndices, x, b, x, choices); + this->matrix.multiplyAndReduceForward(dir, rowGroupIndices, x, b, x, choices, dirOverride); } } - + template void NativeMultiplier::multiplyRow(uint64_t const& rowIndex, std::vector const& x, ValueType& value) const { for (auto const& entry : this->matrix.getRow(rowIndex)) { value += entry.getValue() * x[entry.getColumn()]; } } - + template void NativeMultiplier::multiplyRow2(uint64_t const& rowIndex, std::vector const& x1, ValueType& val1, std::vector const& x2, ValueType& val2) const { for (auto const& entry : this->matrix.getRow(rowIndex)) { @@ -110,12 +110,12 @@ namespace storm { void NativeMultiplier::multAdd(std::vector const& x, std::vector const* b, std::vector& result) const { this->matrix.multiplyWithVector(x, result, b); } - + template - void NativeMultiplier::multAddReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices) const { - this->matrix.multiplyAndReduce(dir, rowGroupIndices, x, b, result, choices); + void NativeMultiplier::multAddReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { + this->matrix.multiplyAndReduce(dir, rowGroupIndices, x, b, result, choices, dirOverride); } - + template void NativeMultiplier::multAddParallel(std::vector const& x, std::vector const* b, std::vector& result) const { #ifdef STORM_HAVE_INTELTBB @@ -125,11 +125,11 @@ namespace storm { multAdd(x, b, result); #endif } - + template - void NativeMultiplier::multAddReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices) const { + void NativeMultiplier::multAddReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { #ifdef STORM_HAVE_INTELTBB - this->matrix.multiplyAndReduceParallel(dir, rowGroupIndices, x, b, result, choices); + this->matrix.multiplyAndReduceParallel(dir, rowGroupIndices, x, b, result, choices, dirOverride); #else STORM_LOG_WARN("Storm was built without support for Intel TBB, defaulting to sequential version."); multAddReduce(dir, rowGroupIndices, x, b, result, choices); diff --git a/src/storm/solver/NativeMultiplier.h b/src/storm/solver/NativeMultiplier.h index 92424f91c..62ae47d07 100644 --- a/src/storm/solver/NativeMultiplier.h +++ b/src/storm/solver/NativeMultiplier.h @@ -9,33 +9,33 @@ namespace storm { template class SparseMatrix; } - + namespace solver { - + template class NativeMultiplier : public Multiplier { public: NativeMultiplier(storm::storage::SparseMatrix const& matrix); virtual ~NativeMultiplier() = default; - + virtual void multiply(Environment const& env, std::vector const& x, std::vector const* b, std::vector& result) const override; virtual void multiplyGaussSeidel(Environment const& env, std::vector& x, std::vector const* b, bool backwards = true) const override; - virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const override; - virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices = nullptr, bool backwards = true) const override; + virtual void multiplyAndReduce(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr, storm::storage::BitVector* dirOverride = nullptr) const override; + virtual void multiplyAndReduceGaussSeidel(Environment const& env, OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector& x, std::vector const* b, std::vector* choices = nullptr, storm::storage::BitVector* dirOverride = nullptr, bool backwards = true) const override; virtual void multiplyRow(uint64_t const& rowIndex, std::vector const& x, ValueType& value) const override; virtual void multiplyRow2(uint64_t const& rowIndex, std::vector const& x1, ValueType& val1, std::vector const& x2, ValueType& val2) const override; private: bool parallelize(Environment const& env) const; - + void multAdd(std::vector const& x, std::vector const* b, std::vector& result) const; - - void multAddReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const; - + + void multAddReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr, storm::storage::BitVector* dirOverride = nullptr) const; + void multAddParallel(std::vector const& x, std::vector const* b, std::vector& result) const; - void multAddReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr) const; - + void multAddReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& x, std::vector const* b, std::vector& result, std::vector* choices = nullptr, storm::storage::BitVector* dirOverride = nullptr) const; + }; - + } } diff --git a/src/storm/storage/SparseMatrix.cpp b/src/storm/storage/SparseMatrix.cpp index d89f7a568..84b8fa306 100644 --- a/src/storm/storage/SparseMatrix.cpp +++ b/src/storm/storage/SparseMatrix.cpp @@ -1753,17 +1753,25 @@ namespace storm { #endif template - void SparseMatrix::multiplyAndReduceForward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { - if (dir == OptimizationDirection::Minimize) { - multiplyAndReduceForward>(rowGroupIndices, vector, summand, result, choices); + void SparseMatrix::multiplyAndReduceForward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { + if(dirOverride && !dirOverride->empty()) { + if (dir == OptimizationDirection::Minimize) { + multiplyAndReduceForward, true>(rowGroupIndices, vector, summand, result, choices, dirOverride); + } else { + multiplyAndReduceForward, true>(rowGroupIndices, vector, summand, result, choices, dirOverride); + } } else { - multiplyAndReduceForward>(rowGroupIndices, vector, summand, result, choices); + if (dir == OptimizationDirection::Minimize) { + multiplyAndReduceForward, false>(rowGroupIndices, vector, summand, result, choices); + } else { + multiplyAndReduceForward, false>(rowGroupIndices, vector, summand, result, choices); + } } } template - template - void SparseMatrix::multiplyAndReduceForward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { + template + void SparseMatrix::multiplyAndReduceForward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { Compare compare; auto elementIt = this->begin(); auto rowGroupIt = rowGroupIndices.begin(); @@ -1782,7 +1790,8 @@ namespace storm { uint64_t selectedChoice; uint64_t currentRow = 0; - for (auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt) { + uint64_t currentRowGroup = 0; + for (auto resultIt = result.begin(), resultIte = result.end(); resultIt != resultIte; ++resultIt, ++choiceIt, ++rowGroupIt, ++currentRowGroup) { ValueType currentValue = storm::utility::zero(); // Only multiply and reduce if there is at least one row in the group. @@ -1816,10 +1825,19 @@ namespace storm { oldSelectedChoiceValue = newValue; } - if (compare(newValue, currentValue)) { - currentValue = newValue; - if (choices) { - selectedChoice = currentRow - *rowGroupIt; + if(dirOverridden) { + if (dirOverride->get(currentRowGroup) ? compare(currentValue, newValue) : compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *rowGroupIt; + } + } + } else { + if (compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *rowGroupIt; + } } } if (summand) { @@ -1829,8 +1847,14 @@ namespace storm { // Finally write value to target vector. *resultIt = currentValue; - if (choices && compare(currentValue, oldSelectedChoiceValue)) { - *choiceIt = selectedChoice; + if(dirOverridden) { + if (choices && dirOverride->get(currentRowGroup) ? compare(oldSelectedChoiceValue, currentValue) : compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } + } else { + if (choices && compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } } } } @@ -1838,23 +1862,31 @@ namespace storm { #ifdef STORM_HAVE_CARL template<> - void SparseMatrix::multiplyAndReduceForward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const { + void SparseMatrix::multiplyAndReduceForward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This operation is not supported."); } #endif template - void SparseMatrix::multiplyAndReduceBackward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { - if (dir == storm::OptimizationDirection::Minimize) { - multiplyAndReduceBackward>(rowGroupIndices, vector, summand, result, choices); + void SparseMatrix::multiplyAndReduceBackward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { + if(dirOverride && !dirOverride->empty()) { + if (dir == storm::OptimizationDirection::Minimize) { + multiplyAndReduceBackward, true>(rowGroupIndices, vector, summand, result, choices, dirOverride); + } else { + multiplyAndReduceBackward, true>(rowGroupIndices, vector, summand, result, choices, dirOverride); + } } else { - multiplyAndReduceBackward>(rowGroupIndices, vector, summand, result, choices); + if (dir == storm::OptimizationDirection::Minimize) { + multiplyAndReduceBackward, false>(rowGroupIndices, vector, summand, result, choices); + } else { + multiplyAndReduceBackward, false>(rowGroupIndices, vector, summand, result, choices); + } } } template - template - void SparseMatrix::multiplyAndReduceBackward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { + template + void SparseMatrix::multiplyAndReduceBackward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { Compare compare; auto elementIt = this->end() - 1; auto rowGroupIt = rowGroupIndices.end() - 2; @@ -1873,7 +1905,8 @@ namespace storm { uint64_t selectedChoice; uint64_t currentRow = this->getRowCount() - 1; - for (auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt) { + uint64_t currentRowGroup = this->getRowGroupCount() - 2; + for (auto resultIt = result.end() - 1, resultIte = result.begin() - 1; resultIt != resultIte; --resultIt, --choiceIt, --rowGroupIt, --currentRowGroup) { ValueType currentValue = storm::utility::zero(); // Only multiply and reduce if there is at least one row in the group. @@ -1905,18 +1938,33 @@ namespace storm { oldSelectedChoiceValue = newValue; } - if (compare(newValue, currentValue)) { - currentValue = newValue; - if (choices) { - selectedChoice = currentRow - *rowGroupIt; + if(directionOverridden) { + if (dirOverride->get(currentRowGroup) ? compare(currentValue, newValue) : compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *rowGroupIt; + } + } + } else { + if (compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *rowGroupIt; + } } } } // Finally write value to target vector. *resultIt = currentValue; - if (choices && compare(currentValue, oldSelectedChoiceValue)) { - *choiceIt = selectedChoice; + if(directionOverridden) { + if (choices && dirOverride->get(currentRowGroup) ? compare(oldSelectedChoiceValue, currentValue) : compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } + } else { + if (choices && compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } } } } @@ -1924,20 +1972,20 @@ namespace storm { #ifdef STORM_HAVE_CARL template<> - void SparseMatrix::multiplyAndReduceBackward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const { + void SparseMatrix::multiplyAndReduceBackward(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This operation is not supported."); } #endif #ifdef STORM_HAVE_INTELTBB - template + template class TbbMultAddReduceFunctor { public: typedef typename storm::storage::SparseMatrix::index_type index_type; typedef typename storm::storage::SparseMatrix::value_type value_type; typedef typename storm::storage::SparseMatrix::const_iterator const_iterator; - TbbMultAddReduceFunctor(std::vector const& rowGroupIndices, std::vector> const& columnsAndEntries, std::vector const& rowIndications, std::vector const& x, std::vector& result, std::vector const* summand, std::vector* choices) : rowGroupIndices(rowGroupIndices), columnsAndEntries(columnsAndEntries), rowIndications(rowIndications), x(x), result(result), summand(summand), choices(choices) { + TbbMultAddReduceFunctor(std::vector const& rowGroupIndices, std::vector> const& columnsAndEntries, std::vector const& rowIndications, std::vector const& x, std::vector& result, std::vector const* summand, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) : rowGroupIndices(rowGroupIndices), columnsAndEntries(columnsAndEntries), rowIndications(rowIndications), x(x), result(result), summand(summand), choices(choices), dirOverride(dirOverride) { // Intentionally left empty. } @@ -1964,7 +2012,8 @@ namespace storm { uint64_t selectedChoice; uint64_t currentRow = *groupIt; - for (; groupIt != groupIte; ++groupIt, ++resultIt, ++choiceIt) { + uint64_t currentRowGroup = *groupIt; + for (; groupIt != groupIte; ++groupIt, ++resultIt, ++choiceIt, ++currentRowGroup) { ValueType currentValue = storm::utility::zero(); // Only multiply and reduce if there is at least one row in the group. @@ -1998,18 +2047,33 @@ namespace storm { oldSelectedChoiceValue = newValue; } - if (compare(newValue, currentValue)) { - currentValue = newValue; - if (choices) { - selectedChoice = currentRow - *groupIt; + if(directionOverridden) { + if (dirOverride.get()->get(currentRowGroup) ? compare(currentValue, newValue) : compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *groupIt; + } + } + } else { + if (compare(newValue, currentValue)) { + currentValue = newValue; + if (choices) { + selectedChoice = currentRow - *groupIt; + } } } } // Finally write value to target vector. *resultIt = currentValue; - if (choices && compare(currentValue, oldSelectedChoiceValue)) { - *choiceIt = selectedChoice; + if(directionOverridden) { + if (choices && dirOverride.get()->get(currentRowGroup) ? compare(oldSelectedChoiceValue, currentValue) : compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } + } else { + if (choices && compare(currentValue, oldSelectedChoiceValue)) { + *choiceIt = selectedChoice; + } } } } @@ -2024,27 +2088,36 @@ namespace storm { std::vector& result; std::vector const* summand; std::vector* choices; + boost::optional dirOverride = boost::none; }; template - void SparseMatrix::multiplyAndReduceParallel(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { - if (dir == storm::OptimizationDirection::Minimize) { - tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices)); + void SparseMatrix::multiplyAndReduceParallel(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { + if(dirOverride && !dirOverride->empty()) { + if (dir == storm::OptimizationDirection::Minimize) { + tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor, true>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices, dirOverride)); + } else { + tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor, true>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices, dirOverride)); + } } else { - tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices)); + if (dir == storm::OptimizationDirection::Minimize) { + tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor, false>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices)); + } else { + tbb::parallel_for(tbb::blocked_range(0, rowGroupIndices.size() - 1, 100), TbbMultAddReduceFunctor, false>(rowGroupIndices, columnsAndValues, rowIndications, vector, result, summand, choices)); + } } } #ifdef STORM_HAVE_CARL template<> - void SparseMatrix::multiplyAndReduceParallel(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { + void SparseMatrix::multiplyAndReduceParallel(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "This operation is not supported."); } #endif #endif template - void SparseMatrix::multiplyAndReduce(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const { + void SparseMatrix::multiplyAndReduce(OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride) const { // If the vector and the result are aliases, we need and temporary vector. std::vector* target; diff --git a/src/storm/storage/SparseMatrix.h b/src/storm/storage/SparseMatrix.h index ba25a2819..8346e5554 100644 --- a/src/storm/storage/SparseMatrix.h +++ b/src/storm/storage/SparseMatrix.h @@ -907,19 +907,19 @@ namespace storm { * the 'new' choice has a value strictly better (wrt. to the optimization direction) value. * @return The resulting vector the content of the given result vector. */ - void multiplyAndReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const; - - void multiplyAndReduceForward(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const; - template - void multiplyAndReduceForward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices) const; - - void multiplyAndReduceBackward(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const; - template - void multiplyAndReduceBackward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const; + void multiplyAndReduce(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; + + void multiplyAndReduceForward(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; + template + void multiplyAndReduceForward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* summand, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; + + void multiplyAndReduceBackward(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; + template + void multiplyAndReduceBackward(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; #ifdef STORM_HAVE_INTELTBB - void multiplyAndReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const; - template - void multiplyAndReduceParallel(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices) const; + void multiplyAndReduceParallel(storm::solver::OptimizationDirection const& dir, std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; + template + void multiplyAndReduceParallel(std::vector const& rowGroupIndices, std::vector const& vector, std::vector const* b, std::vector& result, std::vector* choices, storm::storage::BitVector* dirOverride = nullptr) const; #endif /*!