Browse Source

Merge branch 'foxglynn'

tempestpy_adaptions
dehnert 7 years ago
parent
commit
5600e65067
  1. 24
      src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp
  2. 275
      src/storm/utility/numerical.cpp
  3. 134
      src/storm/utility/numerical.h

24
src/storm/modelchecker/csl/helper/SparseCtmcCslHelper.cpp

@ -632,19 +632,21 @@ namespace storm {
}
// Use Fox-Glynn to get the truncation points and the weights.
std::tuple<uint_fast64_t, uint_fast64_t, ValueType, std::vector<ValueType>> foxGlynnResult = storm::utility::numerical::getFoxGlynnCutoff(lambda, 1e+300, storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision() / 8.0);
STORM_LOG_DEBUG("Fox-Glynn cutoff points: left=" << std::get<0>(foxGlynnResult) << ", right=" << std::get<1>(foxGlynnResult));
// std::tuple<uint_fast64_t, uint_fast64_t, ValueType, std::vector<ValueType>> foxGlynnResult = storm::utility::numerical::getFoxGlynnCutoff(lambda, 1e+300, storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision() / 8.0);
storm::utility::numerical::FoxGlynnResult<ValueType> foxGlynnResult = storm::utility::numerical::foxGlynn(lambda, storm::settings::getModule<storm::settings::modules::GeneralSettings>().getPrecision() / 8.0);
STORM_LOG_DEBUG("Fox-Glynn cutoff points: left=" << foxGlynnResult.left << ", right=" << foxGlynnResult.right);
// Scale the weights so they add up to one.
for (auto& element : std::get<3>(foxGlynnResult)) {
element /= std::get<2>(foxGlynnResult);
for (auto& element : foxGlynnResult.weights) {
element /= foxGlynnResult.totalWeight;
}
// If the cumulative reward is to be computed, we need to adjust the weights.
if (useMixedPoissonProbabilities) {
ValueType sum = storm::utility::zero<ValueType>();
for (auto& element : std::get<3>(foxGlynnResult)) {
for (auto& element : foxGlynnResult.weights) {
sum += element;
element = (1 - sum) / uniformizationRate;
}
@ -654,10 +656,10 @@ namespace storm {
// Initialize result.
std::vector<ValueType> result;
uint_fast64_t startingIteration = std::get<0>(foxGlynnResult);
uint_fast64_t startingIteration = foxGlynnResult.left;
if (startingIteration == 0) {
result = values;
storm::utility::vector::scaleVectorInPlace(result, std::get<3>(foxGlynnResult)[0]);
storm::utility::vector::scaleVectorInPlace(result, foxGlynnResult.weights.front());
++startingIteration;
} else {
if (useMixedPoissonProbabilities) {
@ -672,9 +674,9 @@ namespace storm {
std::unique_ptr<storm::solver::LinearEquationSolver<ValueType>> solver = linearEquationSolverFactory.create(env, std::move(uniformizedMatrix), storm::solver::LinearEquationSolverTask::Multiply);
solver->setCachingEnabled(true);
if (!useMixedPoissonProbabilities && std::get<0>(foxGlynnResult) > 1) {
if (!useMixedPoissonProbabilities && foxGlynnResult.left > 1) {
// Perform the matrix-vector multiplications (without adding).
solver->repeatedMultiply(values, addVector, std::get<0>(foxGlynnResult) - 1);
solver->repeatedMultiply(values, addVector, foxGlynnResult.left - 1);
} else if (useMixedPoissonProbabilities) {
std::function<ValueType(ValueType const&, ValueType const&)> addAndScale = [&uniformizationRate] (ValueType const& a, ValueType const& b) { return a + b / uniformizationRate; };
@ -689,10 +691,10 @@ namespace storm {
// multiplication, scale and add the result.
ValueType weight = 0;
std::function<ValueType(ValueType const&, ValueType const&)> addAndScale = [&weight] (ValueType const& a, ValueType const& b) { return a + weight * b; };
for (uint_fast64_t index = startingIteration; index <= std::get<1>(foxGlynnResult); ++index) {
for (uint_fast64_t index = startingIteration; index <= foxGlynnResult.right; ++index) {
solver->repeatedMultiply(values, addVector, 1);
weight = std::get<3>(foxGlynnResult)[index - std::get<0>(foxGlynnResult)];
weight = foxGlynnResult.weights[index - foxGlynnResult.left];
storm::utility::vector::applyPointwise(result, values, result, addAndScale);
}

275
src/storm/utility/numerical.cpp

@ -0,0 +1,275 @@
#include "storm/utility/numerical.h"
#include <cmath>
#include <boost/math/constants/constants.hpp>
#include "storm/utility/macros.h"
#include "storm/utility/constants.h"
#include "storm/exceptions/InvalidArgumentException.h"
#include "storm/exceptions/PrecisionExceededException.h"
namespace storm {
namespace utility {
namespace numerical {
template<typename ValueType>
FoxGlynnResult<ValueType>::FoxGlynnResult() : left(0), right(0), totalWeight(storm::utility::zero<ValueType>()) {
// Intentionally left empty.
}
/*!
* The following implementation of Fox and Glynn's algorithm is taken from David Jansen's patched version
* in MRMC, which is based on his paper:
*
* https://pms.cs.ru.nl/iris-diglib/src/getContent.php?id=2011-Jansen-UnderstandingFoxGlynn
*
* We have only adapted the code to match more of C++'s and our coding guidelines.
*/
template<typename ValueType>
FoxGlynnResult<ValueType> foxGlynnFinder(ValueType lambda, ValueType epsilon) {
ValueType tau = std::numeric_limits<ValueType>::min();
ValueType omega = std::numeric_limits<ValueType>::max();
ValueType const sqrt_2_pi = boost::math::constants::root_two_pi<ValueType>();
ValueType const log10_e = std::log10(boost::math::constants::e<ValueType>());
uint64_t m = static_cast<uint64_t>(lambda);
int64_t left = 0;
int64_t right = 0;
// tau is only used in underflow checks, which we are going to do in the logarithm domain.
tau = log(tau);
// In error bound comparisons, we always compare with epsilon*sqrt_2_pi.
epsilon *= sqrt_2_pi;
// Compute left truncation point.
if (m < 25) {
// For lambda below 25 the exponential can be smaller than tau. If that is the case we expect
// underflows and warn the user.
if (-lambda <= tau) {
STORM_LOG_WARN("Fox-Glynn: 0 < lambda < 25, underflow near Poi(" << lambda << ", 0) = " << std::exp(-lambda) << ". The results are unreliable.");
}
// Zero is used as left truncation point for lambda <= 25.
left = 0;
} else {
// Compute the left truncation point for lambda >= 25 (for lambda < 25 we use zero as left truncation point).
ValueType const bl = (1 + 1 / lambda) * std::exp((1/lambda) * 0.125);
ValueType const sqrt_lambda = std::sqrt(lambda);
int64_t k;
// Start looking for the left truncation point:
// * start search at k=4 (taken from original Fox-Glynn paper)
// * increase the left truncation point until we fulfil the error condition
for (k = 4;; ++k) {
ValueType max_err;
left = m - static_cast<int64_t>(std::ceil(k*sqrt_lambda + 0.5));
// For small lambda the above calculation can yield negative truncation points, crop them here.
if (left <= 0) {
left = 0;
break;
}
Internal Server Error - tempest - Gitea: Git with a cup of tea

500


Gitea Version: 1.14.5

0