/* * File: ParameterRegion.cpp * Author: tim * * Created on August 10, 2015, 1:51 PM */ #include "src/modelchecker/region/ParameterRegion.h" #include "src/utility/region.h" #include "src/utility/macros.h" #include "src/parser/MappedFile.h" #include "src/settings/SettingsManager.h" #include "src/settings/modules/RegionSettings.h" #include "src/exceptions/InvalidSettingsException.h" #include "src/exceptions/InvalidArgumentException.h" namespace storm { namespace modelchecker { namespace region { template ParameterRegion::ParameterRegion(VariableSubstitutionType const& lowerBounds, VariableSubstitutionType const& upperBounds) : lowerBounds(lowerBounds), upperBounds(upperBounds), checkResult(RegionCheckResult::UNKNOWN) { init(); } template ParameterRegion::ParameterRegion(VariableSubstitutionType&& lowerBounds, VariableSubstitutionType&& upperBounds) : lowerBounds(std::move(lowerBounds)), upperBounds(std::move(upperBounds)), checkResult(RegionCheckResult::UNKNOWN) { init(); } template void ParameterRegion::init() { //check whether both mappings map the same variables, check that lowerbound <= upper bound, and pre-compute the set of variables for (auto const& variableWithLowerBound : this->lowerBounds) { auto variableWithUpperBound = this->upperBounds.find(variableWithLowerBound.first); STORM_LOG_THROW((variableWithUpperBound != upperBounds.end()), storm::exceptions::InvalidArgumentException, "Couldn't create region. No upper bound specified for Variable " << variableWithLowerBound.first); STORM_LOG_THROW((variableWithLowerBound.second<=variableWithUpperBound->second), storm::exceptions::InvalidArgumentException, "Couldn't create region. The lower bound for " << variableWithLowerBound.first << " is larger then the upper bound"); this->variables.insert(variableWithLowerBound.first); } for (auto const& variableWithBound : this->upperBounds) { STORM_LOG_THROW((this->variables.find(variableWithBound.first) != this->variables.end()), storm::exceptions::InvalidArgumentException, "Couldn't create region. No lower bound specified for Variable " << variableWithBound.first); } } template ParameterRegion::~ParameterRegion() { //Intentionally left empty } template std::set::VariableType> ParameterRegion::getVariables() const { return this->variables; } template typename ParameterRegion::CoefficientType const& ParameterRegion::getLowerBound(VariableType const& variable) const { auto const& result = lowerBounds.find(variable); STORM_LOG_THROW(result != lowerBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find a lower bound of a variable that is not specified by this region"); return (*result).second; } template typename ParameterRegion::CoefficientType const& ParameterRegion::getUpperBound(VariableType const& variable) const { auto const& result = upperBounds.find(variable); STORM_LOG_THROW(result != upperBounds.end(), storm::exceptions::InvalidArgumentException, "tried to find an upper bound of a variable that is not specified by this region"); return (*result).second; } template const typename ParameterRegion::VariableSubstitutionType ParameterRegion::getUpperBounds() const { return upperBounds; } template const typename ParameterRegion::VariableSubstitutionType ParameterRegion::getLowerBounds() const { return lowerBounds; } template std::vector::VariableSubstitutionType> ParameterRegion::getVerticesOfRegion(std::set const& consideredVariables) const { std::size_t const numOfVariables = consideredVariables.size(); std::size_t const numOfVertices = std::pow(2, numOfVariables); std::vector resultingVector(numOfVertices, VariableSubstitutionType()); if (numOfVertices == 1) { //no variables are given, the returned vector should still contain an empty map return resultingVector; } for (uint_fast64_t vertexId = 0; vertexId < numOfVertices; ++vertexId) { //interprete vertexId as a bit sequence //the consideredVariables.size() least significant bits of vertex will always represent the next vertex //(00...0 = lower bounds for all variables, 11...1 = upper bounds for all variables) std::size_t variableIndex = 0; for (auto const& variable : consideredVariables) { if ((vertexId >> variableIndex) % 2 == 0) { resultingVector[vertexId].insert(std::pair(variable, getLowerBound(variable))); } else { resultingVector[vertexId].insert(std::pair(variable, getUpperBound(variable))); } ++variableIndex; } } return resultingVector; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getSomePoint() const { return this->getLowerBounds(); } template RegionCheckResult ParameterRegion::getCheckResult() const { return checkResult; } template void ParameterRegion::setCheckResult(RegionCheckResult checkResult) { //a few sanity checks STORM_LOG_THROW((this->checkResult == RegionCheckResult::UNKNOWN || checkResult != RegionCheckResult::UNKNOWN), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from something known to UNKNOWN "); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::EXISTSVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to EXISTSVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSSAT || checkResult != RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSSAT to ALLVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSVIOLATED || checkResult != RegionCheckResult::EXISTSSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSVIOLATED to EXISTSSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSVIOLATED || checkResult != RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSVIOLATED to ALLSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSBOTH || checkResult != RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSBOTH to ALLSAT"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::EXISTSBOTH || checkResult != RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from EXISTSBOTH to ALLVIOLATED"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::ALLSAT || checkResult == RegionCheckResult::ALLSAT), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from ALLSAT to something else"); STORM_LOG_THROW((this->checkResult != RegionCheckResult::ALLVIOLATED || checkResult == RegionCheckResult::ALLVIOLATED), storm::exceptions::InvalidArgumentException, "Tried to change the check result of a region from ALLVIOLATED to something else"); this->checkResult = checkResult; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getViolatedPoint() const { return violatedPoint; } template void ParameterRegion::setViolatedPoint(VariableSubstitutionType const& violatedPoint) { this->violatedPoint = violatedPoint; } template typename ParameterRegion::VariableSubstitutionType ParameterRegion::getSatPoint() const { return satPoint; } template void ParameterRegion::setSatPoint(VariableSubstitutionType const& satPoint) { this->satPoint = satPoint; } template void ParameterRegion::fixVariables(std::map const& fixedVariables) { this->fixedVariables = fixedVariables; } template std::map::VariableType, RegionBoundary> ParameterRegion::getFixedVariables() const { return fixedVariables; } template std::string ParameterRegion::toString() const { std::stringstream regionstringstream; for (auto var : this->getVariables()) { regionstringstream << storm::utility::region::convertNumber(this->getLowerBound(var)); regionstringstream << "<="; regionstringstream << storm::utility::region::getVariableName(var); regionstringstream << "<="; regionstringstream << storm::utility::region::convertNumber(this->getUpperBound(var)); regionstringstream << ","; } std::string regionstring = regionstringstream.str(); //the last comma should actually be a semicolon regionstring = regionstring.substr(0, regionstring.length() - 1) + ";"; return regionstring; } template void ParameterRegion::parseParameterBounds( VariableSubstitutionType& lowerBounds, VariableSubstitutionType& upperBounds, std::string const& parameterBoundsString){ 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"); VariableType var = storm::utility::region::getVariableFromString(parameter); CoefficientType lb = storm::utility::region::convertNumber(parameterBoundsString.substr(0,positionOfFirstRelation)); CoefficientType ub = storm::utility::region::convertNumber(parameterBoundsString.substr(positionOfSecondRelation+2)); lowerBounds.emplace(std::make_pair(var, lb)); upperBounds.emplace(std::make_pair(var, ub)); } template ParameterRegion ParameterRegion::parseRegion( std::string const& regionString){ VariableSubstitutionType lowerBounds; VariableSubstitutionType upperBounds; std::vector parameterBounds; boost::split(parameterBounds, regionString, boost::is_any_of(",")); for(auto const& parameterBound : parameterBounds){ if(!std::all_of(parameterBound.begin(),parameterBound.end(), ::isspace)){ //skip this string if it only consists of space parseParameterBounds(lowerBounds, upperBounds, parameterBound); } } return ParameterRegion(std::move(lowerBounds), std::move(upperBounds)); } template std::vector> ParameterRegion::parseMultipleRegions( std::string const& regionsString){ std::vector result; std::vector 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(parseRegion(regionStr)); } } return result; } template std::vector> ParameterRegion::getRegionsFromSettings(){ 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 parseMultipleRegions(regionsString); } #ifdef STORM_HAVE_CARL template class ParameterRegion; #endif } //namespace region } }