Browse Source

minimal probabilities now working (for some test cases)

Former-commit-id: 9f38386531
main
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())); 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 { std::ostream& AtomicExpressionFormula::writeToStream(std::ostream& out) const {
out << expression; out << expression;
return out; 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 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: private:
// The atomic expression represented by this node in the formula tree. // The atomic expression represented by this node in the formula tree.
storm::expressions::Expression expression; 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())); 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 { std::ostream& AtomicLabelFormula::writeToStream(std::ostream& out) const {
out << "\"" << label << "\""; out << "\"" << label << "\"";
return out; return out;

4
src/logic/AtomicLabelFormula.h

@ -22,9 +22,7 @@ namespace storm {
std::string const& getLabel() const; std::string const& getLabel() const;
virtual void gatherAtomicLabelFormulas(std::vector<std::shared_ptr<AtomicLabelFormula const>>& atomicLabelFormulas) const override; 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; virtual std::ostream& writeToStream(std::ostream& out) const override;
private: private:

6
src/logic/BinaryBooleanStateFormula.cpp

@ -30,11 +30,7 @@ namespace storm {
bool BinaryBooleanStateFormula::isOr() const { bool BinaryBooleanStateFormula::isOr() const {
return this->getOperator() == OperatorType::Or; 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 { std::ostream& BinaryBooleanStateFormula::writeToStream(std::ostream& out) const {
out << "("; out << "(";
this->getLeftSubformula().writeToStream(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::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: private:
OperatorType operatorType; OperatorType operatorType;
}; };

4
src/logic/BooleanLiteralFormula.cpp

@ -24,10 +24,6 @@ namespace storm {
return visitor.visit(*this, data); 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 { std::ostream& BooleanLiteralFormula::writeToStream(std::ostream& out) const {
if (value) { if (value) {
out << "true"; 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 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; virtual std::ostream& writeToStream(std::ostream& out) const override;
private: private:

4
src/logic/BoundedUntilFormula.cpp

@ -44,10 +44,6 @@ namespace storm {
return boost::get<uint_fast64_t>(bounds); 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 { std::ostream& BoundedUntilFormula::writeToStream(std::ostream& out) const {
this->getLeftSubformula().writeToStream(out); 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::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: private:
boost::variant<uint_fast64_t, std::pair<double, double>> bounds; 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 { boost::any ConditionalFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { void ConditionalFormula::gatherAtomicExpressionFormulas(std::vector<std::shared_ptr<AtomicExpressionFormula const>>& atomicExpressionFormulas) const {
this->getSubformula().gatherAtomicExpressionFormulas(atomicExpressionFormulas); this->getSubformula().gatherAtomicExpressionFormulas(atomicExpressionFormulas);
this->getConditionFormula().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::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 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 gatherAtomicLabelFormulas(std::vector<std::shared_ptr<AtomicLabelFormula const>>& atomicLabelFormulas) const override;
virtual void gatherReferencedRewardModels(std::set<std::string>& referencedRewardModels) 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 { std::ostream& CumulativeRewardFormula::writeToStream(std::ostream& out) const {
if (this->hasDiscreteTimeBound()) { if (this->hasDiscreteTimeBound()) {
out << "C<=" << this->getDiscreteTimeBound(); out << "C<=" << this->getDiscreteTimeBound();

2
src/logic/CumulativeRewardFormula.h

@ -32,8 +32,6 @@ namespace storm {
double getContinuousTimeBound() const; double getContinuousTimeBound() const;
virtual std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const override;
private: private:
boost::variant<uint_fast64_t, double> timeBound; 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 { boost::any EventuallyFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { std::ostream& EventuallyFormula::writeToStream(std::ostream& out) const {
out << "F "; out << "F ";
this->getSubformula().writeToStream(out); 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::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: private:
FormulaContext context; FormulaContext context;
}; };

6
src/logic/Formula.cpp

@ -3,6 +3,7 @@
#include "src/logic/FragmentChecker.h" #include "src/logic/FragmentChecker.h"
#include "src/logic/FormulaInformationVisitor.h" #include "src/logic/FormulaInformationVisitor.h"
#include "src/logic/VariableSubstitutionVisitor.h"
#include "src/logic/LabelSubstitutionVisitor.h" #include "src/logic/LabelSubstitutionVisitor.h"
#include "src/logic/ToExpressionVisitor.h" #include "src/logic/ToExpressionVisitor.h"
@ -408,6 +409,11 @@ namespace storm {
return referencedRewardModels; 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 { std::shared_ptr<Formula> Formula::substitute(std::map<std::string, storm::expressions::Expression> const& labelSubstitution) const {
LabelSubstitutionVisitor visitor(labelSubstitution); LabelSubstitutionVisitor visitor(labelSubstitution);
return visitor.substitute(*this); 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();
std::shared_ptr<Formula const> asSharedPointer() const; 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; std::shared_ptr<Formula> substitute(std::map<storm::expressions::Variable, storm::expressions::Expression> const& substitution) const;
virtual std::shared_ptr<Formula> substitute(std::map<std::string, storm::expressions::Expression> const& labelSubstitution) 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 * 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 { boost::any GloballyFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { std::ostream& GloballyFormula::writeToStream(std::ostream& out) const {
out << "G "; out << "G ";

2
src/logic/GloballyFormula.h

@ -17,8 +17,6 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override; virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; 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); 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 { std::ostream& InstantaneousRewardFormula::writeToStream(std::ostream& out) const {
if (this->hasDiscreteTimeBound()) { if (this->hasDiscreteTimeBound()) {
out << "I=" << this->getDiscreteTimeBound(); out << "I=" << this->getDiscreteTimeBound();

4
src/logic/InstantaneousRewardFormula.h

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

3
src/logic/LabelSubstitutionVisitor.cpp

@ -21,7 +21,6 @@ namespace storm {
} else { } else {
return std::static_pointer_cast<Formula>(std::make_shared<AtomicLabelFormula>(f)); 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 { boost::any LongRunAverageOperatorFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { std::ostream& LongRunAverageOperatorFormula::writeToStream(std::ostream& out) const {
out << "LRA"; out << "LRA";
OperatorFormula::writeToStream(out); 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 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; 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); 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 { std::ostream& LongRunAverageRewardFormula::writeToStream(std::ostream& out) const {
return out << "LRA"; return out << "LRA";
} }

2
src/logic/LongRunAverageRewardFormula.h

@ -17,8 +17,6 @@ namespace storm {
virtual bool isRewardPathFormula() const override; virtual bool isRewardPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; 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 { boost::any NextFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { std::ostream& NextFormula::writeToStream(std::ostream& out) const {
out << "X "; out << "X ";
this->getSubformula().writeToStream(out); this->getSubformula().writeToStream(out);

4
src/logic/NextFormula.h

@ -17,9 +17,7 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override; virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; 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 { boost::any ProbabilityOperatorFormula::accept(FormulaVisitor const& visitor, boost::any const& data) const {
return visitor.visit(*this, data); 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 { std::ostream& ProbabilityOperatorFormula::writeToStream(std::ostream& out) const {
out << "P"; out << "P";
OperatorFormula::writeToStream(out); OperatorFormula::writeToStream(out);

4
src/logic/ProbabilityOperatorFormula.h

@ -16,9 +16,7 @@ namespace storm {
virtual bool isProbabilityOperatorFormula() const override; virtual bool isProbabilityOperatorFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; virtual std::ostream& writeToStream(std::ostream& out) const override;
}; };
} }

4
src/logic/RewardOperatorFormula.cpp

@ -40,10 +40,6 @@ namespace storm {
this->getSubformula().gatherReferencedRewardModels(referencedRewardModels); 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 { RewardMeasureType RewardOperatorFormula::getMeasureType() const {
return rewardMeasureType; return rewardMeasureType;
} }

4
src/logic/RewardOperatorFormula.h

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

4
src/logic/TimeOperatorFormula.h

@ -18,9 +18,7 @@ namespace storm {
virtual bool isTimeOperatorFormula() const override; virtual bool isTimeOperatorFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; virtual std::ostream& writeToStream(std::ostream& out) const override;
/*! /*!

6
src/logic/UnaryBooleanStateFormula.cpp

@ -26,11 +26,7 @@ namespace storm {
bool UnaryBooleanStateFormula::isNot() const { bool UnaryBooleanStateFormula::isNot() const {
return this->getOperator() == OperatorType::Not; 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 { std::ostream& UnaryBooleanStateFormula::writeToStream(std::ostream& out) const {
switch (operatorType) { switch (operatorType) {
case OperatorType::Not: out << "!("; break; case OperatorType::Not: out << "!("; break;

2
src/logic/UnaryBooleanStateFormula.h

@ -22,8 +22,6 @@ namespace storm {
OperatorType getOperator() const; OperatorType getOperator() const;
virtual bool isNot() 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; 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); 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 { std::ostream& UntilFormula::writeToStream(std::ostream& out) const {
this->getLeftSubformula().writeToStream(out); this->getLeftSubformula().writeToStream(out);
out << " U "; out << " U ";

4
src/logic/UntilFormula.h

@ -17,9 +17,7 @@ namespace storm {
virtual bool isProbabilityPathFormula() const override; virtual bool isProbabilityPathFormula() const override;
virtual boost::any accept(FormulaVisitor const& visitor, boost::any const& data) 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; 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/settings/modules/GeneralSettings.h"
#include "src/utility/macros.h" #include "src/utility/macros.h"
#include "src/exceptions/InvalidOperationException.h"
#include "src/exceptions/InvalidPropertyException.h" #include "src/exceptions/InvalidPropertyException.h"
#include "src/exceptions/NotSupportedException.h" #include "src/exceptions/NotSupportedException.h"
@ -58,7 +59,13 @@ namespace storm {
template<typename ValueType> template<typename ValueType>
storm::expressions::Expression SparseMdpLearningModelChecker<ValueType>::getTargetStateExpression(storm::logic::Formula const& subformula) const { storm::expressions::Expression SparseMdpLearningModelChecker<ValueType>::getTargetStateExpression(storm::logic::Formula const& subformula) const {
std::shared_ptr<storm::logic::Formula> preparedSubformula = subformula.substitute(program.getLabelToExpressionMapping()); 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> template<typename ValueType>
@ -284,28 +291,41 @@ namespace storm {
} }
template<typename ValueType> 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. // Determine the values of all available actions.
std::vector<std::pair<ActionType, ValueType>> actionValues; std::vector<std::pair<ActionType, ValueType>> actionValues;
StateType rowGroup = explorationInformation.getRowGroup(currentStateId); StateType rowGroup = explorationInformation.getRowGroup(currentStateId);
auto choicesInEcIt = explorationInformation.stateToLeavingActionsOfEndComponent.find(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()) { if (choicesInEcIt != explorationInformation.stateToLeavingActionsOfEndComponent.end()) {
STORM_LOG_TRACE("Sampling from actions leaving the previously detected EC."); STORM_LOG_TRACE("Sampling from actions leaving the previously detected EC.");
for (auto const& row : *choicesInEcIt->second) { 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 { } else {
STORM_LOG_TRACE("Sampling from actions leaving the state."); STORM_LOG_TRACE("Sampling from actions leaving the state.");
for (uint32_t row = explorationInformation.getStartRowOfGroup(rowGroup); row < explorationInformation.getStartRowOfGroup(rowGroup + 1); ++row) { 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."); STORM_LOG_ASSERT(!actionValues.empty(), "Values for actions must not be empty.");
// Sort the actions wrt. to the optimization direction. // 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; } ); std::sort(actionValues.begin(), actionValues.end(), [] (std::pair<ActionType, ValueType> const& a, std::pair<ActionType, ValueType> const& b) { return a.second > b.second; } );
} else { } else {
std::sort(actionValues.begin(), actionValues.end(), [] (std::pair<ActionType, ValueType> const& a, std::pair<ActionType, ValueType> const& b) { return a.second < b.second; } ); 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. // Determine the set of states that was expanded.
std::vector<StateType> relevantStates; std::vector<StateType> relevantStates;
for (StateType state = 0; state < explorationInformation.stateStorage.numberOfStates; ++state) { 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); relevantStates.push_back(state);
} }
} }
StateType sink = relevantStates.size();
// 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();
// Create a mapping for faster look-up during the translation of flexible matrix to the real sparse matrix. // Create a mapping for faster look-up during the translation of flexible matrix to the real sparse matrix.
std::unordered_map<StateType, StateType> relevantStateToNewRowGroupMapping; std::unordered_map<StateType, StateType> relevantStateToNewRowGroupMapping;
@ -382,14 +401,14 @@ namespace storm {
} }
} }
if (unexpandedProbability != storm::utility::zero<ValueType>()) { if (unexpandedProbability != storm::utility::zero<ValueType>()) {
builder.addNextValue(currentRow, unexploredState, unexpandedProbability); builder.addNextValue(currentRow, sink, unexpandedProbability);
} }
++currentRow; ++currentRow;
} }
} }
// Then, make the unexpanded state absorbing. // Then, make the unexpanded state absorbing.
builder.newRowGroup(currentRow); 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."); STORM_LOG_TRACE("Successfully built matrix for MEC decomposition.");
// Go on to step 2. // Go on to step 2.
@ -399,74 +418,102 @@ namespace storm {
// 3. Analyze the MEC decomposition. // 3. Analyze the MEC decomposition.
for (auto const& mec : mecDecomposition) { for (auto const& mec : mecDecomposition) {
// Ignore the (expected) MEC of the unexplored state. // Ignore the (expected) MEC of the sink state.
if (mec.containsState(unexploredState)) { if (mec.containsState(sink)) {
continue; 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. // Check whether a target state is contained in the MEC.
ActionSetPointer leavingChoices = std::make_shared<ActionSet>(); if (!containsTargetState && comparator.isOne(bounds.getLowerBoundForRowGroup(originalRowGroup))) {
for (auto const& stateAndChoices : mec) { containsTargetState = true;
// Compute the state of the original model that corresponds to the current state. }
StateType originalState = relevantStates[stateAndChoices.first]; // For each state, compute the actions that leave the MEC.
uint32_t originalRowGroup = explorationInformation.getRowGroup(originalState); auto includedChoicesIt = stateAndChoices.second.begin();
auto includedChoicesIte = stateAndChoices.second.end();
// Check whether a target state is contained in the MEC. for (auto action = explorationInformation.getStartRowOfGroup(originalRowGroup); action < explorationInformation.getStartRowOfGroup(originalRowGroup + 1); ++action) {
if (!containsTargetState && comparator.isOne(bounds.getLowerBoundForRowGroup(originalRowGroup))) { if (includedChoicesIt != includedChoicesIte) {
containsTargetState = true; 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]) {
// For each state, compute the actions that leave the MEC. STORM_LOG_TRACE("Choice leaves the EC.");
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); 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. explorationInformation.stateToLeavingActionsOfEndComponent[originalState] = leavingChoices;
if (containsTargetState) { }
STORM_LOG_TRACE("MEC contains a target state."); // If one of the states of the EC is a target state, all states in the EC have probability 1.
for (auto const& stateAndChoices : mec) { if (containsTargetState) {
// Compute the state of the original model that corresponds to the current state. STORM_LOG_TRACE("MEC contains a target state.");
StateType const& originalState = relevantStates[stateAndChoices.first]; for (auto const& stateAndChoices : mec) {
// Compute the state of the original model that corresponds to the current state.
STORM_LOG_TRACE("Setting lower bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 1."); StateType const& originalState = relevantStates[stateAndChoices.first];
bounds.setLowerBoundForState(originalState, explorationInformation, storm::utility::one<ValueType>()); STORM_LOG_TRACE("Setting lower bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 1.");
explorationInformation.addTerminalState(originalState); bounds.setLowerBoundForState(originalState, explorationInformation, storm::utility::one<ValueType>());
} explorationInformation.addTerminalState(originalState);
} else if (leavingChoices->empty()) { }
STORM_LOG_TRACE("MEC's leaving choices are empty."); } else if (leavingChoices->empty()) {
// If there is no choice leaving the EC, but it contains no target state, all states have probability 0. STORM_LOG_TRACE("MEC's leaving choices are empty.");
for (auto const& stateAndChoices : mec) { // If there is no choice leaving the EC, but it contains no target state, all states have probability 0.
// Compute the state of the original model that corresponds to the current state. for (auto const& stateAndChoices : mec) {
StateType const& originalState = relevantStates[stateAndChoices.first]; // 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."); STORM_LOG_TRACE("Setting upper bound of state in row group " << explorationInformation.getRowGroup(originalState) << " to 0.");
bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>()); bounds.setUpperBoundForState(originalState, explorationInformation, storm::utility::zero<ValueType>());
explorationInformation.addTerminalState(originalState); 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> template<typename ValueType>
ValueType SparseMdpLearningModelChecker<ValueType>::computeLowerBoundOfAction(ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues const& bounds) const { ValueType SparseMdpLearningModelChecker<ValueType>::computeLowerBoundOfAction(ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues const& bounds) const {
ValueType result = storm::utility::zero<ValueType>(); ValueType result = storm::utility::zero<ValueType>();
@ -525,7 +572,7 @@ namespace storm {
bounds.setBoundsForAction(action, newBoundsForAction); bounds.setBoundsForAction(action, newBoundsForAction);
// Check if we need to update the values for the states. // 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); bounds.setLowerBoundOfStateIfGreaterThanOld(state, explorationInformation, newBoundsForAction.first);
StateType rowGroup = explorationInformation.getRowGroup(state); StateType rowGroup = explorationInformation.getRowGroup(state);
@ -542,7 +589,8 @@ namespace storm {
StateType rowGroup = explorationInformation.getRowGroup(state); StateType rowGroup = explorationInformation.getRowGroup(state);
if (bounds.getLowerBoundForRowGroup(rowGroup) < newBoundsForAction.first) { if (bounds.getLowerBoundForRowGroup(rowGroup) < newBoundsForAction.first) {
if (explorationInformation.getRowGroupSize(rowGroup) > 1) { 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); bounds.setLowerBoundForRowGroup(rowGroup, newBoundsForAction.first);

30
src/modelchecker/reachability/SparseMdpLearningModelChecker.h

@ -21,6 +21,8 @@ namespace storm {
template<typename StateType> template<typename StateType>
class StateStorage; class StateStorage;
} }
class MaximalEndComponent;
} }
namespace generator { namespace generator {
@ -49,7 +51,7 @@ namespace storm {
private: private:
// A struct that keeps track of certain statistics during the computation. // A struct that keeps track of certain statistics during the computation.
struct Statistics { 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. // Intentionally left empty.
} }
@ -170,6 +172,10 @@ namespace storm {
return rowGroupIndices[group + 1] - rowGroupIndices[group]; return rowGroupIndices[group + 1] - rowGroupIndices[group];
} }
bool onlyOneActionAvailable(StateType const& group) const {
return getRowGroupSize(group) == 1;
}
void addTerminalState(StateType const& state) { void addTerminalState(StateType const& state) {
terminalStates.insert(state); terminalStates.insert(state);
} }
@ -185,6 +191,14 @@ namespace storm {
void addRowsToMatrix(std::size_t const& count) { void addRowsToMatrix(std::size_t const& count) {
matrix.resize(matrix.size() + 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. // A struct containg the lower and upper bounds per state and action.
@ -241,6 +255,14 @@ namespace storm {
return upperBoundsPerAction[action]; 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) { ValueType getDifferenceOfStateBounds(StateType const& state, ExplorationInformation const& explorationInformation) {
std::pair<ValueType, ValueType> bounds = getBoundsForState(state, explorationInformation); std::pair<ValueType, ValueType> bounds = getBoundsForState(state, explorationInformation);
return bounds.second - bounds.first; 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; 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; StateType sampleSuccessorFromAction(ActionType const& chosenAction, ExplorationInformation const& explorationInformation) const;
void detectEndComponents(StateActionStack const& stack, ExplorationInformation& explorationInformation, BoundValues& bounds) 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 updateProbabilityBoundsAlongSampledPath(StateActionStack& stack, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;
void updateProbabilityOfAction(StateType const& state, ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues& bounds) const; void updateProbabilityOfAction(StateType const& state, ActionType const& action, ExplorationInformation const& explorationInformation, BoundValues& bounds) const;

|||||||
100:0
Loading…
Cancel
Save