|
|
@ -4,12 +4,18 @@ |
|
|
|
#include "storm/adapters/RationalFunctionAdapter.h"
|
|
|
|
|
|
|
|
#include "storm/utility/macros.h"
|
|
|
|
#include "storm/exceptions/InvalidArgumentException.h"
|
|
|
|
|
|
|
|
namespace storm { |
|
|
|
namespace solver { |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool NoTerminationCondition<ValueType>::terminateNow(std::vector<ValueType> const& currentValues, SolverGuarantee const& guarantee) const { |
|
|
|
bool TerminationCondition<ValueType>::terminateNow(std::vector<ValueType> const& currentValues, SolverGuarantee const& guarantee) const { |
|
|
|
return terminateNow([¤tValues] (uint64_t const& i) {return currentValues[i];}, guarantee); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool NoTerminationCondition<ValueType>::terminateNow(std::function<ValueType(uint64_t const&)> const& valueGetter, SolverGuarantee const& guarantee) const { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
@ -24,14 +30,17 @@ namespace storm { |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool TerminateIfFilteredSumExceedsThreshold<ValueType>::terminateNow(std::vector<ValueType> const& currentValues, SolverGuarantee const& guarantee) const { |
|
|
|
bool TerminateIfFilteredSumExceedsThreshold<ValueType>::terminateNow(std::function<ValueType(uint64_t const&)> const& valueGetter, SolverGuarantee const& guarantee) const { |
|
|
|
if (guarantee != SolverGuarantee::LessOrEqual) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
STORM_LOG_ASSERT(currentValues.size() == filter.size(), "Vectors sizes mismatch."); |
|
|
|
ValueType currentThreshold = storm::utility::vector::sum_if(currentValues, filter); |
|
|
|
return strict ? currentThreshold > this->threshold : currentThreshold >= this->threshold; |
|
|
|
ValueType sum = storm::utility::zero<ValueType>(); |
|
|
|
for (auto pos : filter) { |
|
|
|
sum += valueGetter(pos); |
|
|
|
// Exiting this loop early is not possible as values might be negative
|
|
|
|
} |
|
|
|
return strict ? sum > this->threshold : sum >= this->threshold; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
@ -42,17 +51,47 @@ namespace storm { |
|
|
|
template<typename ValueType> |
|
|
|
TerminateIfFilteredExtremumExceedsThreshold<ValueType>::TerminateIfFilteredExtremumExceedsThreshold(storm::storage::BitVector const& filter, bool strict, ValueType const& threshold, bool useMinimum) : TerminateIfFilteredSumExceedsThreshold<ValueType>(filter, threshold, strict), useMinimum(useMinimum) { |
|
|
|
// Intentionally left empty.
|
|
|
|
STORM_LOG_THROW(!this->filter.empty(), storm::exceptions::InvalidArgumentException, "Empty Filter; Can not take extremum over empty set."); |
|
|
|
cachedExtremumIndex = this->filter.getNextSetIndex(0); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool TerminateIfFilteredExtremumExceedsThreshold<ValueType>::terminateNow(std::vector<ValueType> const& currentValues, SolverGuarantee const& guarantee) const { |
|
|
|
bool TerminateIfFilteredExtremumExceedsThreshold<ValueType>::terminateNow(std::function<ValueType(uint64_t const&)> const& valueGetter, SolverGuarantee const& guarantee) const { |
|
|
|
if (guarantee != SolverGuarantee::LessOrEqual) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
STORM_LOG_ASSERT(currentValues.size() == this->filter.size(), "Vectors sizes mismatch."); |
|
|
|
ValueType currentValue = useMinimum ? storm::utility::vector::min_if(currentValues, this->filter) : storm::utility::vector::max_if(currentValues, this->filter); |
|
|
|
return this->strict ? currentValue > this->threshold : currentValue >= this->threshold; |
|
|
|
ValueType extremum = valueGetter(cachedExtremumIndex); |
|
|
|
if (useMinimum && (this->strict ? extremum <= this->threshold : extremum < this->threshold)) { |
|
|
|
// The extremum can only become smaller so we can return right now.
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (useMinimum) { |
|
|
|
if (this->strict) { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::min(valueGetter(pos), extremum); |
|
|
|
if (extremum <= this->threshold) { |
|
|
|
cachedExtremumIndex = pos; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::min(valueGetter(pos), extremum); |
|
|
|
if (extremum < this->threshold) { |
|
|
|
cachedExtremumIndex = pos; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::max(valueGetter(pos), extremum); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return this->strict ? extremum > this->threshold : extremum >= this->threshold; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
@ -62,18 +101,47 @@ namespace storm { |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
TerminateIfFilteredExtremumBelowThreshold<ValueType>::TerminateIfFilteredExtremumBelowThreshold(storm::storage::BitVector const& filter, bool strict, ValueType const& threshold, bool useMinimum) : TerminateIfFilteredSumExceedsThreshold<ValueType>(filter, threshold, strict), useMinimum(useMinimum) { |
|
|
|
// Intentionally left empty.
|
|
|
|
STORM_LOG_THROW(!this->filter.empty(), storm::exceptions::InvalidArgumentException, "Empty Filter; Can not take extremum over empty set."); |
|
|
|
cachedExtremumIndex = this->filter.getNextSetIndex(0); |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
bool TerminateIfFilteredExtremumBelowThreshold<ValueType>::terminateNow(std::vector<ValueType> const& currentValues, SolverGuarantee const& guarantee) const { |
|
|
|
bool TerminateIfFilteredExtremumBelowThreshold<ValueType>::terminateNow(std::function<ValueType(uint64_t const&)> const& valueGetter, SolverGuarantee const& guarantee) const { |
|
|
|
if (guarantee != SolverGuarantee::GreaterOrEqual) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
STORM_LOG_ASSERT(currentValues.size() == this->filter.size(), "Vectors sizes mismatch."); |
|
|
|
ValueType currentValue = useMinimum ? storm::utility::vector::min_if(currentValues, this->filter) : storm::utility::vector::max_if(currentValues, this->filter); |
|
|
|
return this->strict ? currentValue < this->threshold : currentValue <= this->threshold; |
|
|
|
ValueType extremum = valueGetter(cachedExtremumIndex); |
|
|
|
if (!useMinimum && (this->strict ? extremum >= this->threshold : extremum > this->threshold)) { |
|
|
|
// The extremum can only become larger so we can return right now.
|
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (useMinimum) { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::min(valueGetter(pos), extremum); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (this->strict) { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::max(valueGetter(pos), extremum); |
|
|
|
if (extremum >= this->threshold) { |
|
|
|
cachedExtremumIndex = pos; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
for (auto const& pos : this->filter) { |
|
|
|
extremum = std::max(valueGetter(pos), extremum); |
|
|
|
if (extremum > this->threshold) { |
|
|
|
cachedExtremumIndex = pos; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return this->strict ? extremum < this->threshold : extremum <= this->threshold; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|