#include "storm/solver/TerminationCondition.h" #include "storm/utility/vector.h" #include "storm/adapters/RationalFunctionAdapter.h" #include "storm/utility/macros.h" #include "storm/exceptions/InvalidArgumentException.h" namespace storm { namespace solver { template bool TerminationCondition::terminateNow(std::vector const& currentValues, SolverGuarantee const& guarantee) const { return terminateNow([¤tValues] (uint64_t const& i) {return currentValues[i];}, guarantee); } template bool NoTerminationCondition::terminateNow(std::function const& valueGetter, SolverGuarantee const& guarantee) const { return false; } template bool NoTerminationCondition::requiresGuarantee(SolverGuarantee const&) const { return false; } template TerminateIfFilteredSumExceedsThreshold::TerminateIfFilteredSumExceedsThreshold(storm::storage::BitVector const& filter, ValueType const& threshold, bool strict) : threshold(threshold), filter(filter), strict(strict) { // Intentionally left empty. } template bool TerminateIfFilteredSumExceedsThreshold::terminateNow(std::function const& valueGetter, SolverGuarantee const& guarantee) const { if (guarantee != SolverGuarantee::LessOrEqual) { return false; } ValueType sum = storm::utility::zero(); 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 bool TerminateIfFilteredSumExceedsThreshold::requiresGuarantee(SolverGuarantee const& guarantee) const { return guarantee == SolverGuarantee::LessOrEqual; } template TerminateIfFilteredExtremumExceedsThreshold::TerminateIfFilteredExtremumExceedsThreshold(storm::storage::BitVector const& filter, bool strict, ValueType const& threshold, bool useMinimum) : TerminateIfFilteredSumExceedsThreshold(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 bool TerminateIfFilteredExtremumExceedsThreshold::terminateNow(std::function const& valueGetter, SolverGuarantee const& guarantee) const { if (guarantee != SolverGuarantee::LessOrEqual) { return false; } 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 pos : this->filter) { extremum = std::min(valueGetter(pos), extremum); if (extremum <= this->threshold) { cachedExtremumIndex = pos; return false; } } } else { for (auto pos : this->filter) { extremum = std::min(valueGetter(pos), extremum); if (extremum < this->threshold) { cachedExtremumIndex = pos; return false; } } } } else { for (auto pos : this->filter) { extremum = std::max(valueGetter(pos), extremum); } } return this->strict ? extremum > this->threshold : extremum >= this->threshold; } template bool TerminateIfFilteredExtremumExceedsThreshold::requiresGuarantee(SolverGuarantee const& guarantee) const { return guarantee == SolverGuarantee::LessOrEqual; } template TerminateIfFilteredExtremumBelowThreshold::TerminateIfFilteredExtremumBelowThreshold(storm::storage::BitVector const& filter, bool strict, ValueType const& threshold, bool useMinimum) : TerminateIfFilteredSumExceedsThreshold(filter, threshold, strict), useMinimum(useMinimum) { STORM_LOG_THROW(!this->filter.empty(), storm::exceptions::InvalidArgumentException, "Empty Filter; Can not take extremum over empty set."); cachedExtremumIndex = this->filter.getNextSetIndex(0); } template bool TerminateIfFilteredExtremumBelowThreshold::terminateNow(std::function const& valueGetter, SolverGuarantee const& guarantee) const { if (guarantee != SolverGuarantee::GreaterOrEqual) { return false; } 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 pos : this->filter) { extremum = std::min(valueGetter(pos), extremum); } } else { if (this->strict) { for (auto pos : this->filter) { extremum = std::max(valueGetter(pos), extremum); if (extremum >= this->threshold) { cachedExtremumIndex = pos; return false; } } } else { for (auto 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 bool TerminateIfFilteredExtremumBelowThreshold::requiresGuarantee(SolverGuarantee const& guarantee) const { return guarantee == SolverGuarantee::GreaterOrEqual; } template class TerminationCondition; template class NoTerminationCondition; template class TerminateIfFilteredSumExceedsThreshold; template class TerminateIfFilteredExtremumExceedsThreshold; template class TerminateIfFilteredExtremumBelowThreshold; #ifdef STORM_HAVE_CARL template class TerminationCondition; template class NoTerminationCondition; template class TerminateIfFilteredSumExceedsThreshold; template class TerminateIfFilteredExtremumExceedsThreshold; template class TerminateIfFilteredExtremumBelowThreshold; #endif } }