Browse Source

trying to get the new infrastructure of the DD abstraction layer integrated into the other parts of storm

Former-commit-id: 80a6634565
main
dehnert 10 years ago
parent
commit
7fa7381047
  1. 73
      src/adapters/AddExpressionAdapter.cpp
  2. 2
      src/adapters/AddExpressionAdapter.h
  3. 12
      src/modelchecker/csl/HybridCtmcCslModelChecker.cpp
  4. 8
      src/modelchecker/csl/HybridCtmcCslModelChecker.h
  5. 50
      src/modelchecker/csl/helper/HybridCtmcCslHelper.cpp
  6. 20
      src/modelchecker/csl/helper/HybridCtmcCslHelper.h
  7. 2
      src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp
  8. 4
      src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h
  9. 13
      src/modelchecker/propositional/SymbolicPropositionalModelChecker.h
  10. 32
      src/modelchecker/results/CheckResult.h
  11. 18
      src/modelchecker/results/HybridQuantitativeCheckResult.h
  12. 2
      src/modelchecker/results/SymbolicQualitativeCheckResult.h
  13. 12
      src/modelchecker/results/SymbolicQuantitativeCheckResult.h
  14. 24
      src/models/symbolic/Ctmc.h
  15. 20
      src/models/symbolic/DeterministicModel.h
  16. 20
      src/models/symbolic/Dtmc.h
  17. 20
      src/models/symbolic/Mdp.h
  18. 42
      src/models/symbolic/Model.h
  19. 38
      src/models/symbolic/StandardRewardModel.h
  20. 626
      src/storage/dd/Add.cpp
  21. 671
      src/storage/dd/Add.h
  22. 3
      src/storage/dd/AddIterator.h
  23. 4
      src/storage/dd/Bdd.cpp
  24. 2
      src/storage/dd/Bdd.h
  25. 1084
      src/storage/dd/cudd/CuddAdd.cpp
  26. 828
      src/storage/dd/cudd/CuddAdd.h
  27. 37
      src/storage/dd/cudd/CuddAddIterator.cpp
  28. 32
      src/storage/dd/cudd/CuddAddIterator.h
  29. 2
      src/storage/dd/cudd/CuddOdd.h
  30. 757
      src/storage/dd/cudd/InternalCuddAdd.cpp
  31. 598
      src/storage/dd/cudd/InternalCuddAdd.h
  32. 7
      src/storage/dd/cudd/InternalCuddBdd.h
  33. 50
      src/utility/graph.h
  34. 15
      src/utility/solver.h

73
src/adapters/AddExpressionAdapter.cpp

@ -4,61 +4,60 @@
#include "src/exceptions/ExpressionEvaluationException.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/storage/dd/cudd/CuddDdManager.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/cudd/CuddBdd.h"
#include "src/storage/dd/DdManager.h"
#include "src/storage/dd/Add.h"
#include "src/storage/dd/Bdd.h"
namespace storm {
namespace adapters {
template<storm::dd::DdType Type>
AddExpressionAdapter<Type>::AddExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping) : ddManager(ddManager), variableMapping(variableMapping) {
template<storm::dd::DdType Type, typename ValueType>
AddExpressionAdapter<Type, ValueType>::AddExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping) : ddManager(ddManager), variableMapping(variableMapping) {
// Intentionally left empty.
}
template<storm::dd::DdType Type>
storm::dd::Add<Type> AddExpressionAdapter<Type>::translateExpression(storm::expressions::Expression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Add<Type> AddExpressionAdapter<Type, ValueType>::translateExpression(storm::expressions::Expression const& expression) {
return boost::any_cast<storm::dd::Add<Type>>(expression.accept(*this));
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::IfThenElseExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::IfThenElseExpression const& expression) {
storm::dd::Add<Type> elseDd = boost::any_cast<storm::dd::Add<Type>>(expression.getElseExpression()->accept(*this));
storm::dd::Add<Type> thenDd = boost::any_cast<storm::dd::Add<Type>>(expression.getThenExpression()->accept(*this));
storm::dd::Add<Type> conditionDd = boost::any_cast<storm::dd::Add<Type>>(expression.getCondition()->accept(*this));
return conditionDd.ite(thenDd, elseDd);
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryBooleanFunctionExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::BinaryBooleanFunctionExpression const& expression) {
storm::dd::Bdd<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this)).toBdd();
storm::dd::Bdd<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this)).toBdd();
storm::dd::Add<Type> result;
storm::dd::Add<Type, ValueType> result;
switch (expression.getOperatorType()) {
case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::And:
result = (leftResult && rightResult).toAdd();
result = (leftResult && rightResult).template toAdd<ValueType>();
break;
case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Or:
result = (leftResult || rightResult).toAdd();
result = (leftResult || rightResult).template toAdd<ValueType>();
break;
case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Iff:
result = (leftResult.iff(rightResult)).toAdd();
result = (leftResult.iff(rightResult)).template toAdd<ValueType>();
break;
case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Implies:
result = (!leftResult || rightResult).toAdd();
result = (!leftResult || rightResult).template toAdd<ValueType>();
break;
case storm::expressions::BinaryBooleanFunctionExpression::OperatorType::Xor:
result = (leftResult.exclusiveOr(rightResult)).toAdd();
result = (leftResult.exclusiveOr(rightResult)).template toAdd<ValueType>();
break;
}
return result;
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryNumericalFunctionExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::BinaryNumericalFunctionExpression const& expression) {
storm::dd::Add<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this));
storm::dd::Add<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this));
@ -92,8 +91,8 @@ namespace storm {
return result;
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BinaryRelationExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::BinaryRelationExpression const& expression) {
storm::dd::Add<Type> leftResult = boost::any_cast<storm::dd::Add<Type>>(expression.getFirstOperand()->accept(*this));
storm::dd::Add<Type> rightResult = boost::any_cast<storm::dd::Add<Type>>(expression.getSecondOperand()->accept(*this));
@ -122,15 +121,15 @@ namespace storm {
return result;
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::VariableExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::VariableExpression const& expression) {
auto const& variablePair = variableMapping.find(expression.getVariable());
STORM_LOG_THROW(variablePair != variableMapping.end(), storm::exceptions::InvalidArgumentException, "Cannot translate the given expression, because it contains the variable '" << expression.getVariableName() << "' for which no DD counterpart is known.");
return ddManager->getIdentity(variablePair->second);
return ddManager->template getIdentity<ValueType>(variablePair->second);
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::UnaryBooleanFunctionExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::UnaryBooleanFunctionExpression const& expression) {
storm::dd::Bdd<Type> result = boost::any_cast<storm::dd::Add<Type>>(expression.getOperand()->accept(*this)).toBdd();
switch (expression.getOperatorType()) {
@ -139,11 +138,11 @@ namespace storm {
break;
}
return result.toAdd();
return result.template toAdd<ValueType>();
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::UnaryNumericalFunctionExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::UnaryNumericalFunctionExpression const& expression) {
storm::dd::Add<Type> result = boost::any_cast<storm::dd::Add<Type>>(expression.getOperand()->accept(*this));
switch (expression.getOperatorType()) {
@ -163,23 +162,23 @@ namespace storm {
return result;
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::BooleanLiteralExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::BooleanLiteralExpression const& expression) {
return ddManager->getConstant(expression.getValue());
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::IntegerLiteralExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::IntegerLiteralExpression const& expression) {
return ddManager->getConstant(expression.getValue());
}
template<storm::dd::DdType Type>
boost::any AddExpressionAdapter<Type>::visit(storm::expressions::DoubleLiteralExpression const& expression) {
template<storm::dd::DdType Type, typename ValueType>
boost::any AddExpressionAdapter<Type, ValueType>::visit(storm::expressions::DoubleLiteralExpression const& expression) {
return ddManager->getConstant(expression.getValue());
}
// Explicitly instantiate the symbolic expression adapter
template class AddExpressionAdapter<storm::dd::DdType::CUDD>;
template class AddExpressionAdapter<storm::dd::DdType::CUDD, double>;
} // namespace adapters
} // namespace storm

2
src/adapters/AddExpressionAdapter.h

@ -11,7 +11,7 @@
namespace storm {
namespace adapters {
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType = double>
class AddExpressionAdapter : public storm::expressions::ExpressionVisitor {
public:
AddExpressionAdapter(std::shared_ptr<storm::dd::DdManager<Type>> ddManager, std::map<storm::expressions::Variable, storm::expressions::Variable> const& variableMapping);

12
src/modelchecker/csl/HybridCtmcCslModelChecker.cpp

@ -7,18 +7,18 @@
#include "src/modelchecker/results/SymbolicQualitativeCheckResult.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/cudd/CuddBdd.h"
#include "src/storage/dd/Add.h"
#include "src/storage/dd/Bdd.h"
namespace storm {
namespace modelchecker {
template<storm::dd::DdType DdType, class ValueType>
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(new storm::utility::solver::LinearEquationSolverFactory<ValueType>()) {
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType, ValueType> const& model) : SymbolicPropositionalModelChecker<DdType, ValueType>(model), linearEquationSolverFactory(new storm::utility::solver::LinearEquationSolverFactory<ValueType>()) {
// Intentionally left empty.
}
template<storm::dd::DdType DdType, class ValueType>
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory) : SymbolicPropositionalModelChecker<DdType>(model), linearEquationSolverFactory(std::move(linearEquationSolverFactory)) {
HybridCtmcCslModelChecker<DdType, ValueType>::HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory) : SymbolicPropositionalModelChecker<DdType, ValueType>(model), linearEquationSolverFactory(std::move(linearEquationSolverFactory)) {
// Intentionally left empty.
}
@ -46,8 +46,8 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
storm::models::symbolic::Ctmc<DdType> const& HybridCtmcCslModelChecker<DdType, ValueType>::getModel() const {
return this->template getModelAs<storm::models::symbolic::Ctmc<DdType>>();
storm::models::symbolic::Ctmc<DdType, ValueType> const& HybridCtmcCslModelChecker<DdType, ValueType>::getModel() const {
return this->template getModelAs<storm::models::symbolic::Ctmc<DdType, ValueType>>();
}
template<storm::dd::DdType DdType, class ValueType>

8
src/modelchecker/csl/HybridCtmcCslModelChecker.h

@ -11,10 +11,10 @@ namespace storm {
namespace modelchecker {
template<storm::dd::DdType DdType, class ValueType>
class HybridCtmcCslModelChecker : public SymbolicPropositionalModelChecker<DdType> {
class HybridCtmcCslModelChecker : public SymbolicPropositionalModelChecker<DdType, ValueType> {
public:
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model);
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory);
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType, ValueType> const& model);
explicit HybridCtmcCslModelChecker(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory);
// The implemented methods of the AbstractModelChecker interface.
virtual bool canHandle(storm::logic::Formula const& formula) const override;
@ -27,7 +27,7 @@ namespace storm {
virtual std::unique_ptr<CheckResult> computeLongRunAverage(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional<OptimizationDirection> const& optimalityType = boost::optional<OptimizationDirection>()) override;
protected:
storm::models::symbolic::Ctmc<DdType> const& getModel() const override;
storm::models::symbolic::Ctmc<DdType, ValueType> const& getModel() const override;
private:
// An object that is used for solving linear equations and performing matrix-vector multiplication.

50
src/modelchecker/csl/helper/HybridCtmcCslHelper.cpp

@ -3,9 +3,9 @@
#include "src/modelchecker/csl/helper/SparseCtmcCslHelper.h"
#include "src/modelchecker/prctl/helper/HybridDtmcPrctlHelper.h"
#include "src/storage/dd/cudd/CuddDdManager.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/cudd/CuddBdd.h"
#include "src/storage/dd/DdManager.h"
#include "src/storage/dd/Add.h"
#include "src/storage/dd/Bdd.h"
#include "src/storage/dd/cudd/CuddOdd.h"
#include "src/utility/macros.h"
@ -27,23 +27,23 @@ namespace storm {
namespace helper {
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeReachabilityRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, storm::dd::Bdd<DdType> const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeReachabilityRewards(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, storm::dd::Bdd<DdType> const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
return HybridDtmcPrctlHelper<DdType, ValueType>::computeReachabilityRewards(model, computeProbabilityMatrix(model, rateMatrix, exitRateVector), rewardModel.divideStateRewardVector(exitRateVector), targetStates, qualitative, linearEquationSolverFactory);
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeNextProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& nextStates) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeNextProbabilities(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& nextStates) {
return HybridDtmcPrctlHelper<DdType, ValueType>::computeNextProbabilities(model, computeProbabilityMatrix(model, rateMatrix, exitRateVector), nextStates);
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeUntilProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeUntilProbabilities(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
return HybridDtmcPrctlHelper<DdType, ValueType>::computeUntilProbabilities(model, computeProbabilityMatrix(model, rateMatrix, exitRateVector), phiStates, psiStates, qualitative, linearEquationSolverFactory);
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeBoundedUntilProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, double lowerBound, double upperBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeBoundedUntilProbabilities(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, double lowerBound, double upperBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
// If the time bounds are [0, inf], we rather call untimed reachability.
if (storm::utility::isZero(lowerBound) && upperBound == storm::utility::infinity<ValueType>()) {
@ -74,10 +74,10 @@ namespace storm {
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive.");
// Compute the uniformized matrix.
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0NonPsi, uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0NonPsi, uniformizationRate);
// Compute the vector that is to be added as a compensation for removing the absorbing states.
storm::dd::Add<DdType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * rateMatrix * psiStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(model.getColumnVariables()) / model.getManager().getConstant(uniformizationRate);
storm::dd::Add<DdType, ValueType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * rateMatrix * psiStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(model.getColumnVariables()) / model.getManager().getConstant(uniformizationRate);
// Create an ODD for the translation to an explicit representation.
storm::dd::Odd<DdType> odd(statesWithProbabilityGreater0NonPsi);
@ -122,7 +122,7 @@ namespace storm {
ValueType uniformizationRate = 1.02 * (relevantStates.toAdd() * exitRateVector).getMax();
// Compute the uniformized matrix.
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, relevantStates, uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, relevantStates, uniformizationRate);
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd);
// Compute the transient probabilities.
@ -140,10 +140,10 @@ namespace storm {
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive.");
// Compute the (first) uniformized matrix.
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0NonPsi, uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0NonPsi, uniformizationRate);
// Create the one-step vector.
storm::dd::Add<DdType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * rateMatrix * psiStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(model.getColumnVariables()) / model.getManager().getConstant(uniformizationRate);
storm::dd::Add<DdType, ValueType> b = (statesWithProbabilityGreater0NonPsi.toAdd() * rateMatrix * psiStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd()).sumAbstract(model.getColumnVariables()) / model.getManager().getConstant(uniformizationRate);
// Build an ODD for the relevant states and translate the symbolic parts to their explicit representation.
storm::dd::Odd<DdType> odd = storm::dd::Odd<DdType>(statesWithProbabilityGreater0NonPsi);
@ -204,7 +204,7 @@ namespace storm {
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive.");
// Finally, we compute the second set of transient probabilities.
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0, uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, statesWithProbabilityGreater0, uniformizationRate);
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd);
newSubresult = storm::modelchecker::helper::SparseCtmcCslHelper<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, lowerBound, uniformizationRate, newSubresult, linearEquationSolverFactory);
@ -219,7 +219,7 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeInstantaneousRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeInstantaneousRewards(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
// Only compute the result if the model has a state-based reward model.
STORM_LOG_THROW(rewardModel.hasStateRewards(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
@ -235,7 +235,7 @@ namespace storm {
ValueType uniformizationRate = 1.02 * exitRateVector.getMax();
STORM_LOG_THROW(uniformizationRate > 0, storm::exceptions::InvalidStateException, "The uniformization rate must be positive.");
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, model.getReachableStates(), uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, model.getReachableStates(), uniformizationRate);
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd);
result = storm::modelchecker::helper::SparseCtmcCslHelper<ValueType>::computeTransientProbabilities(explicitUniformizedMatrix, nullptr, timeBound, uniformizationRate, result, linearEquationSolverFactory);
@ -245,7 +245,7 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeCumulativeRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeCumulativeRewards(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
// Only compute the result if the model has a state-based reward model.
STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::InvalidPropertyException, "Missing reward model for formula. Skipping formula.");
@ -264,11 +264,11 @@ namespace storm {
storm::dd::Odd<DdType> odd(model.getReachableStates());
// Compute the uniformized matrix.
storm::dd::Add<DdType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, model.getReachableStates(), uniformizationRate);
storm::dd::Add<DdType, ValueType> uniformizedMatrix = computeUniformizedMatrix(model, rateMatrix, exitRateVector, model.getReachableStates(), uniformizationRate);
storm::storage::SparseMatrix<ValueType> explicitUniformizedMatrix = uniformizedMatrix.toMatrix(odd, odd);
// Then compute the state reward vector to use in the computation.
storm::dd::Add<DdType> totalRewardVector = rewardModel.getTotalRewardVector(rateMatrix, model.getColumnVariables(), exitRateVector);
storm::dd::Add<DdType, ValueType> totalRewardVector = rewardModel.getTotalRewardVector(rateMatrix, model.getColumnVariables(), exitRateVector);
std::vector<ValueType> explicitTotalRewardVector = totalRewardVector.template toVector<ValueType>(odd);
// Finally, compute the transient probabilities.
@ -277,8 +277,8 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeLongRunAverage(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
storm::dd::Add<DdType> probabilityMatrix = computeProbabilityMatrix(model, rateMatrix, exitRateVector);
std::unique_ptr<CheckResult> HybridCtmcCslHelper<DdType, ValueType>::computeLongRunAverage(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory) {
storm::dd::Add<DdType, ValueType> probabilityMatrix = computeProbabilityMatrix(model, rateMatrix, exitRateVector);
// Create ODD for the translation.
storm::dd::Odd<DdType> odd(model.getReachableStates());
@ -291,17 +291,17 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
storm::dd::Add<DdType> HybridCtmcCslHelper<DdType, ValueType>::computeUniformizedMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate) {
storm::dd::Add<DdType, ValueType> HybridCtmcCslHelper<DdType, ValueType>::computeUniformizedMatrix(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& transitionMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate) {
STORM_LOG_DEBUG("Computing uniformized matrix using uniformization rate " << uniformizationRate << ".");
STORM_LOG_DEBUG("Keeping " << maybeStates.getNonZeroCount() << " rows.");
// Cut all non-maybe rows/columns from the transition matrix.
storm::dd::Add<DdType> uniformizedMatrix = transitionMatrix * maybeStates.toAdd() * maybeStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd();
storm::dd::Add<DdType, ValueType> uniformizedMatrix = transitionMatrix * maybeStates.toAdd() * maybeStates.swapVariables(model.getRowColumnMetaVariablePairs()).toAdd();
// Now perform the uniformization.
uniformizedMatrix = uniformizedMatrix / model.getManager().getConstant(uniformizationRate);
storm::dd::Add<DdType> diagonal = model.getRowColumnIdentity() * maybeStates.toAdd();
storm::dd::Add<DdType> diagonalOffset = diagonal;
storm::dd::Add<DdType, ValueType> diagonal = model.getRowColumnIdentity() * maybeStates.toAdd();
storm::dd::Add<DdType, ValueType> diagonalOffset = diagonal;
diagonalOffset -= diagonal * (exitRateVector / model.getManager().getConstant(uniformizationRate));
uniformizedMatrix += diagonalOffset;
@ -309,7 +309,7 @@ namespace storm {
}
template<storm::dd::DdType DdType, class ValueType>
storm::dd::Add<DdType> HybridCtmcCslHelper<DdType, ValueType>::computeProbabilityMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector) {
storm::dd::Add<DdType, ValueType> HybridCtmcCslHelper<DdType, ValueType>::computeProbabilityMatrix(storm::models::symbolic::Ctmc<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector) {
return rateMatrix / exitRateVector;
}

20
src/modelchecker/csl/helper/HybridCtmcCslHelper.h

@ -16,21 +16,21 @@ namespace storm {
template<storm::dd::DdType DdType, typename ValueType>
class HybridCtmcCslHelper {
public:
typedef typename storm::models::symbolic::Model<DdType>::RewardModelType RewardModelType;
typedef typename storm::models::symbolic::Model<DdType, ValueType>::RewardModelType RewardModelType;
static std::unique_ptr<CheckResult> computeBoundedUntilProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, double lowerBound, double upperBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeBoundedUntilProbabilities(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, double lowerBound, double upperBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeInstantaneousRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeInstantaneousRewards(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeCumulativeRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeCumulativeRewards(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, double timeBound, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeUntilProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeUntilProbabilities(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& phiStates, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeReachabilityRewards(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, RewardModelType const& rewardModel, storm::dd::Bdd<DdType> const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeReachabilityRewards(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, RewardModelType const& rewardModel, storm::dd::Bdd<DdType> const& targetStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeLongRunAverage(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeLongRunAverage(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& psiStates, bool qualitative, storm::utility::solver::LinearEquationSolverFactory<ValueType> const& linearEquationSolverFactory);
static std::unique_ptr<CheckResult> computeNextProbabilities(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& nextStates);
static std::unique_ptr<CheckResult> computeNextProbabilities(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& nextStates);
/*!
* Converts the given rate-matrix into a time-abstract probability matrix.
@ -40,7 +40,7 @@ namespace storm {
* @param exitRateVector The exit rate vector of the model.
* @return The probability matrix.
*/
static storm::dd::Add<DdType> computeProbabilityMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& rateMatrix, storm::dd::Add<DdType> const& exitRateVector);
static storm::dd::Add<DdType, ValueType> computeProbabilityMatrix(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& rateMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector);
/*!
* Computes the matrix representing the transitions of the uniformized CTMC.
@ -52,7 +52,7 @@ namespace storm {
* @param uniformizationRate The rate to be used for uniformization.
* @return The uniformized matrix.
*/
static storm::dd::Add<DdType> computeUniformizedMatrix(storm::models::symbolic::Model<DdType> const& model, storm::dd::Add<DdType> const& transitionMatrix, storm::dd::Add<DdType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate);
static storm::dd::Add<DdType, ValueType> computeUniformizedMatrix(storm::models::symbolic::Model<DdType, ValueType> const& model, storm::dd::Add<DdType, ValueType> const& transitionMatrix, storm::dd::Add<DdType, ValueType> const& exitRateVector, storm::dd::Bdd<DdType> const& maybeStates, ValueType uniformizationRate);
};
}

2
src/modelchecker/prctl/HybridDtmcPrctlModelChecker.cpp

@ -4,7 +4,7 @@
#include "src/modelchecker/prctl/helper/SparseDtmcPrctlHelper.h"
#include "src/storage/dd/cudd/CuddOdd.h"
#include "src/storage/dd/cudd/CuddDdManager.h"
#include "src/storage/dd/DdManager.h"
#include "src/utility/macros.h"
#include "src/utility/graph.h"

4
src/modelchecker/prctl/HybridDtmcPrctlModelChecker.h

@ -11,7 +11,7 @@ namespace storm {
namespace modelchecker {
template<storm::dd::DdType DdType, typename ValueType>
class HybridDtmcPrctlModelChecker : public SymbolicPropositionalModelChecker<DdType> {
class HybridDtmcPrctlModelChecker : public SymbolicPropositionalModelChecker<DdType, ValueType> {
public:
explicit HybridDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model);
explicit HybridDtmcPrctlModelChecker(storm::models::symbolic::Dtmc<DdType> const& model, std::unique_ptr<storm::utility::solver::LinearEquationSolverFactory<ValueType>>&& linearEquationSolverFactory);
@ -27,7 +27,7 @@ namespace storm {
virtual std::unique_ptr<CheckResult> computeLongRunAverage(storm::logic::StateFormula const& stateFormula, bool qualitative = false, boost::optional<OptimizationDirection> const& optimalityType = boost::optional<OptimizationDirection>()) override;
protected:
storm::models::symbolic::Dtmc<DdType> const& getModel() const override;
storm::models::symbolic::Dtmc<DdType, ValueType> const& getModel() const override;
private:
// An object that is used for retrieving linear equation solvers.

13
src/modelchecker/propositional/SymbolicPropositionalModelChecker.h

@ -8,17 +8,17 @@
namespace storm {
namespace models {
namespace symbolic {
template<storm::dd::DdType Type> class Model;
template<storm::dd::DdType Type, typename ValueType>
class Model;
}
}
namespace modelchecker {
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType>
class SymbolicPropositionalModelChecker : public AbstractModelChecker {
public:
explicit SymbolicPropositionalModelChecker(storm::models::symbolic::Model<Type> const& model);
explicit SymbolicPropositionalModelChecker(storm::models::symbolic::Model<Type, ValueType> const& model);
// The implemented methods of the AbstractModelChecker interface.
virtual bool canHandle(storm::logic::Formula const& formula) const override;
@ -32,7 +32,7 @@ namespace storm {
*
* @return The model associated with this model checker instance.
*/
virtual storm::models::symbolic::Model<Type> const& getModel() const;
virtual storm::models::symbolic::Model<Type, ValueType> const& getModel() const;
/*!
* Retrieves the model associated with this model checker instance as the given template parameter type.
@ -44,8 +44,9 @@ namespace storm {
private:
// The model that is to be analyzed by the model checker.
storm::models::symbolic::Model<Type> const& model;
storm::models::symbolic::Model<Type, ValueType> const& model;
};
}
}

32
src/modelchecker/results/CheckResult.h

@ -13,10 +13,18 @@ namespace storm {
class QualitativeCheckResult;
class QuantitativeCheckResult;
class ExplicitQualitativeCheckResult;
template <typename ValueType> class ExplicitQuantitativeCheckResult;
template <storm::dd::DdType Type> class SymbolicQualitativeCheckResult;
template <storm::dd::DdType Type> class SymbolicQuantitativeCheckResult;
template <storm::dd::DdType Type> class HybridQuantitativeCheckResult;
template <typename ValueType>
class ExplicitQuantitativeCheckResult;
template <storm::dd::DdType Type>
class SymbolicQualitativeCheckResult;
template <storm::dd::DdType Type, typename ValueType>
class SymbolicQuantitativeCheckResult;
template <storm::dd::DdType Type, typename ValueType>
class HybridQuantitativeCheckResult;
// The base class of all check results.
class CheckResult {
@ -65,17 +73,17 @@ namespace storm {
template <storm::dd::DdType Type>
SymbolicQualitativeCheckResult<Type> const& asSymbolicQualitativeCheckResult() const;
template <storm::dd::DdType Type>
SymbolicQuantitativeCheckResult<Type>& asSymbolicQuantitativeCheckResult();
template <storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeCheckResult<Type, ValueType>& asSymbolicQuantitativeCheckResult();
template <storm::dd::DdType Type>
SymbolicQuantitativeCheckResult<Type> const& asSymbolicQuantitativeCheckResult() const;
template <storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeCheckResult<Type, ValueType> const& asSymbolicQuantitativeCheckResult() const;
template <storm::dd::DdType Type>
HybridQuantitativeCheckResult<Type>& asHybridQuantitativeCheckResult();
template <storm::dd::DdType Type, typename ValueType>
HybridQuantitativeCheckResult<Type, ValueType>& asHybridQuantitativeCheckResult();
template <storm::dd::DdType Type>
HybridQuantitativeCheckResult<Type> const& asHybridQuantitativeCheckResult() const;
template <storm::dd::DdType Type, typename ValueType>
HybridQuantitativeCheckResult<Type, ValueType> const& asHybridQuantitativeCheckResult() const;
virtual std::ostream& writeToStream(std::ostream& out) const = 0;
};

18
src/modelchecker/results/HybridQuantitativeCheckResult.h

@ -2,15 +2,15 @@
#define STORM_MODELCHECKER_HYBRIDQUANTITATIVECHECKRESULT_H_
#include "src/storage/dd/DdType.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/cudd/CuddBdd.h"
#include "src/storage/dd/Add.h"
#include "src/storage/dd/Bdd.h"
#include "src/storage/dd/cudd/CuddOdd.h"
#include "src/modelchecker/results/QuantitativeCheckResult.h"
#include "src/utility/OsDetection.h"
namespace storm {
namespace modelchecker {
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType = double>
class HybridQuantitativeCheckResult : public QuantitativeCheckResult {
public:
HybridQuantitativeCheckResult() = default;
@ -34,21 +34,21 @@ namespace storm {
storm::dd::Bdd<Type> const& getSymbolicStates() const;
storm::dd::Add<Type> const& getSymbolicValueVector() const;
storm::dd::Add<Type, ValueType> const& getSymbolicValueVector() const;
storm::dd::Bdd<Type> const& getExplicitStates() const;
storm::dd::Odd<Type> const& getOdd() const;
std::vector<double> const& getExplicitValueVector() const;
std::vector<ValueType> const& getExplicitValueVector() const;
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual void filter(QualitativeCheckResult const& filter) override;
virtual double getMin() const;
virtual ValueType getMin() const;
virtual double getMax() const;
virtual ValueType getMax() const;
private:
// The set of all reachable states.
@ -58,7 +58,7 @@ namespace storm {
storm::dd::Bdd<Type> symbolicStates;
// The symbolic value vector.
storm::dd::Add<Type> symbolicValues;
storm::dd::Add<Type, ValueType> symbolicValues;
// The set of all states whose result is stored explicitly.
storm::dd::Bdd<Type> explicitStates;
@ -67,7 +67,7 @@ namespace storm {
storm::dd::Odd<Type> odd;
// The explicit value vector.
std::vector<double> explicitValues;
std::vector<ValueType> explicitValues;
};
}
}

2
src/modelchecker/results/SymbolicQualitativeCheckResult.h

@ -2,7 +2,7 @@
#define STORM_MODELCHECKER_SYMBOLICQUALITATIVECHECKRESULT_H_
#include "src/storage/dd/DdType.h"
#include "src/storage/dd/cudd/CuddBdd.h"
#include "src/storage/dd/Bdd.h"
#include "src/modelchecker/results/QualitativeCheckResult.h"
#include "src/utility/OsDetection.h"

12
src/modelchecker/results/SymbolicQuantitativeCheckResult.h

@ -2,13 +2,13 @@
#define STORM_MODELCHECKER_SYMBOLICQUANTITATIVECHECKRESULT_H_
#include "src/storage/dd/DdType.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/Add.h"
#include "src/modelchecker/results/QuantitativeCheckResult.h"
#include "src/utility/OsDetection.h"
namespace storm {
namespace modelchecker {
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType = double>
class SymbolicQuantitativeCheckResult : public QuantitativeCheckResult {
public:
SymbolicQuantitativeCheckResult() = default;
@ -28,15 +28,15 @@ namespace storm {
virtual bool isSymbolicQuantitativeCheckResult() const override;
storm::dd::Add<Type> const& getValueVector() const;
storm::dd::Add<Type, ValueType> const& getValueVector() const;
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual void filter(QualitativeCheckResult const& filter) override;
virtual double getMin() const;
virtual ValueType getMin() const;
virtual double getMax() const;
virtual ValueType getMax() const;
private:
// The set of all reachable states.
@ -46,7 +46,7 @@ namespace storm {
storm::dd::Bdd<Type> states;
// The values of the quantitative check result.
storm::dd::Add<Type> values;
storm::dd::Add<Type, ValueType> values;
};
}
}

24
src/models/symbolic/Ctmc.h

@ -11,17 +11,17 @@ namespace storm {
/*!
* This class represents a continuous-time Markov chain.
*/
template<storm::dd::DdType Type>
class Ctmc : public DeterministicModel<Type> {
template<storm::dd::DdType Type, typename ValueType = double>
class Ctmc : public DeterministicModel<Type, ValueType> {
public:
typedef typename DeterministicModel<Type>::RewardModelType RewardModelType;
typedef typename DeterministicModel<Type, ValueType>::RewardModelType RewardModelType;
Ctmc(Ctmc<Type> const& other) = default;
Ctmc& operator=(Ctmc<Type> const& other) = default;
Ctmc(Ctmc<Type, ValueType> const& other) = default;
Ctmc& operator=(Ctmc<Type, ValueType> const& other) = default;
#ifndef WINDOWS
Ctmc(Ctmc<Type>&& other) = default;
Ctmc& operator=(Ctmc<Type>&& other) = default;
Ctmc(Ctmc<Type, ValueType>&& other) = default;
Ctmc& operator=(Ctmc<Type, ValueType>&& other) = default;
#endif
/*!
@ -44,11 +44,11 @@ namespace storm {
Ctmc(std::shared_ptr<storm::dd::DdManager<Type>> manager,
storm::dd::Bdd<Type> reachableStates,
storm::dd::Bdd<Type> initialStates,
storm::dd::Add<Type> transitionMatrix,
storm::dd::Add<Type, ValueType> transitionMatrix,
std::set<storm::expressions::Variable> const& rowVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter,
std::set<storm::expressions::Variable> const& columnVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter,
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
std::unordered_map<std::string, RewardModelType> const& rewardModels = std::unordered_map<std::string, RewardModelType>());
@ -58,10 +58,10 @@ namespace storm {
*
* @return The exit rate vector.
*/
storm::dd::Add<Type> const& getExitRateVector() const;
storm::dd::Add<Type, ValueType> const& getExitRateVector() const;
private:
storm::dd::Add<Type> exitRates;
storm::dd::Add<Type, ValueType> exitRates;
};
} // namespace symbolic

20
src/models/symbolic/DeterministicModel.h

@ -11,17 +11,17 @@ namespace storm {
/*!
* Base class for all deterministic symbolic models.
*/
template<storm::dd::DdType Type>
class DeterministicModel : public Model<Type> {
template<storm::dd::DdType Type, typename ValueType = double>
class DeterministicModel : public Model<Type, ValueType> {
public:
typedef typename Model<Type>::RewardModelType RewardModelType;
typedef typename Model<Type, ValueType>::RewardModelType RewardModelType;
DeterministicModel(DeterministicModel<Type> const& other) = default;
DeterministicModel& operator=(DeterministicModel<Type> const& other) = default;
DeterministicModel(DeterministicModel<Type, ValueType> const& other) = default;
DeterministicModel& operator=(DeterministicModel<Type, ValueType> const& other) = default;
#ifndef WINDOWS
DeterministicModel(DeterministicModel<Type>&& other) = default;
DeterministicModel& operator=(DeterministicModel<Type>&& other) = default;
DeterministicModel(DeterministicModel<Type, ValueType>&& other) = default;
DeterministicModel& operator=(DeterministicModel<Type, ValueType>&& other) = default;
#endif
/*!
@ -46,11 +46,11 @@ namespace storm {
std::shared_ptr<storm::dd::DdManager<Type>> manager,
storm::dd::Bdd<Type> reachableStates,
storm::dd::Bdd<Type> initialStates,
storm::dd::Add<Type> transitionMatrix,
storm::dd::Add<Type, ValueType> transitionMatrix,
std::set<storm::expressions::Variable> const& rowVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter,
std::set<storm::expressions::Variable> const& columnVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter,
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
std::unordered_map<std::string, RewardModelType> const& rewardModels = std::unordered_map<std::string, RewardModelType>());

20
src/models/symbolic/Dtmc.h

@ -11,17 +11,17 @@ namespace storm {
/*!
* This class represents a discrete-time Markov chain.
*/
template<storm::dd::DdType Type>
class Dtmc : public DeterministicModel<Type> {
template<storm::dd::DdType Type, typename ValueType = double>
class Dtmc : public DeterministicModel<Type, ValueType> {
public:
typedef typename DeterministicModel<Type>::RewardModelType RewardModelType;
typedef typename DeterministicModel<Type, ValueType>::RewardModelType RewardModelType;
Dtmc(Dtmc<Type> const& other) = default;
Dtmc& operator=(Dtmc<Type> const& other) = default;
Dtmc(Dtmc<Type, ValueType> const& other) = default;
Dtmc& operator=(Dtmc<Type, ValueType> const& other) = default;
#ifndef WINDOWS
Dtmc(Dtmc<Type>&& other) = default;
Dtmc& operator=(Dtmc<Type>&& other) = default;
Dtmc(Dtmc<Type, ValueType>&& other) = default;
Dtmc& operator=(Dtmc<Type, ValueType>&& other) = default;
#endif
/*!
@ -44,11 +44,11 @@ namespace storm {
Dtmc(std::shared_ptr<storm::dd::DdManager<Type>> manager,
storm::dd::Bdd<Type> reachableStates,
storm::dd::Bdd<Type> initialStates,
storm::dd::Add<Type> transitionMatrix,
storm::dd::Add<Type, ValueType> transitionMatrix,
std::set<storm::expressions::Variable> const& rowVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter,
std::set<storm::expressions::Variable> const& columnVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter,
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
std::unordered_map<std::string, RewardModelType> const& rewardModels = std::unordered_map<std::string, RewardModelType>());

20
src/models/symbolic/Mdp.h

@ -11,17 +11,17 @@ namespace storm {
/*!
* This class represents a discrete-time Markov decision process.
*/
template<storm::dd::DdType Type>
class Mdp : public NondeterministicModel<Type> {
template<storm::dd::DdType Type, typename ValueType = double>
class Mdp : public NondeterministicModel<Type, ValueType> {
public:
typedef typename NondeterministicModel<Type>::RewardModelType RewardModelType;
typedef typename NondeterministicModel<Type, ValueType>::RewardModelType RewardModelType;
Mdp(Mdp<Type> const& other) = default;
Mdp& operator=(Mdp<Type> const& other) = default;
Mdp(Mdp<Type, ValueType> const& other) = default;
Mdp& operator=(Mdp<Type, ValueType> const& other) = default;
#ifndef WINDOWS
Mdp(Mdp<Type>&& other) = default;
Mdp& operator=(Mdp<Type>&& other) = default;
Mdp(Mdp<Type, ValueType>&& other) = default;
Mdp& operator=(Mdp<Type, ValueType>&& other) = default;
#endif
/*!
@ -46,11 +46,11 @@ namespace storm {
Mdp(std::shared_ptr<storm::dd::DdManager<Type>> manager,
storm::dd::Bdd<Type> reachableStates,
storm::dd::Bdd<Type> initialStates,
storm::dd::Add<Type> transitionMatrix,
storm::dd::Add<Type, ValueType> transitionMatrix,
std::set<storm::expressions::Variable> const& rowVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter,
std::set<storm::expressions::Variable> const& columnVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter,
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
std::set<storm::expressions::Variable> const& nondeterminismVariables,
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),

42
src/models/symbolic/Model.h

@ -15,15 +15,23 @@
namespace storm {
namespace dd {
template<storm::dd::DdType Type> class Dd;
template<storm::dd::DdType Type> class Add;
template<storm::dd::DdType Type> class Bdd;
template<storm::dd::DdType Type> class DdManager;
template<storm::dd::DdType Type>
class Dd;
template<storm::dd::DdType Type, typename ValueType>
class Add;
template<storm::dd::DdType Type>
class Bdd;
template<storm::dd::DdType Type>
class DdManager;
}
namespace adapters {
template<storm::dd::DdType Type> class AddExpressionAdapter;
template<storm::dd::DdType Type, typename ValueType>
class AddExpressionAdapter;
}
namespace models {
@ -35,11 +43,11 @@ namespace storm {
/*!
* Base class for all symbolic models.
*/
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType = double>
class Model : public storm::models::ModelBase {
public:
static const storm::dd::DdType DdType = Type;
typedef StandardRewardModel<Type, double> RewardModelType;
typedef StandardRewardModel<Type, ValueType> RewardModelType;
Model(Model<Type> const& other) = default;
Model& operator=(Model<Type> const& other) = default;
@ -71,11 +79,11 @@ namespace storm {
std::shared_ptr<storm::dd::DdManager<Type>> manager,
storm::dd::Bdd<Type> reachableStates,
storm::dd::Bdd<Type> initialStates,
storm::dd::Add<Type> transitionMatrix,
storm::dd::Add<Type, ValueType> transitionMatrix,
std::set<storm::expressions::Variable> const& rowVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter,
std::set<storm::expressions::Variable> const& columnVariables,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter,
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter,
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs,
std::map<std::string, storm::expressions::Expression> labelToExpressionMap = std::map<std::string, storm::expressions::Expression>(),
std::unordered_map<std::string, RewardModelType> const& rewardModels = std::unordered_map<std::string, RewardModelType>());
@ -141,14 +149,14 @@ namespace storm {
*
* @return A matrix representing the transitions of the model.
*/
storm::dd::Add<Type> const& getTransitionMatrix() const;
storm::dd::Add<Type, ValueType> const& getTransitionMatrix() const;
/*!
* Retrieves the matrix representing the transitions of the model.
*
* @return A matrix representing the transitions of the model.
*/
storm::dd::Add<Type>& getTransitionMatrix();
storm::dd::Add<Type, ValueType>& getTransitionMatrix();
/*!
* Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.
@ -176,7 +184,7 @@ namespace storm {
*
* @return An ADD that represents the diagonal of the transition matrix.
*/
storm::dd::Add<Type> getRowColumnIdentity() const;
storm::dd::Add<Type, ValueType> getRowColumnIdentity() const;
/*!
* Retrieves whether the model has a reward model with the given name.
@ -233,7 +241,7 @@ namespace storm {
*
* @param transitionMatrix The new transition matrix of the model.
*/
void setTransitionMatrix(storm::dd::Add<Type> const& transitionMatrix);
void setTransitionMatrix(storm::dd::Add<Type, ValueType> const& transitionMatrix);
/*!
* Retrieves the mapping of labels to their defining expressions.
@ -282,19 +290,19 @@ namespace storm {
storm::dd::Bdd<Type> initialStates;
// A matrix representing transition relation.
storm::dd::Add<Type> transitionMatrix;
storm::dd::Add<Type, ValueType> transitionMatrix;
// The meta variables used to encode the rows of the transition matrix.
std::set<storm::expressions::Variable> rowVariables;
// An adapter that can translate expressions to DDs over the row meta variables.
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> rowExpressionAdapter;
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> rowExpressionAdapter;
// The meta variables used to encode the columns of the transition matrix.
std::set<storm::expressions::Variable> columnVariables;
// An adapter that can translate expressions to DDs over the column meta variables.
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type>> columnExpressionAdapter;
std::shared_ptr<storm::adapters::AddExpressionAdapter<Type, ValueType>> columnExpressionAdapter;
// A vector holding all pairs of row and column meta variable pairs. This is used to swap the variables
// in the DDs from row to column variables and vice versa.

38
src/models/symbolic/StandardRewardModel.h

@ -9,7 +9,7 @@
namespace storm {
namespace dd {
template <storm::dd::DdType Type>
template <storm::dd::DdType Type, typename ValueType>
class Add;
template <storm::dd::DdType Type>
@ -33,7 +33,7 @@ namespace storm {
* @param stateActionRewardVector The vector of state-action rewards.
* @param transitionRewardMatrix The matrix of transition rewards.
*/
explicit StandardRewardModel(boost::optional<storm::dd::Add<Type>> const& stateRewardVector, boost::optional<storm::dd::Add<Type>> const& stateActionRewardVector, boost::optional<storm::dd::Add<Type>> const& transitionRewardMatrix);
explicit StandardRewardModel(boost::optional<storm::dd::Add<Type, ValueType>> const& stateRewardVector, boost::optional<storm::dd::Add<Type, ValueType>> const& stateActionRewardVector, boost::optional<storm::dd::Add<Type, ValueType>> const& transitionRewardMatrix);
/*!
* Retrieves whether the reward model is empty.
@ -62,7 +62,7 @@ namespace storm {
*
* @return The state reward vector.
*/
storm::dd::Add<Type> const& getStateRewardVector() const;
storm::dd::Add<Type, ValueType> const& getStateRewardVector() const;
/*!
* Retrieves the state rewards of the reward model. Note that it is illegal to call this function if the
@ -70,14 +70,14 @@ namespace storm {
*
* @return The state reward vector.
*/
storm::dd::Add<Type>& getStateRewardVector();
storm::dd::Add<Type, ValueType>& getStateRewardVector();
/*!
* Retrieves an optional value that contains the state reward vector if there is one.
*
* @return The state reward vector if there is one.
*/
boost::optional<storm::dd::Add<Type>> const& getOptionalStateRewardVector() const;
boost::optional<storm::dd::Add<Type, ValueType>> const& getOptionalStateRewardVector() const;
/*!
* Retrieves whether the reward model has state-action rewards.
@ -92,7 +92,7 @@ namespace storm {
*
* @return The state-action reward vector.
*/
storm::dd::Add<Type> const& getStateActionRewardVector() const;
storm::dd::Add<Type, ValueType> const& getStateActionRewardVector() const;
/*!
* Retrieves the state-action rewards of the reward model. Note that it is illegal to call this function
@ -100,14 +100,14 @@ namespace storm {
*
* @return The state-action reward vector.
*/
storm::dd::Add<Type>& getStateActionRewardVector();
storm::dd::Add<Type, ValueType>& getStateActionRewardVector();
/*!
* Retrieves an optional value that contains the state-action reward vector if there is one.
*
* @return The state-action reward vector if there is one.
*/
boost::optional<storm::dd::Add<Type>> const& getOptionalStateActionRewardVector() const;
boost::optional<storm::dd::Add<Type, ValueType>> const& getOptionalStateActionRewardVector() const;
/*!
* Retrieves whether the reward model has transition rewards.
@ -122,7 +122,7 @@ namespace storm {
*
* @return The transition reward matrix.
*/
storm::dd::Add<Type> const& getTransitionRewardMatrix() const;
storm::dd::Add<Type, ValueType> const& getTransitionRewardMatrix() const;
/*!
* Retrieves the transition rewards of the reward model. Note that it is illegal to call this function
@ -130,14 +130,14 @@ namespace storm {
*
* @return The transition reward matrix.
*/
storm::dd::Add<Type>& getTransitionRewardMatrix();
storm::dd::Add<Type, ValueType>& getTransitionRewardMatrix();
/*!
* Retrieves an optional value that contains the transition reward matrix if there is one.
*
* @return The transition reward matrix if there is one.
*/
boost::optional<storm::dd::Add<Type>> const& getOptionalTransitionRewardMatrix() const;
boost::optional<storm::dd::Add<Type, ValueType>> const& getOptionalTransitionRewardMatrix() const;
/*!
* Creates a vector representing the complete reward vector based on the state-, state-action- and
@ -147,7 +147,7 @@ namespace storm {
* @param columnVariables The column variables of the model.
* @return The full state-action reward vector.
*/
storm::dd::Add<Type> getTotalRewardVector(storm::dd::Add<Type> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables) const;
storm::dd::Add<Type, ValueType> getTotalRewardVector(storm::dd::Add<Type, ValueType> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables) const;
/*!
* Creates a vector representing the complete reward vector based on the state-, state-action- and
@ -159,7 +159,7 @@ namespace storm {
* @param columnVariables The column variables of the model.
* @return The full state-action reward vector.
*/
storm::dd::Add<Type> getTotalRewardVector(storm::dd::Add<Type> const& filterAdd, storm::dd::Add<Type> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables) const;
storm::dd::Add<Type, ValueType> getTotalRewardVector(storm::dd::Add<Type, ValueType> const& filterAdd, storm::dd::Add<Type, ValueType> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables) const;
/*!
* Creates a vector representing the complete reward vector based on the state-, state-action- and
@ -170,14 +170,14 @@ namespace storm {
* @param weights The weights used to scale the state-action reward vector.
* @return The full state-action reward vector.
*/
storm::dd::Add<Type> getTotalRewardVector(storm::dd::Add<Type> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables, storm::dd::Add<Type> const& weights) const;
storm::dd::Add<Type, ValueType> getTotalRewardVector(storm::dd::Add<Type, ValueType> const& transitionMatrix, std::set<storm::expressions::Variable> const& columnVariables, storm::dd::Add<Type, ValueType> const& weights) const;
/*!
* Multiplies all components of the reward model with the given DD.
*
* @param filter The filter with which to multiply
*/
StandardRewardModel<Type, ValueType>& operator*=(storm::dd::Add<Type> const& filter);
StandardRewardModel<Type, ValueType>& operator*=(storm::dd::Add<Type, ValueType> const& filter);
/*!
* Divides the state reward vector of the reward model by the given divisor.
@ -185,17 +185,17 @@ namespace storm {
* @param divisor The vector to divide by.
* @return The resulting reward model.
*/
StandardRewardModel<Type, ValueType> divideStateRewardVector(storm::dd::Add<Type> const& divisor) const;
StandardRewardModel<Type, ValueType> divideStateRewardVector(storm::dd::Add<Type, ValueType> const& divisor) const;
private:
// The state reward vector.
boost::optional<storm::dd::Add<Type>> optionalStateRewardVector;
boost::optional<storm::dd::Add<Type, ValueType>> optionalStateRewardVector;
// A vector of state-action-based rewards.
boost::optional<storm::dd::Add<Type>> optionalStateActionRewardVector;
boost::optional<storm::dd::Add<Type, ValueType>> optionalStateActionRewardVector;
// A matrix of transition rewards.
boost::optional<storm::dd::Add<Type>> optionalTransitionRewardMatrix;
boost::optional<storm::dd::Add<Type, ValueType>> optionalTransitionRewardMatrix;
};
}

626
src/storage/dd/Add.cpp

@ -1,8 +1,634 @@
#include "src/storage/dd/Add.h"
#include <boost/algorithm/string/join.hpp>
#include "src/storage/dd/DdMetaVariable.h"
#include "src/storage/dd/DdManager.h"
#include "src/storage/SparseMatrix.h"
#include "src/utility/constants.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace dd {
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>::Add(std::shared_ptr<DdManager<LibraryType> const> ddManager, InternalAdd<LibraryType, ValueType> const& internalAdd, std::set<storm::expressions::Variable> const& containedMetaVariables) : Dd<LibraryType>(ddManager, containedMetaVariables), internalAdd(internalAdd) {
// Intentionally left empty.
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::operator==(Add<LibraryType, ValueType> const& other) const {
return internalAdd == other.internalAdd;
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::operator!=(Add<LibraryType, ValueType> const& other) const {
return internalAdd != other.internalAdd;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::ite(Add<LibraryType, ValueType> const& thenAdd, Add<LibraryType, ValueType> const& elseAdd) const {
std::set<storm::expressions::Variable> metaVariables = Dd<LibraryType>::joinMetaVariables(thenAdd, elseAdd);
metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end());
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.ite(thenAdd.internalAdd, elseAdd.internalAdd), metaVariables);
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator!() const {
return Add<LibraryType, ValueType>(this->getDdManager(), !internalAdd, this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator||(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd || other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>& Add<LibraryType, ValueType>::operator|=(Add<LibraryType, ValueType> const& other) {
this->addMetaVariables(other.getContainedMetaVariables());
internalAdd |= other.internalAdd;
return *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator+(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd + other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>& Add<LibraryType, ValueType>::operator+=(Add<LibraryType, ValueType> const& other) {
this->addMetaVariables(other.getContainedMetaVariables());
internalAdd += other.internalAdd;
return *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator*(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd * other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>& Add<LibraryType, ValueType>::operator*=(Add<LibraryType, ValueType> const& other) {
this->addMetaVariables(other.getContainedMetaVariables());
internalAdd *= other.internalAdd;
return *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator-(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd - other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator-() const {
return this->getDdManager()->getAddZero() - *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>& Add<LibraryType, ValueType>::operator-=(Add<LibraryType, ValueType> const& other) {
this->addMetaVariables(other.getContainedMetaVariables());
internalAdd -= other.internalAdd;
return *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::operator/(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd / other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType>& Add<LibraryType, ValueType>::operator/=(Add<LibraryType, ValueType> const& other) {
this->addMetaVariables(other.getContainedMetaVariables());
internalAdd /= other.internalAdd;
return *this;
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::equals(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.equals(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::notEquals(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.notEquals(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::less(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.less(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::lessOrEqual(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.lessOrEqual(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::greater(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.greater(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::greaterOrEqual(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.greaterOrEqual(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::pow(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.pow(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::mod(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.mod(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::logxy(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.logxy(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::floor() const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.floor(), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::ceil() const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.ceil(), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::minimum(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.minimum(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::maximum(Add<LibraryType, ValueType> const& other) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.maximum(other), Dd<LibraryType>::joinMetaVariables(*this, other));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
Bdd<LibraryType> cube = this->getCube(metaVariables);
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.sumAbstract(cube), Dd<LibraryType>::subtractMetaVariables(*this, cube));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
Bdd<LibraryType> cube = this->getCube(metaVariables);
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.minAbstract(cube), Dd<LibraryType>::subtractMetaVariables(*this, cube));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
Bdd<LibraryType> cube = this->getCube(metaVariables);
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.maxAbstract(cube), Dd<LibraryType>::subtractMetaVariables(*this, cube));
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::equalModuloPrecision(Add<LibraryType, ValueType> const& other, double precision, bool relative) const {
return internalAdd.equalModuloPrecision(other, precision, relative);
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) const {
std::set<storm::expressions::Variable> newContainedMetaVariables;
std::vector<InternalAdd<LibraryType, ValueType>> from;
std::vector<InternalAdd<LibraryType, ValueType>> to;
for (auto const& metaVariablePair : metaVariablePairs) {
DdMetaVariable<LibraryType> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
DdMetaVariable<LibraryType> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
// Keep track of the contained meta variables in the DD.
if (this->containsMetaVariable(metaVariablePair.first)) {
newContainedMetaVariables.insert(metaVariablePair.second);
}
if (this->containsMetaVariable(metaVariablePair.second)) {
newContainedMetaVariables.insert(metaVariablePair.first);
}
for (auto const& ddVariable : variable1.getDdVariables()) {
from.push_back(ddVariable.toAdd());
}
for (auto const& ddVariable : variable2.getDdVariables()) {
to.push_back(ddVariable.toAdd());
}
}
return Bdd<LibraryType>(this->getDdManager(), internalAdd.swapVariables(from, to), newContainedMetaVariables);
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::multiplyMatrix(Add<LibraryType, ValueType> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const {
// Create the CUDD summation variables.
std::vector<InternalAdd<LibraryType, ValueType>> summationDdVariables;
for (auto const& metaVariable : summationMetaVariables) {
for (auto const& ddVariable : this->getDdManager()->getMetaVariable(metaVariable).getDdVariables()) {
summationDdVariables.push_back(ddVariable.toAdd());
}
}
std::set<storm::expressions::Variable> unionOfMetaVariables = Dd<LibraryType>::joinMetaVariables(*this, otherMatrix);
std::set<storm::expressions::Variable> containedMetaVariables;
std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), summationMetaVariables.begin(), summationMetaVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin()));
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.multiplyMatrix(otherMatrix, summationDdVariables), containedMetaVariables);
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::greater(ValueType const& value) const {
return Bdd<LibraryType>(this->getDdManager(), internalAdd.greater(value), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::greaterOrEqual(ValueType const& value) const {
return Bdd<LibraryType>(this->getDdManager(), internalAdd.greaterOrEqual(value), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::less(ValueType const& value) const {
return Bdd<LibraryType>(this->getDdManager(), internalAdd.less(value), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::lessOrEqual(ValueType const& value) const {
return Bdd<LibraryType>(this->getDdManager(), internalAdd.lessOrEqual(value), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::notZero() const {
return this->toBdd();
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::constrain(Add<LibraryType, ValueType> const& constraint) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.constrain(constraint), Dd<LibraryType>::joinMetaVariables(*this, constraint));
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::restrict(Add<LibraryType, ValueType> const& constraint) const {
return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.restrict(constraint), Dd<LibraryType>::joinMetaVariables(*this, constraint));
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::getSupport() const {
return Bdd<LibraryType>(this->getDdManager(), internalAdd.getSupport(), this->getContainedMetaVariables());
}
template<DdType LibraryType, typename ValueType>
uint_fast64_t Add<LibraryType, ValueType>::getNonZeroCount() const {
std::size_t numberOfDdVariables = 0;
for (auto const& metaVariable : this->getContainedMetaVariables()) {
numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariable).getNumberOfDdVariables();
}
return internalAdd.getNonZeroCount(numberOfDdVariables);
}
template<DdType LibraryType, typename ValueType>
uint_fast64_t Add<LibraryType, ValueType>::getLeafCount() const {
return internalAdd.getLeafCount();
}
template<DdType LibraryType, typename ValueType>
uint_fast64_t Add<LibraryType, ValueType>::getNodeCount() const {
return internalAdd.getNodeCount();
}
template<DdType LibraryType, typename ValueType>
ValueType Add<LibraryType, ValueType>::getMin() const {
return internalAdd.getMin();
}
template<DdType LibraryType, typename ValueType>
ValueType Add<LibraryType, ValueType>::getMax() const {
return internalAdd.getMax();
}
template<DdType LibraryType, typename ValueType>
void Add<LibraryType, ValueType>::setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, ValueType const& targetValue) {
std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
metaVariableToValueMap.emplace(metaVariable, variableValue);
this->setValue(metaVariableToValueMap, targetValue);
}
template<DdType LibraryType, typename ValueType>
void Add<LibraryType, ValueType>::setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, ValueType const& targetValue) {
std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
metaVariableToValueMap.emplace(metaVariable1, variableValue1);
metaVariableToValueMap.emplace(metaVariable2, variableValue2);
this->setValue(metaVariableToValueMap, targetValue);
}
template<DdType LibraryType, typename ValueType>
void Add<LibraryType, ValueType>::setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap, ValueType const& targetValue) {
Bdd<LibraryType> valueEncoding = this->getDdManager()->getBddOne();
for (auto const& nameValuePair : metaVariableToValueMap) {
valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
// Also record that the DD now contains the meta variable.
this->addMetaVariable(nameValuePair.first);
}
internalAdd = valueEncoding.toAdd().ite(this->getDdManager()->getConstant(targetValue), internalAdd);
}
template<DdType LibraryType, typename ValueType>
ValueType Add<LibraryType, ValueType>::getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap) const {
std::set<storm::expressions::Variable> remainingMetaVariables(this->getContainedMetaVariables());
Bdd<LibraryType> valueEncoding = this->getDdManager()->getBddOne();
for (auto const& nameValuePair : metaVariableToValueMap) {
valueEncoding &= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
if (this->containsMetaVariable(nameValuePair.first)) {
remainingMetaVariables.erase(nameValuePair.first);
}
}
STORM_LOG_THROW(remainingMetaVariables.empty(), storm::exceptions::InvalidArgumentException, "Cannot evaluate function for which not all inputs were given.");
Add<LibraryType, ValueType> value = *this * valueEncoding.toAdd();
value = value.sumAbstract(this->getContainedMetaVariables());
return value.getMax();
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::isOne() const {
return internalAdd.isOne();
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::isZero() const {
return internalAdd.isZero();
}
template<DdType LibraryType, typename ValueType>
bool Add<LibraryType, ValueType>::isConstant() const {
return internalAdd.isConstant();
}
template<DdType LibraryType, typename ValueType>
uint_fast64_t Add<LibraryType, ValueType>::getIndex() const {
return internalAdd.getIndex();
}
template<DdType LibraryType, typename ValueType>
std::vector<ValueType> Add<LibraryType, ValueType>::toVector() const {
return this->toVector(Odd<LibraryType>(*this));
}
template<DdType LibraryType, typename ValueType>
std::vector<ValueType> Add<LibraryType, ValueType>::toVector(Odd<LibraryType> const& rowOdd) const {
std::vector<ValueType> result(rowOdd.getTotalOffset());
std::vector<uint_fast64_t> ddVariableIndices = this->getDdManager().getSortedVariableIndices();
addToVector(rowOdd, ddVariableIndices, result);
return result;
}
template<DdType LibraryType, typename ValueType>
std::vector<ValueType> Add<LibraryType, ValueType>::toVector(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, std::vector<uint_fast64_t> const& groupOffsets) const {
std::set<storm::expressions::Variable> rowMetaVariables;
// Prepare the proper sets of meta variables.
for (auto const& variable : this->getContainedMetaVariables()) {
if (groupMetaVariables.find(variable) != groupMetaVariables.end()) {
continue;
}
rowMetaVariables.insert(variable);
}
std::vector<uint_fast64_t> ddGroupVariableIndices;
for (auto const& variable : groupMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddGroupVariableIndices.push_back(ddVariable.getIndex());
}
}
std::vector<uint_fast64_t> ddRowVariableIndices;
for (auto const& variable : rowMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddRowVariableIndices.push_back(ddVariable.getIndex());
}
}
return internalAdd.toVector(ddGroupVariableIndices, rowOdd, ddRowVariableIndices, groupOffsets);
}
template<DdType LibraryType, typename ValueType>
storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix() const {
std::set<storm::expressions::Variable> rowVariables;
std::set<storm::expressions::Variable> columnVariables;
for (auto const& variable : this->getContainedMetaVariables()) {
if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
columnVariables.insert(variable);
} else {
rowVariables.insert(variable);
}
}
return toMatrix(rowVariables, columnVariables, Odd<LibraryType>(this->sumAbstract(rowVariables)), Odd<LibraryType>(this->sumAbstract(columnVariables)));
}
template<DdType LibraryType, typename ValueType>
storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::set<storm::expressions::Variable> rowMetaVariables;
std::set<storm::expressions::Variable> columnMetaVariables;
for (auto const& variable : this->getContainedMetaVariables()) {
if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
columnMetaVariables.insert(variable);
} else {
rowMetaVariables.insert(variable);
}
}
return toMatrix(rowMetaVariables, columnMetaVariables, rowOdd, columnOdd);
}
template<DdType LibraryType, typename ValueType>
storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::vector<uint_fast64_t> ddRowVariableIndices;
std::vector<uint_fast64_t> ddColumnVariableIndices;
for (auto const& variable : rowMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddRowVariableIndices.push_back(ddVariable.getIndex());
}
}
std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
for (auto const& variable : columnMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddColumnVariableIndices.push_back(ddVariable.getIndex());
}
}
std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
return internalAdd.toMatrix(rowOdd, ddRowVariableIndices, columnOdd, ddColumnVariableIndices);
}
template<DdType LibraryType, typename ValueType>
storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::set<storm::expressions::Variable> rowMetaVariables;
std::set<storm::expressions::Variable> columnMetaVariables;
for (auto const& variable : this->getContainedMetaVariables()) {
// If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables.
if (groupMetaVariables.find(variable) != groupMetaVariables.end()) {
continue;
}
if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
columnMetaVariables.insert(variable);
} else {
rowMetaVariables.insert(variable);
}
}
// Create the canonical row group sizes and build the matrix.
return toMatrix(rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
}
template<DdType LibraryType, typename ValueType>
storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::vector<uint_fast64_t> ddRowVariableIndices;
std::vector<uint_fast64_t> ddColumnVariableIndices;
std::vector<uint_fast64_t> ddGroupVariableIndices;
std::set<storm::expressions::Variable> rowAndColumnMetaVariables;
for (auto const& variable : rowMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddRowVariableIndices.push_back(ddVariable.getIndex());
}
rowAndColumnMetaVariables.insert(variable);
}
std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
for (auto const& variable : columnMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddColumnVariableIndices.push_back(ddVariable.getIndex());
}
rowAndColumnMetaVariables.insert(variable);
}
std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
for (auto const& variable : groupMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddGroupVariableIndices.push_back(ddVariable.getIndex());
}
}
std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end());
return internalAdd.toMatrix(ddGroupVariableIndices, rowOdd, ddRowVariableIndices, columnOdd, ddColumnVariableIndices);
}
template<DdType LibraryType, typename ValueType>
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> Add<LibraryType, ValueType>::toMatrixVector(storm::dd::Add<LibraryType, ValueType> const& vector, std::vector<uint_fast64_t>&& rowGroupSizes, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::set<storm::expressions::Variable> rowMetaVariables;
std::set<storm::expressions::Variable> columnMetaVariables;
for (auto const& variable : this->getContainedMetaVariables()) {
// If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables.
if (groupMetaVariables.find(variable) != groupMetaVariables.end()) {
continue;
}
if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
columnMetaVariables.insert(variable);
} else {
rowMetaVariables.insert(variable);
}
}
// Create the canonical row group sizes and build the matrix.
return toMatrixVector(vector, std::move(rowGroupSizes), rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
}
template<DdType LibraryType, typename ValueType>
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> Add<LibraryType, ValueType>::toMatrixVector(storm::dd::Add<LibraryType, ValueType> const& vector, std::vector<uint_fast64_t>&& rowGroupIndices, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const {
std::vector<uint_fast64_t> ddRowVariableIndices;
std::vector<uint_fast64_t> ddColumnVariableIndices;
std::vector<uint_fast64_t> ddGroupVariableIndices;
std::set<storm::expressions::Variable> rowAndColumnMetaVariables;
for (auto const& variable : rowMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddRowVariableIndices.push_back(ddVariable.getIndex());
}
rowAndColumnMetaVariables.insert(variable);
}
std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
for (auto const& variable : columnMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddColumnVariableIndices.push_back(ddVariable.getIndex());
}
rowAndColumnMetaVariables.insert(variable);
}
std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
for (auto const& variable : groupMetaVariables) {
DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager()->getMetaVariable(variable);
for (auto const& ddVariable : metaVariable.getDdVariables()) {
ddGroupVariableIndices.push_back(ddVariable.getIndex());
}
}
std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end());
return internalAdd.toMatrixVector(vector.internalAdd, ddGroupVariableIndices, std::move(rowGroupIndices), rowOdd, ddRowVariableIndices, columnOdd, ddColumnVariableIndices);
}
template<DdType LibraryType, typename ValueType>
void Add<LibraryType, ValueType>::exportToDot(std::string const& filename) const {
internalAdd.exportToDot(filename, this->getDdManager()->getDdVariableNames());
}
template<DdType LibraryType, typename ValueType>
AddIterator<LibraryType, ValueType> Add<LibraryType, ValueType>::begin(bool enumerateDontCareMetaVariables) const {
internalAdd.begin(this->getContainedMetaVariables(), enumerateDontCareMetaVariables);
}
template<DdType LibraryType, typename ValueType>
AddIterator<LibraryType, ValueType> Add<LibraryType, ValueType>::end(bool enumerateDontCareMetaVariables) const {
return internalAdd.end(enumerateDontCareMetaVariables);
}
template<DdType LibraryType, typename ValueType>
std::ostream& operator<<(std::ostream& out, Add<LibraryType, ValueType> const& add) {
out << "ADD with " << add.getNonZeroCount() << " nnz, " << add.getNodeCount() << " nodes, " << add.getLeafCount() << " leaves" << std::endl;
std::vector<std::string> variableNames;
for (auto const& variable : add.getContainedMetaVariables()) {
variableNames.push_back(variable.getName());
}
out << "contained variables: " << boost::algorithm::join(variableNames, ", ") << std::endl;
return out;
}
template<DdType LibraryType, typename ValueType>
void Add<LibraryType, ValueType>::addToVector(Odd<LibraryType> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const {
std::function<ValueType (ValueType const&, ValueType const&)> fct = [] (ValueType const& a, ValueType const& b) -> ValueType { return a + b; };
return internalAdd.composeVector(odd, ddVariableIndices, targetVector, fct);
}
template<DdType LibraryType, typename ValueType>
Add<LibraryType, ValueType> Add<LibraryType, ValueType>::fromVector(std::shared_ptr<DdManager<LibraryType> const> ddManager, std::vector<ValueType> const& values, Odd<LibraryType> const& odd, std::set<storm::expressions::Variable> const& metaVariables) {
return Add<LibraryType, ValueType>(ddManager, InternalAdd<LibraryType, ValueType>::fromVector(ddManager, values, odd, ddManager->getSortedVariableIndices(metaVariables)), metaVariables);
}
template<DdType LibraryType, typename ValueType>
Bdd<LibraryType> Add<LibraryType, ValueType>::toBdd() const {
return Bdd<DdType::CUDD>(this->getDdManager(), internalAdd.toBdd(), this->getContainedMetaVariables());
}
template class Add<storm::dd::DdType::CUDD, double>;
}
}

671
src/storage/dd/Add.h

@ -1,6 +1,8 @@
#ifndef STORM_STORAGE_DD_ADD_H_
#define STORM_STORAGE_DD_ADD_H_
#include <map>
#include "src/storage/dd/Dd.h"
#include "src/storage/dd/DdType.h"
@ -8,25 +10,682 @@
namespace storm {
namespace dd {
template<DdType LibraryType>
class Bdd;
template<DdType LibraryType>
class Odd;
template<DdType LibraryType, typename ValueType>
class Add {
class AddIterator;
template<DdType LibraryType, typename ValueType = double>
class Add : public Dd<LibraryType> {
public:
friend class DdManager<LibraryType>;
// Instantiate all copy/move constructors/assignments with the default implementation.
Add() = default;
Add(Add<LibraryType> const& other) = default;
Add& operator=(Add<LibraryType> const& other) = default;
Add(Add<LibraryType>&& other) = default;
Add& operator=(Add<LibraryType>&& other) = default;
Add(Add<LibraryType, ValueType> const& other) = default;
Add& operator=(Add<LibraryType, ValueType> const& other) = default;
Add(Add<LibraryType, ValueType>&& other) = default;
Add& operator=(Add<LibraryType, ValueType>&& other) = default;
/*!
* Retrieves whether the two DDs represent the same function.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the same function.
*/
bool operator==(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves whether the two DDs represent different functions.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the different functions.
*/
bool operator!=(Add<LibraryType, ValueType> const& other) const;
/*!
* Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero
* function value to the function values specified by the first DD and all others to the function values
* specified by the second DD.
*
* @param thenDd The ADD specifying the 'then' part.
* @param elseDd The ADD specifying the 'else' part.
* @return The ADD corresponding to the if-then-else of the operands.
*/
Add<LibraryType, ValueType> ite(Add<LibraryType, ValueType> const& thenAdd, Add<LibraryType, ValueType> const& elseAdd) const;
/*!
* Logically inverts the current ADD. That is, all inputs yielding non-zero values will be mapped to zero in
* the result and vice versa.
*
* @return The resulting ADD.
*/
Add<LibraryType, ValueType> operator!() const;
/*!
* Performs a logical or of the current anBd the given ADD. As a prerequisite, the operand ADDs need to be
* 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return The logical or of the operands.
*/
Add<LibraryType, ValueType> operator||(Add<LibraryType, ValueType> const& other) const;
/*!
* Performs a logical or of the current and the given ADD and assigns it to the current ADD. As a
* prerequisite, the operand ADDs need to be 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return A reference to the current ADD after the operation
*/
Add<LibraryType, ValueType>& operator|=(Add<LibraryType, ValueType> const& other);
/*!
* Adds the two ADDs.
*
* @param other The ADD to add to the current one.
* @return The result of the addition.
*/
Add<LibraryType, ValueType> operator+(Add<LibraryType, ValueType> const& other) const;
/*!
* Adds the given ADD to the current one.
*
* @param other The ADD to add to the current one.
* @return A reference to the current ADD after the operation.
*/
Add<LibraryType, ValueType>& operator+=(Add<LibraryType, ValueType> const& other);
/*!
* Multiplies the two ADDs.
*
* @param other The ADD to multiply with the current one.
* @return The result of the multiplication.
*/
Add<LibraryType, ValueType> operator*(Add<LibraryType, ValueType> const& other) const;
/*!
* Multiplies the given ADD with the current one and assigns the result to the current ADD.
*
* @param other The ADD to multiply with the current one.
* @return A reference to the current ADD after the operation.
*/
Add<LibraryType, ValueType>& operator*=(Add<LibraryType, ValueType> const& other);
/*!
* Subtracts the given ADD from the current one.
*
* @param other The ADD to subtract from the current one.
* @return The result of the subtraction.
*/
Add<LibraryType, ValueType> operator-(Add<LibraryType, ValueType> const& other) const;
/*!
* Subtracts the ADD from the constant zero function.
*
* @return The resulting function represented as a ADD.
*/
Add<LibraryType, ValueType> operator-() const;
/*!
* Subtracts the given ADD from the current one and assigns the result to the current ADD.
*
* @param other The ADD to subtract from the current one.
* @return A reference to the current ADD after the operation.
*/
Add<LibraryType, ValueType>& operator-=(Add<LibraryType, ValueType> const& other);
/*!
* Divides the current ADD by the given one.
*
* @param other The ADD by which to divide the current one.
* @return The result of the division.
*/
Add<LibraryType, ValueType> operator/(Add<LibraryType, ValueType> const& other) const;
/*!
* Divides the current ADD by the given one and assigns the result to the current ADD.
*
* @param other The ADD by which to divide the current one.
* @return A reference to the current ADD after the operation.
*/
Add<LibraryType, ValueType>& operator/=(Add<LibraryType, ValueType> const& other);
/*!
* Retrieves the function that maps all evaluations to one that have identical function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> equals(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one that have distinct function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> notEquals(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> less(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less or
* equal than the one in the given ADD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> lessOrEqual(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> greater(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* or equal than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> greaterOrEqual(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that represents the current ADD to the power of the given ADD.
*
* @other The exponent function (given as an ADD).
* @retur The resulting ADD.
*/
Add<LibraryType, ValueType> pow(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that represents the current ADD modulo the given ADD.
*
* @other The modul function (given as an ADD).
* @retur The resulting ADD.
*/
Add<LibraryType, ValueType> mod(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that represents the logarithm of the current ADD to the bases given by the second
* ADD.
*
* @other The base function (given as an ADD).
* @retur The resulting ADD.
*/
Add<LibraryType, ValueType> logxy(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that floors all values in the current ADD.
*
* @retur The resulting ADD.
*/
Add<LibraryType, ValueType> floor() const;
/*!
* Retrieves the function that ceils all values in the current ADD.
*
* @retur The resulting ADD.
*/
Add<LibraryType, ValueType> ceil() const;
/*!
* Retrieves the function that maps all evaluations to the minimum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> minimum(Add<LibraryType, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to the maximum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<LibraryType, ValueType> maximum(Add<LibraryType, ValueType> const& other) const;
/*!
* Sum-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<LibraryType, ValueType> sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Min-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<LibraryType, ValueType> minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Max-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<LibraryType, ValueType> maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Checks whether the current and the given ADD represent the same function modulo some given precision.
*
* @param other The ADD with which to compare.
* @param precision An upper bound on the maximal difference between any two function values that is to be
* tolerated.
* @param relative If set to true, not the absolute values have to be within the precision, but the relative
* values.
*/
bool equalModuloPrecision(Add<LibraryType, ValueType> const& other, double precision, bool relative = true) const;
/*!
* Swaps the given pairs of meta variables in the ADD. The pairs of meta variables must be guaranteed to have
* the same number of underlying ADD variables.
*
* @param metaVariablePairs A vector of meta variable pairs that are to be swapped for one another.
* @return The resulting ADD.
*/
Add<LibraryType, ValueType> swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) const;
/*!
* Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given meta
* variables.
*
* @param otherMatrix The matrix with which to multiply.
* @param summationMetaVariables The names of the meta variables over which to sum during the matrix-
* matrix multiplication.
* @return An ADD representing the result of the matrix-matrix multiplication.
*/
Add<LibraryType, ValueType> multiplyMatrix(Add<LibraryType, ValueType> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* larger than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<LibraryType> greater(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value larger or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<LibraryType> greaterOrEqual(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* lower than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<LibraryType> less(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value less or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<LibraryType> lessOrEqual(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value unequal to
* zero are mapped to one and all others to zero.
*
* @return The resulting DD.
*/
Bdd<LibraryType> notZero() const;
/*!
* Computes the constraint of the current ADD with the given constraint. That is, the function value of the
* resulting ADD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
Add<LibraryType, ValueType> constrain(Add<LibraryType, ValueType> const& constraint) const;
/*!
* Computes the restriction of the current ADD with the given constraint. That is, the function value of the
* resulting DD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
Add<LibraryType, ValueType> restrict(Add<LibraryType, ValueType> const& constraint) const;
/*!
* Retrieves the support of the current ADD.
*
* @return The support represented as a BDD.
*/
Bdd<LibraryType> getSupport() const override;
/*!
* Retrieves the number of encodings that are mapped to a non-zero value.
*
* @return The number of encodings that are mapped to a non-zero value.
*/
virtual uint_fast64_t getNonZeroCount() const override;
/*!
* Retrieves the number of leaves of the ADD.
*
* @return The number of leaves of the ADD.
*/
virtual uint_fast64_t getLeafCount() const override;
/*!
* Retrieves the number of nodes necessary to represent the DD.
*
* @return The number of nodes in this DD.
*/
virtual uint_fast64_t getNodeCount() const override;
/*!
* Retrieves the lowest function value of any encoding.
*
* @return The lowest function value of any encoding.
*/
ValueType getMin() const;
/*!
* Retrieves the highest function value of any encoding.
*
* @return The highest function value of any encoding.
*/
ValueType getMax() const;
/*!
* Sets the function values of all encodings that have the given value of the meta variable to the given
* target value.
*
* @param metaVariable The meta variable that has to be equal to the given value.
* @param variableValue The value that the meta variable is supposed to have. This must be within the range
* of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, ValueType const& targetValue);
/*!
* Sets the function values of all encodings that have the given values of the two meta variables to the
* given target value.
*
* @param metaVariable1 The first meta variable that has to be equal to the first given
* value.
* @param variableValue1 The value that the first meta variable is supposed to have. This must be within the
* range of the meta variable.
* @param metaVariable2 The second meta variable that has to be equal to the second given
* value.
* @param variableValue2 The value that the second meta variable is supposed to have. This must be within
* the range of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, ValueType const& targetValue);
/*!
* Sets the function values of all encodings that have the given values of the given meta variables to the
* given target value.
*
* @param metaVariableToValueMap A mapping of meta variables to the values they are supposed to have. All
* values must be within the range of the respective meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap = std::map<storm::expressions::Variable, int_fast64_t>(), ValueType const& targetValue = 0);
/*!
* Retrieves the value of the function when all meta variables are assigned the values of the given mapping.
* Note that the mapping must specify values for all meta variables contained in the DD.
*
* @param metaVariableToValueMap A mapping of meta variables to their values.
* @return The value of the function evaluated with the given input.
*/
ValueType getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap = std::map<storm::expressions::Variable, int_fast64_t>()) const;
/*!
* Retrieves whether this ADD represents the constant one function.
*
* @return True if this ADD represents the constant one function.
*/
bool isOne() const;
/*!
* Retrieves whether this ADD represents the constant zero function.
*
* @return True if this ADD represents the constant zero function.
*/
bool isZero() const;
/*!
* Retrieves whether this ADD represents a constant function.
*
* @return True if this ADD represents a constants function.
*/
bool isConstant() const;
/*!
* Retrieves the index of the topmost variable in the DD.
*
* @return The index of the topmost variable in DD.
*/
virtual uint_fast64_t getIndex() const override;
/*!
* Converts the ADD to a vector.
*
* @return The vector that is represented by this ADD.
*/
std::vector<ValueType> toVector() const;
/*!
* Converts the ADD to a vector. The given offset-labeled DD is used to determine the correct row of
* each entry.
*
* @param rowOdd The ODD used for determining the correct row.
* @return The vector that is represented by this ADD.
*/
std::vector<ValueType> toVector(storm::dd::Odd<LibraryType> const& rowOdd) const;
/*!
* Converts the ADD to a row-grouped vector. The given offset-labeled DD is used to determine the correct
* row group of each entry. Note that the group meta variables are assumed to be at the very top in the
* variable ordering.
*
* @param groupMetaVariables The meta variables responsible for the row-grouping.
* @param rowOdd The ODD used for determining the correct row.
* @return The vector that is represented by this ADD.
*/
std::vector<ValueType> toVector(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, std::vector<uint_fast64_t> const& groupOffsets) const;
/*!
* Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
* row, whereas all primed variables are assumed to encode the column.
*
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<ValueType> toMatrix() const;
/*!
* Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
* row, whereas all primed variables are assumed to encode the column. The given offset-labeled DDs are used
* to determine the correct row and column, respectively, for each entry.
*
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<ValueType> toMatrix(storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Converts the ADD to a (sparse) double matrix. The given offset-labeled DDs are used to determine the
* correct row and column, respectively, for each entry.
*
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<ValueType> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix. The given offset-labeled DDs are used to
* determine the correct row and column, respectively, for each entry. Note: this function assumes that
* the meta variables used to distinguish different row groups are at the very top of the ADD.
*
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<ValueType> toMatrix(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix and the given vector to a row-grouped vector.
* The given offset-labeled DDs are used to determine the correct row and column, respectively, for each
* entry. Note: this function assumes that the meta variables used to distinguish different row groups are
* at the very top of the ADD.
*
* @param vector The symbolic vector to convert.
* @param rowGroupSizes A vector specifying the sizes of the row groups.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> toMatrixVector(storm::dd::Add<LibraryType, ValueType> const& vector, std::vector<uint_fast64_t>&& rowGroupSizes, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Exports the DD to the given file in the dot format.
*
* @param filename The name of the file to which the DD is to be exported.
*/
void exportToDot(std::string const& filename) const override;
/*!
* Retrieves an iterator that points to the first meta variable assignment with a non-zero function value.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points to the first meta variable assignment with a non-zero function value.
*/
AddIterator<LibraryType, ValueType> begin(bool enumerateDontCareMetaVariables = true) const;
/*!
* Retrieves an iterator that points past the end of the container.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points past the end of the container.
*/
AddIterator<LibraryType, ValueType> end(bool enumerateDontCareMetaVariables = true) const;
friend std::ostream & operator<<(std::ostream& out, const Add<LibraryType, ValueType>& add);
/*!
* Converts the ADD to a BDD by mapping all values unequal to zero to 1. This effectively does the same as
* a call to notZero().
*
* @return The corresponding BDD.
*/
Bdd<LibraryType> toBdd() const;
private:
/*!
* Creates a DD that encapsulates the given CUDD ADD.
*
* @param ddManager The manager responsible for this DD.
* @param cuddBdd The CUDD BDD to store.
* @param containedMetaVariables The meta variables that appear in the DD.
*/
Add(std::shared_ptr<DdManager<LibraryType> const> ddManager, InternalAdd<LibraryType, ValueType> const& internalAdd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
/*!
* We provide a conversion operator from the BDD to its internal type to ease calling the internal functions.
*/
operator InternalAdd<LibraryType, ValueType>();
operator InternalAdd<LibraryType, ValueType> const() const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix. If the optional vector is given, it is also
* translated to an explicit row-grouped vector with the same row-grouping. The given offset-labeled DDs
* are used to determine the correct row and column, respectively, for each entry. Note: this function
* assumes that the meta variables used to distinguish different row groups are at the very top of the ADD.
*
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD and and a vector corresponding to the symbolic vector
* (if it was given).
*/
storm::storage::SparseMatrix<ValueType> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix and the given vector to an equally row-grouped
* explicit vector. The given offset-labeled DDs are used to determine the correct row and column,
* respectively, for each entry. Note: this function assumes that the meta variables used to distinguish
* different row groups are at the very top of the ADD.
*
* @param vector The vector that is to be transformed to an equally grouped explicit vector.
* @param rowGroupSizes A vector specifying the sizes of the row groups.
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD and and a vector corresponding to the symbolic vector
* (if it was given).
*/
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> toMatrixVector(storm::dd::Add<LibraryType, ValueType> const& vector, std::vector<uint_fast64_t>&& rowGroupSizes, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<LibraryType> const& rowOdd, storm::dd::Odd<LibraryType> const& columnOdd) const;
/*!
* Adds the current (DD-based) vector to the given explicit one.
*
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered.
* @param targetVector The vector to which the translated DD-based vector is to be added.
*/
void addToVector(Odd<LibraryType> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const;
/*!
* Builds an ADD representing the given vector.
*
* @param ddManager The manager responsible for the ADD.
* @param values The vector that is to be represented by the ADD.
* @param odd The ODD used for the translation.
* @param metaVariables The meta variables used for the translation.
* @return The resulting (CUDD) ADD.
*/
static Add<LibraryType, ValueType> fromVector(std::shared_ptr<DdManager<LibraryType> const> ddManager, std::vector<ValueType> const& values, Odd<LibraryType> const& odd, std::set<storm::expressions::Variable> const& metaVariables);
// The internal ADD that depends on the chosen library.
InternalAdd<LibraryType> internalAdd;
InternalAdd<LibraryType, ValueType> internalAdd;
};
}
}

3
src/storage/dd/DdForwardIterator.h → src/storage/dd/AddIterator.h

@ -6,7 +6,8 @@
namespace storm {
namespace dd {
// Declare DdIterator class so we can then specialize it for the different DD types.
template<DdType Type> class DdForwardIterator;
template<DdType Type, typename ValueType>
class DdForwardIterator;
}
}

4
src/storage/dd/Bdd.cpp

@ -36,7 +36,7 @@ namespace storm {
template<DdType LibraryType>
template<typename ValueType>
Bdd<LibraryType> Bdd<LibraryType>::fromVector(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables, std::function<bool (ValueType const&)> const& filter) {
Bdd<LibraryType> Bdd<LibraryType>::fromVector(std::shared_ptr<DdManager<LibraryType> const> ddManager, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables, std::function<bool (ValueType const&)> const& filter) {
return Bdd<LibraryType>(ddManager, InternalBdd<LibraryType>::fromVector(ddManager, values, odd, ddManager->getSortedVariableIndices(metaVariables), filter), metaVariables);
}
@ -52,7 +52,7 @@ namespace storm {
template<DdType LibraryType>
Bdd<LibraryType> Bdd<LibraryType>::ite(Bdd<LibraryType> const& thenBdd, Bdd<LibraryType> const& elseBdd) const {
std::set<storm::expressions::Variable> metaVariables = Dd<LibraryType>::joinMetaVariables(*this, thenBdd);
std::set<storm::expressions::Variable> metaVariables = Dd<LibraryType>::joinMetaVariables(thenBdd, elseBdd);
metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end());
return Bdd<LibraryType>(this->getDdManager(), internalBdd.ite(thenBdd.internalBdd, elseBdd.internalBdd), metaVariables);
}

2
src/storage/dd/Bdd.h

@ -263,7 +263,7 @@ namespace storm {
* @return The resulting (CUDD) BDD.
*/
template<typename ValueType>
static Bdd<LibraryType> fromVector(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables, std::function<bool (ValueType const&)> const& filter);
static Bdd<LibraryType> fromVector(std::shared_ptr<DdManager<LibraryType> const> ddManager, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables, std::function<bool (ValueType const&)> const& filter);
// The internal BDD that depends on the chosen library.
InternalBdd<LibraryType> internalBdd;

1084
src/storage/dd/cudd/CuddAdd.cpp
File diff suppressed because it is too large
View File

828
src/storage/dd/cudd/CuddAdd.h

@ -1,828 +0,0 @@
#ifndef STORM_STORAGE_DD_CUDDADD_H_
#define STORM_STORAGE_DD_CUDDADD_H_
#include <boost/optional.hpp>
#include <map>
#include "src/storage/dd/Add.h"
#include "src/storage/dd/cudd/CuddDd.h"
#include "src/storage/dd/cudd/CuddDdForwardIterator.h"
#include "src/storage/expressions/Variable.h"
#include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD.
#include "cuddObj.hh"
namespace storm {
namespace storage {
template<typename T> class SparseMatrix;
class BitVector;
template<typename E, typename V> class MatrixEntry;
}
namespace dd {
// Forward-declare some classes.
template<DdType Type> class DdManager;
template<DdType Type> class Odd;
template<DdType Type> class Bdd;
template<>
class Add<DdType::CUDD> : public Dd<DdType::CUDD> {
public:
// Declare the DdManager and DdIterator class as friend so it can access the internals of a DD.
friend class DdManager<DdType::CUDD>;
friend class DdForwardIterator<DdType::CUDD>;
friend class Bdd<DdType::CUDD>;
friend class Odd<DdType::CUDD>;
/*!
* Creates an ADD from the given explicit vector.
*
* @param ddManager The manager responsible for this DD.
* @param values The vector that is to be represented by the ADD.
* @param odd An ODD that is used to do the translation.
* @param metaVariables The meta variables to use to encode the vector.
*/
Add(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, std::vector<double> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables);
// Instantiate all copy/move constructors/assignments with the default implementation.
Add() = default;
Add(Add<DdType::CUDD> const& other) = default;
Add& operator=(Add<DdType::CUDD> const& other) = default;
#ifndef WINDOWS
Add(Add<DdType::CUDD>&& other) = default;
Add& operator=(Add<DdType::CUDD>&& other) = default;
#endif
/*!
* Retrieves whether the two DDs represent the same function.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the same function.
*/
bool operator==(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves whether the two DDs represent different functions.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the different functions.
*/
bool operator!=(Add<DdType::CUDD> const& other) const;
/*!
* Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero
* function value to the function values specified by the first DD and all others to the function values
* specified by the second DD.
*
* @param thenDd The ADD specifying the 'then' part.
* @param elseDd The ADD specifying the 'else' part.
* @return The ADD corresponding to the if-then-else of the operands.
*/
Add<DdType::CUDD> ite(Add<DdType::CUDD> const& thenDd, Add<DdType::CUDD> const& elseDd) const;
/*!
* Logically inverts the current ADD. That is, all inputs yielding non-zero values will be mapped to zero in
* the result and vice versa.
*
* @return The resulting ADD.
*/
Add<DdType::CUDD> operator!() const;
/*!
* Performs a logical or of the current anBd the given ADD. As a prerequisite, the operand ADDs need to be
* 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return The logical or of the operands.
*/
Add<DdType::CUDD> operator||(Add<DdType::CUDD> const& other) const;
/*!
* Performs a logical or of the current and the given ADD and assigns it to the current ADD. As a
* prerequisite, the operand ADDs need to be 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return A reference to the current ADD after the operation
*/
Add<DdType::CUDD>& operator|=(Add<DdType::CUDD> const& other);
/*!
* Adds the two ADDs.
*
* @param other The ADD to add to the current one.
* @return The result of the addition.
*/
Add<DdType::CUDD> operator+(Add<DdType::CUDD> const& other) const;
/*!
* Adds the given ADD to the current one.
*
* @param other The ADD to add to the current one.
* @return A reference to the current ADD after the operation.
*/
Add<DdType::CUDD>& operator+=(Add<DdType::CUDD> const& other);
/*!
* Multiplies the two ADDs.
*
* @param other The ADD to multiply with the current one.
* @return The result of the multiplication.
*/
Add<DdType::CUDD> operator*(Add<DdType::CUDD> const& other) const;
/*!
* Multiplies the given ADD with the current one and assigns the result to the current ADD.
*
* @param other The ADD to multiply with the current one.
* @return A reference to the current ADD after the operation.
*/
Add<DdType::CUDD>& operator*=(Add<DdType::CUDD> const& other);
/*!
* Subtracts the given ADD from the current one.
*
* @param other The ADD to subtract from the current one.
* @return The result of the subtraction.
*/
Add<DdType::CUDD> operator-(Add<DdType::CUDD> const& other) const;
/*!
* Subtracts the ADD from the constant zero function.
*
* @return The resulting function represented as a ADD.
*/
Add<DdType::CUDD> operator-() const;
/*!
* Subtracts the given ADD from the current one and assigns the result to the current ADD.
*
* @param other The ADD to subtract from the current one.
* @return A reference to the current ADD after the operation.
*/
Add<DdType::CUDD>& operator-=(Add<DdType::CUDD> const& other);
/*!
* Divides the current ADD by the given one.
*
* @param other The ADD by which to divide the current one.
* @return The result of the division.
*/
Add<DdType::CUDD> operator/(Add<DdType::CUDD> const& other) const;
/*!
* Divides the current ADD by the given one and assigns the result to the current ADD.
*
* @param other The ADD by which to divide the current one.
* @return A reference to the current ADD after the operation.
*/
Add<DdType::CUDD>& operator/=(Add<DdType::CUDD> const& other);
/*!
* Retrieves the function that maps all evaluations to one that have identical function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> equals(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one that have distinct function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> notEquals(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> less(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less or
* equal than the one in the given ADD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> lessOrEqual(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> greater(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* or equal than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> greaterOrEqual(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that represents the current ADD to the power of the given ADD.
*
* @other The exponent function (given as an ADD).
* @retur The resulting ADD.
*/
Add<DdType::CUDD> pow(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that represents the current ADD modulo the given ADD.
*
* @other The modul function (given as an ADD).
* @retur The resulting ADD.
*/
Add<DdType::CUDD> mod(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that represents the logarithm of the current ADD to the bases given by the second
* ADD.
*
* @other The base function (given as an ADD).
* @retur The resulting ADD.
*/
Add<DdType::CUDD> logxy(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that floors all values in the current ADD.
*
* @retur The resulting ADD.
*/
Add<DdType::CUDD> floor() const;
/*!
* Retrieves the function that ceils all values in the current ADD.
*
* @retur The resulting ADD.
*/
Add<DdType::CUDD> ceil() const;
/*!
* Retrieves the function that maps all evaluations to the minimum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> minimum(Add<DdType::CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to the maximum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
Add<DdType::CUDD> maximum(Add<DdType::CUDD> const& other) const;
/*!
* Sum-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<DdType::CUDD> sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Min-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<DdType::CUDD> minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Max-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
Add<DdType::CUDD> maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const;
/*!
* Checks whether the current and the given ADD represent the same function modulo some given precision.
*
* @param other The ADD with which to compare.
* @param precision An upper bound on the maximal difference between any two function values that is to be
* tolerated.
* @param relative If set to true, not the absolute values have to be within the precision, but the relative
* values.
*/
bool equalModuloPrecision(Add<DdType::CUDD> const& other, double precision, bool relative = true) const;
/*!
* Swaps the given pairs of meta variables in the ADD. The pairs of meta variables must be guaranteed to have
* the same number of underlying ADD variables.
*
* @param metaVariablePairs A vector of meta variable pairs that are to be swapped for one another.
* @return The resulting ADD.
*/
Add<DdType::CUDD> swapVariables(std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) const;
/*!
* Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given meta
* variables.
*
* @param otherMatrix The matrix with which to multiply.
* @param summationMetaVariables The names of the meta variables over which to sum during the matrix-
* matrix multiplication.
* @return An ADD representing the result of the matrix-matrix multiplication.
*/
Add<DdType::CUDD> multiplyMatrix(Add<DdType::CUDD> const& otherMatrix, std::set<storm::expressions::Variable> const& summationMetaVariables) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* larger than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<DdType::CUDD> greater(double value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value larger or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<DdType::CUDD> greaterOrEqual(double value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* lower than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<DdType::CUDD> less(double value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value less or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
Bdd<DdType::CUDD> lessOrEqual(double value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value unequal to
* zero are mapped to one and all others to zero.
*
* @return The resulting DD.
*/
Bdd<DdType::CUDD> notZero() const;
/*!
* Computes the constraint of the current ADD with the given constraint. That is, the function value of the
* resulting ADD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
Add<DdType::CUDD> constrain(Add<DdType::CUDD> const& constraint) const;
/*!
* Computes the restriction of the current ADD with the given constraint. That is, the function value of the
* resulting DD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
Add<DdType::CUDD> restrict(Add<DdType::CUDD> const& constraint) const;
/*!
* Retrieves the support of the current ADD.
*
* @return The support represented as a BDD.
*/
Bdd<DdType::CUDD> getSupport() const override;
/*!
* Retrieves the number of encodings that are mapped to a non-zero value.
*
* @return The number of encodings that are mapped to a non-zero value.
*/
virtual uint_fast64_t getNonZeroCount() const override;
/*!
* Retrieves the number of leaves of the ADD.
*
* @return The number of leaves of the ADD.
*/
virtual uint_fast64_t getLeafCount() const override;
/*!
* Retrieves the number of nodes necessary to represent the DD.
*
* @return The number of nodes in this DD.
*/
virtual uint_fast64_t getNodeCount() const override;
/*!
* Retrieves the lowest function value of any encoding.
*
* @return The lowest function value of any encoding.
*/
double getMin() const;
/*!
* Retrieves the highest function value of any encoding.
*
* @return The highest function value of any encoding.
*/
double getMax() const;
/*!
* Sets the function values of all encodings that have the given value of the meta variable to the given
* target value.
*
* @param metaVariable The meta variable that has to be equal to the given value.
* @param variableValue The value that the meta variable is supposed to have. This must be within the range
* of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, double targetValue);
/*!
* Sets the function values of all encodings that have the given values of the two meta variables to the
* given target value.
*
* @param metaVariable1 The first meta variable that has to be equal to the first given
* value.
* @param variableValue1 The value that the first meta variable is supposed to have. This must be within the
* range of the meta variable.
* @param metaVariable2 The second meta variable that has to be equal to the second given
* value.
* @param variableValue2 The value that the second meta variable is supposed to have. This must be within
* the range of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, double targetValue);
/*!
* Sets the function values of all encodings that have the given values of the given meta variables to the
* given target value.
*
* @param metaVariableToValueMap A mapping of meta variables to the values they are supposed to have. All
* values must be within the range of the respective meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap = std::map<storm::expressions::Variable, int_fast64_t>(), double targetValue = 0);
/*!
* Retrieves the value of the function when all meta variables are assigned the values of the given mapping.
* Note that the mapping must specify values for all meta variables contained in the DD.
*
* @param metaVariableToValueMap A mapping of meta variables to their values.
* @return The value of the function evaluated with the given input.
*/
double getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap = std::map<storm::expressions::Variable, int_fast64_t>()) const;
/*!
* Retrieves whether this ADD represents the constant one function.
*
* @return True if this ADD represents the constant one function.
*/
bool isOne() const;
/*!
* Retrieves whether this ADD represents the constant zero function.
*
* @return True if this ADD represents the constant zero function.
*/
bool isZero() const;
/*!
* Retrieves whether this ADD represents a constant function.
*
* @return True if this ADD represents a constants function.
*/
bool isConstant() const;
/*!
* Retrieves the index of the topmost variable in the DD.
*
* @return The index of the topmost variable in DD.
*/
virtual uint_fast64_t getIndex() const override;
/*!
* Converts the ADD to a vector.
*
* @return The vector that is represented by this ADD.
*/
template<typename ValueType>
std::vector<ValueType> toVector() const;
/*!
* Converts the ADD to a vector. The given offset-labeled DD is used to determine the correct row of
* each entry.
*
* @param rowOdd The ODD used for determining the correct row.
* @return The vector that is represented by this ADD.
*/
template<typename ValueType>
std::vector<ValueType> toVector(storm::dd::Odd<DdType::CUDD> const& rowOdd) const;
/*!
* Converts the ADD to a row-grouped vector. The given offset-labeled DD is used to determine the correct
* row group of each entry. Note that the group meta variables are assumed to be at the very top in the
* variable ordering.
*
* @param groupMetaVariables The meta variables responsible for the row-grouping.
* @param rowOdd The ODD used for determining the correct row.
* @return The vector that is represented by this ADD.
*/
template<typename ValueType>
std::vector<ValueType> toVector(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> groupOffsets) const;
/*!
* Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
* row, whereas all primed variables are assumed to encode the column.
*
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<double> toMatrix() const;
/*!
* Converts the ADD to a (sparse) double matrix. All contained non-primed variables are assumed to encode the
* row, whereas all primed variables are assumed to encode the column. The given offset-labeled DDs are used
* to determine the correct row and column, respectively, for each entry.
*
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<double> toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Converts the ADD to a (sparse) double matrix. The given offset-labeled DDs are used to determine the
* correct row and column, respectively, for each entry.
*
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<double> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix. The given offset-labeled DDs are used to
* determine the correct row and column, respectively, for each entry. Note: this function assumes that
* the meta variables used to distinguish different row groups are at the very top of the ADD.
*
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
storm::storage::SparseMatrix<double> toMatrix(std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix and the given vector to a row-grouped vector.
* The given offset-labeled DDs are used to determine the correct row and column, respectively, for each
* entry. Note: this function assumes that the meta variables used to distinguish different row groups are
* at the very top of the ADD.
*
* @param vector The symbolic vector to convert.
* @param rowGroupSizes A vector specifying the sizes of the row groups.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD.
*/
std::pair<storm::storage::SparseMatrix<double>, std::vector<double>> toMatrixVector(storm::dd::Add<storm::dd::DdType::CUDD> const& vector, std::vector<uint_fast64_t>&& rowGroupSizes, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Exports the DD to the given file in the dot format.
*
* @param filename The name of the file to which the DD is to be exported.
*/
void exportToDot(std::string const& filename = "") const override;
/*!
* Retrieves an iterator that points to the first meta variable assignment with a non-zero function value.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points to the first meta variable assignment with a non-zero function value.
*/
DdForwardIterator<DdType::CUDD> begin(bool enumerateDontCareMetaVariables = true) const;
/*!
* Retrieves an iterator that points past the end of the container.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points past the end of the container.
*/
DdForwardIterator<DdType::CUDD> end(bool enumerateDontCareMetaVariables = true) const;
friend std::ostream & operator<<(std::ostream& out, const Add<DdType::CUDD>& add);
/*!
* Converts the ADD to a BDD by mapping all values unequal to zero to 1. This effectively does the same as
* a call to notZero().
*
* @return The corresponding BDD.
*/
Bdd<DdType::CUDD> toBdd() const;
private:
/*!
* Retrieves the CUDD ADD object associated with this ADD.
*
* @return The CUDD ADD object associated with this ADD.
*/
ADD getCuddAdd() const;
/*!
* Retrieves the raw DD node of CUDD associated with this ADD.
*
* @return The DD node of CUDD associated with this ADD.
*/
DdNode* getCuddDdNode() const;
/*!
* Creates an ADD that encapsulates the given CUDD ADD.
*
* @param ddManager The manager responsible for this DD.
* @param cuddAdd The CUDD ADD to store.
* @param containedMetaVariables The meta variables that appear in the DD.
*/
Add(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, ADD cuddAdd, std::set<storm::expressions::Variable> const& containedMetaVariables = std::set<storm::expressions::Variable>());
/*!
* Converts the ADD to a row-grouped (sparse) double matrix. If the optional vector is given, it is also
* translated to an explicit row-grouped vector with the same row-grouping. The given offset-labeled DDs
* are used to determine the correct row and column, respectively, for each entry. Note: this function
* assumes that the meta variables used to distinguish different row groups are at the very top of the ADD.
*
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD and and a vector corresponding to the symbolic vector
* (if it was given).
*/
storm::storage::SparseMatrix<double> toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Converts the ADD to a row-grouped (sparse) double matrix and the given vector to an equally row-grouped
* explicit vector. The given offset-labeled DDs are used to determine the correct row and column,
* respectively, for each entry. Note: this function assumes that the meta variables used to distinguish
* different row groups are at the very top of the ADD.
*
* @param vector The vector that is to be transformed to an equally grouped explicit vector.
* @param rowGroupSizes A vector specifying the sizes of the row groups.
* @param rowMetaVariables The meta variables that encode the rows of the matrix.
* @param columnMetaVariables The meta variables that encode the columns of the matrix.
* @param groupMetaVariables The meta variables that are used to distinguish different row groups.
* @param rowOdd The ODD used for determining the correct row.
* @param columnOdd The ODD used for determining the correct column.
* @return The matrix that is represented by this ADD and and a vector corresponding to the symbolic vector
* (if it was given).
*/
std::pair<storm::storage::SparseMatrix<double>,std::vector<double>> toMatrixVector(storm::dd::Add<storm::dd::DdType::CUDD> const& vector, std::vector<uint_fast64_t>&& rowGroupSizes, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd<DdType::CUDD> const& rowOdd, storm::dd::Odd<DdType::CUDD> const& columnOdd) const;
/*!
* Helper function to convert the DD into a (sparse) matrix.
*
* @param dd The DD to convert.
* @param rowIndications A vector indicating at which position in the columnsAndValues vector the entries
* of row i start. Note: this vector is modified in the computation. More concretely, each entry i in the
* vector will be increased by the number of entries in the row. This can be used to count the number
* of entries in each row. If the values are not to be modified, a copy needs to be provided or the entries
* need to be restored afterwards.
* @param columnsAndValues The vector that will hold the columns and values of non-zero entries upon successful
* completion.
* @param rowGroupOffsets The row offsets at which a given row group starts.
* @param rowOdd The ODD used for the row translation.
* @param columnOdd The ODD used for the column translation.
* @param currentRowLevel The currently considered row level in the DD.
* @param currentColumnLevel The currently considered row level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentRowOffset The current row offset.
* @param currentColumnOffset The current row offset.
* @param ddRowVariableIndices The (sorted) indices of all DD row variables that need to be considered.
* @param ddColumnVariableIndices The (sorted) indices of all DD row variables that need to be considered.
* @param generateValues If set to true, the vector columnsAndValues is filled with the actual entries, which
* only works if the offsets given in rowIndications are already correct. If they need to be computed first,
* this flag needs to be false.
*/
void toMatrixRec(DdNode const* dd, std::vector<uint_fast64_t>& rowIndications, std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>>& columnsAndValues, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, Odd<DdType::CUDD> const& columnOdd, uint_fast64_t currentRowLevel, uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& ddColumnVariableIndices, bool generateValues = true) const;
/*!
* Helper function to convert the DD into an (explicit) vector.
*
* @param dd The DD to convert.
* @param result The vector that will hold the values upon successful completion.
* @param rowGroupOffsets The row offsets at which a given row group starts.
* @param rowOdd The ODD used for the row translation.
* @param currentRowLevel The currently considered row level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentRowOffset The current row offset.
* @param ddRowVariableIndices The (sorted) indices of all DD row variables that need to be considered.
*/
template<typename ValueType>
void toVectorRec(DdNode const* dd, std::vector<ValueType>& result, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, uint_fast64_t currentRowLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices) const;
/*!
* Splits the given matrix DD into the groups using the given group variables.
*
* @param dd The DD to split.
* @param groups A vector that is to be filled with the DDs for the individual groups.
* @param ddGroupVariableIndices The (sorted) indices of all DD group variables that need to be considered.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param remainingMetaVariables The meta variables that remain in the DDs after the groups have been split.
*/
void splitGroupsRec(DdNode* dd, std::vector<Add<DdType::CUDD>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables) const;
/*!
* Splits the given matrix and vector DDs into the groups using the given group variables.
*
* @param dd1 The matrix DD to split.
* @param dd2 The vector DD to split.
* @param groups A vector that is to be filled with the pairs of matrix/vector DDs for the individual groups.
* @param ddGroupVariableIndices The (sorted) indices of all DD group variables that need to be considered.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param remainingMetaVariables1 The meta variables that remain in the matrix DD after the groups have been split.
* @param remainingMetaVariables2 The meta variables that remain in the vector DD after the groups have been split.
*/
void splitGroupsRec(DdNode* dd1, DdNode* dd2, std::vector<std::pair<Add<DdType::CUDD>, Add<DdType::CUDD>>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::set<storm::expressions::Variable> const& remainingMetaVariables1, std::set<storm::expressions::Variable> const& remainingMetaVariables2) const;
/*!
* Adds the current (DD-based) vector to the given explicit one.
*
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered.
* @param targetVector The vector to which the translated DD-based vector is to be added.
*/
template<typename ValueType>
void addToVector(Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const;
/*!
* Performs a recursive step to perform the given function between the given DD-based vector and the given
* explicit vector.
*
* @param dd The DD to add to the explicit vector.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentOffset The current offset.
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered.
* @param targetVector The vector to which the translated DD-based vector is to be added.
*/
template<typename ValueType>
void modifyVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, double const&)> const& function) const;
/*!
* Builds an ADD representing the given vector.
*
* @param ddManager The manager responsible for the ADD.
* @param values The vector that is to be represented by the ADD.
* @param odd The ODD used for the translation.
* @param metaVariables The meta variables used for the translation.
* @return The resulting (CUDD) ADD.
*/
template<typename ValueType>
static ADD fromVector(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::set<storm::expressions::Variable> const& metaVariables);
/*!
* Builds an ADD representing the given vector.
*
* @param manager The manager responsible for the ADD.
* @param currentOffset The current offset in the vector.
* @param currentLevel The current level in the DD.
* @param maxLevel The maximal level in the DD.
* @param values The vector that is to be represented by the ADD.
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) list of DD variable indices to use.
* @return The resulting (CUDD) ADD node.
*/
template<typename ValueType>
static DdNode* fromVectorRec(::DdManager* manager, uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices);
// The ADD created by CUDD.
ADD cuddAdd;
};
}
}
#endif /* STORM_STORAGE_DD_CUDDADD_H_ */

37
src/storage/dd/cudd/CuddDdForwardIterator.cpp → src/storage/dd/cudd/CuddAddIterator.cpp

@ -1,4 +1,4 @@
#include "src/storage/dd/cudd/CuddDdForwardIterator.h"
#include "src/storage/dd/cudd/CuddAddIterator.h"
#include "src/storage/dd/cudd/CuddDdManager.h"
#include "src/storage/dd/DdMetaVariable.h"
#include "src/utility/macros.h"
@ -6,11 +6,13 @@
namespace storm {
namespace dd {
DdForwardIterator<DdType::CUDD>::DdForwardIterator() : ddManager(), generator(), cube(), value(), isAtEnd(), metaVariables(), enumerateDontCareMetaVariables(), cubeCounter(), relevantDontCareDdVariables(), currentValuation() {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>::DdForwardIterator() : ddManager(), generator(), cube(), value(), isAtEnd(), metaVariables(), enumerateDontCareMetaVariables(), cubeCounter(), relevantDontCareDdVariables(), currentValuation() {
// Intentionally left empty.
}
DdForwardIterator<DdType::CUDD>::DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables) : ddManager(ddManager), generator(generator), cube(cube), value(value), isAtEnd(isAtEnd), metaVariables(metaVariables), enumerateDontCareMetaVariables(enumerateDontCareMetaVariables), cubeCounter(), relevantDontCareDdVariables(), currentValuation(ddManager->getExpressionManager().getSharedPointer()) {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>::DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables) : ddManager(ddManager), generator(generator), cube(cube), value(value), isAtEnd(isAtEnd), metaVariables(metaVariables), enumerateDontCareMetaVariables(enumerateDontCareMetaVariables), cubeCounter(), relevantDontCareDdVariables(), currentValuation(ddManager->getExpressionManager().getSharedPointer()) {
// If the given generator is not yet at its end, we need to create the current valuation from the cube from
// scratch.
if (!this->isAtEnd) {
@ -19,13 +21,15 @@ namespace storm {
}
}
DdForwardIterator<DdType::CUDD>::DdForwardIterator(DdForwardIterator<DdType::CUDD>&& other) : ddManager(other.ddManager), generator(other.generator), cube(other.cube), value(other.value), isAtEnd(other.isAtEnd), metaVariables(other.metaVariables), cubeCounter(other.cubeCounter), relevantDontCareDdVariables(other.relevantDontCareDdVariables), currentValuation(other.currentValuation) {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>::DdForwardIterator(AddIterator<DdType::CUDD, ValueType>&& other) : ddManager(other.ddManager), generator(other.generator), cube(other.cube), value(other.value), isAtEnd(other.isAtEnd), metaVariables(other.metaVariables), cubeCounter(other.cubeCounter), relevantDontCareDdVariables(other.relevantDontCareDdVariables), currentValuation(other.currentValuation) {
// Null-out the pointers of which we took possession.
other.cube = nullptr;
other.generator = nullptr;
}
DdForwardIterator<DdType::CUDD>& DdForwardIterator<DdType::CUDD>::operator=(DdForwardIterator<DdType::CUDD>&& other) {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>& AddIterator<DdType::CUDD, ValueType>::operator=(AddIterator<DdType::CUDD, ValueType>&& other) {
if (this != &other) {
this->ddManager = other.ddManager;
this->generator = other.generator;
@ -44,7 +48,8 @@ namespace storm {
return *this;
}
DdForwardIterator<DdType::CUDD>::~DdForwardIterator() {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>::~DdForwardIterator() {
// We free the pointers sind Cudd allocates them using malloc rather than new/delete.
if (this->cube != nullptr) {
free(this->cube);
@ -54,7 +59,8 @@ namespace storm {
}
}
DdForwardIterator<DdType::CUDD>& DdForwardIterator<DdType::CUDD>::operator++() {
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType>& AddIterator<DdType::CUDD, ValueType>::operator++() {
STORM_LOG_ASSERT(!this->isAtEnd, "Illegally incrementing iterator that is already at its end.");
// If there were no (relevant) don't cares or we have enumerated all combination, we need to eliminate the
@ -76,7 +82,8 @@ namespace storm {
return *this;
}
void DdForwardIterator<DdType::CUDD>::treatNextInCube() {
template<typename ValueType>
void AddIterator<DdType::CUDD, ValueType>::treatNextInCube() {
// Start by increasing the counter and check which bits we need to set/unset in the new valuation.
++this->cubeCounter;
@ -99,7 +106,8 @@ namespace storm {
}
}
void DdForwardIterator<DdType::CUDD>::treatNewCube() {
template<typename ValueType>
void AddIterator<DdType::CUDD, ValueType>::treatNewCube() {
this->relevantDontCareDdVariables.clear();
// Now loop through the bits of all meta variables and check whether they need to be set, not set or are
@ -150,7 +158,8 @@ namespace storm {
this->cubeCounter = 0;
}
bool DdForwardIterator<DdType::CUDD>::operator==(DdForwardIterator<DdType::CUDD> const& other) const {
template<typename ValueType>
bool AddIterator<DdType::CUDD, ValueType>::operator==(AddIterator<DdType::CUDD, ValueType> const& other) const {
if (this->isAtEnd && other.isAtEnd) {
return true;
} else {
@ -162,12 +171,16 @@ namespace storm {
}
}
bool DdForwardIterator<DdType::CUDD>::operator!=(DdForwardIterator<DdType::CUDD> const& other) const {
template<typename ValueType>
bool AddIterator<DdType::CUDD, ValueType>::operator!=(AddIterator<DdType::CUDD, ValueType> const& other) const {
return !(*this == other);
}
std::pair<storm::expressions::SimpleValuation, double> DdForwardIterator<DdType::CUDD>::operator*() const {
template<typename ValueType>
std::pair<storm::expressions::SimpleValuation, double> AddIterator<DdType::CUDD, ValueType>::operator*() const {
return std::make_pair(currentValuation, value);
}
template class AddIterator<DdType::CUDD, double>;
}
}

32
src/storage/dd/cudd/CuddDdForwardIterator.h → src/storage/dd/cudd/CuddAddIterator.h

@ -1,5 +1,5 @@
#ifndef STORM_STORAGE_DD_CUDDDDFORWARDITERATOR_H_
#define STORM_STORAGE_DD_CUDDDDFORWARDITERATOR_H_
#ifndef STORM_STORAGE_DD_CUDDAddIterator_H_
#define STORM_STORAGE_DD_CUDDAddIterator_H_
#include <memory>
#include <cstdint>
@ -7,7 +7,7 @@
#include <tuple>
#include <utility>
#include "src/storage/dd/DdForwardIterator.h"
#include "src/storage/dd/AddIterator.h"
#include "src/storage/expressions/SimpleValuation.h"
// Include the C++-interface of CUDD.
@ -19,31 +19,31 @@ namespace storm {
template<DdType Type> class DdManager;
template<DdType Type> class Add;
template<>
class DdForwardIterator<DdType::CUDD> {
template<typename ValueType>
class AddIterator<DdType::CUDD, ValueType> {
public:
friend class Add<DdType::CUDD>;
// Default-instantiate the constructor.
DdForwardIterator();
AddIterator();
// Forbid copy-construction and copy assignment, because ownership of the internal pointer is unclear then.
DdForwardIterator(DdForwardIterator<DdType::CUDD> const& other) = delete;
DdForwardIterator& operator=(DdForwardIterator<DdType::CUDD> const& other) = delete;
AddIterator(AddIterator<DdType::CUDD, ValueType> const& other) = delete;
AddIterator& operator=(AddIterator<DdType::CUDD, ValueType> const& other) = delete;
// Provide move-construction and move-assignment, though.
DdForwardIterator(DdForwardIterator<DdType::CUDD>&& other);
DdForwardIterator& operator=(DdForwardIterator<DdType::CUDD>&& other);
AddIterator(AddIterator<DdType::CUDD, ValueType>&& other);
AddIterator& operator=(AddIterator<DdType::CUDD, ValueType>&& other);
/*!
* Destroys the forward iterator and frees the generator as well as the cube if they are not the nullptr.
*/
~DdForwardIterator();
~AddIterator();
/*!
* Moves the iterator one position forward.
*/
DdForwardIterator<DdType::CUDD>& operator++();
AddIterator<DdType::CUDD, ValueType>& operator++();
/*!
* Returns a pair consisting of a valuation of meta variables and the value to which this valuation is
@ -60,7 +60,7 @@ namespace storm {
* @param other The iterator with which to compare.
* @return True if the two iterators are considered equal.
*/
bool operator==(DdForwardIterator<DdType::CUDD> const& other) const;
bool operator==(AddIterator<DdType::CUDD, ValueType> const& other) const;
/*!
* Compares the iterator with the given one. Two iterators are considered unequal iff they are not
@ -69,7 +69,7 @@ namespace storm {
* @param other The iterator with which to compare.
* @return True if the two iterators are considered unequal.
*/
bool operator!=(DdForwardIterator<DdType::CUDD> const& other) const;
bool operator!=(AddIterator<DdType::CUDD, ValueType> const& other) const;
private:
/*!
@ -85,7 +85,7 @@ namespace storm {
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
*/
DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<storm::expressions::Variable> const* metaVariables = nullptr, bool enumerateDontCareMetaVariables = true);
AddIterator(std::shared_ptr<DdManager<DdType::CUDD> const> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<storm::expressions::Variable> const* metaVariables = nullptr, bool enumerateDontCareMetaVariables = true);
/*!
* Recreates the internal information when a new cube needs to be treated.
@ -133,4 +133,4 @@ namespace storm {
}
}
#endif /* STORM_STORAGE_DD_CUDDDDFORWARDITERATOR_H_ */
#endif /* STORM_STORAGE_DD_CUDDAddIterator_H_ */

2
src/storage/dd/cudd/CuddOdd.h

@ -5,7 +5,7 @@
#include <unordered_map>
#include "src/storage/dd/Odd.h"
#include "src/storage/dd/cudd/CuddAdd.h"
#include "src/storage/dd/Add.h"
#include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD.

757
src/storage/dd/cudd/InternalCuddAdd.cpp

@ -0,0 +1,757 @@
#include "src/storage/dd/cudd/InternalCuddAdd.h"
#include "src/storage/dd/cudd/CuddOdd.h"
#include "src/storage/dd/cudd/InternalCuddDdManager.h"
#include "src/storage/dd/cudd/InternalCuddBdd.h"
#include "src/storage/SparseMatrix.h"
#include "src/utility/constants.h"
namespace storm {
namespace dd {
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::operator==(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return this->getCuddAdd() == other.getCuddAdd();
}
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::operator!=(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return !(*this == other);
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::ite(InternalAdd<DdType::CUDD, ValueType> const& thenDd, InternalAdd<DdType::CUDD, ValueType> const& elseDd) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Ite(thenDd.getCuddAdd(), elseDd.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator!() const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, ~this->getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator||(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd() | other.getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType>& InternalAdd<DdType::CUDD, ValueType>::operator|=(InternalAdd<DdType::CUDD, ValueType> const& other) {
this->cuddAdd = this->getCuddAdd() | other.getCuddAdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator+(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd() + other.getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType>& InternalAdd<DdType::CUDD, ValueType>::operator+=(InternalAdd<DdType::CUDD, ValueType> const& other) {
this->cuddAdd = this->getCuddAdd() + other.getCuddAdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator*(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd() * other.getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType>& InternalAdd<DdType::CUDD, ValueType>::operator*=(InternalAdd<DdType::CUDD, ValueType> const& other) {
this->cuddAdd = this->getCuddAdd() * other.getCuddAdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator-(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd() - other.getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType>& InternalAdd<DdType::CUDD, ValueType>::operator-=(InternalAdd<DdType::CUDD, ValueType> const& other) {
this->cuddAdd = this->getCuddAdd() - other.getCuddAdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::operator/(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd() / other.getCuddAdd());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType>& InternalAdd<DdType::CUDD, ValueType>::operator/=(InternalAdd<DdType::CUDD, ValueType> const& other) {
this->cuddAdd = this->getCuddAdd() / other.getCuddAdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::equals(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Equals(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::notEquals(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().NotEquals(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::less(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().LessThan(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::lessOrEqual(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().LessThanOrEqual(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::greater(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().GreaterThan(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::greaterOrEqual(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().GreaterThanOrEqual(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::pow(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Pow(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::mod(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Mod(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::logxy(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().LogXY(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::floor() const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Floor());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::ceil() const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Ceil());
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::minimum(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Minimum(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::maximum(InternalAdd<DdType::CUDD, ValueType> const& other) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Maximum(other.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::sumAbstract(InternalBdd<DdType::CUDD> const& cube) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().ExistAbstract(cube.getCuddBdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::minAbstract(InternalBdd<DdType::CUDD> const& cube) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().MinAbstract(cube.getCuddBdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::maxAbstract(InternalBdd<DdType::CUDD> const& cube) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().MaxAbstract(cube.getCuddBdd()));
}
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::equalModuloPrecision(InternalAdd<DdType::CUDD, ValueType> const& other, double precision, bool relative) const {
if (relative) {
return this->getCuddAdd().EqualSupNormRel(other.getCuddAdd(), precision);
} else {
return this->getCuddAdd().EqualSupNorm(other.getCuddAdd(), precision);
}
};
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::swapVariables(std::vector<InternalAdd<DdType::CUDD, ValueType>> const& from, std::vector<InternalAdd<DdType::CUDD, ValueType>> const& to) const {
std::vector<ADD> fromAdd;
std::vector<ADD> toAdd;
for (auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
fromAdd.push_back(it1->getCuddAdd());
toAdd.push_back(it2->getCuddAdd());
}
return InternalBdd<DdType::CUDD>(ddManager, this->getCuddBdd().SwapVariables(fromAdd, toAdd));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::multiplyMatrix(InternalAdd<DdType::CUDD, ValueType> const& otherMatrix, std::vector<InternalAdd<DdType::CUDD, ValueType>> const& summationDdVariables) const {
// Create the CUDD summation variables.
std::vector<ADD> summationAdds;
for (auto const& ddVariable : summationDdVariables) {
summationAdds.push_back(ddVariable.toAdd().getCuddAdd());
}
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().MatrixMultiply(otherMatrix.getCuddAdd(), summationAdds));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::greater(ValueType const& value) const {
return InternalBdd<DdType::CUDD>(ddManager, this->getCuddAdd().BddStrictThreshold(value));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::greaterOrEqual(ValueType const& value) const {
return InternalBdd<DdType::CUDD>(ddManager, this->getCuddAdd().BddThreshold(value));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::less(ValueType const& value) const {
return InternalBdd<DdType::CUDD>(ddManager, ~this->getCuddAdd().BddThreshold(value));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::lessOrEqual(ValueType const& value) const {
return InternalBdd<DdType::CUDD>(ddManager, ~this->getCuddAdd().BddStrictThreshold(value));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::notZero() const {
return this->toBdd();
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::constrain(InternalAdd<DdType::CUDD, ValueType> const& constraint) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Constrain(constraint.getCuddAdd()));
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::restrict(InternalAdd<DdType::CUDD, ValueType> const& constraint) const {
return InternalAdd<DdType::CUDD, ValueType>(ddManager, this->getCuddAdd().Restrict(constraint.getCuddAdd()));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::getSupport() const {
return InternalBdd<DdType::CUDD>(ddManager, this->getCuddAdd().Support());
}
template<typename ValueType>
uint_fast64_t InternalAdd<DdType::CUDD, ValueType>::getNonZeroCount(uint_fast64_t numberOfDdVariables) const {
return static_cast<uint_fast64_t>(this->getCuddAdd().CountMinterm(static_cast<int>(numberOfDdVariables)));
}
template<typename ValueType>
uint_fast64_t InternalAdd<DdType::CUDD, ValueType>::getLeafCount() const {
return static_cast<uint_fast64_t>(this->getCuddAdd().CountLeaves());
}
template<typename ValueType>
uint_fast64_t InternalAdd<DdType::CUDD, ValueType>::getNodeCount() const {
return static_cast<uint_fast64_t>(this->getCuddAdd().nodeCount());
}
template<typename ValueType>
ValueType InternalAdd<DdType::CUDD, ValueType>::getMin() const {
ADD constantMinAdd = this->getCuddAdd().FindMin();
return static_cast<double>(Cudd_V(constantMinAdd.getNode()));
}
template<typename ValueType>
ValueType InternalAdd<DdType::CUDD, ValueType>::getMax() const {
ADD constantMaxAdd = this->getCuddAdd().FindMax();
return static_cast<double>(Cudd_V(constantMaxAdd.getNode()));
}
template<typename ValueType>
InternalBdd<DdType::CUDD> InternalAdd<DdType::CUDD, ValueType>::toBdd() const {
return InternalBdd<DdType::CUDD>(ddManager, this->getCuddAdd().BddPattern());
}
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::isOne() const {
return this->getCuddAdd().IsOne();
}
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::isZero() const {
return this->getCuddAdd().IsZero();
}
template<typename ValueType>
bool InternalAdd<DdType::CUDD, ValueType>::isConstant() const {
return Cudd_IsConstant(this->getCuddAdd().getNode());
}
template<typename ValueType>
uint_fast64_t InternalAdd<DdType::CUDD, ValueType>::getIndex() const {
return static_cast<uint_fast64_t>(this->getCuddAdd().NodeReadIndex());
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::exportToDot(std::string const& filename, std::vector<std::string> const& ddVariableNamesAsStrings) const {
// Build the name input of the DD.
std::vector<char*> ddNames;
std::string ddName("f");
ddNames.push_back(new char[ddName.size() + 1]);
std::copy(ddName.c_str(), ddName.c_str() + 2, ddNames.back());
// Now build the variables names.
std::vector<char*> ddVariableNames;
for (auto const& element : ddVariableNamesAsStrings) {
ddVariableNames.push_back(new char[element.size() + 1]);
std::copy(element.c_str(), element.c_str() + element.size() + 1, ddVariableNames.back());
}
// Open the file, dump the DD and close it again.
FILE* filePointer = fopen(filename.c_str() , "w");
std::vector<ADD> cuddAddVector = { this->getCuddAdd() };
this->getDdManager()->getCuddManager().DumpDot(cuddAddVector, &ddVariableNames[0], &ddNames[0], filePointer);
fclose(filePointer);
// Finally, delete the names.
for (char* element : ddNames) {
delete[] element;
}
for (char* element : ddVariableNames) {
delete[] element;
}
}
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::begin(std::set<storm::expressions::Variable> const& metaVariables, bool enumerateDontCareMetaVariables) const {
int* cube;
double value;
DdGen* generator = this->getCuddAdd().FirstCube(&cube, &value);
return AddIterator<DdType::CUDD, ValueType>(ddManager, generator, cube, value, (Cudd_IsGenEmpty(generator) != 0), &metaVariables, enumerateDontCareMetaVariables);
}
template<typename ValueType>
AddIterator<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::end(bool enumerateDontCareMetaVariables) const {
return AddIterator<DdType::CUDD, ValueType>(ddManager, nullptr, nullptr, 0, true, nullptr, enumerateDontCareMetaVariables);
}
template<typename ValueType>
ADD InternalAdd<DdType::CUDD, ValueType>::getCuddAdd() const {
return this->cuddAdd;
}
template<typename ValueType>
DdNode* InternalAdd<DdType::CUDD, ValueType>::getCuddDdNode() const {
return this->getCuddAdd().getNode();
}
template<typename ValueType>
std::vector<ValueType> InternalAdd<DdType::CUDD, ValueType>::toVector(std::vector<uint_fast64_t> const& ddGroupVariableIndices, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& groupOffsets) const {
// Start by splitting the symbolic vector into groups.
std::vector<InternalAdd<DdType::CUDD, ValueType>> groups;
splitGroupsRec(this->getCuddDdNode(), groups, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
// Now iterate over the groups and add them to the resulting vector.
std::vector<ValueType> result(groupOffsets.back(), storm::utility::zero<ValueType>());
for (uint_fast64_t i = 0; i < groups.size(); ++i) {
toVectorRec(groups[i].getCuddDdNode(), result, groupOffsets, rowOdd, 0, ddRowVariableIndices.size(), 0, ddRowVariableIndices);
}
return result;
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::addToExplicitVector(storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const {
composeVector(odd, ddVariableIndices, targetVector, std::plus<ValueType>());
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::composeVector(storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
composeVectorRec(this->getCuddDdNode(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, targetVector, function);
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::composeVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
// For the empty DD, we do not need to add any entries.
if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
return;
}
// If we are at the maximal level, the value to be set is stored as a constant in the DD.
if (currentLevel == maxLevel) {
targetVector[currentOffset] = function(targetVector[currentOffset], Cudd_V(dd));
} else if (ddVariableIndices[currentLevel] < dd->index) {
// If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set
// and for the one in which it is not set.
composeVectorRec(dd, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeVectorRec(dd, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
} else {
// Otherwise, we simply recursively call the function for both (different) cases.
composeVectorRec(Cudd_E(dd), currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeVectorRec(Cudd_T(dd), currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
}
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::toVectorRec(DdNode const* dd, std::vector<ValueType>& result, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, uint_fast64_t currentRowLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices) const {
// For the empty DD, we do not need to add any entries.
if (dd == Cudd_ReadZero(ddManager->getCuddManager().getManager())) {
return;
}
// If we are at the maximal level, the value to be set is stored as a constant in the DD.
if (currentRowLevel == maxLevel) {
result[rowGroupOffsets[currentRowOffset]] = Cudd_V(dd);
} else if (ddRowVariableIndices[currentRowLevel] < dd->index) {
toVectorRec(dd, result, rowGroupOffsets, rowOdd.getElseSuccessor(), currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
toVectorRec(dd, result, rowGroupOffsets, rowOdd.getThenSuccessor(), currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
} else {
toVectorRec(Cudd_E(dd), result, rowGroupOffsets, rowOdd.getElseSuccessor(), currentRowLevel + 1, maxLevel, currentRowOffset, ddRowVariableIndices);
toVectorRec(Cudd_T(dd), result, rowGroupOffsets, rowOdd.getThenSuccessor(), currentRowLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(), ddRowVariableIndices);
}
}
template<typename ValueType>
storm::storage::SparseMatrix<ValueType> InternalAdd<DdType::CUDD, ValueType>::toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices) const {
// Prepare the vectors that represent the matrix.
std::vector<uint_fast64_t> rowIndications(rowOdd.getTotalOffset() + 1);
std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>> columnsAndValues(this->getNonZeroCount());
// Create a trivial row grouping.
std::vector<uint_fast64_t> trivialRowGroupIndices(rowIndications.size());
uint_fast64_t i = 0;
for (auto& entry : trivialRowGroupIndices) {
entry = i;
++i;
}
// Use the toMatrixRec function to compute the number of elements in each row. Using the flag, we prevent
// it from actually generating the entries in the entry vector.
toMatrixRec(this->getCuddDdNode(), rowIndications, columnsAndValues, trivialRowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, false);
// TODO: counting might be faster by just summing over the primed variables and then using the ODD to convert
// the resulting (DD) vector to an explicit vector.
// Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
uint_fast64_t tmp = 0;
uint_fast64_t tmp2 = 0;
for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
tmp2 = rowIndications[i];
rowIndications[i] = rowIndications[i - 1] + tmp;
std::swap(tmp, tmp2);
}
rowIndications[0] = 0;
// Now actually fill the entry vector.
toMatrixRec(this->getCuddDdNode(), rowIndications, columnsAndValues, trivialRowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, true);
// Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
rowIndications[i] = rowIndications[i - 1];
}
rowIndications[0] = 0;
// Construct matrix and return result.
return storm::storage::SparseMatrix<double>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(trivialRowGroupIndices), false);
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::toMatrixRec(DdNode const* dd, std::vector<uint_fast64_t>& rowIndications, std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>>& columnsAndValues, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, Odd<DdType::CUDD> const& columnOdd, uint_fast64_t currentRowLevel, uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& ddColumnVariableIndices, bool generateValues) const {
// For the empty DD, we do not need to add any entries.
if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
return;
}
// If we are at the maximal level, the value to be set is stored as a constant in the DD.
if (currentRowLevel + currentColumnLevel == maxLevel) {
if (generateValues) {
columnsAndValues[rowIndications[rowGroupOffsets[currentRowOffset]]] = storm::storage::MatrixEntry<uint_fast64_t, double>(currentColumnOffset, Cudd_V(dd));
}
++rowIndications[rowGroupOffsets[currentRowOffset]];
} else {
DdNode const* elseElse;
DdNode const* elseThen;
DdNode const* thenElse;
DdNode const* thenThen;
if (ddColumnVariableIndices[currentColumnLevel] < dd->index) {
elseElse = elseThen = thenElse = thenThen = dd;
} else if (ddRowVariableIndices[currentColumnLevel] < dd->index) {
elseElse = thenElse = Cudd_E(dd);
elseThen = thenThen = Cudd_T(dd);
} else {
DdNode const* elseNode = Cudd_E(dd);
if (ddColumnVariableIndices[currentColumnLevel] < elseNode->index) {
elseElse = elseThen = elseNode;
} else {
elseElse = Cudd_E(elseNode);
elseThen = Cudd_T(elseNode);
}
DdNode const* thenNode = Cudd_T(dd);
if (ddColumnVariableIndices[currentColumnLevel] < thenNode->index) {
thenElse = thenThen = thenNode;
} else {
thenElse = Cudd_E(thenNode);
thenThen = Cudd_T(thenNode);
}
}
// Visit else-else.
toMatrixRec(elseElse, rowIndications, columnsAndValues, rowGroupOffsets, rowOdd.getElseSuccessor(), columnOdd.getElseSuccessor(), currentRowLevel + 1, currentColumnLevel + 1, maxLevel, currentRowOffset, currentColumnOffset, ddRowVariableIndices, ddColumnVariableIndices, generateValues);
// Visit else-then.
toMatrixRec(elseThen, rowIndications, columnsAndValues, rowGroupOffsets, rowOdd.getElseSuccessor(), columnOdd.getThenSuccessor(), currentRowLevel + 1, currentColumnLevel + 1, maxLevel, currentRowOffset, currentColumnOffset + columnOdd.getElseOffset(), ddRowVariableIndices, ddColumnVariableIndices, generateValues);
// Visit then-else.
toMatrixRec(thenElse, rowIndications, columnsAndValues, rowGroupOffsets, rowOdd.getThenSuccessor(), columnOdd.getElseSuccessor(), currentRowLevel + 1, currentColumnLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(), currentColumnOffset, ddRowVariableIndices, ddColumnVariableIndices, generateValues);
// Visit then-then.
toMatrixRec(thenThen, rowIndications, columnsAndValues, rowGroupOffsets, rowOdd.getThenSuccessor(), columnOdd.getThenSuccessor(), currentRowLevel + 1, currentColumnLevel + 1, maxLevel, currentRowOffset + rowOdd.getElseOffset(), currentColumnOffset + columnOdd.getElseOffset(), ddRowVariableIndices, ddColumnVariableIndices, generateValues);
}
}
template<typename ValueType>
storm::storage::SparseMatrix<ValueType> InternalAdd<DdType::CUDD, ValueType>::toMatrix(std::vector<uint_fast64_t> const& ddGroupVariableIndices, InternalBdd<DdType::CUDD> const& groupVariableCube, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices, InternalBdd<DdType::CUDD> const& columnVariableCube) const {
// Start by computing the offsets (in terms of rows) for each row group.
InternalAdd<DdType::CUDD, ValueType> stateToNumberOfChoices = this->notZero().existsAbstract(columnVariableCube).toAdd().sumAbstract(groupVariableCube);
std::vector<ValueType> rowGroupIndicesAsValueType = stateToNumberOfChoices.toVector(rowOdd);
std::vector<uint_fast64_t> rowGroupIndices(rowGroupIndicesAsValueType.size() + 1);
std::transform(rowGroupIndicesAsValueType.begin(), rowGroupIndicesAsValueType.end(), rowGroupIndices.begin(), [] (ValueType const& value) { return static_cast<uint_fast64_t>(value); });
uint_fast64_t tmp = 0;
uint_fast64_t tmp2 = 0;
for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) {
tmp2 = rowGroupIndices[i];
rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp;
std::swap(tmp, tmp2);
}
rowGroupIndices[0] = 0;
// Next, we split the matrix into one for each group. This only works if the group variables are at the very
// top.
std::vector<InternalAdd<DdType::CUDD, ValueType>> groups;
splitGroupsRec(this->getCuddDdNode(), groups, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
// Create the actual storage for the non-zero entries.
std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>> columnsAndValues(this->getNonZeroCount());
// Now compute the indices at which the individual rows start.
std::vector<uint_fast64_t> rowIndications(rowGroupIndices.back() + 1);
std::vector<InternalAdd<DdType::CUDD, ValueType>> statesWithGroupEnabled(groups.size());
InternalAdd<DdType::CUDD, ValueType> stateToRowGroupCount = this->getDdManager()->getAddZero();
for (uint_fast64_t i = 0; i < groups.size(); ++i) {
auto const& dd = groups[i];
toMatrixRec(dd.getCuddDdNode(), rowIndications, columnsAndValues, rowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, false);
statesWithGroupEnabled[i] = dd.notZero().existsAbstract(columnVariableCube).toAdd();
stateToRowGroupCount += statesWithGroupEnabled[i];
statesWithGroupEnabled[i].addToVector(rowOdd, ddRowVariableIndices, rowGroupIndices);
}
// Since we modified the rowGroupIndices, we need to restore the correct values.
std::function<uint_fast64_t (uint_fast64_t const&, double const&)> fct = [] (uint_fast64_t const& a, double const& b) -> uint_fast64_t { return a - static_cast<uint_fast64_t>(b); };
composeVectorRec(stateToRowGroupCount.getCuddDdNode(), 0, ddRowVariableIndices.size(), 0, rowOdd, ddRowVariableIndices, rowGroupIndices, fct);
// Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
tmp = 0;
tmp2 = 0;
for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
tmp2 = rowIndications[i];
rowIndications[i] = rowIndications[i - 1] + tmp;
std::swap(tmp, tmp2);
}
rowIndications[0] = 0;
// Now actually fill the entry vector.
for (uint_fast64_t i = 0; i < groups.size(); ++i) {
auto const& dd = groups[i];
toMatrixRec(dd.getCuddDdNode(), rowIndications, columnsAndValues, rowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, true);
statesWithGroupEnabled[i].addToVector(rowOdd, ddRowVariableIndices, rowGroupIndices);
}
// Since we modified the rowGroupIndices, we need to restore the correct values.
composeVectorRec(stateToRowGroupCount.getCuddDdNode(), 0, ddRowVariableIndices.size(), 0, rowOdd, ddRowVariableIndices, rowGroupIndices, fct);
// Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
rowIndications[i] = rowIndications[i - 1];
}
rowIndications[0] = 0;
return storm::storage::SparseMatrix<ValueType>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices), true);
}
template<typename ValueType>
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> InternalAdd<DdType::CUDD, ValueType>::toMatrixVector(InternalAdd<DdType::CUDD, ValueType> const& vector, std::vector<uint_fast64_t> const& ddGroupVariableIndices, std::vector<uint_fast64_t>&& rowGroupIndices, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices, InternalBdd<DdType::CUDD> const& columnVariableCube) {
// Transform the row group sizes to the actual row group indices.
rowGroupIndices.resize(rowGroupIndices.size() + 1);
uint_fast64_t tmp = 0;
uint_fast64_t tmp2 = 0;
for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) {
tmp2 = rowGroupIndices[i];
rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp;
std::swap(tmp, tmp2);
}
rowGroupIndices[0] = 0;
// Create the explicit vector we need to fill later.
std::vector<double> explicitVector(rowGroupIndices.back());
// Next, we split the matrix into one for each group. This only works if the group variables are at the very top.
std::vector<std::pair<InternalAdd<DdType::CUDD, ValueType>, InternalAdd<DdType::CUDD, ValueType>>> groups;
splitGroupsRec(this->getCuddDdNode(), vector.getCuddDdNode(), groups, ddGroupVariableIndices, 0, ddGroupVariableIndices.size());
// Create the actual storage for the non-zero entries.
std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>> columnsAndValues(this->getNonZeroCount());
// Now compute the indices at which the individual rows start.
std::vector<uint_fast64_t> rowIndications(rowGroupIndices.back() + 1);
std::vector<storm::dd::InternalAdd<DdType::CUDD, ValueType>> statesWithGroupEnabled(groups.size());
storm::dd::InternalAdd<storm::dd::DdType::CUDD, ValueType> stateToRowGroupCount = this->getDdManager()->getAddZero();
for (uint_fast64_t i = 0; i < groups.size(); ++i) {
std::pair<storm::dd::InternalAdd<DdType::CUDD, ValueType>, storm::dd::InternalAdd<DdType::CUDD, ValueType>> ddPair = groups[i];
toMatrixRec(ddPair.first.getCuddDdNode(), rowIndications, columnsAndValues, rowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, false);
toVectorRec(ddPair.second.getCuddDdNode(), explicitVector, rowGroupIndices, rowOdd, 0, ddRowVariableIndices.size(), 0, ddRowVariableIndices);
statesWithGroupEnabled[i] = (ddPair.first.notZero().existsAbstract(columnVariableCube) || ddPair.second.notZero()).toAdd();
stateToRowGroupCount += statesWithGroupEnabled[i];
statesWithGroupEnabled[i].addToVector(rowOdd, ddRowVariableIndices, rowGroupIndices);
}
// Since we modified the rowGroupIndices, we need to restore the correct values.
std::function<uint_fast64_t (uint_fast64_t const&, double const&)> fct = [] (uint_fast64_t const& a, double const& b) -> uint_fast64_t { return a - static_cast<uint_fast64_t>(b); };
composeVectorRec(stateToRowGroupCount.getCuddDdNode(), 0, ddRowVariableIndices.size(), 0, rowOdd, ddRowVariableIndices, rowGroupIndices, fct);
// Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
tmp = 0;
tmp2 = 0;
for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
tmp2 = rowIndications[i];
rowIndications[i] = rowIndications[i - 1] + tmp;
std::swap(tmp, tmp2);
}
rowIndications[0] = 0;
// Now actually fill the entry vector.
for (uint_fast64_t i = 0; i < groups.size(); ++i) {
auto const& dd = groups[i].first;
toMatrixRec(dd.getCuddDdNode(), rowIndications, columnsAndValues, rowGroupIndices, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0, ddRowVariableIndices, ddColumnVariableIndices, true);
statesWithGroupEnabled[i].addToVector(rowOdd, ddRowVariableIndices, rowGroupIndices);
}
// Since we modified the rowGroupIndices, we need to restore the correct values.
composeVectorRec(stateToRowGroupCount.getCuddDdNode(), 0, ddRowVariableIndices.size(), 0, rowOdd, ddRowVariableIndices, rowGroupIndices, fct);
// Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
rowIndications[i] = rowIndications[i - 1];
}
rowIndications[0] = 0;
return std::make_pair(storm::storage::SparseMatrix<ValueType>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices), true), std::move(explicitVector));
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::splitGroupsRec(DdNode* dd, std::vector<InternalAdd<DdType::CUDD, ValueType>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel) const {
// For the empty DD, we do not need to create a group.
if (dd == Cudd_ReadZero(this->getDdManager()->getCuddManager().getManager())) {
return;
}
if (currentLevel == maxLevel) {
groups.push_back(InternalAdd<DdType::CUDD, ValueType>(ddManager, ADD(ddManager->getCuddManager(), dd)));
} else if (ddGroupVariableIndices[currentLevel] < dd->index) {
splitGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(dd, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
} else {
splitGroupsRec(Cudd_E(dd), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(Cudd_T(dd), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
}
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::splitGroupsRec(DdNode* dd1, DdNode* dd2, std::vector<std::pair<InternalAdd<DdType::CUDD, ValueType>, InternalAdd<DdType::CUDD, ValueType>>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel) const {
// For the empty DD, we do not need to create a group.
if (dd1 == Cudd_ReadZero(ddManager->getCuddManager().getManager()) && dd2 == Cudd_ReadZero(ddManager->getCuddManager().getManager())) {
return;
}
if (currentLevel == maxLevel) {
groups.push_back(std::make_pair(InternalAdd<DdType::CUDD, ValueType>(ddManager, ADD(ddManager->getCuddManager(), dd1)),
InternalAdd<DdType::CUDD, ValueType>(ddManager, ADD(ddManager->getCuddManager(), dd2))));
} else if (ddGroupVariableIndices[currentLevel] < dd1->index) {
if (ddGroupVariableIndices[currentLevel] < dd2->index) {
splitGroupsRec(dd1, dd2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(dd1, dd2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
} else {
splitGroupsRec(dd1, Cudd_T(dd2), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(dd1, Cudd_E(dd2), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
}
} else if (ddGroupVariableIndices[currentLevel] < dd2->index) {
splitGroupsRec(Cudd_T(dd1), dd2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(Cudd_E(dd1), dd2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
} else {
splitGroupsRec(Cudd_T(dd1), Cudd_T(dd2), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
splitGroupsRec(Cudd_E(dd1), Cudd_E(dd2), groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
}
}
template<typename ValueType>
InternalAdd<DdType::CUDD, ValueType> InternalAdd<DdType::CUDD, ValueType>::fromVector(InternalDdManager<DdType::CUDD> const* ddManager, std::vector<ValueType> const& values, storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices) {
uint_fast64_t offset = 0;
return InternalAdd<DdType::CUDD, ValueType>(ddManager, ADD(ddManager->getCuddManager(), fromVectorRec(ddManager->getCuddManager().getManager(), offset, 0, ddVariableIndices.size(), values, odd, ddVariableIndices)));
}
template<typename ValueType>
DdNode* InternalAdd<DdType::CUDD, ValueType>::fromVectorRec(::DdManager* manager, uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices) {
if (currentLevel == maxLevel) {
// If we are in a terminal node of the ODD, we need to check whether the then-offset of the ODD is one
// (meaning the encoding is a valid one) or zero (meaning the encoding is not valid). Consequently, we
// need to copy the next value of the vector iff the then-offset is greater than zero.
if (odd.getThenOffset() > 0) {
return Cudd_addConst(manager, values[currentOffset++]);
} else {
return Cudd_ReadZero(manager);
}
} else {
// If the total offset is zero, we can just return the constant zero DD.
if (odd.getThenOffset() + odd.getElseOffset() == 0) {
return Cudd_ReadZero(manager);
}
// Determine the new else-successor.
DdNode* elseSuccessor = nullptr;
if (odd.getElseOffset() > 0) {
elseSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, values, odd.getElseSuccessor(), ddVariableIndices);
} else {
elseSuccessor = Cudd_ReadZero(manager);
}
Cudd_Ref(elseSuccessor);
// Determine the new then-successor.
DdNode* thenSuccessor = nullptr;
if (odd.getThenOffset() > 0) {
thenSuccessor = fromVectorRec(manager, currentOffset, currentLevel + 1, maxLevel, values, odd.getThenSuccessor(), ddVariableIndices);
} else {
thenSuccessor = Cudd_ReadZero(manager);
}
Cudd_Ref(thenSuccessor);
// Create a node representing ITE(currentVar, thenSuccessor, elseSuccessor);
DdNode* result = Cudd_addIthVar(manager, static_cast<int>(ddVariableIndices[currentLevel]));
Cudd_Ref(result);
DdNode* newResult = Cudd_addIte(manager, result, thenSuccessor, elseSuccessor);
Cudd_Ref(newResult);
// Dispose of the intermediate results
Cudd_RecursiveDeref(manager, result);
Cudd_RecursiveDeref(manager, thenSuccessor);
Cudd_RecursiveDeref(manager, elseSuccessor);
// Before returning, we remove the protection imposed by the previous call to Cudd_Ref.
Cudd_Deref(newResult);
return newResult;
}
}
template class InternalAdd<DdType::CUDD, double>;
}
}

598
src/storage/dd/cudd/InternalCuddAdd.h

@ -6,24 +6,37 @@
#include "src/storage/dd/DdType.h"
#include "src/storage/dd/InternalAdd.h"
#include "src/storage/expressions/Variable.h"
// Include the C++-interface of CUDD.
#include "cuddObj.hh"
namespace storm {
namespace storage {
template<typename T> class SparseMatrix;
template<typename T>
class SparseMatrix;
class BitVector;
template<typename E, typename V> class MatrixEntry;
template<typename E, typename V>
class MatrixEntry;
}
namespace dd {
// Forward-declare some classes.
template<DdType Type> class DdManager;
template<DdType Type> class Odd;
template<DdType Type> class Bdd;
template<DdType LibraryType>
class InternalDdManager;
template<DdType LibraryType>
class InternalBdd;
template<DdType LibraryType, typename ValueType>
class AddIterator;
template<DdType LibraryType>
class Odd;
template<typename ValueType>
class InternalAdd<DdType::CUDD, ValueType> : public Dd<DdType::CUDD> {
class InternalAdd<DdType::CUDD, ValueType> {
public:
/*!
* Creates an ADD that encapsulates the given CUDD ADD.
@ -32,8 +45,478 @@ namespace storm {
* @param cuddAdd The CUDD ADD to store.
* @param containedMetaVariables The meta variables that appear in the DD.
*/
Add(InternalDdManager<DdType::CUDD> const* ddManager, ADD cuddAdd);
InternalAdd(InternalDdManager<DdType::CUDD> const* ddManager, ADD cuddAdd);
// Instantiate all copy/move constructors/assignments with the default implementation.
InternalAdd() = default;
InternalAdd(InternalAdd<DdType::CUDD, ValueType> const& other) = default;
InternalAdd& operator=(InternalAdd<DdType::CUDD, ValueType> const& other) = default;
InternalAdd(InternalAdd<DdType::CUDD, ValueType>&& other) = default;
InternalAdd& operator=(InternalAdd<DdType::CUDD, ValueType>&& other) = default;
/*!
* Retrieves whether the two DDs represent the same function.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the same function.
*/
bool operator==(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves whether the two DDs represent different functions.
*
* @param other The DD that is to be compared with the current one.
* @return True if the DDs represent the different functions.
*/
bool operator!=(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Performs an if-then-else with the given operands, i.e. maps all valuations that are mapped to a non-zero
* function value to the function values specified by the first DD and all others to the function values
* specified by the second DD.
*
* @param thenDd The ADD specifying the 'then' part.
* @param elseDd The ADD specifying the 'else' part.
* @return The ADD corresponding to the if-then-else of the operands.
*/
InternalAdd<DdType::CUDD, ValueType> ite(InternalAdd<DdType::CUDD, ValueType> const& thenAdd, InternalAdd<DdType::CUDD, ValueType> const& elseAdd) const;
/*!
* Logically inverts the current ADD. That is, all inputs yielding non-zero values will be mapped to zero in
* the result and vice versa.
*
* @return The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> operator!() const;
/*!
* Performs a logical or of the current anBd the given ADD. As a prerequisite, the operand ADDs need to be
* 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return The logical or of the operands.
*/
InternalAdd<DdType::CUDD, ValueType> operator||(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Performs a logical or of the current and the given ADD and assigns it to the current ADD. As a
* prerequisite, the operand ADDs need to be 0/1 ADDs.
*
* @param other The second ADD used for the operation.
* @return A reference to the current ADD after the operation
*/
InternalAdd<DdType::CUDD, ValueType>& operator|=(InternalAdd<DdType::CUDD, ValueType> const& other);
/*!
* Adds the two ADDs.
*
* @param other The ADD to add to the current one.
* @return The result of the addition.
*/
InternalAdd<DdType::CUDD, ValueType> operator+(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Adds the given ADD to the current one.
*
* @param other The ADD to add to the current one.
* @return A reference to the current ADD after the operation.
*/
InternalAdd<DdType::CUDD, ValueType>& operator+=(InternalAdd<DdType::CUDD, ValueType> const& other);
/*!
* Multiplies the two ADDs.
*
* @param other The ADD to multiply with the current one.
* @return The result of the multiplication.
*/
InternalAdd<DdType::CUDD, ValueType> operator*(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Multiplies the given ADD with the current one and assigns the result to the current ADD.
*
* @param other The ADD to multiply with the current one.
* @return A reference to the current ADD after the operation.
*/
InternalAdd<DdType::CUDD, ValueType>& operator*=(InternalAdd<DdType::CUDD, ValueType> const& other);
/*!
* Subtracts the given ADD from the current one.
*
* @param other The ADD to subtract from the current one.
* @return The result of the subtraction.
*/
InternalAdd<DdType::CUDD, ValueType> operator-(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Subtracts the given ADD from the current one and assigns the result to the current ADD.
*
* @param other The ADD to subtract from the current one.
* @return A reference to the current ADD after the operation.
*/
InternalAdd<DdType::CUDD, ValueType>& operator-=(InternalAdd<DdType::CUDD, ValueType> const& other);
/*!
* Divides the current ADD by the given one.
*
* @param other The ADD by which to divide the current one.
* @return The result of the division.
*/
InternalAdd<DdType::CUDD, ValueType> operator/(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Divides the current ADD by the given one and assigns the result to the current ADD.
*
* @param other The ADD by which to divide the current one.
* @return A reference to the current ADD after the operation.
*/
InternalAdd<DdType::CUDD, ValueType>& operator/=(InternalAdd<DdType::CUDD, ValueType> const& other);
/*!
* Retrieves the function that maps all evaluations to one that have identical function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> equals(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one that have distinct function values.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> notEquals(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> less(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are less or
* equal than the one in the given ADD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> lessOrEqual(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> greater(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first ADD are greater
* or equal than the one in the given ADD.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> greaterOrEqual(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that represents the current ADD to the power of the given ADD.
*
* @other The exponent function (given as an ADD).
* @retur The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> pow(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that represents the current ADD modulo the given ADD.
*
* @other The modul function (given as an ADD).
* @retur The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> mod(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that represents the logarithm of the current ADD to the bases given by the second
* ADD.
*
* @other The base function (given as an ADD).
* @retur The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> logxy(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that floors all values in the current ADD.
*
* @retur The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> floor() const;
/*!
* Retrieves the function that ceils all values in the current ADD.
*
* @retur The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> ceil() const;
/*!
* Retrieves the function that maps all evaluations to the minimum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> minimum(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Retrieves the function that maps all evaluations to the maximum of the function values of the two ADDs.
*
* @param other The ADD with which to perform the operation.
* @return The resulting function represented as an ADD.
*/
InternalAdd<DdType::CUDD, ValueType> maximum(InternalAdd<DdType::CUDD, ValueType> const& other) const;
/*!
* Sum-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
InternalAdd<DdType::CUDD, ValueType> sumAbstract(InternalBdd<DdType::CUDD> const& cube) const;
/*!
* Min-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
InternalAdd<DdType::CUDD, ValueType> minAbstract(InternalBdd<DdType::CUDD> const& cube) const;
/*!
* Max-abstracts from the given meta variables.
*
* @param metaVariables The meta variables from which to abstract.
*/
InternalAdd<DdType::CUDD, ValueType> maxAbstract(InternalBdd<DdType::CUDD> const& cube) const;
/*!
* Checks whether the current and the given ADD represent the same function modulo some given precision.
*
* @param other The ADD with which to compare.
* @param precision An upper bound on the maximal difference between any two function values that is to be
* tolerated.
* @param relative If set to true, not the absolute values have to be within the precision, but the relative
* values.
*/
bool equalModuloPrecision(InternalAdd<DdType::CUDD, ValueType> const& other, double precision, bool relative = true) const;
/*!
* Swaps the given pairs of meta variables in the ADD. The pairs of meta variables must be guaranteed to have
* the same number of underlying ADD variables.
*
* @param metaVariablePairs A vector of meta variable pairs that are to be swapped for one another.
* @return The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> swapVariables(std::vector<InternalAdd<DdType::CUDD, ValueType>> const& from, std::vector<InternalAdd<DdType::CUDD, ValueType>> const& to) const;
/*!
* Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given meta
* variables.
*
* @param otherMatrix The matrix with which to multiply.
* @param summationMetaVariables The names of the meta variables over which to sum during the matrix-
* matrix multiplication.
* @return An ADD representing the result of the matrix-matrix multiplication.
*/
InternalAdd<DdType::CUDD, ValueType> multiplyMatrix(InternalAdd<DdType::CUDD, ValueType> const& otherMatrix, std::vector<InternalAdd<DdType::CUDD, ValueType>> const& summationDdVariables) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* larger than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
InternalBdd<DdType::CUDD> greater(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value larger or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
InternalBdd<DdType::CUDD> greaterOrEqual(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value strictly
* lower than the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
InternalBdd<DdType::CUDD> less(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value less or equal
* to the given value are mapped to one and all others to zero.
*
* @param value The value used for the comparison.
* @return The resulting BDD.
*/
InternalBdd<DdType::CUDD> lessOrEqual(ValueType const& value) const;
/*!
* Computes a BDD that represents the function in which all assignments with a function value unequal to
* zero are mapped to one and all others to zero.
*
* @return The resulting DD.
*/
InternalBdd<DdType::CUDD> notZero() const;
/*!
* Computes the constraint of the current ADD with the given constraint. That is, the function value of the
* resulting ADD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> constrain(InternalAdd<DdType::CUDD, ValueType> const& constraint) const;
/*!
* Computes the restriction of the current ADD with the given constraint. That is, the function value of the
* resulting DD will be the same as the current ones for all assignments mapping to one in the constraint
* and may be different otherwise.
*
* @param constraint The constraint to use for the operation.
* @return The resulting ADD.
*/
InternalAdd<DdType::CUDD, ValueType> restrict(InternalAdd<DdType::CUDD, ValueType> const& constraint) const;
/*!
* Retrieves the support of the current ADD.
*
* @return The support represented as a BDD.
*/
InternalBdd<DdType::CUDD> getSupport() const;
/*!
* Retrieves the number of encodings that are mapped to a non-zero value.
*
* @return The number of encodings that are mapped to a non-zero value.
*/
virtual uint_fast64_t getNonZeroCount(uint_fast64_t numberOfDdVariables) const;
/*!
* Retrieves the number of leaves of the ADD.
*
* @return The number of leaves of the ADD.
*/
virtual uint_fast64_t getLeafCount() const;
/*!
* Retrieves the number of nodes necessary to represent the DD.
*
* @return The number of nodes in this DD.
*/
virtual uint_fast64_t getNodeCount() const;
/*!
* Retrieves the lowest function value of any encoding.
*
* @return The lowest function value of any encoding.
*/
ValueType getMin() const;
/*!
* Retrieves the highest function value of any encoding.
*
* @return The highest function value of any encoding.
*/
ValueType getMax() const;
/*!
* Converts the ADD to a BDD by mapping all values unequal to zero to 1. This effectively does the same as
* a call to notZero().
*
* @return The corresponding BDD.
*/
InternalBdd<DdType::CUDD> toBdd() const;
/*!
* Retrieves whether this ADD represents the constant one function.
*
* @return True if this ADD represents the constant one function.
*/
bool isOne() const;
/*!
* Retrieves whether this ADD represents the constant zero function.
*
* @return True if this ADD represents the constant zero function.
*/
bool isZero() const;
/*!
* Retrieves whether this ADD represents a constant function.
*
* @return True if this ADD represents a constants function.
*/
bool isConstant() const;
/*!
* Retrieves the index of the topmost variable in the DD.
*
* @return The index of the topmost variable in DD.
*/
virtual uint_fast64_t getIndex() const;
/*!
* Exports the DD to the given file in the dot format.
*
* @param filename The name of the file to which the DD is to be exported.
*/
void exportToDot(std::string const& filename, std::vector<std::string> const& ddVariableNamesAsStrings) const;
/*!
* Retrieves an iterator that points to the first meta variable assignment with a non-zero function value.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points to the first meta variable assignment with a non-zero function value.
*/
AddIterator<DdType::CUDD, ValueType> begin(std::set<storm::expressions::Variable> const& metaVariables, bool enumerateDontCareMetaVariables = true) const;
/*!
* Retrieves an iterator that points past the end of the container.
*
* @param enumerateDontCareMetaVariables If set to true, all meta variable assignments are enumerated, even
* if a meta variable does not at all influence the the function value.
* @return An iterator that points past the end of the container.
*/
AddIterator<DdType::CUDD, ValueType> end(bool enumerateDontCareMetaVariables = true) const;
/*!
* Converts the ADD to a vector. The given offset-labeled DD is used to determine the correct row of
* each entry.
*
* @param rowOdd The ODD used for determining the correct row.
* @return The vector that is represented by this ADD.
*/
std::vector<ValueType> toVector(std::vector<uint_fast64_t> const& ddGroupVariableIndices, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& groupOffsets) const;
void addToExplicitVector(storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector) const;
void composeVector(storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
storm::storage::SparseMatrix<ValueType> toMatrix(storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices) const;
storm::storage::SparseMatrix<ValueType> toMatrix(std::vector<uint_fast64_t> const& ddGroupVariableIndices, InternalBdd<DdType::CUDD> const& groupVariableCube, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices, InternalBdd<DdType::CUDD> const& columnVariableCube) const;
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> toMatrixVector(InternalAdd<DdType::CUDD, ValueType> const& vector, std::vector<uint_fast64_t> const& ddGroupVariableIndices, std::vector<uint_fast64_t>&& rowGroupIndices, storm::dd::Odd<DdType::CUDD> const& rowOdd, std::vector<uint_fast64_t> const& ddRowVariableIndices, storm::dd::Odd<DdType::CUDD> const& columnOdd, std::vector<uint_fast64_t> const& ddColumnVariableIndices, InternalBdd<DdType::CUDD> const& columnVariableCube);
static InternalAdd<DdType::CUDD, ValueType> fromVector(InternalDdManager<DdType::CUDD> const* ddManager, std::vector<ValueType> const& values, storm::dd::Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices);
private:
/*!
@ -50,10 +533,105 @@ namespace storm {
*/
DdNode* getCuddDdNode() const;
/*!
* Performs a recursive step to perform the given function between the given DD-based vector and the given
* explicit vector.
*
* @param dd The DD to add to the explicit vector.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentOffset The current offset.
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered.
* @param targetVector The vector to which the translated DD-based vector is to be added.
*/
void composeVectorRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
/*!
* Helper function to convert the DD into an (explicit) vector.
*
* @param dd The DD to convert.
* @param result The vector that will hold the values upon successful completion.
* @param rowGroupOffsets The row offsets at which a given row group starts.
* @param rowOdd The ODD used for the row translation.
* @param currentRowLevel The currently considered row level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentRowOffset The current row offset.
* @param ddRowVariableIndices The (sorted) indices of all DD row variables that need to be considered.
*/
void toVectorRec(DdNode const* dd, std::vector<ValueType>& result, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, uint_fast64_t currentRowLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices) const;
/*!
* Helper function to convert the DD into a (sparse) matrix.
*
* @param dd The DD to convert.
* @param rowIndications A vector indicating at which position in the columnsAndValues vector the entries
* of row i start. Note: this vector is modified in the computation. More concretely, each entry i in the
* vector will be increased by the number of entries in the row. This can be used to count the number
* of entries in each row. If the values are not to be modified, a copy needs to be provided or the entries
* need to be restored afterwards.
* @param columnsAndValues The vector that will hold the columns and values of non-zero entries upon successful
* completion.
* @param rowGroupOffsets The row offsets at which a given row group starts.
* @param rowOdd The ODD used for the row translation.
* @param columnOdd The ODD used for the column translation.
* @param currentRowLevel The currently considered row level in the DD.
* @param currentColumnLevel The currently considered row level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param currentRowOffset The current row offset.
* @param currentColumnOffset The current row offset.
* @param ddRowVariableIndices The (sorted) indices of all DD row variables that need to be considered.
* @param ddColumnVariableIndices The (sorted) indices of all DD row variables that need to be considered.
* @param generateValues If set to true, the vector columnsAndValues is filled with the actual entries, which
* only works if the offsets given in rowIndications are already correct. If they need to be computed first,
* this flag needs to be false.
*/
void toMatrixRec(DdNode const* dd, std::vector<uint_fast64_t>& rowIndications, std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>>& columnsAndValues, std::vector<uint_fast64_t> const& rowGroupOffsets, Odd<DdType::CUDD> const& rowOdd, Odd<DdType::CUDD> const& columnOdd, uint_fast64_t currentRowLevel, uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset, uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t> const& ddRowVariableIndices, std::vector<uint_fast64_t> const& ddColumnVariableIndices, bool generateValues = true) const;
/*!
* Splits the given matrix DD into the groups using the given group variables.
*
* @param dd The DD to split.
* @param groups A vector that is to be filled with the DDs for the individual groups.
* @param ddGroupVariableIndices The (sorted) indices of all DD group variables that need to be considered.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param remainingMetaVariables The meta variables that remain in the DDs after the groups have been split.
*/
void splitGroupsRec(DdNode* dd, std::vector<InternalAdd<DdType::CUDD, ValueType>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel) const;
/*!
* Splits the given matrix and vector DDs into the groups using the given group variables.
*
* @param dd1 The matrix DD to split.
* @param dd2 The vector DD to split.
* @param groups A vector that is to be filled with the pairs of matrix/vector DDs for the individual groups.
* @param ddGroupVariableIndices The (sorted) indices of all DD group variables that need to be considered.
* @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered.
* @param remainingMetaVariables1 The meta variables that remain in the matrix DD after the groups have been split.
* @param remainingMetaVariables2 The meta variables that remain in the vector DD after the groups have been split.
*/
void splitGroupsRec(DdNode* dd1, DdNode* dd2, std::vector<std::pair<InternalAdd<DdType::CUDD, ValueType>, InternalAdd<DdType::CUDD, ValueType>>>& groups, std::vector<uint_fast64_t> const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel) const;
/*!
* Builds an ADD representing the given vector.
*
* @param manager The manager responsible for the ADD.
* @param currentOffset The current offset in the vector.
* @param currentLevel The current level in the DD.
* @param maxLevel The maximal level in the DD.
* @param values The vector that is to be represented by the ADD.
* @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) list of DD variable indices to use.
* @return The resulting (CUDD) ADD node.
*/
static DdNode* fromVectorRec(::DdManager* manager, uint_fast64_t& currentOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<ValueType> const& values, Odd<DdType::CUDD> const& odd, std::vector<uint_fast64_t> const& ddVariableIndices);
InternalDdManager<DdType::CUDD> const* ddManager;
ADD cuddBdd;
}
ADD cuddAdd;
};
}
}

7
src/storage/dd/cudd/InternalCuddBdd.h

@ -27,12 +27,17 @@ namespace storm {
template<DdType LibraryType>
class InternalDdManager;
template<DdType LibraryType, typename ValueType>
class InternalAdd;
template<storm::dd::DdType LibraryType>
class Odd;
template<>
class InternalBdd<storm::dd::DdType::CUDD> {
class InternalBdd<DdType::CUDD> {
public:
friend class InternalAdd<DdType::CUDD, double>;
/*!
* Creates a DD that encapsulates the given CUDD ADD.
*

50
src/utility/graph.h

@ -21,16 +21,24 @@ namespace storm {
namespace models {
namespace symbolic {
template<storm::dd::DdType T> class Model;
template<storm::dd::DdType T> class DeterministicModel;
template<storm::dd::DdType T> class NondeterministicModel;
template<storm::dd::DdType Type, typename ValueType>
class Model;
template<storm::dd::DdType Type, typename ValueType>
class DeterministicModel;
template<storm::dd::DdType Type, typename ValueType>
class NondeterministicModel;
}
}
namespace dd {
template<storm::dd::DdType T> class Bdd;
template<storm::dd::DdType T> class Add;
template<storm::dd::DdType Type>
class Bdd;
template<storm::dd::DdType Type, typename ValueType>
class Add;
}
@ -409,8 +417,8 @@ namespace storm {
* @param psiStates The BDD containing all psi states of the model.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProbGreater0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProbGreater0E(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
/*!
* Computes the set of states for which there does not exist a scheduler that achieves a probability greater
@ -422,8 +430,8 @@ namespace storm {
* @param psiStates The psi states of the model.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProb0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProb0A(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
/*!
* Computes the set of states for which all schedulers achieve a probability greater than zero of satisfying
@ -435,8 +443,8 @@ namespace storm {
* @param psiStates The BDD containing all psi states of the model.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProbGreater0A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProbGreater0A(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
/*!
* Computes the set of states for which there exists a scheduler that achieves probability zero of satisfying
@ -448,8 +456,8 @@ namespace storm {
* @param psiStates The BDD containing all psi states of the model.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProb0E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) ;
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProb0E(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) ;
/*!
* Computes the set of states for which all schedulers achieve probability one of satisfying phi until psi.
@ -462,8 +470,8 @@ namespace storm {
* all schedulers.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProb1A(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0A);
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProb1A(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0A);
/*!
* Computes the set of states for which there exists a scheduler that achieves probability one of satisfying
@ -477,14 +485,14 @@ namespace storm {
* greater than zero.
* @return A BDD representing all such states.
*/
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> performProb1E(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0E) ;
template <storm::dd::DdType Type, typename ValueType = double>
storm::dd::Bdd<Type> performProb1E(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0E);
template <storm::dd::DdType Type>
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Max(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) ;
template <storm::dd::DdType Type, typename ValueType = double>
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Max(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
template <storm::dd::DdType Type>
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(storm::models::symbolic::NondeterministicModel<Type> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) ;
template <storm::dd::DdType Type, typename ValueType = double>
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(storm::models::symbolic::NondeterministicModel<Type, ValueType> const& model, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates);
/*!
* Performs a topological sort of the states of the system according to the given transitions.

15
src/utility/solver.h

@ -30,8 +30,11 @@ namespace storm {
}
namespace dd {
template<storm::dd::DdType T> class Add;
template<storm::dd::DdType T> class Bdd;
template<storm::dd::DdType Type, typename ValueType>
class Add;
template<storm::dd::DdType Type>
class Bdd;
}
namespace expressions {
@ -45,19 +48,19 @@ namespace storm {
template<storm::dd::DdType Type, typename ValueType>
class SymbolicLinearEquationSolverFactory {
public:
virtual std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<Type, ValueType>> create(storm::dd::Add<Type> const& A, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs) const;
virtual std::unique_ptr<storm::solver::SymbolicLinearEquationSolver<Type, ValueType>> create(storm::dd::Add<Type, ValueType> const& A, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs) const;
};
template<storm::dd::DdType Type, typename ValueType>
class SymbolicMinMaxLinearEquationSolverFactory {
public:
virtual std::unique_ptr<storm::solver::SymbolicMinMaxLinearEquationSolver<Type, ValueType>> create(storm::dd::Add<Type> const& A, storm::dd::Bdd<Type> const& allRows, storm::dd::Bdd<Type> const& illegalMask, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& choiceVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs) const;
virtual std::unique_ptr<storm::solver::SymbolicMinMaxLinearEquationSolver<Type, ValueType>> create(storm::dd::Add<Type, ValueType> const& A, storm::dd::Bdd<Type> const& allRows, storm::dd::Bdd<Type> const& illegalMask, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& choiceVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs) const;
};
template<storm::dd::DdType Type>
template<storm::dd::DdType Type, typename ValueType>
class SymbolicGameSolverFactory {
public:
virtual std::unique_ptr<storm::solver::SymbolicGameSolver<Type>> create(storm::dd::Add<Type> const& A, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables) const;
virtual std::unique_ptr<storm::solver::SymbolicGameSolver<Type>> create(storm::dd::Add<Type, ValueType> const& A, storm::dd::Bdd<Type> const& allRows, std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables, std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, std::set<storm::expressions::Variable> const& player1Variables, std::set<storm::expressions::Variable> const& player2Variables) const;
};
template<typename ValueType>

Loading…
Cancel
Save