Browse Source

more work on explicit game solving

main
dehnert 7 years ago
parent
commit
edbe3b1952
  1. 6
      src/storm/abstraction/ExplicitQualitativeGameResultMinMax.h
  2. 25
      src/storm/abstraction/ExplicitQualitativeResult.h
  3. 29
      src/storm/abstraction/ExplicitQualitativeResultMinMax.cpp
  4. 28
      src/storm/abstraction/ExplicitQualitativeResultMinMax.h
  5. 24
      src/storm/abstraction/QualitativeGameResult.h
  6. 25
      src/storm/abstraction/QualitativeMdpResult.h
  7. 40
      src/storm/abstraction/QualitativeMdpResultMinMax.h
  8. 33
      src/storm/abstraction/QualitativeResult.cpp
  9. 23
      src/storm/abstraction/QualitativeResult.h
  10. 4
      src/storm/abstraction/QualitativeResultMinMax.cpp
  11. 1
      src/storm/abstraction/QualitativeResultMinMax.h
  12. 61
      src/storm/abstraction/QuantitativeGameResult.h
  13. 22
      src/storm/abstraction/QuantitativeGameResultMinMax.h
  14. 19
      src/storm/abstraction/SymbolicQualitativeGameResult.cpp
  15. 19
      src/storm/abstraction/SymbolicQualitativeGameResult.h
  16. 29
      src/storm/abstraction/SymbolicQualitativeGameResultMinMax.cpp
  17. 25
      src/storm/abstraction/SymbolicQualitativeGameResultMinMax.h
  18. 20
      src/storm/abstraction/SymbolicQualitativeMdpResult.cpp
  19. 23
      src/storm/abstraction/SymbolicQualitativeMdpResult.h
  20. 29
      src/storm/abstraction/SymbolicQualitativeMdpResultMinMax.cpp
  21. 27
      src/storm/abstraction/SymbolicQualitativeMdpResultMinMax.h
  22. 26
      src/storm/abstraction/SymbolicQualitativeResult.h
  23. 8
      src/storm/abstraction/SymbolicQualitativeResultMinMax.cpp
  24. 14
      src/storm/abstraction/SymbolicQualitativeResultMinMax.h
  25. 61
      src/storm/abstraction/SymbolicQuantitativeGameResult.cpp
  26. 41
      src/storm/abstraction/SymbolicQuantitativeGameResult.h
  27. 12
      src/storm/abstraction/SymbolicQuantitativeGameResultMinMax.cpp
  28. 20
      src/storm/abstraction/SymbolicQuantitativeGameResultMinMax.h
  29. 97
      src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp
  30. 12
      src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.h
  31. 4
      src/storm/settings/modules/AbstractionSettings.cpp
  32. 2
      src/storm/settings/modules/AbstractionSettings.h
  33. 6
      src/storm/storage/dd/Add.cpp
  34. 27
      src/storm/storage/dd/cudd/InternalCuddAdd.cpp
  35. 22
      src/storm/storage/dd/cudd/InternalCuddAdd.h
  36. 29
      src/storm/storage/dd/sylvan/InternalSylvanAdd.cpp
  37. 23
      src/storm/storage/dd/sylvan/InternalSylvanAdd.h
  38. 16
      src/storm/utility/graph.cpp
  39. 12
      src/storm/utility/graph.h
  40. 6
      src/test/storm/utility/GraphTest.cpp

6
src/storm/abstraction/QualitativeGameResultMinMax.h → src/storm/abstraction/ExplicitQualitativeGameResultMinMax.h

@ -8,10 +8,9 @@
namespace storm { namespace storm {
namespace abstraction { namespace abstraction {
template<storm::dd::DdType Type>
class QualitativeGameResultMinMax : public SymbolicQualitativeResultMinMax<Type> {
class ExplicitQualitativeGameResultMinMax : public QualitativeResultMinMax {
public: public:
QualitativeGameResultMinMax() = default;
ExplicitQualitativeGameResultMinMax() = default;
virtual QualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const override { virtual QualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const override {
if (dir == storm::OptimizationDirection::Minimize) { if (dir == storm::OptimizationDirection::Minimize) {
@ -37,3 +36,4 @@ namespace storm {
} }
} }

25
src/storm/abstraction/ExplicitQualitativeResult.h

@ -0,0 +1,25 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/abstraction/QualitativeResult.h"
namespace storm {
namespace storage {
class BitVector;
}
namespace abstraction {
class ExplicitQualitativeResult : public QualitativeResult {
public:
virtual ~ExplicitQualitativeResult() = default;
virtual storm::storage::BitVector const& getStates() const = 0;
};
}
}

29
src/storm/abstraction/ExplicitQualitativeResultMinMax.cpp

@ -0,0 +1,29 @@
#include "storm/abstraction/ExplicitQualitativeResultMinMax.h"
#include "storm/abstraction/ExplicitQualitativeResult.h"
namespace storm {
namespace abstraction {
bool ExplicitQualitativeResultMinMax::isExplicit() const {
return true;
}
ExplicitQualitativeResult const& ExplicitQualitativeResultMinMax::getProb0Min() const {
return getProb0(storm::OptimizationDirection::Minimize);
}
ExplicitQualitativeResult const& ExplicitQualitativeResultMinMax::getProb1Min() const {
return getProb1(storm::OptimizationDirection::Minimize);
}
ExplicitQualitativeResult const& ExplicitQualitativeResultMinMax::getProb0Max() const {
return getProb0(storm::OptimizationDirection::Maximize);
}
ExplicitQualitativeResult const& ExplicitQualitativeResultMinMax::getProb1Max() const {
return getProb1(storm::OptimizationDirection::Maximize);
}
}
}

28
src/storm/abstraction/ExplicitQualitativeResultMinMax.h

@ -0,0 +1,28 @@
#pragma once
#include "storm/solver/OptimizationDirection.h"
#include "storm/abstraction/QualitativeResultMinMax.h"
namespace storm {
namespace abstraction {
class ExplicitQualitativeResult;
class ExplicitQualitativeResultMinMax : public QualitativeResultMinMax {
public:
ExplicitQualitativeResultMinMax() = default;
virtual bool isExplicit() const override;
ExplicitQualitativeResult const& getProb0Min() const;
ExplicitQualitativeResult const& getProb1Min() const;
ExplicitQualitativeResult const& getProb0Max() const;
ExplicitQualitativeResult const& getProb1Max() const;
virtual ExplicitQualitativeResult const& getProb0(storm::OptimizationDirection const& dir) const = 0;
virtual ExplicitQualitativeResult const& getProb1(storm::OptimizationDirection const& dir) const = 0;
};
}
}

24
src/storm/abstraction/QualitativeGameResult.h

@ -1,24 +0,0 @@
#pragma once
#include "storm/utility/graph.h"
#include "storm/abstraction/QualitativeResult.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
struct QualitativeGameResult : public storm::utility::graph::GameProb01Result<Type>, public QualitativeResult<Type> {
QualitativeGameResult() = default;
QualitativeGameResult(storm::utility::graph::GameProb01Result<Type> const& prob01Result) : storm::utility::graph::GameProb01Result<Type>(prob01Result) {
// Intentionally left empty.
}
virtual storm::dd::Bdd<Type> const& getStates() const override {
return this->getPlayer1States();
}
};
}
}

25
src/storm/abstraction/QualitativeMdpResult.h

@ -1,25 +0,0 @@
#pragma once
#include "storm/abstraction/QualitativeResult.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
struct QualitativeMdpResult : public QualitativeResult<Type> {
QualitativeMdpResult() = default;
QualitativeMdpResult(storm::dd::Bdd<Type> const& states) : states(states) {
// Intentionally left empty.
}
virtual storm::dd::Bdd<Type> const& getStates() const override {
return states;
}
storm::dd::Bdd<Type> states;
};
}
}

40
src/storm/abstraction/QualitativeMdpResultMinMax.h

@ -1,40 +0,0 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/abstraction/SymbolicQualitativeResultMinMax.h"
#include "storm/abstraction/QualitativeMdpResult.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type>
class QualitativeMdpResultMinMax : public SymbolicQualitativeResultMinMax<Type> {
public:
QualitativeMdpResultMinMax() = default;
virtual QualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const override {
if (dir == storm::OptimizationDirection::Minimize) {
return prob0Min;
} else {
return prob0Max;
}
}
virtual QualitativeResult<Type> const& getProb1(storm::OptimizationDirection const& dir) const override {
if (dir == storm::OptimizationDirection::Minimize) {
return prob1Min;
} else {
return prob1Max;
}
}
QualitativeMdpResult<Type> prob0Min;
QualitativeMdpResult<Type> prob1Min;
QualitativeMdpResult<Type> prob0Max;
QualitativeMdpResult<Type> prob1Max;
};
}
}

33
src/storm/abstraction/QualitativeResult.cpp

@ -1,3 +1,36 @@
#include "storm/abstraction/QualitativeResult.h" #include "storm/abstraction/QualitativeResult.h"
#include "storm/abstraction/SymbolicQualitativeResult.h"
#include "storm/abstraction/ExplicitQualitativeResult.h"
namespace storm {
namespace abstraction {
bool QualitativeResult::isSymbolic() const {
return false;
}
bool QualitativeResult::isExplicit() const {
return false;
}
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type>& QualitativeResult::asSymbolicQualitativeResult() {
return static_cast<SymbolicQualitativeResult<Type>&>(*this);
}
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& QualitativeResult::asSymbolicQualitativeResult() const {
return static_cast<SymbolicQualitativeResult<Type> const&>(*this);
}
ExplicitQualitativeResult& QualitativeResult::asExplicitQualitativeResult() {
return static_cast<ExplicitQualitativeResult&>(*this);
}
ExplicitQualitativeResult const& QualitativeResult::asExplicitQualitativeResult() const {
return static_cast<ExplicitQualitativeResult const&>(*this);
}
}
}

23
src/storm/abstraction/QualitativeResult.h

@ -3,22 +3,29 @@
#include "storm/storage/dd/DdType.h" #include "storm/storage/dd/DdType.h"
namespace storm { namespace storm {
namespace dd {
template <storm::dd::DdType Type>
class Bdd;
}
namespace abstraction { namespace abstraction {
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
class SymbolicQualitativeResult;
class ExplicitQualitativeResult;
class QualitativeResult { class QualitativeResult {
public: public:
virtual ~QualitativeResult() = default; virtual ~QualitativeResult() = default;
virtual storm::dd::Bdd<Type> const& getStates() const = 0;
virtual bool isSymbolic() const;
virtual bool isExplicit() const;
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type>& asSymbolicQualitativeResult();
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& asSymbolicQualitativeResult() const;
ExplicitQualitativeResult& asExplicitQualitativeResult();
ExplicitQualitativeResult const& asExplicitQualitativeResult() const;
}; };
} }
} }

4
src/storm/abstraction/QualitativeResultMinMax.cpp

@ -9,6 +9,10 @@ namespace storm {
return false; return false;
} }
bool QualitativeResultMinMax::isExplicit() const {
return false;
}
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
SymbolicQualitativeResultMinMax<Type> const& QualitativeResultMinMax::asSymbolicQualitativeResultMinMax() const { SymbolicQualitativeResultMinMax<Type> const& QualitativeResultMinMax::asSymbolicQualitativeResultMinMax() const {
return static_cast<SymbolicQualitativeResultMinMax<Type> const&>(*this); return static_cast<SymbolicQualitativeResultMinMax<Type> const&>(*this);

1
src/storm/abstraction/QualitativeResultMinMax.h

@ -13,6 +13,7 @@ namespace storm {
virtual ~QualitativeResultMinMax() = default; virtual ~QualitativeResultMinMax() = default;
virtual bool isSymbolic() const; virtual bool isSymbolic() const;
virtual bool isExplicit() const;
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
SymbolicQualitativeResultMinMax<Type> const& asSymbolicQualitativeResultMinMax() const; SymbolicQualitativeResultMinMax<Type> const& asSymbolicQualitativeResultMinMax() const;

61
src/storm/abstraction/QuantitativeGameResult.h

@ -1,61 +0,0 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/storage/dd/Add.h"
#include "storm/storage/dd/Bdd.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
struct QuantitativeGameResult {
QuantitativeGameResult() = default;
QuantitativeGameResult(storm::dd::Add<Type, ValueType> const& values) : values(values) {
// Intentionally left empty.
}
QuantitativeGameResult(boost::optional<std::pair<ValueType, ValueType>> const& initialStatesRange, storm::dd::Add<Type, ValueType> const& values, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy) : initialStatesRange(initialStatesRange), values(values), player1Strategy(player1Strategy), player2Strategy(player2Strategy) {
// Intentionally left empty.
}
bool hasPlayer1Strategy() const {
return static_cast<bool>(player1Strategy);
}
storm::dd::Bdd<Type> const& getPlayer1Strategy() const {
return player1Strategy.get();
}
storm::dd::Bdd<Type>& getPlayer1Strategy() {
return player1Strategy.get();
}
bool hasPlayer2Strategy() const {
return static_cast<bool>(player2Strategy);
}
storm::dd::Bdd<Type> const& getPlayer2Strategy() const {
return player2Strategy.get();
}
storm::dd::Bdd<Type>& getPlayer2Strategy() {
return player2Strategy.get();
}
bool hasInitialStatesRange() const {
return static_cast<bool>(initialStatesRange);
}
std::pair<ValueType, ValueType> const& getInitialStatesRange() const {
return initialStatesRange.get();
}
boost::optional<std::pair<ValueType, ValueType>> initialStatesRange;
storm::dd::Add<Type, ValueType> values;
boost::optional<storm::dd::Bdd<Type>> player1Strategy;
boost::optional<storm::dd::Bdd<Type>> player2Strategy;
};
}
}

22
src/storm/abstraction/QuantitativeGameResultMinMax.h

@ -1,22 +0,0 @@
#pragma once
#include "storm/abstraction/QuantitativeGameResult.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
class QuantitativeGameResultMinMax {
public:
QuantitativeGameResultMinMax() = default;
QuantitativeGameResultMinMax(QuantitativeGameResult<Type, ValueType> const& min, QuantitativeGameResult<Type, ValueType> const& max) : min(min), max(max) {
// Intentionally left empty.
}
QuantitativeGameResult<Type, ValueType> min;
QuantitativeGameResult<Type, ValueType> max;
};
}
}

19
src/storm/abstraction/SymbolicQualitativeGameResult.cpp

@ -0,0 +1,19 @@
#include "storm/abstraction/SymbolicQualitativeGameResult.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
SymbolicQualitativeGameResult<Type>::SymbolicQualitativeGameResult(storm::utility::graph::SymbolicGameProb01Result<Type> const& prob01Result) : storm::utility::graph::SymbolicGameProb01Result<Type>(prob01Result) {
// Intentionally left empty.
}
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> const& SymbolicQualitativeGameResult<Type>::getStates() const {
return this->getPlayer1States();
}
template class SymbolicQualitativeGameResult<storm::dd::DdType::CUDD>;
template class SymbolicQualitativeGameResult<storm::dd::DdType::Sylvan>;
}
}

19
src/storm/abstraction/SymbolicQualitativeGameResult.h

@ -0,0 +1,19 @@
#pragma once
#include "storm/utility/graph.h"
#include "storm/abstraction/SymbolicQualitativeResult.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
class SymbolicQualitativeGameResult : public storm::utility::graph::SymbolicGameProb01Result<Type>, public SymbolicQualitativeResult<Type> {
SymbolicQualitativeGameResult() = default;
SymbolicQualitativeGameResult(storm::utility::graph::SymbolicGameProb01Result<Type> const& prob01Result);
virtual storm::dd::Bdd<Type> const& getStates() const override;
};
}
}

29
src/storm/abstraction/SymbolicQualitativeGameResultMinMax.cpp

@ -0,0 +1,29 @@
#include "storm/abstraction/SymbolicQualitativeGameResultMinMax.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& SymbolicQualitativeGameResultMinMax<Type>::getProb0(storm::OptimizationDirection const& dir) const {
if (dir == storm::OptimizationDirection::Minimize) {
return prob0Min;
} else {
return prob0Max;
}
}
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& SymbolicQualitativeGameResultMinMax<Type>::getProb1(storm::OptimizationDirection const& dir) const {
if (dir == storm::OptimizationDirection::Minimize) {
return prob1Min;
} else {
return prob1Max;
}
}
template class SymbolicQualitativeResultMinMax<storm::dd::DdType::CUDD>;
template class SymbolicQualitativeResultMinMax<storm::dd::DdType::Sylvan>;
}
}

25
src/storm/abstraction/SymbolicQualitativeGameResultMinMax.h

@ -0,0 +1,25 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/abstraction/SymbolicQualitativeResultMinMax.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type>
class SymbolicQualitativeGameResultMinMax : public SymbolicQualitativeResultMinMax<Type> {
public:
SymbolicQualitativeGameResultMinMax() = default;
virtual SymbolicQualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const override;
virtual SymbolicQualitativeResult<Type> const& getProb1(storm::OptimizationDirection const& dir) const override;
SymbolicQualitativeResult<Type> prob0Min;
SymbolicQualitativeResult<Type> prob1Min;
SymbolicQualitativeResult<Type> prob0Max;
SymbolicQualitativeResult<Type> prob1Max;
};
}
}

20
src/storm/abstraction/SymbolicQualitativeMdpResult.cpp

@ -0,0 +1,20 @@
#include "storm/abstraction/SymbolicQualitativeMdpResult.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
SymbolicQualitativeMdpResult<Type>::SymbolicQualitativeMdpResult(storm::dd::Bdd<Type> const& states) : states(states) {
// Intentionally left empty.
}
template <storm::dd::DdType Type>
storm::dd::Bdd<Type> const& SymbolicQualitativeMdpResult<Type>::getStates() const {
return states;
}
template class SymbolicQualitativeMdpResult<storm::dd::DdType::CUDD>;
template class SymbolicQualitativeMdpResult<storm::dd::DdType::Sylvan>;
}
}

23
src/storm/abstraction/SymbolicQualitativeMdpResult.h

@ -0,0 +1,23 @@
#pragma once
#include "storm/abstraction/SymbolicQualitativeResult.h"
#include "storm/storage/dd/Bdd.h"
namespace storm {
namespace abstraction {
template <storm::dd::DdType Type>
class SymbolicQualitativeMdpResult : public SymbolicQualitativeResult<Type> {
SymbolicQualitativeMdpResult() = default;
SymbolicQualitativeMdpResult(storm::dd::Bdd<Type> const& states);
virtual storm::dd::Bdd<Type> const& getStates() const override;
storm::dd::Bdd<Type> states;
};
}
}

29
src/storm/abstraction/SymbolicQualitativeMdpResultMinMax.cpp

@ -0,0 +1,29 @@
#include "storm/abstraction/SymbolicQualitativeMdpResultMinMax.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& SymbolicQualitativeMdpResultMinMax<Type>::getProb0(storm::OptimizationDirection const& dir) const {
if (dir == storm::OptimizationDirection::Minimize) {
return prob0Min;
} else {
return prob0Max;
}
}
template<storm::dd::DdType Type>
SymbolicQualitativeResult<Type> const& SymbolicQualitativeMdpResultMinMax<Type>::getProb1(storm::OptimizationDirection const& dir) const {
if (dir == storm::OptimizationDirection::Minimize) {
return prob1Min;
} else {
return prob1Max;
}
}
template class SymbolicQualitativeMdpResultMinMax<storm::dd::DdType::CUDD>;
template class SymbolicQualitativeMdpResultMinMax<storm::dd::DdType::Sylvan>;
}
}

27
src/storm/abstraction/SymbolicQualitativeMdpResultMinMax.h

@ -0,0 +1,27 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/abstraction/SymbolicQualitativeResultMinMax.h"
#include "storm/abstraction/SymbolicQualitativeMdpResult.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type>
class SymbolicQualitativeMdpResultMinMax : public SymbolicQualitativeResultMinMax<Type> {
public:
SymbolicQualitativeMdpResultMinMax() = default;
virtual SymbolicQualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const override;
virtual SymbolicQualitativeResult<Type> const& getProb1(storm::OptimizationDirection const& dir) const override;
SymbolicQualitativeMdpResult<Type> prob0Min;
SymbolicQualitativeMdpResult<Type> prob1Min;
SymbolicQualitativeMdpResult<Type> prob0Max;
SymbolicQualitativeMdpResult<Type> prob1Max;
};
}
}

26
src/storm/abstraction/SymbolicQualitativeResult.h

@ -0,0 +1,26 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/abstraction/QualitativeResult.h"
namespace storm {
namespace dd {
template <storm::dd::DdType Type>
class Bdd;
}
namespace abstraction {
template <storm::dd::DdType Type>
class SymbolicQualitativeResult : public QualitativeResult {
public:
virtual ~SymbolicQualitativeResult() = default;
virtual storm::dd::Bdd<Type> const& getStates() const = 0;
};
}
}

8
src/storm/abstraction/SymbolicQualitativeResultMinMax.cpp

@ -11,22 +11,22 @@ namespace storm {
} }
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
QualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb0Min() const {
SymbolicQualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb0Min() const {
return getProb0(storm::OptimizationDirection::Minimize); return getProb0(storm::OptimizationDirection::Minimize);
} }
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
QualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb1Min() const {
SymbolicQualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb1Min() const {
return getProb1(storm::OptimizationDirection::Minimize); return getProb1(storm::OptimizationDirection::Minimize);
} }
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
QualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb0Max() const {
SymbolicQualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb0Max() const {
return getProb0(storm::OptimizationDirection::Maximize); return getProb0(storm::OptimizationDirection::Maximize);
} }
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
QualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb1Max() const {
SymbolicQualitativeResult<Type> const& SymbolicQualitativeResultMinMax<Type>::getProb1Max() const {
return getProb1(storm::OptimizationDirection::Maximize); return getProb1(storm::OptimizationDirection::Maximize);
} }

14
src/storm/abstraction/SymbolicQualitativeResultMinMax.h

@ -14,7 +14,7 @@ namespace storm {
namespace abstraction { namespace abstraction {
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
class QualitativeResult;
class SymbolicQualitativeResult;
template<storm::dd::DdType Type> template<storm::dd::DdType Type>
class SymbolicQualitativeResultMinMax : public QualitativeResultMinMax { class SymbolicQualitativeResultMinMax : public QualitativeResultMinMax {
@ -23,13 +23,13 @@ namespace storm {
virtual bool isSymbolic() const override; virtual bool isSymbolic() const override;
QualitativeResult<Type> const& getProb0Min() const;
QualitativeResult<Type> const& getProb1Min() const;
QualitativeResult<Type> const& getProb0Max() const;
QualitativeResult<Type> const& getProb1Max() const;
SymbolicQualitativeResult<Type> const& getProb0Min() const;
SymbolicQualitativeResult<Type> const& getProb1Min() const;
SymbolicQualitativeResult<Type> const& getProb0Max() const;
SymbolicQualitativeResult<Type> const& getProb1Max() const;
virtual QualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const = 0;
virtual QualitativeResult<Type> const& getProb1(storm::OptimizationDirection const& dir) const = 0;
virtual SymbolicQualitativeResult<Type> const& getProb0(storm::OptimizationDirection const& dir) const = 0;
virtual SymbolicQualitativeResult<Type> const& getProb1(storm::OptimizationDirection const& dir) const = 0;
}; };
} }
} }

61
src/storm/abstraction/SymbolicQuantitativeGameResult.cpp

@ -0,0 +1,61 @@
#include "storm/abstraction/SymbolicQuantitativeGameResult.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeGameResult<Type, ValueType>::SymbolicQuantitativeGameResult(storm::dd::Add<Type, ValueType> const& values) : values(values) {
// Intentionally left empty.
}
template<storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeGameResult<Type, ValueType>::SymbolicQuantitativeGameResult(boost::optional<std::pair<ValueType, ValueType>> const& initialStatesRange, storm::dd::Add<Type, ValueType> const& values, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy) : initialStatesRange(initialStatesRange), values(values), player1Strategy(player1Strategy), player2Strategy(player2Strategy) {
// Intentionally left empty.
}
template<storm::dd::DdType Type, typename ValueType>
bool SymbolicQuantitativeGameResult<Type, ValueType>::hasPlayer1Strategy() const {
return static_cast<bool>(player1Strategy);
}
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Bdd<Type> const& SymbolicQuantitativeGameResult<Type, ValueType>::getPlayer1Strategy() const {
return player1Strategy.get();
}
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Bdd<Type>& SymbolicQuantitativeGameResult<Type, ValueType>::getPlayer1Strategy() {
return player1Strategy.get();
}
template<storm::dd::DdType Type, typename ValueType>
bool SymbolicQuantitativeGameResult<Type, ValueType>::hasPlayer2Strategy() const {
return static_cast<bool>(player2Strategy);
}
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Bdd<Type> const& SymbolicQuantitativeGameResult<Type, ValueType>::getPlayer2Strategy() const {
return player2Strategy.get();
}
template<storm::dd::DdType Type, typename ValueType>
storm::dd::Bdd<Type>& SymbolicQuantitativeGameResult<Type, ValueType>::getPlayer2Strategy() {
return player2Strategy.get();
}
template<storm::dd::DdType Type, typename ValueType>
bool SymbolicQuantitativeGameResult<Type, ValueType>::hasInitialStatesRange() const {
return static_cast<bool>(initialStatesRange);
}
template<storm::dd::DdType Type, typename ValueType>
std::pair<ValueType, ValueType> const& SymbolicQuantitativeGameResult<Type, ValueType>::getInitialStatesRange() const {
return initialStatesRange.get();
}
template class SymbolicQuantitativeGameResult<storm::dd::DdType::CUDD, double>;
template class SymbolicQuantitativeGameResult<storm::dd::DdType::Sylvan, double>;
}
}

41
src/storm/abstraction/SymbolicQuantitativeGameResult.h

@ -0,0 +1,41 @@
#pragma once
#include "storm/storage/dd/DdType.h"
#include "storm/storage/dd/Add.h"
#include "storm/storage/dd/Bdd.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
class SymbolicQuantitativeGameResult {
public:
SymbolicQuantitativeGameResult() = default;
SymbolicQuantitativeGameResult(storm::dd::Add<Type, ValueType> const& values);
SymbolicQuantitativeGameResult(boost::optional<std::pair<ValueType, ValueType>> const& initialStatesRange, storm::dd::Add<Type, ValueType> const& values, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy);
bool hasPlayer1Strategy() const;
storm::dd::Bdd<Type> const& getPlayer1Strategy() const;
storm::dd::Bdd<Type>& getPlayer1Strategy();
bool hasPlayer2Strategy() const;
storm::dd::Bdd<Type> const& getPlayer2Strategy() const;
storm::dd::Bdd<Type>& getPlayer2Strategy();
bool hasInitialStatesRange() const;
std::pair<ValueType, ValueType> const& getInitialStatesRange() const;
boost::optional<std::pair<ValueType, ValueType>> initialStatesRange;
storm::dd::Add<Type, ValueType> values;
boost::optional<storm::dd::Bdd<Type>> player1Strategy;
boost::optional<storm::dd::Bdd<Type>> player2Strategy;
};
}
}

12
src/storm/abstraction/SymbolicQuantitativeGameResultMinMax.cpp

@ -0,0 +1,12 @@
#include "storm/abstraction/SymbolicQuantitativeGameResultMinMax.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
SymbolicQuantitativeGameResultMinMax<Type, ValueType>::SymbolicQuantitativeGameResultMinMax(SymbolicQuantitativeGameResult<Type, ValueType> const& min, SymbolicQuantitativeGameResult<Type, ValueType> const& max) : min(min), max(max) {
// Intentionally left empty.
}
}
}

20
src/storm/abstraction/SymbolicQuantitativeGameResultMinMax.h

@ -0,0 +1,20 @@
#pragma once
#include "storm/abstraction/SymbolicQuantitativeGameResult.h"
namespace storm {
namespace abstraction {
template<storm::dd::DdType Type, typename ValueType>
class SymbolicQuantitativeGameResultMinMax {
public:
SymbolicQuantitativeGameResultMinMax() = default;
SymbolicQuantitativeGameResultMinMax(SymbolicQuantitativeGameResult<Type, ValueType> const& min, SymbolicQuantitativeGameResult<Type, ValueType> const& max);
SymbolicQuantitativeGameResult<Type, ValueType> min;
SymbolicQuantitativeGameResult<Type, ValueType> max;
};
}
}

97
src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp

@ -367,8 +367,7 @@ namespace storm {
auto abstractionEnd = std::chrono::high_resolution_clock::now(); auto abstractionEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Abstraction in iteration " << iterations << " has " << game.getNumberOfStates() << " (player 1) states, " << game.getNumberOfTransitions() << " transitions, " << game.getBottomStates().getNonZeroCount() << " bottom states (computed in " << std::chrono::duration_cast<std::chrono::milliseconds>(abstractionEnd - abstractionStart).count() << "ms)."); STORM_LOG_DEBUG("Abstraction in iteration " << iterations << " has " << game.getNumberOfStates() << " (player 1) states, " << game.getNumberOfTransitions() << " transitions, " << game.getBottomStates().getNonZeroCount() << " bottom states (computed in " << std::chrono::duration_cast<std::chrono::milliseconds>(abstractionEnd - abstractionStart).count() << "ms).");
// (2) Prepare transition matrix BDD and target state BDD for later use.
storm::dd::Bdd<Type> transitionMatrixBdd = game.getTransitionMatrix().toBdd();
// (2) Prepare initial, constraint and target state BDDs for later use.
storm::dd::Bdd<Type> initialStates = game.getInitialStates(); storm::dd::Bdd<Type> initialStates = game.getInitialStates();
STORM_LOG_THROW(initialStates.getNonZeroCount() == 1 || checkTask.isBoundSet(), storm::exceptions::InvalidPropertyException, "Game-based abstraction refinement requires a bound on the formula for model with " << initialStates.getNonZeroCount() << " initial states."); STORM_LOG_THROW(initialStates.getNonZeroCount() == 1 || checkTask.isBoundSet(), storm::exceptions::InvalidPropertyException, "Game-based abstraction refinement requires a bound on the formula for model with " << initialStates.getNonZeroCount() << " initial states.");
storm::dd::Bdd<Type> constraintStates = globalConstraintStates && game.getReachableStates(); storm::dd::Bdd<Type> constraintStates = globalConstraintStates && game.getReachableStates();
@ -383,23 +382,50 @@ namespace storm {
// game.getReachableStates().template toAdd<ValueType>().exportToDot("reach.dot"); // game.getReachableStates().template toAdd<ValueType>().exportToDot("reach.dot");
// #endif // #endif
// (3) compute all states with probability 0/1 wrt. to the two different player 2 goals (min/max).
std::unique_ptr<CheckResult> result;
if (solveMode == storm::settings::modules::AbstractionSettings::SolveMode::Dd) {
result = performSymbolicAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner, previousQualitativeResult, previousMinQuantitativeResult);
} else {
result = performExplicitAbstractionSolutionStep(env, checkTask, game, player1Direction, initialStates, constraintStates, targetStates, refiner);
}
if (result) {
printStatistics(*abstractor, game);
return result;
}
auto iterationEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Iteration " << iterations << " took " << std::chrono::duration_cast<std::chrono::milliseconds>(iterationEnd - iterationStart).count() << "ms.");
}
STORM_LOG_ASSERT(false, "This point must not be reached.");
return nullptr;
}
template<storm::dd::DdType Type, typename ModelType>
std::unique_ptr<CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performSymbolicAbstractionSolutionStep(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type> const& initialStates, storm::dd::Bdd<Type> const& constraintStates, storm::dd::Bdd<Type> const& targetStates, storm::abstraction::MenuGameRefiner<Type, ValueType> const& refiner, boost::optional<QualitativeGameResultMinMax<Type>>& previousQualitativeResult, boost::optional<QuantitativeGameResult<Type, ValueType>>& previousMinQuantitativeResult) {
STORM_LOG_TRACE("Using dd-based solving.");
// Prepare transition matrix BDD.
storm::dd::Bdd<Type> transitionMatrixBdd = game.getTransitionMatrix().toBdd();
// (1) compute all states with probability 0/1 wrt. to the two different player 2 goals (min/max).
auto qualitativeStart = std::chrono::high_resolution_clock::now(); auto qualitativeStart = std::chrono::high_resolution_clock::now();
QualitativeGameResultMinMax<Type> qualitativeResult = computeProb01States(previousQualitativeResult, game, player1Direction, transitionMatrixBdd, constraintStates, targetStates); QualitativeGameResultMinMax<Type> qualitativeResult = computeProb01States(previousQualitativeResult, game, player1Direction, transitionMatrixBdd, constraintStates, targetStates);
std::unique_ptr<CheckResult> result = checkForResultAfterQualitativeCheck<Type, ValueType>(checkTask, initialStates, qualitativeResult); std::unique_ptr<CheckResult> result = checkForResultAfterQualitativeCheck<Type, ValueType>(checkTask, initialStates, qualitativeResult);
if (result) { if (result) {
printStatistics(*abstractor, game);
return result; return result;
} }
previousQualitativeResult = qualitativeResult; previousQualitativeResult = qualitativeResult;
auto qualitativeEnd = std::chrono::high_resolution_clock::now(); auto qualitativeEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Qualitative computation completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(qualitativeEnd - qualitativeStart).count() << "ms."); STORM_LOG_DEBUG("Qualitative computation completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(qualitativeEnd - qualitativeStart).count() << "ms.");
// (4) compute the states for which we have to determine quantitative information.
// (2) compute the states for which we have to determine quantitative information.
storm::dd::Bdd<Type> maybeMin = !(qualitativeResult.prob0Min.getPlayer1States() || qualitativeResult.prob1Min.getPlayer1States()) && game.getReachableStates(); storm::dd::Bdd<Type> maybeMin = !(qualitativeResult.prob0Min.getPlayer1States() || qualitativeResult.prob1Min.getPlayer1States()) && game.getReachableStates();
storm::dd::Bdd<Type> maybeMax = !(qualitativeResult.prob0Max.getPlayer1States() || qualitativeResult.prob1Max.getPlayer1States()) && game.getReachableStates(); storm::dd::Bdd<Type> maybeMax = !(qualitativeResult.prob0Max.getPlayer1States() || qualitativeResult.prob1Max.getPlayer1States()) && game.getReachableStates();
// (5) if the initial states are not maybe states, then we can refine at this point.
// (3) if the initial states are not maybe states, then we can refine at this point.
storm::dd::Bdd<Type> initialMaybeStates = (initialStates && maybeMin) || (initialStates && maybeMax); storm::dd::Bdd<Type> initialMaybeStates = (initialStates && maybeMin) || (initialStates && maybeMax);
bool qualitativeRefinement = false; bool qualitativeRefinement = false;
if (initialMaybeStates.isZero()) { if (initialMaybeStates.isZero()) {
@ -420,13 +446,11 @@ namespace storm {
return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(storm::storage::sparse::state_type(0), ValueType(0.5)); return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(storm::storage::sparse::state_type(0), ValueType(0.5));
} }
// (6) if we arrived at this point and no refinement was made, we need to compute the quantitative solution.
// (4) if we arrived at this point and no refinement was made, we need to compute the quantitative solution.
if (!qualitativeRefinement) { if (!qualitativeRefinement) {
// At this point, we know that we cannot answer the query without further numeric computation. // At this point, we know that we cannot answer the query without further numeric computation.
STORM_LOG_TRACE("Starting numerical solution step."); STORM_LOG_TRACE("Starting numerical solution step.");
// Solve abstraction using the selected mode.
if (solveMode == storm::settings::modules::AbstractionSettings::SolveMode::Dd) {
STORM_LOG_TRACE("Using dd-based solving."); STORM_LOG_TRACE("Using dd-based solving.");
storm::dd::Add<Type, ValueType> initialStatesAdd = initialStates.template toAdd<ValueType>(); storm::dd::Add<Type, ValueType> initialStatesAdd = initialStates.template toAdd<ValueType>();
@ -439,7 +463,6 @@ namespace storm {
previousMinQuantitativeResult = quantitativeResult.min; previousMinQuantitativeResult = quantitativeResult.min;
result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize, quantitativeResult.min.getInitialStatesRange()); result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Minimize, quantitativeResult.min.getInitialStatesRange());
if (result) { if (result) {
printStatistics(*abstractor, game);
return result; return result;
} }
@ -447,7 +470,6 @@ namespace storm {
quantitativeResult.max = computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Maximize, game, qualitativeResult, initialStatesAdd, maybeMax, boost::make_optional(quantitativeResult.min)); quantitativeResult.max = computeQuantitativeResult(env, player1Direction, storm::OptimizationDirection::Maximize, game, qualitativeResult, initialStatesAdd, maybeMax, boost::make_optional(quantitativeResult.min));
result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize, quantitativeResult.max.getInitialStatesRange()); result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, storm::OptimizationDirection::Maximize, quantitativeResult.max.getInitialStatesRange());
if (result) { if (result) {
printStatistics(*abstractor, game);
return result; return result;
} }
@ -457,7 +479,6 @@ namespace storm {
// (9) Check whether the lower and upper bounds are close enough to terminate with an answer. // (9) Check whether the lower and upper bounds are close enough to terminate with an answer.
result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.min.getInitialStatesRange().first, quantitativeResult.max.getInitialStatesRange().second, comparator); result = checkForResultAfterQuantitativeCheck<ValueType>(quantitativeResult.min.getInitialStatesRange().first, quantitativeResult.max.getInitialStatesRange().second, comparator);
if (result) { if (result) {
printStatistics(*abstractor, game);
return result; return result;
} }
@ -468,38 +489,52 @@ namespace storm {
STORM_LOG_ASSERT(quantitativeResult.max.getPlayer2Strategy().isZero() || quantitativeResult.max.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.getPlayer2Variables()).getMax() <= 1, "Player 2 strategy for max is illegal."); STORM_LOG_ASSERT(quantitativeResult.max.getPlayer2Strategy().isZero() || quantitativeResult.max.getPlayer2Strategy().template toAdd<ValueType>().sumAbstract(game.getPlayer2Variables()).getMax() <= 1, "Player 2 strategy for max is illegal.");
auto quantitativeRefinementStart = std::chrono::high_resolution_clock::now(); auto quantitativeRefinementStart = std::chrono::high_resolution_clock::now();
// (10) If we arrived at this point, it means that we have all qualitative and quantitative // (10) If we arrived at this point, it means that we have all qualitative and quantitative
// information about the game, but we could not yet answer the query. In this case, we need to refine. // information about the game, but we could not yet answer the query. In this case, we need to refine.
refiner.refine(game, transitionMatrixBdd, quantitativeResult); refiner.refine(game, transitionMatrixBdd, quantitativeResult);
auto quantitativeRefinementEnd = std::chrono::high_resolution_clock::now(); auto quantitativeRefinementEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Quantitative refinement completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(quantitativeRefinementEnd - quantitativeRefinementStart).count() << "ms."); STORM_LOG_DEBUG("Quantitative refinement completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(quantitativeRefinementEnd - quantitativeRefinementStart).count() << "ms.");
} else {
}
// Return null to indicate no result has been found yet.
return nullptr;
}
template<storm::dd::DdType Type, typename ModelType>
std::unique_ptr<CheckResult> GameBasedMdpModelChecker<Type, ModelType>::performExplicitAbstractionSolutionStep(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type> const& initialStatesBdd, storm::dd::Bdd<Type> const& constraintStatesBdd, storm::dd::Bdd<Type> const& targetStatesBdd, storm::abstraction::MenuGameRefiner<Type, ValueType> const& refiner) {
STORM_LOG_TRACE("Using hybrid solving."); STORM_LOG_TRACE("Using hybrid solving.");
auto relevantStates = maybeMin || maybeMax || targetStates;
auto relevantStatesAdd = relevantStates.template toAdd<ValueType>();
storm::dd::Odd odd = relevantStates.createOdd();
// (0) Start by transforming the necessary symbolic elements to explicit ones.
storm::dd::Odd odd = game.getReachableStates().createOdd();
auto relevantStatesTransitionMatrix = game.getTransitionMatrix() * relevantStatesAdd * relevantStatesAdd.swapVariables(game.getRowColumnMetaVariablePairs());
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<uint64_t>> transitionMatrixLabeling = relevantStatesTransitionMatrix.toLabeledMatrix(game.getRowVariables(), game.getColumnVariables(), game.getNondeterminismVariables(), game.getPlayer1Variables(), odd, odd, true);
auto const& transitionMatrix = transitionMatrixLabeling.first;
auto const& labeling = transitionMatrixLabeling.second;
std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<uint64_t>> transitionMatrixAndLabeling = game.getTransitionMatrix().toLabeledMatrix(game.getRowVariables(), game.getColumnVariables(), game.getNondeterminismVariables(), game.getPlayer1Variables(), odd, odd, true);
auto const& transitionMatrix = transitionMatrixAndLabeling.first;
auto const& labeling = transitionMatrixAndLabeling.second;
std::cout << transitionMatrix << std::endl;
for (auto const& e : labeling) {
std::cout << e << std::endl;
}
storm::storage::BitVector initialStates = initialStatesBdd.toVector(odd);
storm::storage::BitVector constraintStates = constraintStatesBdd.toVector(odd);
storm::storage::BitVector targetStates = targetStatesBdd.toVector(odd);
exit(-1);
// (1) compute all states with probability 0/1 wrt. to the two different player 2 goals (min/max).
auto qualitativeStart = std::chrono::high_resolution_clock::now();
ExplicitQualitativeGameResultMinMax qualitativeResult = computeProb01States(game, player1Direction, transitionMatrix, constraintStates, targetStates);
std::unique_ptr<CheckResult> result = checkForResultAfterQualitativeCheck<Type, ValueType>(checkTask, initialStates, qualitativeResult);
if (result) {
return result;
} }
auto qualitativeEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Qualitative computation completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(qualitativeEnd - qualitativeStart).count() << "ms.");
}
auto iterationEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Iteration " << iterations << " took " << std::chrono::duration_cast<std::chrono::milliseconds>(iterationEnd - iterationStart).count() << "ms.");
}
STORM_LOG_ASSERT(false, "This point must not be reached.");
return nullptr;
std::cout << transitionMatrix << std::endl;
std::cout << labeling.size() << std::endl;
std::cout << initialStates << std::endl;
std::cout << constraintStates << std::endl;
std::cout << targetStates << std::endl;
exit(-1);
} }
template<storm::dd::DdType Type, typename ModelType> template<storm::dd::DdType Type, typename ModelType>

12
src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.h

@ -27,6 +27,15 @@ namespace storm {
template<storm::dd::DdType Type, typename ValueType> template<storm::dd::DdType Type, typename ValueType>
class MenuGameAbstractor; class MenuGameAbstractor;
template<storm::dd::DdType Type, typename ValueType>
class MenuGameRefiner;
template<storm::dd::DdType Type>
class QualitativeGameResultMinMax;
template<storm::dd::DdType Type, typename ValueType>
struct QuantitativeGameResult;
} }
namespace modelchecker { namespace modelchecker {
@ -59,6 +68,9 @@ namespace storm {
*/ */
std::unique_ptr<CheckResult> performGameBasedAbstractionRefinement(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression); std::unique_ptr<CheckResult> performGameBasedAbstractionRefinement(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::expressions::Expression const& constraintExpression, storm::expressions::Expression const& targetStateExpression);
std::unique_ptr<CheckResult> performSymbolicAbstractionSolutionStep(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type> const& initialStates, storm::dd::Bdd<Type> const& constraintStates, storm::dd::Bdd<Type> const& targetStates, storm::abstraction::MenuGameRefiner<Type, ValueType> const& refiner, boost::optional<QualitativeGameResultMinMax<Type>>& previousQualitativeResult, boost::optional<abstraction::QuantitativeGameResult<Type, ValueType>>& previousMinQuantitativeResult);
std::unique_ptr<CheckResult> performExplicitAbstractionSolutionStep(Environment const& env, CheckTask<storm::logic::Formula> const& checkTask, storm::abstraction::MenuGame<Type, ValueType> const& game, storm::OptimizationDirection player1Direction, storm::dd::Bdd<Type> const& initialStates, storm::dd::Bdd<Type> const& constraintStates, storm::dd::Bdd<Type> const& targetStates, storm::abstraction::MenuGameRefiner<Type, ValueType> const& refiner);
/*! /*!
* Retrieves the initial predicates for the abstraction. * Retrieves the initial predicates for the abstraction.
*/ */

4
src/storm/settings/modules/AbstractionSettings.cpp

@ -44,7 +44,7 @@ namespace storm {
.setDefaultValueString("all").build()) .setDefaultValueString("all").build())
.build()); .build());
std::vector<std::string> solveModes = {"dd", "hybrid"};
std::vector<std::string> solveModes = {"dd", "sparse"};
this->addOption(storm::settings::OptionBuilder(moduleName, solveModeOptionName, true, "Sets how the abstractions are solved.") this->addOption(storm::settings::OptionBuilder(moduleName, solveModeOptionName, true, "Sets how the abstractions are solved.")
.addArgument(storm::settings::ArgumentBuilder::createStringArgument("mode", "The mode to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(solveModes)) .addArgument(storm::settings::ArgumentBuilder::createStringArgument("mode", "The mode to use.").addValidatorString(ArgumentValidatorFactory::createMultipleChoiceValidator(solveModes))
.setDefaultValueString("dd").build()) .setDefaultValueString("dd").build())
@ -110,7 +110,7 @@ namespace storm {
if (solveModeAsString == "dd") { if (solveModeAsString == "dd") {
return SolveMode::Dd; return SolveMode::Dd;
} }
return SolveMode::Hybrid;
return SolveMode::Sparse;
} }
bool AbstractionSettings::isAddAllGuardsSet() const { bool AbstractionSettings::isAddAllGuardsSet() const {

2
src/storm/settings/modules/AbstractionSettings.h

@ -28,7 +28,7 @@ namespace storm {
}; };
enum class SolveMode { enum class SolveMode {
Dd, Hybrid
Dd, Sparse
}; };
/*! /*!

6
src/storm/storage/dd/Add.cpp

@ -810,13 +810,11 @@ namespace storm {
} }
statesWithGroupEnabled[i] = groupNotZero.existsAbstract(columnMetaVariables).template toAdd<uint_fast64_t>(); statesWithGroupEnabled[i] = groupNotZero.existsAbstract(columnMetaVariables).template toAdd<uint_fast64_t>();
statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
if (buildLabeling) { if (buildLabeling) {
uint64_t currentLabel = groupLabels[i]; uint64_t currentLabel = groupLabels[i];
std::cout << "current label is " << currentLabel << std::endl;
// statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, labeling, [currentLabel] (uint_fast64_t a, uint_fast64_t l) { return currentLabel; });
statesWithGroupEnabled[i].forEach(rowOdd, ddRowVariableIndices, [currentLabel, &rowGroupIndices, &labeling] (uint64_t const& offset, uint_fast64_t const& value) { labeling[rowGroupIndices[offset]] = currentLabel; });
} }
statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
} }
// Since we modified the rowGroupIndices, we need to restore the correct values. // Since we modified the rowGroupIndices, we need to restore the correct values.

27
src/storm/storage/dd/cudd/InternalCuddAdd.cpp

@ -494,16 +494,24 @@ namespace storm {
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const { void InternalAdd<DdType::CUDD, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
composeWithExplicitVectorRec(this->getCuddDdNode(), nullptr, 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, targetVector, function);
forEachRec(this->getCuddDdNode(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, [&function, &targetVector] (uint64_t const& offset, ValueType const& value) { targetVector[offset] = function(targetVector[offset], value); });
}
template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::forEach(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const {
forEachRec(this->getCuddDdNode(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, function);
} }
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const { void InternalAdd<DdType::CUDD, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
composeWithExplicitVectorRec(this->getCuddDdNode(), &offsets, 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, targetVector, function);
forEachRec(this->getCuddDdNode(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, [&function, &targetVector, &offsets] (uint64_t const& offset, ValueType const& value) {
ValueType& targetValue = targetVector[offsets[offset]];
targetValue = function(targetValue, value);
});
} }
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::CUDD, ValueType>::composeWithExplicitVectorRec(DdNode const* dd, std::vector<uint_fast64_t> const* offsets, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
void InternalAdd<DdType::CUDD, ValueType>::forEachRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const {
// For the empty DD, we do not need to add any entries. // For the empty DD, we do not need to add any entries.
if (dd == Cudd_ReadZero(ddManager->getCuddManager().getManager())) { if (dd == Cudd_ReadZero(ddManager->getCuddManager().getManager())) {
return; return;
@ -511,24 +519,22 @@ namespace storm {
// If we are at the maximal level, the value to be set is stored as a constant in the DD. // If we are at the maximal level, the value to be set is stored as a constant in the DD.
if (currentLevel == maxLevel) { if (currentLevel == maxLevel) {
ValueType& targetValue = targetVector[offsets != nullptr ? (*offsets)[currentOffset] : currentOffset];
targetValue = function(targetValue, storm::utility::convertNumber<ValueType>(Cudd_V(dd)));
function(currentOffset, storm::utility::convertNumber<ValueType>(Cudd_V(dd)));
} else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) { } else if (ddVariableIndices[currentLevel] < Cudd_NodeReadIndex(dd)) {
// If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set // 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. // and for the one in which it is not set.
composeWithExplicitVectorRec(dd, offsets, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeWithExplicitVectorRec(dd, offsets, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
forEachRec(dd, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, function);
forEachRec(dd, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, function);
} else { } else {
// Otherwise, we simply recursively call the function for both (different) cases. // Otherwise, we simply recursively call the function for both (different) cases.
composeWithExplicitVectorRec(Cudd_E_const(dd), offsets, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeWithExplicitVectorRec(Cudd_T_const(dd), offsets, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
forEachRec(Cudd_E_const(dd), currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, function);
forEachRec(Cudd_T_const(dd), currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, function);
} }
} }
template<typename ValueType> template<typename ValueType>
std::vector<uint64_t> InternalAdd<DdType::CUDD, ValueType>::decodeGroupLabels(std::vector<uint_fast64_t> const& ddGroupVariableIndices, storm::storage::BitVector const& ddLabelVariableIndices) const { std::vector<uint64_t> InternalAdd<DdType::CUDD, ValueType>::decodeGroupLabels(std::vector<uint_fast64_t> const& ddGroupVariableIndices, storm::storage::BitVector const& ddLabelVariableIndices) const {
std::vector<uint64_t> result; std::vector<uint64_t> result;
std::cout << ddLabelVariableIndices << std::endl;
decodeGroupLabelsRec(this->getCuddDdNode(), result, ddGroupVariableIndices, ddLabelVariableIndices, 0, ddGroupVariableIndices.size(), 0); decodeGroupLabelsRec(this->getCuddDdNode(), result, ddGroupVariableIndices, ddLabelVariableIndices, 0, ddGroupVariableIndices.size(), 0);
return result; return result;
} }
@ -546,7 +552,6 @@ namespace storm {
uint64_t elseLabel = label; uint64_t elseLabel = label;
uint64_t thenLabel = label; uint64_t thenLabel = label;
std::cout << "currentLevel " << currentLevel << " is in labels? " << ddLabelVariableIndices.get(currentLevel) << std::endl;
if (ddLabelVariableIndices.get(currentLevel)) { if (ddLabelVariableIndices.get(currentLevel)) {
elseLabel <<= 1; elseLabel <<= 1;
thenLabel = (thenLabel << 1) | 1; thenLabel = (thenLabel << 1) | 1;

22
src/storm/storage/dd/cudd/InternalCuddAdd.h

@ -549,6 +549,18 @@ namespace storm {
*/ */
void composeWithExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const; void composeWithExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
/*!
* Composes the ADD with an explicit vector by performing a specified function between the entries of this
* ADD and the explicit vector.
*
* @param odd The ODD to use for the translation from symbolic to explicit positions.
* @param ddVariableIndices The indices of the DD variables present in this ADD.
* @param targetVector The explicit vector that is to be composed with the ADD. The results are written to
* this vector again.
* @param function The function to perform in the composition.
*/
void forEach(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const;
/*! /*!
* Composes the (row-grouped) ADD with an explicit vector by performing a specified function between the * Composes the (row-grouped) ADD with an explicit vector by performing a specified function between the
* entries of this ADD and the explicit vector. * entries of this ADD and the explicit vector.
@ -646,18 +658,18 @@ namespace storm {
private: private:
/*! /*!
* Performs a recursive step to perform the given function between the given DD-based vector and the given
* explicit vector.
* Performs a recursive step for forEach.
* *
* @param dd The DD to add to the explicit vector.
* @param dd The DD to traverse.
* @param currentLevel The currently considered level in the DD. * @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered. * @param maxLevel The number of levels that need to be considered.
* @param currentOffset The current offset. * @param currentOffset The current offset.
* @param odd The ODD used for the translation. * @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered. * @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.
* @param function The callback invoked for every element. The first argument is the offset and the second
* is the value.
*/ */
void composeWithExplicitVectorRec(DdNode const* dd, std::vector<uint_fast64_t> const* offsets, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
void forEachRec(DdNode const* dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const;
/*! /*!
* Splits the given matrix DD into the groups using the given group variables. * Splits the given matrix DD into the groups using the given group variables.

29
src/storm/storage/dd/sylvan/InternalSylvanAdd.cpp

@ -884,16 +884,24 @@ namespace storm {
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::Sylvan, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const { void InternalAdd<DdType::Sylvan, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
composeWithExplicitVectorRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()), nullptr, 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, targetVector, function);
forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, [&function, &targetVector] (uint64_t const& offset, ValueType const& value) { targetVector[offset] = function(targetVector[offset], value); });
} }
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::Sylvan, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const { void InternalAdd<DdType::Sylvan, ValueType>::composeWithExplicitVector(storm::dd::Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
composeWithExplicitVectorRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()), &offsets, 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, targetVector, function);
forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, [&function, &targetVector, &offsets] (uint64_t const& offset, ValueType const& value) {
ValueType& targetValue = targetVector[offsets[offset]];
targetValue = function(targetValue, value);
});
} }
template<typename ValueType> template<typename ValueType>
void InternalAdd<DdType::Sylvan, ValueType>::composeWithExplicitVectorRec(MTBDD dd, bool negated, std::vector<uint_fast64_t> const* offsets, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const {
void InternalAdd<DdType::Sylvan, ValueType>::forEach(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const {
forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, function);
}
template<typename ValueType>
void InternalAdd<DdType::Sylvan, ValueType>::forEachRec(MTBDD dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const {
// For the empty DD, we do not need to add any entries. // For the empty DD, we do not need to add any entries.
if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) { if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) {
return; return;
@ -901,24 +909,19 @@ namespace storm {
// If we are at the maximal level, the value to be set is stored as a constant in the DD. // If we are at the maximal level, the value to be set is stored as a constant in the DD.
if (currentLevel == maxLevel) { if (currentLevel == maxLevel) {
ValueType& targetValue = targetVector[offsets != nullptr ? (*offsets)[currentOffset] : currentOffset];
targetValue = function(targetValue, getValue(dd));
function(currentOffset, getValue(dd));
} else if (mtbdd_isleaf(dd) || ddVariableIndices[currentLevel] < mtbdd_getvar(dd)) { } else if (mtbdd_isleaf(dd) || ddVariableIndices[currentLevel] < mtbdd_getvar(dd)) {
// If we skipped a level, we need to enumerate the explicit entries for the case in which the bit is set // 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. // and for the one in which it is not set.
composeWithExplicitVectorRec(dd, negated, offsets, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeWithExplicitVectorRec(dd, negated, offsets, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
forEachRec(dd, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, function);
forEachRec(dd, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, function);
} else { } else {
// Otherwise, we simply recursively call the function for both (different) cases. // Otherwise, we simply recursively call the function for both (different) cases.
MTBDD thenNode = mtbdd_gethigh(dd); MTBDD thenNode = mtbdd_gethigh(dd);
MTBDD elseNode = mtbdd_getlow(dd); MTBDD elseNode = mtbdd_getlow(dd);
// Determine whether we have to evaluate the successors as if they were complemented.
bool elseComplemented = mtbdd_hascomp(elseNode) ^ negated;
bool thenComplemented = mtbdd_hascomp(thenNode) ^ negated;
composeWithExplicitVectorRec(mtbdd_regular(elseNode), elseComplemented, offsets, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, targetVector, function);
composeWithExplicitVectorRec(mtbdd_regular(thenNode), thenComplemented, offsets, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, targetVector, function);
forEachRec(elseNode, currentLevel + 1, maxLevel, currentOffset, odd.getElseSuccessor(), ddVariableIndices, function);
forEachRec(thenNode, currentLevel + 1, maxLevel, currentOffset + odd.getElseOffset(), odd.getThenSuccessor(), ddVariableIndices, function);
} }
} }

23
src/storm/storage/dd/sylvan/InternalSylvanAdd.h

@ -553,6 +553,18 @@ namespace storm {
*/ */
void composeWithExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const; void composeWithExplicitVector(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<uint_fast64_t> const& offsets, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
/*!
* Composes the ADD with an explicit vector by performing a specified function between the entries of this
* ADD and the explicit vector.
*
* @param odd The ODD to use for the translation from symbolic to explicit positions.
* @param ddVariableIndices The indices of the DD variables present in this ADD.
* @param targetVector The explicit vector that is to be composed with the ADD. The results are written to
* this vector again.
* @param function The function to perform in the composition.
*/
void forEach(Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const;
/*! /*!
* Splits the ADD into several ADDs that differ in the encoding of the given group variables (given via indices). * Splits the ADD into several ADDs that differ in the encoding of the given group variables (given via indices).
* *
@ -647,19 +659,18 @@ namespace storm {
static std::shared_ptr<Odd> createOddRec(BDD dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_map<BDD, std::shared_ptr<Odd>>>& uniqueTableForLevels); static std::shared_ptr<Odd> createOddRec(BDD dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<std::unordered_map<BDD, std::shared_ptr<Odd>>>& uniqueTableForLevels);
/*! /*!
* Performs a recursive step to perform the given function between the given DD-based vector and the given
* explicit vector.
* Performs a recursive step for forEach.
* *
* @param dd The DD to add to the explicit vector.
* @param negated A flag indicating whether the DD node is to be interpreted as being negated.
* @param dd The DD to traverse.
* @param currentLevel The currently considered level in the DD. * @param currentLevel The currently considered level in the DD.
* @param maxLevel The number of levels that need to be considered. * @param maxLevel The number of levels that need to be considered.
* @param currentOffset The current offset. * @param currentOffset The current offset.
* @param odd The ODD used for the translation. * @param odd The ODD used for the translation.
* @param ddVariableIndices The (sorted) indices of all DD variables that need to be considered. * @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.
* @param function The callback invoked for every element. The first argument is the offset and the second
* is the value.
*/ */
void composeWithExplicitVectorRec(MTBDD dd, bool negated, std::vector<uint_fast64_t> const* offsets, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::vector<ValueType>& targetVector, std::function<ValueType (ValueType const&, ValueType const&)> const& function) const;
void forEachRec(MTBDD dd, uint_fast64_t currentLevel, uint_fast64_t maxLevel, uint_fast64_t currentOffset, Odd const& odd, std::vector<uint_fast64_t> const& ddVariableIndices, std::function<void (uint64_t const&, ValueType const&)> const& function) const;
/*! /*!
* Splits the given matrix DD into the labelings of the gropus using the given group variables. * Splits the given matrix DD into the labelings of the gropus using the given group variables.

16
src/storm/utility/graph.cpp

@ -1084,7 +1084,7 @@ namespace storm {
} }
template <storm::dd::DdType Type, typename ValueType> template <storm::dd::DdType Type, typename ValueType>
GameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy) {
SymbolicGameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy) {
// The solution sets. // The solution sets.
storm::dd::Bdd<Type> player1States = psiStates; storm::dd::Bdd<Type> player1States = psiStates;
@ -1147,11 +1147,11 @@ namespace storm {
player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables()); player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables());
} }
return GameProb01Result<Type>(player1States, player2States, player1StrategyBdd, player2StrategyBdd);
return SymbolicGameProb01Result<Type>(player1States, player2States, player1StrategyBdd, player2StrategyBdd);
} }
template <storm::dd::DdType Type, typename ValueType> template <storm::dd::DdType Type, typename ValueType>
GameProb01Result<Type> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<Type>> const& player1Candidates) {
SymbolicGameProb01Result<Type> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<Type>> const& player1Candidates) {
// Create the potential prob1 states of player 1. // Create the potential prob1 states of player 1.
storm::dd::Bdd<Type> maybePlayer1States = model.getReachableStates(); storm::dd::Bdd<Type> maybePlayer1States = model.getReachableStates();
@ -1284,7 +1284,7 @@ namespace storm {
} }
} }
return GameProb01Result<Type>(maybePlayer1States, maybePlayer2States, player1StrategyBdd, player2StrategyBdd);
return SymbolicGameProb01Result<Type>(maybePlayer1States, maybePlayer2States, player1StrategyBdd, player2StrategyBdd);
} }
template <typename T> template <typename T>
@ -1568,9 +1568,9 @@ namespace storm {
template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(storm::models::symbolic::NondeterministicModel<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates); template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(storm::models::symbolic::NondeterministicModel<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates);
template GameProb01Result<storm::dd::DdType::CUDD> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
template SymbolicGameProb01Result<storm::dd::DdType::CUDD> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
template GameProb01Result<storm::dd::DdType::CUDD> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::CUDD>> const& player1Candidates);
template SymbolicGameProb01Result<storm::dd::DdType::CUDD> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::CUDD, double> const& model, storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::CUDD> const& phiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::CUDD>> const& player1Candidates);
// Instantiations for Sylvan (double). // Instantiations for Sylvan (double).
@ -1608,9 +1608,9 @@ namespace storm {
template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(storm::models::symbolic::NondeterministicModel<storm::dd::DdType::Sylvan, double> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates); template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(storm::models::symbolic::NondeterministicModel<storm::dd::DdType::Sylvan, double> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates);
template GameProb01Result<storm::dd::DdType::Sylvan> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::Sylvan> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
template SymbolicGameProb01Result<storm::dd::DdType::Sylvan> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::Sylvan> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
template GameProb01Result<storm::dd::DdType::Sylvan> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::Sylvan> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
template SymbolicGameProb01Result<storm::dd::DdType::Sylvan> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<storm::dd::DdType::Sylvan> const& model, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& phiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
// Instantiations for Sylvan (rational number). // Instantiations for Sylvan (rational number).

12
src/storm/utility/graph.h

@ -10,7 +10,9 @@
#include "storm/storage/Scheduler.h" #include "storm/storage/Scheduler.h"
#include "storm/models/sparse/NondeterministicModel.h" #include "storm/models/sparse/NondeterministicModel.h"
#include "storm/models/sparse/DeterministicModel.h" #include "storm/models/sparse/DeterministicModel.h"
#include "storm/storage/dd/DdType.h" #include "storm/storage/dd/DdType.h"
#include "storm/storage/dd/Bdd.h"
#include "storm/solver/OptimizationDirection.h" #include "storm/solver/OptimizationDirection.h"
@ -542,9 +544,9 @@ namespace storm {
std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(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); std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> performProb01Min(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);
template <storm::dd::DdType Type> template <storm::dd::DdType Type>
struct GameProb01Result {
GameProb01Result() = default;
GameProb01Result(storm::dd::Bdd<Type> const& player1States, storm::dd::Bdd<Type> const& player2States, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy = boost::none, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy = boost::none) : player1States(player1States), player2States(player2States), player1Strategy(player1Strategy), player2Strategy(player2Strategy) {
struct SymbolicGameProb01Result {
SymbolicGameProb01Result() = default;
SymbolicGameProb01Result(storm::dd::Bdd<Type> const& player1States, storm::dd::Bdd<Type> const& player2States, boost::optional<storm::dd::Bdd<Type>> const& player1Strategy = boost::none, boost::optional<storm::dd::Bdd<Type>> const& player2Strategy = boost::none) : player1States(player1States), player2States(player2States), player1Strategy(player1Strategy), player2Strategy(player2Strategy) {
// Intentionally left empty. // Intentionally left empty.
} }
@ -597,7 +599,7 @@ namespace storm {
* @param producePlayer2Strategy A flag indicating whether the strategy of player 2 shall be produced. * @param producePlayer2Strategy A flag indicating whether the strategy of player 2 shall be produced.
*/ */
template <storm::dd::DdType Type, typename ValueType> template <storm::dd::DdType Type, typename ValueType>
GameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy = false, bool producePlayer2Strategy = false);
SymbolicGameProb01Result<Type> performProb0(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy = false, bool producePlayer2Strategy = false);
/*! /*!
* Computes the set of states that have probability 1 given the strategies of the two players. * Computes the set of states that have probability 1 given the strategies of the two players.
@ -611,7 +613,7 @@ namespace storm {
* @param player1Candidates If given, this set constrains the candidates of player 1 states that are considered. * @param player1Candidates If given, this set constrains the candidates of player 1 states that are considered.
*/ */
template <storm::dd::DdType Type, typename ValueType> template <storm::dd::DdType Type, typename ValueType>
GameProb01Result<Type> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy = false, bool producePlayer2Strategy = false, boost::optional<storm::dd::Bdd<Type>> const& player1Candidates = boost::none);
SymbolicGameProb01Result<Type> performProb1(storm::models::symbolic::StochasticTwoPlayerGame<Type, ValueType> const& model, storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy = false, bool producePlayer2Strategy = false, boost::optional<storm::dd::Bdd<Type>> const& player1Candidates = boost::none);
/*! /*!
* Performs a topological sort of the states of the system according to the given transitions. * Performs a topological sort of the states of the system according to the given transitions.

6
src/test/storm/utility/GraphTest.cpp

@ -227,7 +227,7 @@ TEST(GraphTest, SymbolicProb01StochasticGameDieSmall) {
// The target states are those states where !(s < 3). // The target states are those states where !(s < 3).
storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = !abstractor.getStates(initialPredicates[0]) && game.getReachableStates(); storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = !abstractor.getStates(initialPredicates[0]) && game.getReachableStates();
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
storm::utility::graph::SymbolicGameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
EXPECT_EQ(0ull, result.getPlayer1States().getNonZeroCount()); EXPECT_EQ(0ull, result.getPlayer1States().getNonZeroCount());
EXPECT_TRUE(result.hasPlayer1Strategy()); EXPECT_TRUE(result.hasPlayer1Strategy());
EXPECT_TRUE(result.hasPlayer2Strategy()); EXPECT_TRUE(result.hasPlayer2Strategy());
@ -366,7 +366,7 @@ TEST(GraphTest, SymbolicProb01StochasticGameTwoDice) {
// The target states are those states where s1 == 7 & s2 == 7 & d1 + d2 == 2. // The target states are those states where s1 == 7 & s2 == 7 & d1 + d2 == 2.
storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = abstractor.getStates(initialPredicates[7]) && abstractor.getStates(initialPredicates[22]) && abstractor.getStates(initialPredicates[9]) && abstractor.getStates(initialPredicates[24]) && game.getReachableStates(); storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = abstractor.getStates(initialPredicates[7]) && abstractor.getStates(initialPredicates[22]) && abstractor.getStates(initialPredicates[9]) && abstractor.getStates(initialPredicates[24]) && game.getReachableStates();
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
storm::utility::graph::SymbolicGameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
EXPECT_EQ(153ull, result.getPlayer1States().getNonZeroCount()); EXPECT_EQ(153ull, result.getPlayer1States().getNonZeroCount());
ASSERT_TRUE(result.hasPlayer1Strategy()); ASSERT_TRUE(result.hasPlayer1Strategy());
ASSERT_TRUE(result.hasPlayer2Strategy()); ASSERT_TRUE(result.hasPlayer2Strategy());
@ -538,7 +538,7 @@ TEST(GraphTest, SymbolicProb01StochasticGameWlan) {
// The target states are those states where col == 2. // The target states are those states where col == 2.
storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = abstractor.getStates(initialPredicates[2]) && game.getReachableStates(); storm::dd::Bdd<storm::dd::DdType::CUDD> targetStates = abstractor.getStates(initialPredicates[2]) && game.getReachableStates();
storm::utility::graph::GameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
storm::utility::graph::SymbolicGameProb01Result<storm::dd::DdType::CUDD> result = storm::utility::graph::performProb0(game, game.getQualitativeTransitionMatrix(), game.getReachableStates(), targetStates, storm::OptimizationDirection::Minimize, storm::OptimizationDirection::Minimize, true, true);
EXPECT_EQ(2831ull, result.getPlayer1States().getNonZeroCount()); EXPECT_EQ(2831ull, result.getPlayer1States().getNonZeroCount());
EXPECT_TRUE(result.hasPlayer1Strategy()); EXPECT_TRUE(result.hasPlayer1Strategy());
EXPECT_TRUE(result.hasPlayer2Strategy()); EXPECT_TRUE(result.hasPlayer2Strategy());

Loading…
Cancel
Save