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.
189 lines
12 KiB
189 lines
12 KiB
/*
|
|
* File: Regions.cpp
|
|
* Author: Tim Quatmann
|
|
*
|
|
* Created on May 13, 2015, 12:54 PM
|
|
*/
|
|
|
|
#include <string>
|
|
|
|
#include "src/utility/regions.h"
|
|
#include "src/exceptions/NotImplementedException.h"
|
|
#include "src/exceptions/InvalidArgumentException.h"
|
|
#include "adapters/CarlAdapter.h"
|
|
#include "exceptions/InvalidSettingsException.h"
|
|
#include "parser/MappedFile.h"
|
|
|
|
namespace storm {
|
|
namespace utility{
|
|
namespace regions {
|
|
|
|
template<typename ParametricType, typename ConstantType>
|
|
void RegionParser<ParametricType, ConstantType>::parseParameterBounds(
|
|
std::map<VariableType, BoundType>& lowerBounds,
|
|
std::map<VariableType, BoundType>& upperBounds,
|
|
std::string const& parameterBoundsString,
|
|
double const precision){
|
|
double actualPrecision = (precision==0.0 ? storm::settings::generalSettings().getPrecision() : precision);
|
|
|
|
std::string::size_type positionOfFirstRelation = parameterBoundsString.find("<=");
|
|
STORM_LOG_THROW(positionOfFirstRelation!=std::string::npos, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundsString << " I could not find a '<=' after the first number");
|
|
std::string::size_type positionOfSecondRelation = parameterBoundsString.find("<=", positionOfFirstRelation+2);
|
|
STORM_LOG_THROW(positionOfSecondRelation!=std::string::npos, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundsString << " I could not find a '<=' after the parameter");
|
|
|
|
std::string parameter=parameterBoundsString.substr(positionOfFirstRelation+2,positionOfSecondRelation-(positionOfFirstRelation+2));
|
|
//removes all whitespaces from the parameter string:
|
|
parameter.erase(std::remove_if(parameter.begin(), parameter.end(), isspace), parameter.end());
|
|
STORM_LOG_THROW(parameter.length()>0, storm::exceptions::InvalidArgumentException, "When parsing the region" << parameterBoundsString << " I could not find a parameter");
|
|
double lowerBound, upperBound;
|
|
try{
|
|
lowerBound=std::stod(parameterBoundsString.substr(0,positionOfFirstRelation));
|
|
upperBound=std::stod(parameterBoundsString.substr(positionOfSecondRelation+2));
|
|
}
|
|
catch (std::exception const& exception) {
|
|
STORM_LOG_ERROR("Failed to parse the region: " << parameterBoundsString << ". The correct format for regions is lowerBound<=parameter<=upperbound");
|
|
throw exception;
|
|
}
|
|
|
|
VariableType var = getVariableFromString<VariableType>(parameter);
|
|
BoundType lb = convertNumber<double, BoundType>(lowerBound, true, actualPrecision);
|
|
STORM_LOG_WARN_COND((lowerBound==convertNumber<BoundType, double>(lb, true, actualPrecision)), "The lower bound of '"<< parameterBoundsString << "' could not be parsed accurately. Increase precision?");
|
|
BoundType ub = convertNumber<double, BoundType>(upperBound, false, actualPrecision);
|
|
STORM_LOG_WARN_COND((upperBound==convertNumber<BoundType, double>(ub, true, actualPrecision)), "The upper bound of '"<< parameterBoundsString << "' could not be parsed accurately. Increase precision?");
|
|
lowerBounds.emplace(std::make_pair(var, lb));
|
|
upperBounds.emplace(std::make_pair(var, ub));
|
|
// std::cout << "parsed bounds " << parameterBoundsString << ": lb=" << lowerBound << " ub=" << upperBound << " param='" << parameter << "' precision=" << actualPrecision << std::endl;
|
|
}
|
|
|
|
template<typename ParametricType, typename ConstantType>
|
|
typename RegionParser<ParametricType, ConstantType>::ParameterRegion RegionParser<ParametricType, ConstantType>::parseRegion(std::string const& regionString, double precision){
|
|
double actualPrecision = (precision==0.0 ? storm::settings::generalSettings().getPrecision() : precision);
|
|
std::map<VariableType, BoundType> lowerBounds;
|
|
std::map<VariableType, BoundType> upperBounds;
|
|
std::vector<std::string> parameterBounds;
|
|
boost::split(parameterBounds, regionString, boost::is_any_of(","));
|
|
for(auto const& parameterBound : parameterBounds){
|
|
RegionParser<ParametricType, ConstantType>::parseParameterBounds(lowerBounds, upperBounds, parameterBound, actualPrecision);
|
|
}
|
|
return ParameterRegion(lowerBounds, upperBounds);
|
|
}
|
|
|
|
template<typename ParametricType, typename ConstantType>
|
|
std::vector<typename RegionParser<ParametricType, ConstantType>::ParameterRegion> RegionParser<ParametricType, ConstantType>::parseMultipleRegions(std::string const& regionsString, double precision){
|
|
double actualPrecision = (precision==0.0 ? storm::settings::generalSettings().getPrecision() : precision);
|
|
std::vector<ParameterRegion> result;
|
|
std::vector<std::string> regionsStrVec;
|
|
boost::split(regionsStrVec, regionsString, boost::is_any_of(";"));
|
|
for(auto const& regionStr : regionsStrVec){
|
|
if(!std::all_of(regionStr.begin(),regionStr.end(),isspace)){ //skip this string if it only consists of space
|
|
result.emplace_back(RegionParser<ParametricType, ConstantType>::parseRegion(regionStr, actualPrecision));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
template<typename ParametricType, typename ConstantType>
|
|
std::vector<typename RegionParser<ParametricType, ConstantType>::ParameterRegion> RegionParser<ParametricType, ConstantType>::getRegionsFromSettings(double precision){
|
|
STORM_LOG_THROW(storm::settings::regionSettings().isRegionsSet() || storm::settings::regionSettings().isRegionFileSet(), storm::exceptions::InvalidSettingsException, "Tried to obtain regions from the settings but no regions are specified.");
|
|
STORM_LOG_THROW(!(storm::settings::regionSettings().isRegionsSet() && storm::settings::regionSettings().isRegionFileSet()), storm::exceptions::InvalidSettingsException, "Regions are specified via file AND cmd line. Only one option is allowed.");
|
|
|
|
std::string regionsString;
|
|
if(storm::settings::regionSettings().isRegionsSet()){
|
|
regionsString = storm::settings::regionSettings().getRegionsFromCmdLine();
|
|
}
|
|
else{
|
|
//if we reach this point we can assume that the region is given as a file.
|
|
STORM_LOG_THROW(storm::parser::MappedFile::fileExistsAndIsReadable(storm::settings::regionSettings().getRegionFilePath().c_str()), storm::exceptions::InvalidSettingsException, "The path to the file in which the regions are specified is not valid.");
|
|
storm::parser::MappedFile mf(storm::settings::regionSettings().getRegionFilePath().c_str());
|
|
regionsString = std::string(mf.getData(),mf.getDataSize());
|
|
}
|
|
return RegionParser<ParametricType, ConstantType>::parseMultipleRegions(regionsString,precision);
|
|
}
|
|
|
|
|
|
template<>
|
|
storm::RationalFunction::CoeffType convertNumber<double, storm::RationalFunction::CoeffType>(double const& number, bool const& roundDown, double const& precision){
|
|
double actualPrecision = (precision==0.0 ? storm::settings::generalSettings().getPrecision() : precision);
|
|
uint_fast64_t denominator = 1.0/actualPrecision;
|
|
uint_fast64_t numerator;
|
|
if(roundDown){
|
|
numerator= number*denominator; //this will always round down
|
|
} else{
|
|
numerator = std::ceil(number*denominator);
|
|
}
|
|
storm::RationalFunction::CoeffType result(numerator);
|
|
result = result/denominator;
|
|
return result;
|
|
}
|
|
|
|
template<>
|
|
storm::RationalFunction convertNumber<double, storm::RationalFunction>(double const& number, bool const& roundDown, double const& precision){
|
|
return storm::RationalFunction(convertNumber<double, storm::RationalFunction::CoeffType>(number, roundDown, precision));
|
|
}
|
|
|
|
template<>
|
|
double convertNumber<cln::cl_RA, double>(cln::cl_RA const& number, bool const& roundDown, double const& precision){
|
|
return cln::double_approx(number);
|
|
}
|
|
|
|
template<>
|
|
double convertNumber<double, double>(double const& number, bool const& roundDown, double const& precision){
|
|
return number;
|
|
}
|
|
|
|
template<>
|
|
cln::cl_RA convertNumber<cln::cl_RA, cln::cl_RA>(cln::cl_RA const& number, bool const& roundDown, double const& precision){
|
|
return number;
|
|
}
|
|
|
|
|
|
template<>
|
|
storm::Variable getVariableFromString<storm::Variable>(std::string variableString){
|
|
storm::Variable const& var = carl::VariablePool::getInstance().findVariableWithName(variableString);
|
|
STORM_LOG_THROW(var!=carl::Variable::NO_VARIABLE, storm::exceptions::InvalidArgumentException, "Variable '" + variableString + "' could not be found.");
|
|
return var;
|
|
}
|
|
|
|
template<>
|
|
std::string getVariableName<storm::Variable>(storm::Variable variable){
|
|
return carl::VariablePool::getInstance().getName(variable);
|
|
}
|
|
|
|
template<>
|
|
typename storm::modelchecker::SparseDtmcRegionModelChecker<storm::RationalFunction,double>::BoundType evaluateFunction<storm::RationalFunction, double>(
|
|
storm::RationalFunction const& function,
|
|
std::map<typename storm::modelchecker::SparseDtmcRegionModelChecker<storm::RationalFunction,double>::VariableType,
|
|
typename storm::modelchecker::SparseDtmcRegionModelChecker<storm::RationalFunction,double>::BoundType> const& point){
|
|
return function.evaluate(point);
|
|
}
|
|
|
|
template<>
|
|
bool functionIsLinear<storm::RationalFunction>(storm::RationalFunction const& function){
|
|
// Note: At this moment there is no function in carl for rationalFunctions.
|
|
// We therefore check whether the numerator is linear and the denominator constant.
|
|
// We simplify the function to (hopefully) avoid wrong answers for situations like x^2/x
|
|
storm::utility::simplify(function);
|
|
bool result=(function.nominator().isLinear() && function.denominator().isConstant());
|
|
STORM_LOG_WARN_COND(result, "The function " << function << "is not considered as linear.");
|
|
return result;
|
|
}
|
|
|
|
//explicit instantiations
|
|
template double convertNumber<double, double>(double const& number, bool const& roundDown, double const& precision);
|
|
|
|
#ifdef STORM_HAVE_CARL
|
|
template class RegionParser<storm::RationalFunction, double>;
|
|
|
|
template storm::RationalFunction convertNumber<double, storm::RationalFunction>(double const& number, bool const& roundDown, double const& precision);
|
|
template storm::RationalFunction::CoeffType convertNumber<double, storm::RationalFunction::CoeffType>(double const& number, bool const& roundDown, double const& precision);
|
|
template double convertNumber<cln::cl_RA, double>(storm::RationalFunction::CoeffType const& number, bool const& roundDown, double const& precision);
|
|
template cln::cl_RA convertNumber<cln::cl_RA, cln::cl_RA>(cln::cl_RA const& number, bool const& roundDown, double const& precision);
|
|
|
|
template storm::Variable getVariableFromString<storm::Variable>(std::string variableString);
|
|
template std::string getVariableName<storm::Variable>(storm::Variable variable);
|
|
|
|
template bool functionIsLinear<storm::RationalFunction>(storm::RationalFunction const& function);
|
|
#endif
|
|
}
|
|
}
|
|
}
|