You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
185 lines
8.7 KiB
185 lines
8.7 KiB
#include "storm/modelchecker/prctl/helper/rewardbounded/CostLimitClosure.h"
|
|
#include "storm/utility/macros.h"
|
|
#include "storm/exceptions/IllegalArgumentException.h"
|
|
#include "storm/utility/solver.h"
|
|
#include "storm/solver/SmtSolver.h"
|
|
|
|
namespace storm {
|
|
namespace modelchecker {
|
|
namespace helper {
|
|
namespace rewardbounded {
|
|
CostLimit::CostLimit(uint64_t const &costLimit) : value(costLimit) {
|
|
// Intentionally left empty
|
|
}
|
|
|
|
bool CostLimit::isInfinity() const {
|
|
return value == std::numeric_limits<uint64_t>::max();
|
|
}
|
|
|
|
uint64_t const& CostLimit::get() const {
|
|
STORM_LOG_ASSERT(!isInfinity(), "Tried to get an infinite cost limit as int.");
|
|
return value;
|
|
}
|
|
|
|
uint64_t& CostLimit::get() {
|
|
STORM_LOG_ASSERT(!isInfinity(), "Tried to get an infinite cost limit as int.");
|
|
return value;
|
|
}
|
|
|
|
bool CostLimit::operator<(CostLimit const& other) const {
|
|
// Since infinity is represented by the max integer, we can compare this way.
|
|
return value < other.value;
|
|
}
|
|
|
|
bool CostLimit::operator==(CostLimit const& other) const {
|
|
return value == other.value;
|
|
}
|
|
|
|
CostLimit CostLimit::infinity() {
|
|
return CostLimit(std::numeric_limits<uint64_t>::max());
|
|
}
|
|
|
|
bool CostLimitClosure::CostLimitsCompare::operator()(storm::modelchecker::helper::rewardbounded::CostLimits const& lhs, storm::modelchecker::helper::rewardbounded::CostLimits const& rhs) const {
|
|
for (uint64_t i = 0; i < lhs.size(); ++i) {
|
|
if (lhs[i] < rhs[i]) {
|
|
return true;
|
|
} else if (rhs[i] < lhs[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
CostLimitClosure::CostLimitClosure(storm::storage::BitVector const &downwardDimensions)
|
|
: downwardDimensions(downwardDimensions) {
|
|
// Intentionally left empty
|
|
}
|
|
|
|
bool CostLimitClosure::insert(CostLimits const& costLimits) {
|
|
// Iterate over all points in the generator and check whether they dominate the given point or vice versa
|
|
// TODO: make this more efficient by exploiting the order of the generator set.
|
|
std::vector<CostLimits> pointsToErase;
|
|
for (auto const& b : generator) {
|
|
if (dominates(b, costLimits)) {
|
|
// The given point is already contained in this closure.
|
|
// Since domination is transitive, this should not happen:
|
|
STORM_LOG_ASSERT(pointsToErase.empty(), "Inconsistent generator of CostLimitClosure.");
|
|
return false;
|
|
}
|
|
if (dominates(costLimits, b)) {
|
|
// b will be dominated by the new point so we erase it later.
|
|
// Note that b != newPoint holds if we reach this point
|
|
pointsToErase.push_back(b);
|
|
}
|
|
}
|
|
for (auto const& b : pointsToErase) {
|
|
generator.erase(b);
|
|
}
|
|
generator.insert(std::move(costLimits));
|
|
return true;
|
|
}
|
|
|
|
bool CostLimitClosure::contains(CostLimits const& costLimits) const {
|
|
// Iterate over all points in the generator and check whether they dominate the given point.
|
|
// TODO: make this more efficient by exploiting the order of the generator set.
|
|
for (auto const&b : generator) {
|
|
if (dominates(b,costLimits)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CostLimitClosure::containsUpwardClosure(CostLimits const& costLimits) const {
|
|
CostLimits infinityProjection(costLimits);
|
|
for (auto const& dim : downwardDimensions) {
|
|
infinityProjection[dim] = CostLimit::infinity();
|
|
}
|
|
return contains(infinityProjection);
|
|
}
|
|
|
|
bool CostLimitClosure::empty() const {
|
|
return generator.empty();
|
|
}
|
|
|
|
bool CostLimitClosure::full() const {
|
|
CostLimits p(dimension(), CostLimit(0));
|
|
for (auto const& dim : downwardDimensions) {
|
|
p[dim] = CostLimit::infinity();
|
|
}
|
|
return contains(p);
|
|
}
|
|
|
|
bool CostLimitClosure::dominates(CostLimits const& lhs, CostLimits const& rhs) const {
|
|
for (uint64_t i = 0; i < lhs.size(); ++i) {
|
|
if (downwardDimensions.get(i)) {
|
|
if (lhs[i] < rhs[i]) {
|
|
return false;
|
|
}
|
|
} else {
|
|
if (rhs[i] < lhs[i]) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
std::vector<CostLimits> CostLimitClosure::getDominatingCostLimits(CostLimits const& costLimits) const {
|
|
std::vector<CostLimits> result;
|
|
for (auto const &b : generator) {
|
|
if (dominates(b, costLimits)) {
|
|
result.push_back(b);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
typename CostLimitClosure::GeneratorType const &CostLimitClosure::getGenerator() const {
|
|
return generator;
|
|
}
|
|
|
|
uint64_t CostLimitClosure::dimension() const {
|
|
return downwardDimensions.size();
|
|
}
|
|
|
|
bool CostLimitClosure::unionFull(CostLimitClosure const& first, CostLimitClosure const& second) {
|
|
assert(first.dimension() == second.dimension());
|
|
uint64_t dimension = first.dimension();
|
|
auto manager = std::make_shared<storm::expressions::ExpressionManager>();
|
|
auto solver = storm::utility::solver::getSmtSolver(*manager);
|
|
|
|
std::vector<storm::expressions::Expression> point;
|
|
storm::expressions::Expression zero = manager->integer(0);
|
|
for (uint64_t i = 0; i < dimension; ++i) {
|
|
point.push_back(manager->declareIntegerVariable("x" + std::to_string(i)).getExpression());
|
|
solver->add(point.back() >= zero);
|
|
}
|
|
for (auto const& cl : {first, second}) {
|
|
for (auto const& q : cl.getGenerator()) {
|
|
storm::expressions::Expression pointNotDominated;
|
|
for (uint64_t i = 0; i < point.size(); ++i) {
|
|
if (!cl.downwardDimensions.get(i) || !q[i].isInfinity()) {
|
|
assert(!q[i].isInfinity());
|
|
storm::expressions::Expression qi = manager->integer(q[i].get());
|
|
storm::expressions::Expression piNotDominated = cl.downwardDimensions.get(i) ? point[i] > qi : point[i] < qi;
|
|
if (piNotDominated.isInitialized()) {
|
|
pointNotDominated = pointNotDominated || piNotDominated;
|
|
} else {
|
|
pointNotDominated = piNotDominated;
|
|
}
|
|
}
|
|
}
|
|
if (pointNotDominated.isInitialized()) {
|
|
solver->add(pointNotDominated);
|
|
} else {
|
|
solver->add(manager->boolean(false));
|
|
}
|
|
}
|
|
}
|
|
return solver->check() == storm::solver::SmtSolver::CheckResult::Unsat;;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|