dehnert
7 years ago
13 changed files with 756 additions and 483 deletions
-
299src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.cpp
-
98src/storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h
-
142src/storm/modelchecker/prctl/helper/SparseDtmcPrctlHelper.cpp
-
118src/storm/modelchecker/prctl/helper/SparseMdpPrctlHelper.cpp
-
158src/storm/solver/AbstractEquationSolver.cpp
-
107src/storm/solver/AbstractEquationSolver.h
-
29src/storm/solver/IterativeMinMaxLinearEquationSolver.cpp
-
116src/storm/solver/LinearEquationSolver.cpp
-
88src/storm/solver/LinearEquationSolver.h
-
38src/storm/solver/MinMaxLinearEquationSolver.cpp
-
43src/storm/solver/MinMaxLinearEquationSolver.h
-
2src/storm/solver/NativeLinearEquationSolver.cpp
-
1src/storm/storage/ConsecutiveUint64DynamicPriorityQueue.h
@ -0,0 +1,299 @@ |
|||
#include "storm/modelchecker/prctl/helper/DsMpiUpperRewardBoundsComputer.h"
|
|||
|
|||
#include "storm-config.h"
|
|||
|
|||
#include "storm/storage/BitVector.h"
|
|||
#include "storm/storage/ConsecutiveUint64DynamicPriorityQueue.h"
|
|||
#include "storm/storage/SparseMatrix.h"
|
|||
|
|||
#include "storm/storage/sparse/StateType.h"
|
|||
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/utility/constants.h"
|
|||
#include "storm/utility/ConstantsComparator.h"
|
|||
|
|||
namespace storm { |
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
template<typename ValueType> |
|||
DsMpiDtmcUpperRewardBoundsComputer<ValueType>::DsMpiDtmcUpperRewardBoundsComputer(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards, std::vector<ValueType> const& oneStepTargetProbabilities) : transitionMatrix(transitionMatrix), originalRewards(rewards), originalOneStepTargetProbabilities(oneStepTargetProbabilities), backwardTransitions(transitionMatrix.transpose()), p(transitionMatrix.getRowGroupCount()), w(transitionMatrix.getRowGroupCount()), rewards(rewards), targetProbabilities(oneStepTargetProbabilities) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
template<typename ValueType> |
|||
std::vector<ValueType> DsMpiDtmcUpperRewardBoundsComputer<ValueType>::computeUpperBounds() { |
|||
sweep(); |
|||
ValueType lambda = computeLambda(); |
|||
STORM_LOG_TRACE("DS-MPI computed lambda as " << lambda << "."); |
|||
|
|||
// Finally compute the upper bounds for the states.
|
|||
std::vector<ValueType> result(transitionMatrix.getRowGroupCount()); |
|||
auto one = storm::utility::one<ValueType>(); |
|||
for (storm::storage::sparse::state_type state = 0; state < result.size(); ++state) { |
|||
result[state] = w[state] + (one - p[state]) * lambda; |
|||
} |
|||
|
|||
#ifndef NDEBUG
|
|||
ValueType max = storm::utility::zero<ValueType>(); |
|||
uint64_t nonZeroCount = 0; |
|||
for (auto const& e : result) { |
|||
if (!storm::utility::isZero(e)) { |
|||
++nonZeroCount; |
|||
max = std::max(max, e); |
|||
} |
|||
} |
|||
STORM_LOG_TRACE("DS-MPI computed " << nonZeroCount << " non-zero upper bounds and a maximal bound of " << max << "."); |
|||
#endif
|
|||
return result; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
ValueType DsMpiDtmcUpperRewardBoundsComputer<ValueType>::computeLambda() const { |
|||
ValueType lambda = storm::utility::zero<ValueType>(); |
|||
for (storm::storage::sparse::state_type state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { |
|||
lambda = std::max(lambda, computeLambdaForChoice(state)); |
|||
} |
|||
return lambda; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
ValueType DsMpiDtmcUpperRewardBoundsComputer<ValueType>::computeLambdaForChoice(uint64_t choice) const { |
|||
ValueType localLambda = storm::utility::zero<ValueType>(); |
|||
uint64_t state = this->getStateForChoice(choice); |
|||
|
|||
// Check whether condition (I) or (II) applies.
|
|||
ValueType sum = storm::utility::zero<ValueType>(); |
|||
for (auto const& e : transitionMatrix.getRow(choice)) { |
|||
sum += e.getValue() * p[e.getColumn()]; |
|||
} |
|||
sum += originalOneStepTargetProbabilities[choice]; |
|||
|
|||
if (p[state] < sum) { |
|||
STORM_LOG_TRACE("Condition (I) does apply for state " << state << " as " << p[state] << " < " << sum << "."); |
|||
// Condition (I) applies.
|
|||
localLambda = sum - p[state]; |
|||
ValueType nominator = originalRewards[choice]; |
|||
for (auto const& e : transitionMatrix.getRow(choice)) { |
|||
nominator += e.getValue() * w[e.getColumn()]; |
|||
} |
|||
nominator -= w[state]; |
|||
localLambda = nominator / localLambda; |
|||
} else { |
|||
STORM_LOG_TRACE("Condition (I) does not apply for state " << state << " as " << p[state] << " < " << sum << "."); |
|||
// Here, condition (II) automatically applies and as the resulting local lambda is 0, we
|
|||
// don't need to consider it.
|
|||
|
|||
#ifndef NDEBUG
|
|||
// Actually check condition (II).
|
|||
ValueType sum = originalRewards[choice]; |
|||
for (auto const& e : transitionMatrix.getRow(choice)) { |
|||
sum += e.getValue() * w[e.getColumn()]; |
|||
} |
|||
STORM_LOG_WARN_COND(w[state] >= sum || storm::utility::ConstantsComparator<ValueType>().isEqual(w[state], sum), "Expected condition (II) to hold in state " << state << ", but " << w[state] << " < " << sum << "."); |
|||
#endif
|
|||
} |
|||
|
|||
return localLambda; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
uint64_t DsMpiDtmcUpperRewardBoundsComputer<ValueType>::getStateForChoice(uint64_t choice) const { |
|||
return choice; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiDtmcPriorityLess { |
|||
public: |
|||
DsMpiDtmcPriorityLess(DsMpiDtmcUpperRewardBoundsComputer<ValueType> const& dsmpi) : dsmpi(dsmpi) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
bool operator()(storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { |
|||
ValueType pa = dsmpi.targetProbabilities[a]; |
|||
ValueType pb = dsmpi.targetProbabilities[b]; |
|||
if (pa < pb) { |
|||
return true; |
|||
} else if (pa == pb) { |
|||
return dsmpi.rewards[a] > dsmpi.rewards[b]; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private: |
|||
DsMpiDtmcUpperRewardBoundsComputer<ValueType> const& dsmpi; |
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
void DsMpiDtmcUpperRewardBoundsComputer<ValueType>::sweep() { |
|||
// Create a priority queue that allows for easy retrieval of the currently best state.
|
|||
storm::storage::ConsecutiveUint64DynamicPriorityQueue<DsMpiDtmcPriorityLess<ValueType>> queue(transitionMatrix.getRowCount(), DsMpiDtmcPriorityLess<ValueType>(*this)); |
|||
|
|||
// Keep track of visited states.
|
|||
storm::storage::BitVector visited(p.size()); |
|||
|
|||
while (!queue.empty()) { |
|||
// Get first entry in queue.
|
|||
storm::storage::sparse::state_type currentState = queue.popTop(); |
|||
|
|||
// Mark state as visited.
|
|||
visited.set(currentState); |
|||
|
|||
// Set weight and probability for the state.
|
|||
w[currentState] = rewards[currentState]; |
|||
p[currentState] = targetProbabilities[currentState]; |
|||
|
|||
for (auto const& e : backwardTransitions.getRow(currentState)) { |
|||
if (visited.get(e.getColumn())) { |
|||
continue; |
|||
} |
|||
|
|||
// Update reward/probability values.
|
|||
rewards[e.getColumn()] += e.getValue() * w[currentState]; |
|||
targetProbabilities[e.getColumn()] += e.getValue() * p[currentState]; |
|||
|
|||
// Increase priority of element.
|
|||
queue.increase(e.getColumn()); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
DsMpiMdpUpperRewardBoundsComputer<ValueType>::DsMpiMdpUpperRewardBoundsComputer(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards, std::vector<ValueType> const& oneStepTargetProbabilities) : DsMpiDtmcUpperRewardBoundsComputer<ValueType>(transitionMatrix, rewards, oneStepTargetProbabilities), policy(transitionMatrix.getRowCount()) { |
|||
|
|||
// Create a mapping from choices to states.
|
|||
// Also pick a choice in each state that maximizes the target probability and minimizes the reward.
|
|||
choiceToState.resize(transitionMatrix.getRowCount()); |
|||
for (uint64_t state = 0; state < transitionMatrix.getRowGroupCount(); ++state) { |
|||
uint64_t choice = transitionMatrix.getRowGroupIndices()[state]; |
|||
|
|||
boost::optional<ValueType> minReward; |
|||
ValueType maxProb = storm::utility::zero<ValueType>(); |
|||
|
|||
for (uint64_t row = choice, endRow = transitionMatrix.getRowGroupIndices()[state + 1]; row < endRow; ++row) { |
|||
choiceToState[row] = state; |
|||
|
|||
if (this->targetProbabilities[row] > maxProb) { |
|||
maxProb = this->targetProbabilities[row]; |
|||
minReward = this->rewards[row]; |
|||
choice = row; |
|||
} else if (this->targetProbabilities[row] == maxProb && (!minReward || minReward.get() > this->rewards[row])) { |
|||
minReward = this->rewards[row]; |
|||
choice = row; |
|||
} |
|||
} |
|||
|
|||
setChoiceInState(state, choice); |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
ValueType DsMpiMdpUpperRewardBoundsComputer<ValueType>::computeLambda() const { |
|||
ValueType lambda = storm::utility::zero<ValueType>(); |
|||
for (storm::storage::sparse::state_type state = 0; state < this->transitionMatrix.getRowGroupCount(); ++state) { |
|||
lambda = std::max(lambda, this->computeLambdaForChoice(this->getChoiceInState(state))); |
|||
} |
|||
return lambda; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getStateForChoice(uint64_t choice) const { |
|||
return choiceToState[choice]; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiMdpPriorityLess { |
|||
public: |
|||
DsMpiMdpPriorityLess(DsMpiMdpUpperRewardBoundsComputer<ValueType> const& dsmpi) : dsmpi(dsmpi) { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
bool operator()(storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { |
|||
uint64_t choiceA = dsmpi.getChoiceInState(a); |
|||
uint64_t choiceB = dsmpi.getChoiceInState(b); |
|||
|
|||
ValueType pa = dsmpi.targetProbabilities[choiceA]; |
|||
ValueType pb = dsmpi.targetProbabilities[choiceB]; |
|||
if (pa < pb) { |
|||
return true; |
|||
} else if (pa == pb) { |
|||
return dsmpi.rewards[choiceB] > dsmpi.rewards[choiceB]; |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
private: |
|||
DsMpiMdpUpperRewardBoundsComputer<ValueType> const& dsmpi; |
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
void DsMpiMdpUpperRewardBoundsComputer<ValueType>::sweep() { |
|||
// Create a priority queue that allows for easy retrieval of the currently best state.
|
|||
storm::storage::ConsecutiveUint64DynamicPriorityQueue<DsMpiMdpPriorityLess<ValueType>> queue(this->transitionMatrix.getRowGroupCount(), DsMpiMdpPriorityLess<ValueType>(*this)); |
|||
|
|||
// Keep track of visited states.
|
|||
storm::storage::BitVector visited(this->transitionMatrix.getRowGroupCount()); |
|||
|
|||
while (!queue.empty()) { |
|||
// Get first entry in queue.
|
|||
storm::storage::sparse::state_type currentState = queue.popTop(); |
|||
|
|||
// Mark state as visited.
|
|||
visited.set(currentState); |
|||
|
|||
// Set weight and probability for the state.
|
|||
uint64_t choiceInCurrentState = this->getChoiceInState(currentState); |
|||
this->w[currentState] = this->rewards[choiceInCurrentState]; |
|||
this->p[currentState] = this->targetProbabilities[choiceInCurrentState]; |
|||
|
|||
for (auto const& choiceEntry : this->backwardTransitions.getRow(currentState)) { |
|||
uint64_t predecessor = this->getStateForChoice(choiceEntry.getColumn()); |
|||
if (visited.get(predecessor)) { |
|||
continue; |
|||
} |
|||
|
|||
// Update reward/probability values.
|
|||
this->rewards[choiceEntry.getColumn()] += choiceEntry.getValue() * this->w[currentState]; |
|||
this->targetProbabilities[choiceEntry.getColumn()] += choiceEntry.getValue() * this->p[currentState]; |
|||
|
|||
// If the choice is not the one that is currently taken in the predecessor state, we might need
|
|||
// to update it.
|
|||
uint64_t currentChoiceInPredecessor = this->getChoiceInState(predecessor); |
|||
if (currentChoiceInPredecessor != choiceEntry.getColumn()) { |
|||
// Check whether the updates choice now becomes a better choice in the predecessor state.
|
|||
ValueType const& newTargetProbability = this->targetProbabilities[choiceEntry.getColumn()]; |
|||
ValueType const& newReward = this->rewards[choiceEntry.getColumn()]; |
|||
ValueType const& currentTargetProbability = this->targetProbabilities[this->getChoiceInState(predecessor)]; |
|||
ValueType const& currentReward = this->rewards[this->getChoiceInState(predecessor)]; |
|||
|
|||
if (newTargetProbability > currentTargetProbability || (newTargetProbability == currentTargetProbability && newReward < currentReward)) { |
|||
setChoiceInState(predecessor, choiceEntry.getColumn()); |
|||
} |
|||
} |
|||
|
|||
// Notify the priority of a potential increase of the priority of the element.
|
|||
queue.increase(predecessor); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
uint64_t DsMpiMdpUpperRewardBoundsComputer<ValueType>::getChoiceInState(uint64_t state) const { |
|||
return policy[state]; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void DsMpiMdpUpperRewardBoundsComputer<ValueType>::setChoiceInState(uint64_t state, uint64_t choice) { |
|||
policy[state] = choice; |
|||
} |
|||
|
|||
template class DsMpiDtmcUpperRewardBoundsComputer<double>; |
|||
template class DsMpiMdpUpperRewardBoundsComputer<double>; |
|||
|
|||
#ifdef STORM_HAVE_CARL
|
|||
template class DsMpiDtmcUpperRewardBoundsComputer<storm::RationalNumber>; |
|||
template class DsMpiMdpUpperRewardBoundsComputer<storm::RationalNumber>; |
|||
#endif
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,98 @@ |
|||
#pragma once |
|||
|
|||
#include <vector> |
|||
|
|||
namespace storm { |
|||
namespace storage { |
|||
template<typename ValueType> |
|||
class SparseMatrix; |
|||
} |
|||
|
|||
namespace modelchecker { |
|||
namespace helper { |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiDtmcPriorityLess; |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiDtmcUpperRewardBoundsComputer { |
|||
public: |
|||
/*! |
|||
* Creates an object that can compute upper bounds on the expected rewards for the provided DTMC. |
|||
* |
|||
* @param transitionMatrix The matrix defining the transitions of the system without the transitions |
|||
* that lead directly to the goal state. |
|||
* @param rewards The rewards of each state. |
|||
* @param oneStepTargetProbabilities For each state the probability to go to a goal state in one step. |
|||
*/ |
|||
DsMpiDtmcUpperRewardBoundsComputer(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards, std::vector<ValueType> const& oneStepTargetProbabilities); |
|||
|
|||
/*! |
|||
* Computes upper bounds on the expected rewards. |
|||
*/ |
|||
std::vector<ValueType> computeUpperBounds(); |
|||
|
|||
protected: |
|||
/*! |
|||
* Performs a Dijkstra sweep. |
|||
*/ |
|||
virtual void sweep(); |
|||
|
|||
/*! |
|||
* Computes the lambda used for the estimation. |
|||
*/ |
|||
virtual ValueType computeLambda() const; |
|||
|
|||
/*! |
|||
* Computes the lambda just for the provided choice. |
|||
*/ |
|||
ValueType computeLambdaForChoice(uint64_t choice) const; |
|||
|
|||
/*! |
|||
* Retrieves the state associated with the given choice. |
|||
*/ |
|||
virtual uint64_t getStateForChoice(uint64_t choice) const; |
|||
|
|||
// References to input data. |
|||
storm::storage::SparseMatrix<ValueType> const& transitionMatrix; |
|||
std::vector<ValueType> const& originalRewards; |
|||
std::vector<ValueType> const& originalOneStepTargetProbabilities; |
|||
|
|||
// Derived from input data. |
|||
storm::storage::SparseMatrix<ValueType> backwardTransitions; |
|||
|
|||
// Data that the algorithm uses internally. |
|||
std::vector<ValueType> p; |
|||
std::vector<ValueType> w; |
|||
std::vector<ValueType> rewards; |
|||
std::vector<ValueType> targetProbabilities; |
|||
|
|||
friend class DsMpiDtmcPriorityLess<ValueType>; |
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiMdpPriorityLess; |
|||
|
|||
template<typename ValueType> |
|||
class DsMpiMdpUpperRewardBoundsComputer : public DsMpiDtmcUpperRewardBoundsComputer<ValueType> { |
|||
public: |
|||
/*! |
|||
* Creates an object that can compute upper bounds on the expected rewards for the provided DTMC. |
|||
*/ |
|||
DsMpiMdpUpperRewardBoundsComputer(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<ValueType> const& rewards, std::vector<ValueType> const& oneStepTargetProbabilities); |
|||
|
|||
private: |
|||
virtual void sweep() override; |
|||
virtual ValueType computeLambda() const override; |
|||
virtual uint64_t getStateForChoice(uint64_t choice) const override; |
|||
uint64_t getChoiceInState(uint64_t state) const; |
|||
void setChoiceInState(uint64_t state, uint64_t choice); |
|||
|
|||
std::vector<uint64_t> choiceToState; |
|||
std::vector<uint64_t> policy; |
|||
|
|||
friend class DsMpiMdpPriorityLess<ValueType>; |
|||
}; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,158 @@ |
|||
#include "storm/solver/AbstractEquationSolver.h"
|
|||
|
|||
#include "storm/adapters/RationalNumberAdapter.h"
|
|||
#include "storm/adapters/RationalFunctionAdapter.h"
|
|||
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/exceptions/UnmetRequirementException.h"
|
|||
|
|||
namespace storm { |
|||
namespace solver { |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setTerminationCondition(std::unique_ptr<TerminationCondition<ValueType>> terminationCondition) { |
|||
this->terminationCondition = std::move(terminationCondition); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::resetTerminationCondition() { |
|||
this->terminationCondition = nullptr; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
bool AbstractEquationSolver<ValueType>::hasCustomTerminationCondition() const { |
|||
return static_cast<bool>(this->terminationCondition); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
TerminationCondition<ValueType> const& AbstractEquationSolver<ValueType>::getTerminationCondition() const { |
|||
return *terminationCondition; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
bool AbstractEquationSolver<ValueType>::hasLowerBound(BoundType const& type) const { |
|||
if (type == BoundType::Any) { |
|||
return static_cast<bool>(lowerBound) || static_cast<bool>(lowerBounds); |
|||
} else if (type == BoundType::Global) { |
|||
return static_cast<bool>(lowerBound); |
|||
} else if (type == BoundType::Local) { |
|||
return static_cast<bool>(lowerBounds); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
bool AbstractEquationSolver<ValueType>::hasUpperBound(BoundType const& type) const { |
|||
if (type == BoundType::Any) { |
|||
return static_cast<bool>(upperBound) || static_cast<bool>(upperBounds); |
|||
} else if (type == BoundType::Global) { |
|||
return static_cast<bool>(upperBound); |
|||
} else if (type == BoundType::Local) { |
|||
return static_cast<bool>(upperBounds); |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setLowerBound(ValueType const& value) { |
|||
lowerBound = value; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setUpperBound(ValueType const& value) { |
|||
upperBound = value; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setBounds(ValueType const& lower, ValueType const& upper) { |
|||
setLowerBound(lower); |
|||
setUpperBound(upper); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
ValueType const& AbstractEquationSolver<ValueType>::getLowerBound() const { |
|||
return lowerBound.get(); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
ValueType const& AbstractEquationSolver<ValueType>::getUpperBound() const { |
|||
return upperBound.get(); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getLowerBounds() const { |
|||
return lowerBounds.get(); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
std::vector<ValueType> const& AbstractEquationSolver<ValueType>::getUpperBounds() const { |
|||
return upperBounds.get(); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setLowerBounds(std::vector<ValueType> const& values) { |
|||
lowerBounds = values; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType> const& values) { |
|||
upperBounds = values; |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setUpperBounds(std::vector<ValueType>&& values) { |
|||
upperBounds = std::move(values); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::setBounds(std::vector<ValueType> const& lower, std::vector<ValueType> const& upper) { |
|||
setLowerBounds(lower); |
|||
setUpperBounds(upper); |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::createLowerBoundsVector(std::vector<ValueType>& lowerBoundsVector) const { |
|||
if (this->hasLowerBound(BoundType::Local)) { |
|||
lowerBoundsVector = this->getLowerBounds(); |
|||
} else { |
|||
STORM_LOG_THROW(this->hasLowerBound(BoundType::Global), storm::exceptions::UnmetRequirementException, "Cannot create lower bounds vector without lower bound."); |
|||
for (auto& e : lowerBoundsVector) { |
|||
e = this->getLowerBound(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
template<typename ValueType> |
|||
void AbstractEquationSolver<ValueType>::createUpperBoundsVector(std::unique_ptr<std::vector<ValueType>>& upperBoundsVector, uint64_t length) const { |
|||
STORM_LOG_ASSERT(this->hasUpperBound(), "Expecting upper bound(s)."); |
|||
if (!upperBoundsVector) { |
|||
if (this->hasUpperBound(BoundType::Local)) { |
|||
STORM_LOG_ASSERT(length == this->getUpperBounds().size(), "Mismatching sizes."); |
|||
upperBoundsVector = std::make_unique<std::vector<ValueType>>(this->getUpperBounds()); |
|||
} else { |
|||
upperBoundsVector = std::make_unique<std::vector<ValueType>>(length, this->getUpperBound()); |
|||
} |
|||
} else { |
|||
if (this->hasUpperBound(BoundType::Global)) { |
|||
for (auto& e : *upperBoundsVector) { |
|||
e = this->getUpperBound(); |
|||
} |
|||
} else { |
|||
auto upperBoundsIt = this->getUpperBounds().begin(); |
|||
for (auto& e : *upperBoundsVector) { |
|||
e = *upperBoundsIt; |
|||
++upperBoundsIt; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
template class AbstractEquationSolver<double>; |
|||
|
|||
#ifdef STORM_HAVE_CARL
|
|||
template class AbstractEquationSolver<storm::RationalNumber>; |
|||
template class AbstractEquationSolver<storm::RationalFunction>; |
|||
#endif
|
|||
|
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue