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

/*
* 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
}
}
}