Browse Source

minimal probabilities now working (for some test cases)

Former-commit-id: 9f38386531
tempestpy_adaptions
dehnert 9 years ago
parent
commit
599a3e99c7
  1. 4
      src/logic/AtomicExpressionFormula.cpp
  2. 2
      src/logic/AtomicExpressionFormula.h
  3. 4
      src/logic/AtomicLabelFormula.cpp
  4. 4
      src/logic/AtomicLabelFormula.h
  5. 6
      src/logic/BinaryBooleanStateFormula.cpp
  6. 2
      src/logic/BinaryBooleanStateFormula.h
  7. 4
      src/logic/BooleanLiteralFormula.cpp
  8. 2
      src/logic/BooleanLiteralFormula.h
  9. 4
      src/logic/BoundedUntilFormula.cpp
  10. 2
      src/logic/BoundedUntilFormula.h
  11. 6
      src/logic/ConditionalFormula.cpp
  12. 2
      src/logic/ConditionalFormula.h
  13. 4
      src/logic/CumulativeRewardFormula.cpp
  14. 2
      src/logic/CumulativeRewardFormula.h
  15. 6
      src/logic/EventuallyFormula.cpp
  16. 2
      src/logic/EventuallyFormula.h
  17. 6
      src/logic/Formula.cpp
  18. 4
      src/logic/Formula.h
  19. 4
      src/logic/GloballyFormula.cpp
  20. 2
      src/logic/GloballyFormula.h
  21. 6
      src/logic/InstantaneousRewardFormula.cpp
  22. 4
      src/logic/InstantaneousRewardFormula.h
  23. 3
      src/logic/LabelSubstitutionVisitor.cpp
  24. 6
      src/logic/LongRunAverageOperatorFormula.cpp
  25. 2
      src/logic/LongRunAverageOperatorFormula.h
  26. 4
      src/logic/LongRunAverageRewardFormula.cpp
  27. 2
      src/logic/LongRunAverageRewardFormula.h
  28. 6
      src/logic/NextFormula.cpp
  29. 4
      src/logic/NextFormula.h
  30. 6
      src/logic/ProbabilityOperatorFormula.cpp
  31. 4
      src/logic/ProbabilityOperatorFormula.h
  32. 4
      src/logic/RewardOperatorFormula.cpp
  33. 4
      src/logic/RewardOperatorFormula.h
  34. 6
      src/logic/TimeOperatorFormula.cpp
  35. 4
      src/logic/TimeOperatorFormula.h
  36. 6
      src/logic/UnaryBooleanStateFormula.cpp
  37. 2
      src/logic/UnaryBooleanStateFormula.h
  38. 4
      src/logic/UntilFormula.cpp
  39. 4
      src/logic/UntilFormula.h
  40. 21
      src/logic/VariableSubstitutionVisitor.cpp
  41. 29
      src/logic/VariableSubstitutionVisitor.h
  42. 186
      src/modelchecker/reachability/SparseMdpLearningModelChecker.cpp
  43. 30
      src/modelchecker/reachability/SparseMdpLearningModelChecker.h

4
src/logic/AtomicExpressionFormula.cpp

@ -24,10 +24,6 @@ namespace storm {
atomicExpressionFormulas.push_back(std::dynamic_pointer_cast<AtomicExpressionFormula const>(this->shared_from_this()));
}
std::shared_ptr<Formula> AtomicExpressionFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<AtomicExpressionFormula>(this->expression.substitute(substitution));
}
std::ostream& AtomicExpressionFormula::writeToStream(std::ostream& out) const {
out << expression;
return out;

2
src/logic/AtomicExpressionFormula.h

@ -23,8 +23,6 @@ namespace storm {
virtual void gatherAtomicExpressionFormulas(std::vector<std::shared_ptr<AtomicExpressionFormula const>>& atomicExpressionFormulas) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
// The atomic expression represented by this node in the formula tree.
storm::expressions::Expression expression;

4
src/logic/AtomicLabelFormula.cpp

@ -25,10 +25,6 @@ namespace storm {
atomicExpressionFormulas.push_back(std::dynamic_pointer_cast<AtomicLabelFormula const>(this->shared_from_this()));
}
std::shared_ptr<Formula> AtomicLabelFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<AtomicLabelFormula>(*this);
}
std::ostream& AtomicLabelFormula::writeToStream(std::ostream& out) const {
out << "\"" << label << "\"";
return out;

4
src/logic/AtomicLabelFormula.h

@ -22,9 +22,7 @@ namespace storm {
std::string const& getLabel() const;
virtual void gatherAtomicLabelFormulas(std::vector<std::shared_ptr<AtomicLabelFormula const>>& atomicLabelFormulas) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
private:

6
src/logic/BinaryBooleanStateFormula.cpp

@ -30,11 +30,7 @@ namespace storm {
bool BinaryBooleanStateFormula::isOr() const {
return this->getOperator() == OperatorType::Or;
}
std::shared_ptr<Formula> BinaryBooleanStateFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<BinaryBooleanStateFormula>(this->operatorType, this->getLeftSubformula().substitute(substitution), this->getRightSubformula().substitute(substitution));
}
std::ostream& BinaryBooleanStateFormula::writeToStream(std::ostream& out) const {
out << "(";
this->getLeftSubformula().writeToStream(out);

2
src/logic/BinaryBooleanStateFormula.h

@ -28,8 +28,6 @@ namespace storm {
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
OperatorType operatorType;
};

4
src/logic/BooleanLiteralFormula.cpp

@ -24,10 +24,6 @@ namespace storm {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> BooleanLiteralFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<BooleanLiteralFormula>(*this);
}
std::ostream& BooleanLiteralFormula::writeToStream(std::ostream& out) const {
if (value) {
out << "true";

2
src/logic/BooleanLiteralFormula.h

@ -19,8 +19,6 @@ namespace storm {
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
private:

4
src/logic/BoundedUntilFormula.cpp

@ -44,10 +44,6 @@ namespace storm {
return boost::get<uint_fast64_t>(bounds);
}
std::shared_ptr<Formula> BoundedUntilFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<BoundedUntilFormula>(this->getLeftSubformula().substitute(substitution), this->getRightSubformula().substitute(substitution), bounds);
}
std::ostream& BoundedUntilFormula::writeToStream(std::ostream& out) const {
this->getLeftSubformula().writeToStream(out);

2
src/logic/BoundedUntilFormula.h

@ -26,8 +26,6 @@ namespace storm {
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
boost::variant<uint_fast64_t, std::pair<double, double>> bounds;
};

6
src/logic/ConditionalFormula.cpp

@ -33,11 +33,7 @@ namespace storm {
boost::any ConditionalFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> ConditionalFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<ConditionalFormula>(this->getSubformula().substitute(substitution), this->getConditionFormula().substitute(substitution), context);
}
void ConditionalFormula::gatherAtomicExpressionFormulas(std::vector<std::shared_ptr<AtomicExpressionFormula const>>& atomicExpressionFormulas) const {
this->getSubformula().gatherAtomicExpressionFormulas(atomicExpressionFormulas);
this->getConditionFormula().gatherAtomicExpressionFormulas(atomicExpressionFormulas);

2
src/logic/ConditionalFormula.h

@ -25,8 +25,6 @@ namespace storm {
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual void gatherAtomicExpressionFormulas(std::vector<std::shared_ptr<AtomicExpressionFormula const>>& atomicExpressionFormulas) const override;
virtual void gatherAtomicLabelFormulas(std::vector<std::shared_ptr<AtomicLabelFormula const>>& atomicLabelFormulas) const override;
virtual void gatherReferencedRewardModels(std::set<std::string>& referencedRewardModels) const override;

4
src/logic/CumulativeRewardFormula.cpp

@ -44,10 +44,6 @@ namespace storm {
}
}
std::shared_ptr<Formula> CumulativeRewardFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<CumulativeRewardFormula>(*this);
}
std::ostream& CumulativeRewardFormula::writeToStream(std::ostream& out) const {
if (this->hasDiscreteTimeBound()) {
out << "C<=" << this->getDiscreteTimeBound();

2
src/logic/CumulativeRewardFormula.h

@ -32,8 +32,6 @@ namespace storm {
double getContinuousTimeBound() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
boost::variant<uint_fast64_t, double> timeBound;
};

6
src/logic/EventuallyFormula.cpp

@ -45,11 +45,7 @@ namespace storm {
boost::any EventuallyFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> EventuallyFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<EventuallyFormula>(this->getSubformula().substitute(substitution), context);
}
std::ostream& EventuallyFormula::writeToStream(std::ostream& out) const {
out << "F ";
this->getSubformula().writeToStream(out);

2
src/logic/EventuallyFormula.h

@ -28,8 +28,6 @@ namespace storm {
virtual std::ostream& writeToStream(std::ostream& out) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
FormulaContext context;
};

6
src/logic/Formula.cpp

@ -3,6 +3,7 @@
#include "src/logic/FragmentChecker.h"
#include "src/logic/FormulaInformationVisitor.h"
#include "src/logic/VariableSubstitutionVisitor.h"
#include "src/logic/LabelSubstitutionVisitor.h"
#include "src/logic/ToExpressionVisitor.h"
@ -408,6 +409,11 @@ namespace storm {
return referencedRewardModels;
}
std::shared_ptr<Formula> Formula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
VariableSubstitutionVisitor visitor(substitution);
return visitor.substitute(*this);
}
std::shared_ptr<Formula> Formula::substitute(std::map<std::string, storm::expressions::Expression> const& labelSubstitution) const {
LabelSubstitutionVisitor visitor(labelSubstitution);
return visitor.substitute(*this);

4
src/logic/Formula.h

@ -186,8 +186,8 @@ namespace storm {
std::shared_ptr<Formula const> asSharedPointer();
std::shared_ptr<Formula const> asSharedPointer() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const = 0;
virtual std::shared_ptr<Formula> substitute(std::map<std::string, storm::expressions::Expression> const& labelSubstitution) const;
std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
std::shared_ptr<Formula> substitute(std::map<std::string, storm::expressions::Expression> const& labelSubstitution) const;
/*!
* Takes the formula and converts it to an equivalent expression assuming that only atomic expression formulas

4
src/logic/GloballyFormula.cpp

@ -19,10 +19,6 @@ namespace storm {
boost::any GloballyFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> GloballyFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<GloballyFormula>(this->getSubformula().substitute(substitution));
}
std::ostream& GloballyFormula::writeToStream(std::ostream& out) const {
out << "G ";

2
src/logic/GloballyFormula.h

@ -17,8 +17,6 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
};

6
src/logic/InstantaneousRewardFormula.cpp

@ -43,11 +43,7 @@ namespace storm {
return boost::get<double>(timeBound);
}
}
std::shared_ptr<Formula> InstantaneousRewardFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<InstantaneousRewardFormula>(*this);
}
std::ostream& InstantaneousRewardFormula::writeToStream(std::ostream& out) const {
if (this->hasDiscreteTimeBound()) {
out << "I=" << this->getDiscreteTimeBound();

4
src/logic/InstantaneousRewardFormula.h

@ -32,9 +32,7 @@ namespace storm {
bool hasContinuousTimeBound() const;
double getContinuousTimeBound() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
boost::variant<uint_fast64_t, double> timeBound;
};

3
src/logic/LabelSubstitutionVisitor.cpp

@ -21,7 +21,6 @@ namespace storm {
} else {
return std::static_pointer_cast<Formula>(std::make_shared<AtomicLabelFormula>(f));
}
}
}
}
}

6
src/logic/LongRunAverageOperatorFormula.cpp

@ -18,11 +18,7 @@ namespace storm {
boost::any LongRunAverageOperatorFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> LongRunAverageOperatorFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<LongRunAverageOperatorFormula>(this->getSubformula().substitute(substitution), this->operatorInformation);
}
std::ostream& LongRunAverageOperatorFormula::writeToStream(std::ostream& out) const {
out << "LRA";
OperatorFormula::writeToStream(out);

2
src/logic/LongRunAverageOperatorFormula.h

@ -17,8 +17,6 @@ namespace storm {
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
};
}

4
src/logic/LongRunAverageRewardFormula.cpp

@ -20,10 +20,6 @@ namespace storm {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> LongRunAverageRewardFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::shared_ptr<Formula>(new LongRunAverageRewardFormula());
}
std::ostream& LongRunAverageRewardFormula::writeToStream(std::ostream& out) const {
return out << "LRA";
}

2
src/logic/LongRunAverageRewardFormula.h

@ -17,8 +17,6 @@ namespace storm {
virtual bool isRewardPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;

6
src/logic/NextFormula.cpp

@ -19,11 +19,7 @@ namespace storm {
boost::any NextFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> NextFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<NextFormula>(this->getSubformula().substitute(substitution));
}
std::ostream& NextFormula::writeToStream(std::ostream& out) const {
out << "X ";
this->getSubformula().writeToStream(out);

4
src/logic/NextFormula.h

@ -17,9 +17,7 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
};
}

6
src/logic/ProbabilityOperatorFormula.cpp

@ -18,11 +18,7 @@ namespace storm {
boost::any ProbabilityOperatorFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> ProbabilityOperatorFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<ProbabilityOperatorFormula>(this->getSubformula().substitute(substitution), this->operatorInformation);
}
std::ostream& ProbabilityOperatorFormula::writeToStream(std::ostream& out) const {
out << "P";
OperatorFormula::writeToStream(out);

4
src/logic/ProbabilityOperatorFormula.h

@ -16,9 +16,7 @@ namespace storm {
virtual bool isProbabilityOperatorFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
};
}

4
src/logic/RewardOperatorFormula.cpp

@ -40,10 +40,6 @@ namespace storm {
this->getSubformula().gatherReferencedRewardModels(referencedRewardModels);
}
std::shared_ptr<Formula> RewardOperatorFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<RewardOperatorFormula>(this->getSubformula().substitute(substitution), this->rewardModelName, this->operatorInformation, this->rewardMeasureType);
}
RewardMeasureType RewardOperatorFormula::getMeasureType() const {
return rewardMeasureType;
}

4
src/logic/RewardOperatorFormula.h

@ -50,9 +50,7 @@ namespace storm {
* @return The measure type.
*/
RewardMeasureType getMeasureType() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private:
// The (optional) name of the reward model this property refers to.
boost::optional<std::string> rewardModelName;

6
src/logic/TimeOperatorFormula.cpp

@ -18,11 +18,7 @@ namespace storm {
boost::any TimeOperatorFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> TimeOperatorFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<TimeOperatorFormula>(this->getSubformula().substitute(substitution), this->operatorInformation, this->rewardMeasureType);
}
RewardMeasureType TimeOperatorFormula::getMeasureType() const {
return rewardMeasureType;
}

4
src/logic/TimeOperatorFormula.h

@ -18,9 +18,7 @@ namespace storm {
virtual bool isTimeOperatorFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
/*!

6
src/logic/UnaryBooleanStateFormula.cpp

@ -26,11 +26,7 @@ namespace storm {
bool UnaryBooleanStateFormula::isNot() const {
return this->getOperator() == OperatorType::Not;
}
std::shared_ptr<Formula> UnaryBooleanStateFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<UnaryBooleanStateFormula>(this->operatorType, this->getSubformula().substitute(substitution));
}
std::ostream& UnaryBooleanStateFormula::writeToStream(std::ostream& out) const {
switch (operatorType) {
case OperatorType::Not: out << "!("; break;

2
src/logic/UnaryBooleanStateFormula.h

@ -22,8 +22,6 @@ namespace storm {
OperatorType getOperator() const;
virtual bool isNot() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;

4
src/logic/UntilFormula.cpp

@ -20,10 +20,6 @@ namespace storm {
return visitor.visit(*this, data);
}
std::shared_ptr<Formula> UntilFormula::substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const {
return std::make_shared<UntilFormula>(this->getLeftSubformula().substitute(substitution), this->getRightSubformula().substitute(substitution));
}
std::ostream& UntilFormula::writeToStream(std::ostream& out) const {
this->getLeftSubformula().writeToStream(out);
out << " U ";

4
src/logic/UntilFormula.h

@ -17,9 +17,7 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) const override;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
virtual std::ostream& writeToStream(std::ostream& out) const override;
};
}

21
src/logic/VariableSubstitutionVisitor.cpp

@ -0,0 +1,21 @@
#include "src/logic/VariableSubstitutionVisitor.h"
#include "src/logic/Formulas.h"
namespace storm {
namespace logic {
VariableSubstitutionVisitor::VariableSubstitutionVisitor(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) : substitution(substitution) {
// Intentionally left empty.
}
std::shared_ptr<Formula> VariableSubstitutionVisitor::substitute(Formula const& f) const {
boost::any result = f.accept(*this, boost::any());
return boost::any_cast<std::shared_ptr<Formula>>(result);
}
boost::any VariableSubstitutionVisitor::visit(AtomicExpressionFormula const& f, boost::any const& data) const {
return std::static_pointer_cast<Formula>(std::make_shared<AtomicExpressionFormula>(f.getExpression().substitute(substitution)));
}
}
}

29
src/logic/VariableSubstitutionVisitor.h

@ -0,0 +1,29 @@
#ifndef STORM_LOGIC_VARIABLESUBSTITUTIONVISITOR_H_
#define STORM_LOGIC_VARIABLESUBSTITUTIONVISITOR_H_
#include <map>
#include "src/logic/CloneVisitor.h"
#include "src/storage/expressions/Expression.h"
namespace storm {
namespace logic {
class VariableSubstitutionVisitor : public CloneVisitor {
public:
VariableSubstitutionVisitor(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution);
std::shared_ptr<Formula> substitute(Formula const& f) const;
virtual boost::any visit(AtomicExpressionFormula const& f, boost::any const& data) const override;
private:
std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution;
};
}
}
#endif /* STORM_LOGIC_VARIABLESUBSTITUTIONVISITOR_H_ */

186
src/modelchecker/reachability/SparseMdpLearningModelChecker.cpp

@ -15,6 +15,7 @@
#include "src/settings/modules/GeneralSettings.h"
#include "src/utility/macros.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/InvalidPropertyException.h"
#include "src/exceptions/NotSupportedException.h"
@ -58,7 +59,13 @@ namespace storm {
template<typename ValueType>
storm::expressions::Expression SparseMdpLearningModelChecker<ValueType>::getTargetStateExpression(storm::logic::Formula const& subformula) const {
std::shared_ptr<storm::logic::Formula> preparedSubformula = subformula.substitute(program.getLabelToExpressionMapping());
return preparedSubformula->toExpression();
storm::expressions::Expression result;
try {
result = preparedSubformula->toExpression();
} catch(storm::exceptions::InvalidOperationException const& e) {
STORM_LOG_THROW(false, storm::exceptions::InvalidPropertyException, "The property refers to unknown labels.");
}
return result;
}
template<typename ValueType>
@ -284,28 +291,41 @@ namespace storm {
}
template<typename ValueType>
uint32_t SparseMdpLearningModelChecker<ValueType>::sampleActionOfState(StateType const& currentStateId, ExplorationInformation const& explorationInformation, BoundValues& bounds) const {
typename SparseMdpLearningModelChecker<ValueType>::ActionType SparseMdpLearningModelChecker<ValueType>::sampleActionOfState(StateType const& currentStateId, ExplorationInformation const& explorationInformation, BoundValues& bounds) const {
// Determine the values of all available actions.
std::vector<std::pair<ActionType, ValueType>> actionValues;
StateType rowGroup = explorationInformation.getRowGroup(currentStateId);
auto choicesInEcIt = explorationInformation.stateToLeavingActionsOfEndComponent.find(currentStateId);
// Check for cases in which we do not need to perform more work.
if (choicesInEcIt == explorationInformation.stateToLeavingActionsOfEndComponent.end()) {
if (explorationInformation.onlyOneActionAvailable(rowGroup)) {
return explorationInformation.getStartRowOfGroup(rowGroup);
}
} else {
if (choicesInEcIt->second->size() == 1) {
return *choicesInEcIt->second->begin();
}
}
// If there are more choices to consider, start by gathering the values of relevant actions.
if (choicesInEcIt != explorationInformation.stateToLeavingActionsOfEndComponent.end()) {
STORM_LOG_TRACE("Sampling from actions leaving the previously detected EC.");
for (auto const& row : *choicesInEcIt->second) {
actionValues.push_back(std::make_pair(row, computeUpperBoundOfAction(row, explorationInformation, bounds)));
actionValues.push_back(std::make_pair(row, bounds.getBoundForAction(explorationInformation.optimizationDirection, row)));
}
} else {
STORM_LOG_TRACE("Sampling from actions leaving the state.");
for (uint32_t row = explorationInformation.getStartRowOfGroup(rowGroup); row < explorationInformation.getStartRowOfGroup(rowGroup + 1); ++row) {
actionValues.push_back(std::make_pair(row, computeUpperBoundOfAction(row, explorationInformation, bounds)));
actionValues.push_back(std::make_pair(row, bounds.getBoundForAction(explorationInformation.optimizationDirection, row)));
}
}
STORM_LOG_ASSERT(!actionValues.empty(), "Values for actions must not be empty.");
// Sort the actions wrt. to the optimization direction.
if (explorationInformation.optimizationDirection == storm::OptimizationDirection::Maximize) {
if (explorationInformation.maximize()) {
std::sort(actionValues.begin(), actionValues.end(), [] (std::pair<ActionType, ValueType> const& a, std::pair<ActionType, ValueType> const& b) { return a.second > b.second; } );
} else {
std::sort(actionValues.begin(), actionValues.end(), [] (std::pair<ActionType, ValueType> const& a, std::pair<ActionType, ValueType> const& b) { return a.second < b.second; } );
@ -349,14 +369,13 @@ namespace storm {
// Determine the set of states that was expanded.
std::vector<StateType> relevantStates;
for (StateType state = 0; state < explorationInformation.stateStorage.numberOfStates; ++state) {
if (!explorationInformation.isUnexplored(state)) {
// Add the state to the relevant states if it's unexplored. Additionally, if we are computing minimal
// probabilities, we only consider it relevant if it's not a target state.
if (!explorationInformation.isUnexplored(state) && (explorationInformation.maximize() || !comparator.isOne(bounds.getLowerBoundForState(state, explorationInformation)))) {
relevantStates.push_back(state);
}
}
// Sort according to the actual row groups so we can insert the elements in order later.
std::sort(relevantStates.begin(), relevantStates.end(), [&explorationInformation] (StateType const& a, StateType const& b) { return explorationInformation.getRowGroup(a) < explorationInformation.getRowGroup(b); });
StateType unexploredState = relevantStates.size();
StateType sink = relevantStates.size();
// Create a mapping for faster look-up during the translation of flexible matrix to the real sparse matrix.
std::unordered_map<StateType, StateType> relevantStateToNewRowGroupMapping;
@ -382,14 +401,14 @@ namespace storm {
}
}
if (unexpandedProbability != storm::utility::zero<ValueType>()) {
builder.addNextValue(currentRow, unexploredState, unexpandedProbability);
builder.addNextValue(currentRow, sink, unexpandedProbability);
}
++currentRow;
}
}
// Then, make the unexpanded state absorbing.
builder.newRowGroup(currentRow);
builder.addNextValue(currentRow, unexploredState, storm::utility::one<ValueType>());
builder.addNextValue(currentRow, sink, storm::utility::one<ValueType>());
STORM_LOG_TRACE("Successfully built matrix for MEC decomposition.");
// Go on to step 2.
@ -399,74 +418,102 @@ namespace storm {
// 3. Analyze the MEC decomposition.
for (auto const& mec : mecDecomposition) {
// Ignore the (expected) MEC of the unexplored state.
if (mec.containsState(unexploredState)) {
// Ignore the (expected) MEC of the sink state.
if (mec.containsState(sink)) {
continue;
}
bool containsTargetState = false;
if (explorationInformation.maximize()) {
analyzeMecForMaximalProbabilities(mec, relevantStates, relevantStatesMatrix, explorationInformation, bounds);
} else {
analyzeMecForMinimalProbabilities(mec, relevantStates, relevantStatesMatrix, explorationInformation, bounds);
}
}
}
template<typename ValueType>
void SparseMdpLearningModelChecker<ValueType>::analyzeMecForMaximalProbabilities(storm::storage::MaximalEndComponent const& mec, std::vector<StateType> const& relevantStates, storm::storage::SparseMatrix<ValueType> const& relevantStatesMatrix, ExplorationInformation& explorationInformation, BoundValues& bounds) const {
// For maximal probabilities, we check (a) which MECs contain a target state, because the associated states
// have a probability of 1 (and we can therefore set their lower bounds to 1) and (b) which of the remaining
// MECs have no outgoing action, because the associated states have a probability of 0 (and we can therefore
// set their upper bounds to 0).
bool containsTargetState = false;
// Now we record all choices leaving the EC.
ActionSetPointer leavingChoices = std::make_shared<ActionSet>();
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType originalState = relevantStates[stateAndChoices.first];
StateType originalRowGroup = explorationInformation.getRowGroup(originalState);
// Now we record all choices leaving the EC.
ActionSetPointer leavingChoices = std::make_shared<ActionSet>();
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType originalState = relevantStates[stateAndChoices.first];
uint32_t originalRowGroup = explorationInformation.getRowGroup(originalState);
// Check whether a target state is contained in the MEC.
if (!containsTargetState && comparator.isOne(bounds.getLowerBoundForRowGroup(originalRowGroup))) {
containsTargetState = true;
}
// For each state, compute the actions that leave the MEC.
auto includedChoicesIt = stateAndChoices.second.begin();
auto includedChoicesIte = stateAndChoices.second.end();
for (auto action = explorationInformation.getStartRowOfGroup(originalRowGroup); action < explorationInformation.getStartRowOfGroup(originalRowGroup + 1); ++action) {
if (includedChoicesIt != includedChoicesIte) {
STORM_LOG_TRACE("Next (local) choice contained in MEC is " << (*includedChoicesIt - relevantStatesMatrix.getRowGroupIndices()[stateAndChoices.first]));
STORM_LOG_TRACE("Current (local) choice iterated is " << (action - explorationInformation.getStartRowOfGroup(originalRowGroup)));
if (action - explorationInformation.getStartRowOfGroup(originalRowGroup) != *includedChoicesIt - relevantStatesMatrix.getRowGroupIndices()[stateAndChoices.first]) {
STORM_LOG_TRACE("Choice leaves the EC.");
leavingChoices->insert(action);
} else {
STORM_LOG_TRACE("Choice stays in the EC.");
++includedChoicesIt;
}
} else {
STORM_LOG_TRACE("Choice leaves the EC, because there is no more choice staying in the EC.");
// Check whether a target state is contained in the MEC.
if (!containsTargetState && comparator.isOne(bounds.getLowerBoundForRowGroup(originalRowGroup))) {
containsTargetState = true;
}
// For each state, compute the actions that leave the MEC.
auto includedChoicesIt = stateAndChoices.second.begin();
auto includedChoicesIte = stateAndChoices.second.end();
for (auto action = explorationInformation.getStartRowOfGroup(originalRowGroup); action < explorationInformation.getStartRowOfGroup(originalRowGroup + 1); ++action) {
if (includedChoicesIt != includedChoicesIte) {
STORM_LOG_TRACE("Next (local) choice contained in MEC is " << (*includedChoicesIt - relevantStatesMatrix.getRowGroupIndices()[stateAndChoices.first]));
STORM_LOG_TRACE("Current (local) choice iterated is " << (action - explorationInformation.getStartRowOfGroup(originalRowGroup)));
if (action - explorationInformation.getStartRowOfGroup(originalRowGroup) != *includedChoicesIt - relevantStatesMatrix.getRowGroupIndices()[stateAndChoices.first]) {
STORM_LOG_TRACE("Choice leaves the EC.");
leavingChoices->insert(action);
} else {
STORM_LOG_TRACE("Choice stays in the EC.");
++includedChoicesIt;
}
} else {
STORM_LOG_TRACE("Choice leaves the EC, because there is no more choice staying in the EC.");
leavingChoices->insert(action);
}
explorationInformation.stateToLeavingActionsOfEndComponent[originalState] = leavingChoices;
}
// If one of the states of the EC is a target state, all states in the EC have probability 1.
if (containsTargetState) {
STORM_LOG_TRACE("MEC contains a target state.");
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType const& originalState = relevantStates[stateAndChoices.first];
STORM_LOG_TRACE("Setting lower bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 1.");
bounds.setLowerBoundForState(originalState, explorationInformation, storm::utility::one<ValueType>());
explorationInformation.addTerminalState(originalState);
}
} else if (leavingChoices->empty()) {
STORM_LOG_TRACE("MEC's leaving choices are empty.");
// If there is no choice leaving the EC, but it contains no target state, all states have probability 0.
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType const& originalState = relevantStates[stateAndChoices.first];
STORM_LOG_TRACE("Setting upper bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 0.");
bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>());
explorationInformation.addTerminalState(originalState);
}
explorationInformation.stateToLeavingActionsOfEndComponent[originalState] = leavingChoices;
}
// If one of the states of the EC is a target state, all states in the EC have probability 1.
if (containsTargetState) {
STORM_LOG_TRACE("MEC contains a target state.");
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType const& originalState = relevantStates[stateAndChoices.first];
STORM_LOG_TRACE("Setting lower bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 1.");
bounds.setLowerBoundForState(originalState, explorationInformation, storm::utility::one<ValueType>());
explorationInformation.addTerminalState(originalState);
}
} else if (leavingChoices->empty()) {
STORM_LOG_TRACE("MEC's leaving choices are empty.");
// If there is no choice leaving the EC, but it contains no target state, all states have probability 0.
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType const& originalState = relevantStates[stateAndChoices.first];
STORM_LOG_TRACE("Setting upper bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 0.");
bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>());
explorationInformation.addTerminalState(originalState);
}
}
}
template<typename ValueType>
void SparseMdpLearningModelChecker<ValueType>::analyzeMecForMinimalProbabilities(storm::storage::MaximalEndComponent const& mec, std::vector<StateType> const& relevantStates, storm::storage::SparseMatrix<ValueType> const& relevantStatesMatrix, ExplorationInformation& explorationInformation, BoundValues& bounds) const {
// For minimal probabilities, all found MECs are guaranteed to not contain a target state. Hence, in all
// associated states, the probability is 0 and we can set the upper bounds of the states to 0).
for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
StateType originalState = relevantStates[stateAndChoices.first];
bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>());
explorationInformation.addTerminalState(originalState);
}
}
template<typename ValueType>
ValueType SparseMdpLearningModelChecker<ValueType>::computeLowerBoundOfAction(ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues const& bounds) const {
ValueType result = storm::utility::zero<ValueType>();
@ -525,7 +572,7 @@ namespace storm {
bounds.setBoundsForAction(action, newBoundsForAction);
// Check if we need to update the values for the states.
if (explorationInformation.optimizationDirection == storm::OptimizationDirection::Maximize) {
if (explorationInformation.maximize()) {
bounds.setLowerBoundOfStateIfGreaterThanOld(state, explorationInformation, newBoundsForAction.first);
StateType rowGroup = explorationInformation.getRowGroup(state);
@ -542,7 +589,8 @@ namespace storm {
StateType rowGroup = explorationInformation.getRowGroup(state);
if (bounds.getLowerBoundForRowGroup(rowGroup) < newBoundsForAction.first) {
if (explorationInformation.getRowGroupSize(rowGroup) > 1) {
newBoundsForAction.first = std::min(newBoundsForAction.first, computeBoundOverAllOtherActions(storm::OptimizationDirection::Maximize, state, action, explorationInformation, bounds));
ValueType min = computeBoundOverAllOtherActions(storm::OptimizationDirection::Minimize, state, action, explorationInformation, bounds);
newBoundsForAction.first = std::min(newBoundsForAction.first, min);
}
bounds.setLowerBoundForRowGroup(rowGroup, newBoundsForAction.first);

30
src/modelchecker/reachability/SparseMdpLearningModelChecker.h

@ -21,6 +21,8 @@ namespace storm {
template<typename StateType>
class StateStorage;
}
class MaximalEndComponent;
}
namespace generator {
@ -49,7 +51,7 @@ namespace storm {
private:
// A struct that keeps track of certain statistics during the computation.
struct Statistics {
Statistics() : iterations(0), maxPathLength(0), numberOfTargetStates(0), numberOfExploredStates(0), pathLengthUntilEndComponentDetection(27) {
Statistics() : iterations(0), maxPathLength(0), numberOfTargetStates(0), numberOfExploredStates(0), pathLengthUntilEndComponentDetection(10000) {
// Intentionally left empty.
}
@ -170,6 +172,10 @@ namespace storm {
return rowGroupIndices[group + 1] - rowGroupIndices[group];
}
bool onlyOneActionAvailable(StateType const& group) const {
return getRowGroupSize(group) == 1;
}
void addTerminalState(StateType const& state) {
terminalStates.insert(state);
}
@ -185,6 +191,14 @@ namespace storm {
void addRowsToMatrix(std::size_t const& count) {
matrix.resize(matrix.size() + count);
}
bool maximize() const {
return optimizationDirection == storm::OptimizationDirection::Maximize;
}
bool minimize() const {
return !maximize();
}
};
// A struct containg the lower and upper bounds per state and action.
@ -241,6 +255,14 @@ namespace storm {
return upperBoundsPerAction[action];
}
ValueType const& getBoundForAction(storm::OptimizationDirection const& direction, ActionType const& action) const {
if (direction == storm::OptimizationDirection::Maximize) {
return getUpperBoundForAction(action);
} else {
return getLowerBoundForAction(action);
}
}
ValueType getDifferenceOfStateBounds(StateType const& state, ExplorationInformation const& explorationInformation) {
std::pair<ValueType, ValueType> bounds = getBoundsForState(state, explorationInformation);
return bounds.second - bounds.first;
@ -312,12 +334,16 @@ namespace storm {
bool exploreState(StateGeneration& stateGeneration, StateType const& currentStateId, storm::generator::CompressedState const& currentState, ExplorationInformation& explorationInformation, BoundValues& bounds, Statistics& stats) const;
uint32_t sampleActionOfState(StateType const& currentStateId, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;
ActionType sampleActionOfState(StateType const& currentStateId, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;
StateType sampleSuccessorFromAction(ActionType const& chosenAction, ExplorationInformation const& explorationInformation) const;
void detectEndComponents(StateActionStack const& stack, ExplorationInformation& explorationInformation, BoundValues& bounds) const;
void analyzeMecForMaximalProbabilities(storm::storage::MaximalEndComponent const& mec, std::vector<StateType> const& relevantStates, storm::storage::SparseMatrix<ValueType> const& relevantStatesMatrix, ExplorationInformation& explorationInformation, BoundValues& bounds) const;
void analyzeMecForMinimalProbabilities(storm::storage::MaximalEndComponent const& mec, std::vector<StateType> const& relevantStates, storm::storage::SparseMatrix<ValueType> const& relevantStatesMatrix, ExplorationInformation& explorationInformation, BoundValues& bounds) const;
void updateProbabilityBoundsAlongSampledPath(StateActionStack& stack, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;
void updateProbabilityOfAction(StateType const& state, ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;

Loading…
Cancel
Save